Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Configuration

volee reads ~/.config/volee/config.toml (or $XDG_CONFIG_HOME/volee, or $VOLEE_CONFIG_DIR). Every setting is optional and a missing file means the defaults.

volee config init    # write a commented example
volee config check   # validate the file and show what it sets
volee config path    # print where the file is

Unknown keys are errors, reported with their line, so a typo never turns into a setting that silently does nothing.

Example

[agents]
model = "opus"
permission_mode = "auto"
wake_timeout = 3600

[repos.billing]
path = "~/code/billing"
base = "develop"
model = "sonnet"
setup = ["bun install"]

[tui]
theme = "catppuccin-mocha"

[tui.keys]
take-over = "ctrl-a"

[tui.tools]
git = "gitui"

[agents]

KeyDefaultMeaning
modelthe harness defaultModel for the agents volee launches, unless the repository sets one.
permission_modemanualacceptEdits, auto, manual, dontAsk or plan, passed to Claude Code with every launch and resume. manual asks before every tool that needs permission: the agent then waits until you take it over and answer. volee never passes bypassPermissions, and never leaves the mode to your own Claude Code default. OpenCode agents get --auto when the mode is auto, and nothing otherwise.
wake_timeout3600Seconds an idle agent stays reachable by the wake-up hook. Afterwards, a message resumes the session instead.
resume_after_reboottrueResume, in new volee hosts, the agents a reboot interrupted, the first time the daemon starts afterwards (after a reboot). false: they show as stopped, and your next message to one resumes it.

Worktrees

volee creates each agent’s worktree inside its repository, at .claude/worktrees/<name>, where Claude Code keeps its own. <name> is the branch with every character other than a letter, a digit, ., _ or - replaced by -: feat/invoices becomes feat-invoices. volee adds that folder to the repository’s local exclude file so git status stays clean. The location is not configurable: Claude Code only trusts a session started from a repository you trust, and never a worktree elsewhere (see ADR 0013). Run claude once in each repository you list below and accept its trust prompt.

[repos.<name>]

One table per repository volee may launch agents in. <name> is what you type on the command line and what agents see; it uses letters, digits, -, _ and ..

KeyRequiredMeaning
pathyesThe main checkout. ~ is expanded. A folder inside another repository is refused, so that agents never land in the repository around it.
basenoThe branch work starts from. The repository’s default branch when unset.
modelnoModel for this repository’s agents.
setupnoCommands that prepare each new worktree before its agent starts, such as ["bun install"]. See below.
mergenoHow volee merges this repository’s pull requests once you approved a mission: "merge" (a merge commit), "squash" or "rebase". When unset, the first of the three the repository allows on GitHub. A repository without a remote is always merged with a merge commit.

Setup commands

A new worktree holds the tracked files only: no dependencies, and none of the files git ignores. setup prepares it before the agent starts (ADR 0017):

[repos.shop]
path = "~/code/shop"
setup = [
  "cp \"$VOLEE_REPO_ROOT/.env.local\" .",
  "bun install",
]

The daemon runs the commands in order, each with /bin/sh -c, in the new worktree. Besides the daemon’s environment, they get VOLEE_REPO (the repository’s name), VOLEE_REPO_ROOT (its main checkout), VOLEE_WORKTREE, VOLEE_BRANCH and VOLEE_BASE. Each may run for 15 minutes, after which it is killed with everything it started. Meanwhile the agent is listed as launching, with the command that runs; what the commands print goes to setup.log in the agent’s folder of volee’s state directory as they print it, so tail -f follows it, and volee spawn says where it is. Until the agent’s session starts, its preview in the interface and volee logs show the end of that log.

If a command fails, the launch fails: no session starts, the worktree and branch stay, and the agent is listed as failed with the command and the last line it printed. Fix the cause and run the same volee spawn again: volee reuses the worktree while git sees it clean, and runs the setup again, so keep the commands safe to run twice. Commands that write only files git ignores, such as dependencies or a .env.local listed in .gitignore, keep the worktree clean; if the setup left other files, remove the worktree and its branch before launching again. If the agent’s mission ends during the setup, the launch stops and no session starts. A mission’s coordinator works in the main checkout and runs no setup.

Some setups, each checked with volee config check:

# Bun, and a .env.local that git ignores, from the main checkout.
setup = ['cp "$VOLEE_REPO_ROOT/.env.local" .', "bun install"]

# npm, exactly as the lockfile says.
setup = ["npm ci"]

# Python with uv.
setup = ["uv sync"]

# A monorepo with a .env.local in several apps and packages.
setup = [
  '''cd "$VOLEE_REPO_ROOT" && find apps packages -maxdepth 2 -name .env.local | while read -r file; do mkdir -p "$VOLEE_WORKTREE/${file%/*}" && cp "$file" "$VOLEE_WORKTREE/$file"; done''',
  "bun install",
]

Package managers also run scripts: the project’s own and its dependencies’ (postinstall, prepare). They run in the new worktree, which shares the repository’s git configuration with your main checkout, so a script that runs git config (to set core.hooksPath, for example) changes it for every checkout of the repository. If that matters, skip the scripts (bun install --ignore-scripts, npm ci --ignore-scripts) and run the ones you need as setup commands of their own.

[messages]

KeyDefaultMeaning
summariesfalseLets volee summarize a thread with a model when you ask (volee summary). Each summary runs Claude Code with your account, usually for a few cents.
summary_modelhaikuThe model summaries use.

A summary runs claude -p with no tools, no MCP server, none of your hooks and no saved session, in a directory of volee’s own: the model reads the thread and nothing else.

[missions]

KeyDefaultMeaning
max_workers8The most agents one mission may launch besides its coordinator, counting those that already stopped.

A coordinator launches workers with its spawn_worker tool, without asking you, so this limit is what keeps a coordinator gone wrong from starting sessions without end. Launches that run at the same time all count. A coordinator that reaches the limit gets a refusal that tells it to ask you. Workers also stay in the repositories the mission names: volee compares their main checkouts, never their directory names.

[git]

KeyDefaultMeaning
fetch"launched"Which repositories the daemon fetches in the background: "launched" (those of agents volee launched), "all" (also those of sessions volee only discovered) or "never".

To tell whether an agent’s commits are pushed, and whether its branch was merged, volee compares the branch with origin. The daemon therefore runs git fetch --prune origin in an agent’s repository at most every five minutes, in batch mode: a fetch that needs a password fails instead of waiting, and only your remote-tracking branches change (--prune forgets the ones deleted on the remote; FETCH_HEAD is left alone).

By default it fetches only the repositories of agents volee launched: their remote is part of the work volee started. A session you started yourself is yours, and so is its remote: volee reads its repository but leaves fetching to you, and compares with what your last fetch brought. Set "all" to have those repositories fetched too, or "never" to fetch only by hand (for example on a metered connection, or with remotes that need a hardware key). With fetches off, push states and merges are as current as your last fetch, and new agents start from origin/<base> as that fetch left it.

[tui]

KeyDefaultMeaning
themelight or dark, matching the terminalA built-in theme or a file in ~/.config/volee/themes/; see Themes. Without it, volee uses catppuccin-latte on a light terminal and catppuccin-mocha otherwise. The theme picker (Space t) writes it for you, and volee --theme <name> overrides it for one run.
background"terminal"Whose background shows under volee’s text: "terminal", your terminal’s own (its color and its transparency), or "theme", the theme’s color. The theme colors the text, the borders and what fills a cell on purpose (a selection, a badge, a notice) either way; see Themes.
reduced_motionfalseStop animations: a new message lights up its line on the network instead of travelling along it, and spinners stop.
keysnoneKey overrides; see below.
toolsfound on the machinePrograms o opens an agent’s worktree with; see below.

[tui.keys]

Every key of the interface, the wall and a take over can be changed. Name the action (the interface guide lists them by context) and give it one key, a list of keys, or an empty list to unbind it. At the top of [tui.keys], the keys replace the action’s keys in every context where it has some; in a [tui.keys.<context>] table, only there:

[tui.keys]
take-over = ["enter", "ctrl-a"]   # opening an agent
new-agent = ["c", "space n"]
adopt = []

[tui.keys.agents]
first = "home"

[tui.keys.wall]
take-over = "enter"

[tui.keys.attached]
leave = "ctrl-g"

A key is written like q, G, ctrl-c, alt-x, shift-tab, enter, esc, space, home, pgdn or f5; a sequence of up to three keys with spaces between them, like g g or space n (gg works too). volee refuses, naming the action, an unknown action or context, two actions on the same key where both apply, and a key that both acts and starts a longer sequence. The leave key must be Control and a letter other than h, i, j or m.

[tui.tools]

The interface can open an agent’s worktree in your own tools. None is required and none is forced: volee offers the ones it finds, and each key below replaces what it would find.

KeyFound when unsetRuns
editor$VISUAL, then $EDITOR, with .in this terminal
diffnvim -c 'DiffviewOpen {base}', when diffview.nvim is installedin this terminal
gitlazygit, when installedin this terminal
idecode {dir}, when VS Code’s code is installedin a window of its own, in the background

Each value is a command line, split like a shell would (quotes, no variables or pipes) and run in the agent’s worktree. {dir} stands for the worktree and {base} for the branch the agent started from, each passed as one argument. Keep them out of sh -c '...': the base may come from a coordinator agent (volee only accepts a plain branch name, but a shell is still the wrong place for text an agent chose). An empty string turns a tool off, even when it is installed:

[tui.tools]
editor = "hx"                   # instead of $EDITOR
diff = "git difftool -d {base}"
git = ""                        # never offer lazygit
ide = "zed {dir}"

Tools that run in the terminal take it over, as taking over an agent does, and the interface comes back when they exit.