plugins
kage runs Lua plugins inside a sandboxed runtime. Drop any .lua file into ~/.config/kage/plugins/ and kage loads it at startup. File changes during a session trigger a hot reload between turns; nothing carries over the boundary.
what plugins can do
- register new tools the agent can call
- override built-in tools (filter
bash, auditwrite) - add slash / colon commands the user invokes
- bind keyboard chords to handlers (
kage.register_keybinding) - open blocking dialogs - select, confirm, input, editor (
kage.ui.*), even from a command or keybinding handler - contribute status-bar widgets and transient status messages
- take over the header / footer chrome rows (
kage.ui.set_header/set_footer) - add prompt-input autocomplete providers, including a built-in
@filepath completer (kage.add_autocomplete_provider) - intercept raw key events before the dispatcher (
kage.on_terminal_input) - subscribe to ~25 events (lifecycle, message stream, tool calls), transform the context or provider request, rewrite or replace the compaction summary, veto session ops
- trigger compaction, fork sessions, inject messages, write custom session entries and labels
what plugins cannot do by default
- spawn subprocesses
- read or write arbitrary filesystem paths (
kage.fs.*is workdir-scoped) - open network sockets outside
kage.http(which respects an allow-list) - rewrite or reseat the live session
- load native shared libraries
- start background threads
The sandbox strips os.execute, io.popen, package.loadlib, dofile, loadfile, and a handful of other escape hatches before your code runs. Routine string, math, table functions stay.
Subprocess access and session rewriting are available as opt-in, per-plugin capabilities the user grants in config - closed by default, loud when granted.
minimal example
~/.config/kage/plugins/hello.lua:
lua
kage.register_command({
name = "hello",
description = "say hi",
handler = function(args)
kage.notify("hello " .. (args.rest or "there"))
end,
})Restart kage (or wait for the watcher to pick it up). Type :hello or /hello. You should see a transient toast.
next steps
- Lua API - every function exposed under
kage.* - Capabilities - the opt-in tier for subprocesses and session rewriting
- Examples - longer plugins that demonstrate the patterns