kapelle is in private preview. The npm release is coming soon.

Guide

Everything a new kapellmeister needs: install, your first room, and every command. Read it top to bottom once, then come back to the part you need.

PRIVATE PREVIEW

The npm package is not out yet. It is coming soon. Until then, people with access to the repository install from source.

1Install

You need Node 24 or newer, git, and macOS or Linux. WSL counts as Linux. Windows is not supported.

npm · coming soon$ npm install -g kapelle
$ kapelle --help
pnpm · coming soon$ pnpm add -g kapelle
$ kapelle --help
bun · coming soon$ bun add -g kapelle
$ kapelle --help
from source · needs repository access$ git clone https://github.com/EdwardLiuyc/kapelle.git
$ cd kapelle
$ npm install
$ npm link           # puts kapelle on your PATH
$ kapelle --help

From source, npm unlink -g kapelle undoes the link. If npm link fails with EACCES, npm's global folder belongs to root. Use a folder you own instead of sudo:

$ npm config set prefix ~/.local    # then add ~/.local/bin to PATH

From source, you can check kapelle with no agent and no account. A fake agent ships with the repository:

$ npm run selftest

You should see ✓ allowed Write ACP_TEST.md. Delete ACP_TEST.md when you are done.

2Quick start

kapelle is the client. The agent is a separate program, and it logs in by itself. pi is the default. Install pi and its ACP adapter, then log in to pi once:

$ npm i -g @earendil-works/pi-coding-agent pi-acp
$ pi                   # type /login, then quit

Now send one prompt, inside any repository:

$ kapelle "summarise this repo in three sentences"
READ THIS FIRST

pi works in your own checkout here, and it never asks for permission, so no mode can stop its changes. Read What a mode cannot stop before you give it real work.

Useful options:

  • --agent <id> picks another agent. See Supported agents.
  • --cwd <dir> works in another folder.
  • --mode safe|ask|auto sets what the agent may do. See Modes.
  • --verbose shows the agent's own error output.
  • --quiet hides normal output, but never the safety notices.

3Rooms, runs, agents

Five words cover all of kapelle:

agent
A coding agent such as pi, Claude Code or Copilot. It runs as a separate program. kapelle talks to it with ACP, the Agent Client Protocol.
daemon
One background program that holds all your work, for all your repositories. Close the terminal, and the work stays.
room
A long chat with a team of agents. Each agent keeps its memory across messages. You decide who does what by choosing who to message.
run
Many tasks at once, from one file. Each task has its own prompt, agent and mode, and ends with a result.
worktree
A separate checkout of your repository. Each agent in a room, and each task in a run, gets its own, on its own branch. Your own checkout stays yours.

Open a room

Rooms live in the daemon. Start it once, and add each repository once:

$ kapelle daemon start     # terminal 1: runs until Ctrl-C
$ kapelle daemon add .     # terminal 2: in your repository

Then open a room:

$ kapelle chat new --agent pi     # open a room and chat in it
$ kapelle chat                    # every room, on a terminal
$ kapelle chat list               # every room, as text
$ kapelle chat attach <roomId>     # rejoin a room; its history replays
$ kapelle chat dismiss <roomId>    # stop the room's agents

Each agent in a room works on its own branch, kapelle/<roomId>/<agentId>.

The room API is new, and it can still change.

Talk to agents

Type a message and press Enter. It goes to the room's orchestrator: the agent whose role is orchestrator. Start a message with @name to send it to that agent instead. In an agent's thread, the box always starts with its @name.

An agent works on one message at a time. A message to a busy agent waits in a queue.

Add a second agent with /add. For example, a reviewer on pi that may only read:

/add pi --name rev --mode safe

Then talk to it by name:

@rev review the last commit on dev's branch

Room commands

A command never reaches an agent. Room commands work in any view. An agent's command needs its @name first.

CommandWhat it does
/leaveExit. The rooms and their agents stay alive.
/dismissStop the room's agents. Uncommitted work stays in each agent's checkout.
/helpShow the commands on the screen.
/new [agent]Open a new room. Options: --cmd, --name, --title, --cwd.
/add <agent>Add an agent to the room. Options: --cmd, --name, --role, --mode, --base @name|ref.
@name /mode <m>Set the agent's mode: ask, safe or auto.
@name /role <r>Set the agent's role, or none.
@name /rename <new>Rename the agent.
@name /cancelCancel the agent's turn.
@name /removeRemove the agent from the room.

/new or /add alone opens a form.

Keys and marks

On a terminal, a sidebar lists every room and its agents.

KeyWhat it does
alt+↑ alt+↓, or ctrl+p ctrl+nPick a room's timeline or one agent's thread. A click works too.
ctrl+tHide or show the sidebar.
ctrl+oOpen the menu: cancel a turn, change a mode, view changes, fast-forward, add an agent, and more.
ctrl+xShow or hide the side pane: a diff, your message history, or a shell.
ctrl+]Move the keys between the side pane and the message box.
ctrl+rYour earlier messages, to pick one again.

A mark next to each agent says what it is doing. A room takes the mark of its most urgent agent.

MarkMeaning
?Asks you something. The bell rings once.
!Looks stuck: no progress for a while, or the same step again and again.
◐Busy. A timer shows how long.
⏸Paused. It comes back on its next message.
✕Killed during a turn.
◌Exited.
●Something new you have not seen.
○Nothing new.

Take the work

In a room, kapelle never commits for an agent. An agent commits its own branch. Uncommitted work stays in the agent's checkout.

  • See an agent's changes: ctrl+o, then view changes. The side pane shows the diff. b switches between uncommitted changes and the whole branch.
  • Give one agent another's work: ctrl+o, then fast-forward from …. The pane shows what it would bring, and Enter confirms.
  • Take the work into your own checkout with git, when you are ready.
$ git log -p kapelle/<roomId>/<agentId>
$ git merge kapelle/<roomId>/<agentId>

Run files

A run hands out many tasks at once. Each task has its own prompt, agent and mode, and each ends with a result.

{
  "agent": "pi",
  "mode": "safe",
  "tasks": [
    { "id": "summarise", "prompt": "Summarise what this project does in three sentences." },
    { "id": "look-for-bugs", "prompt": "List any obvious bugs or missing error handling you can see." }
  ]
}
$ kapelle run --file tasks.json

In a git repository, each task gets its own worktree, on a branch named kapelle/<runId>/<taskId>. Keep working in your own checkout while the agents work in theirs. Your uncommitted changes do not reach the tasks, and kapelle tells you so. Outside a git repository, the tasks share the folder.

When a task ends done or warned, kapelle commits its work on the task's branch. Task ids name git branches, so kapelle checks them and never changes them.

In the background

With the daemon running, hand the run over and follow it from any terminal:

$ kapelle run --file tasks.json --detach   # prints the run id
$ kapelle ps                               # every run and each task's status
$ kapelle attach <runId>                    # watch it, and answer its ask prompts
$ kapelle attach <runId> --task <taskId>    # watch one task in full

kapelle rings the bell and sends a desktop notification when a run needs you.

Merge the results

$ kapelle merge <runId> --squash

This puts the changes of all tasks into your working tree, unstaged. It makes no commit. It refuses when two tasks change the same file, or when your own changes touch a file a task changed.

Look at one task's work first with git log -p kapelle/<runId>/<taskId>.

Where the work lives

Worktrees and records live in ~/.local/state/kapelle/. Nothing goes into your repository.

$ kapelle workspace                    # where this repository's work lives
$ kapelle workspace move <old> <new>   # after you move or rename the repository

Use workspace move, not a plain mv. A plain mv breaks git's link to each worktree.

The lead and the loop coming soon

Most issues run the same loop: plan, build, review, open the PR, answer the bot reviews, hand over. The orchestrator lets one agent lead that loop. It gives the work to the other agents in the room, reads their reports, and decides the next step. It does none of the work itself, and you decide every choice.

  • A recipe. You describe your loop in a Markdown file. Only the orchestrator reads it, so the same orchestrator serves any repository.
  • Plain sight. The orchestrator talks to the others only through kapelle, in your timeline. Agents never talk to each other directly.
  • A fence. A stop button, a cap on the turns it gives out, and a bell when it waits for you.
  • A decision log. Every choice it put to you, and your answer.

This part of the guide grows when the orchestrator ships.

Supported agents

Pick one with --agent <id>. Each agent logs in by itself.

--agentInstallTested
pi (default)npm i -g @earendil-works/pi-coding-agent pi-acpyes
claudenpm i -g @agentclientprotocol/claude-agent-acp, then claude auth loginyes
copilotThe Copilot CLI (copilot --acp)yes
opencodenpm i -g opencode-ai, then opencode auth loginyes
geminiThe Gemini CLI (gemini --acp)not yet
ompoh-my-pi (omp acp)not yet

Any other ACP agent works too: --cmd "some-agent --acp".

Claude Code has no ACP mode of its own, so it needs the adapter above. If you see spawn claude-agent-acp ENOENT, the adapter is not on your PATH. Check with command -v claude-agent-acp. You can run kapelle from inside a Claude Code session.

Modes: safe, ask, auto

ModeWhat it does
safeAllows reads. Refuses every change the agent asks about.
askAllows reads. Asks you about each change. A run in your terminal needs the terminal: without one, kapelle uses safe and prints a notice. A room, or a run started with --detach, asks through the daemon: the question waits for your answer, and is refused at the time limit.
autoAllows everything. File paths outside the workspace are still refused.

In a room, each agent has its own mode. The default is auto, because a room is often left alone, and an ask default would leave it waiting.

In the question box, each answer has a number. Deny comes first, so a stray Enter says no. A key only moves the cursor, and only Enter answers.

What a mode cannot stop

A MODE IS A FILTER, NOT A SANDBOX

A mode decides the answer when an agent asks for permission. An agent that changes files through its own shell does not ask. pi and opencode never ask, so safe does not stop them.

kapelle always refuses a file path outside the workspace, in every mode. But this only covers file requests that go through kapelle.

kapelle prints a notice about this, and --quiet never hides it. If you need a wall, run the agent in a container.

Commands

kapelle "<prompt>" [--agent id] [--cmd "cmd"] [--cwd dir] [--mode m] [--verbose] [--quiet]
kapelle run --file <run.json> [--detach] [--cwd dir]
kapelle attach <runId> [--task <taskId>]
kapelle ps
kapelle merge <runId> [--squash] [--cwd dir]
kapelle workspace [--cwd dir]
kapelle workspace move <old-repo> <new-repo>
kapelle daemon start [--port n] [--permission-timeout s]
kapelle daemon add <path>
kapelle chat [new | attach | list | dismiss]

kapelle --help and kapelle chat --help print the full list.

Configuration

Two optional JSON files, and KAPELLE_* environment variables. Nothing creates the files for you. Both are strict: an unknown key or a wrong type is refused, and the error names the file and the key.

Your user file

~/.config/kapelle/config.json holds the daemon's settings:

{ "port": 4719, "permissionTimeoutMs": 120000 }

Your repository's file

.kapelle/config.json in your repository holds the run defaults. It is the only file kapelle reads from your repository. You may commit it.

KeyWhat it sets
stallIdleMsWarn when an agent shows no progress for this long. 0 turns it off.
stallRepeatCountWarn when an agent repeats the same step this many times. 0 turns it off.
ttlMsCancel a run's task after this long. 0 turns it off.
maxConcurrencyHow many tasks of a run work at once.
retentionMsHow long finished runs and dismissed rooms are kept.

A KAPELLE_* variable overrides both files. A value in a run file still wins over all of them.

Troubleshooting

An agent fails to start

It often shows as Internal error (code -32603). Run again with --verbose to see the agent's own error output. In a run, read the task's .stderr.log file in the run's record folder. kapelle workspace tells you where that is.

spawn claude-agent-acp ENOENT

The Claude Code adapter is not on your PATH. Install it, then check with command -v claude-agent-acp.

--mode ask became safe

ask in a plain run needs a terminal to ask you in. Without one, kapelle uses safe and says so. Use --detach to answer through the daemon instead.

Worktrees show as prunable

The repository was moved with a plain mv. Run kapelle workspace move <old> <new> to repair the links.