Neovim client for plurnk-service.
It consumes the daemon's AG-UI+ HTTP/SSE interface directly; no Node or CLI
subprocess. The pitch: use LLMs the vim way — your buffers, your motions,
your : line.
Requires: Neovim ≥ 0.10, a running plurnk-service daemon (default 127.0.0.1:3044).
require("plurnk").setup({ host = "127.0.0.1", port = 3044 })
require("plurnk").apply_default_keymaps() -- optional; only fills unmapped keys:AI/ prints this table in-editor.
| Form | Effect |
|---|---|
:AI |
toggle workspace tab ⇄ where you came from |
:AI {text} |
prompt (act) |
:AI? {text} |
ask — read-only loop: flags.mode="ask", the engine 403s edits/exec |
:AI: {text} |
act (the default) |
:AI! {cmd} |
exec {cmd} via the daemon; bare :AI! execs the visual selection |
:AI?? / :: |
new workspace, then prompt |
:AI??? |
new headless workspace (no project root) |
:AI???? |
new worker in the current workspace (fork) |
:AI... {text} |
inject into the running loop (a mid-loop prompt steers too) |
:AI/{verb} |
models workspaces workers workspace worker rename log yolo ping, membership pick hide view drop members, open accept reject next prev stop clear |
Visual mode prepends the selection: '<,'>AI? explain this. No-space forms (:AI?? hi) work via cmdline abbreviations.
One tab per worker (a conversation); a workspace is the world containing workers. One workspace is live per Neovim instance; switching notifies. Each worker tab: glyph waterfall on top (the worker's log, exactly what the model sees), 3-line input below — <CR> in normal mode submits; ? /: /! prefixes and raw <<DSL work there too. Streams (exec output) open as 1│/2│-prefixed splits; wiping a live stream buffer cancels it.
Side-effecting ops pause for review. EDIT opens a diffsplit (left disk, right proposed): <localleader>a accept, <localleader>e accept-with-edits, r reject, c cancel. EXEC opens a scratch: a/r/c. Global: <leader>ay/ae/an, <leader>a]/a[ cycle pending, :PlurnkYolo auto-accepts.
vim.opt.statusline = "%f %{v:lua.require('plurnk').statusline()} %l/%L"
-- plurnk[workspace·worker] · 🤖 alias · L3·T2 · ✅ 200 · $0.0042- Transport: AG-UI+ over HTTP/SSE (
curl -Nundervim.system) against the daemon's in-process module; events un-project to the daemon shapes dispatch renders. The threadId is the workspace name, verbatim; the workspace (world) ridesforwardedProps.plurnk.workspaceon every run. - Client contract:
SPEC.md(this repo). External protocol: the plurnk-agui SPEC. Runtime model: the plurnk-service SPEC. - Notifications consumed:
log/entry(routed per-run byentry.worker_id),loop/proposal(server-resolvedflags.yolo/noProposalsare skipped),loop/terminated,telemetry/event,stream/event,stream/concluded. - Tests:
./tests/runner.sh— one headless nvim per spec; boots a private daemon from the sibling../plurnk-servicecheckout (tmp DB, ephemeral port) unlessPLURNK_PORTis set.PLURNK_SERVICE_DIRoverrides the daemon location. - Project management:
AGENTS.md(local). Audit + roadmap: #16.