Skip to content

ka.toml reference

Configuration is strict TOML: unknown keys are hard errors carrying the TOML position, so typos never silently pass. ka config schema emits the JSON schema for editor integration; ka config print shows the resolved result.

Lowest to highest; each textual layer overlays the last and set fields win:

built-in defaults
→ ~/.config/ka/ka.toml (user)
→ .ka/ka.toml (project, trust-gated)
→ extra --config files (repeatable, last wins)
→ environment (KA_MODEL, KA_MODE, …)
→ CLI flags

Project layers are loaded only after the trust gate accepts the directory (first use prompts; the decision is stored in ~/.local/state/ka/trust.json).

The project layer is anchored at the project root: the nearest .git ancestor of the launch directory (stopping at $HOME and the filesystem root; the launch directory itself if there is none). The whole project-scope .ka/ layer lives there (config, skills, rules, agents, commands, hooks, plus everything ka generates: plans, staged memories, always-allow saves), so sessions started in a subdirectory share one .ka.

Key Type Default Meaning
model selector none Default model (vendor/model@effort)
effort low|medium|high|max none Default reasoning effort
mode guarded|accept_edits|free|plan free Permission mode
max_steps integer 20 Tool-execution steps per prompt before forcing a text reply
cwd path process cwd Working directory override
model = "ollama/qwen3.5:9b"
mode = "accept_edits"
max_steps = 30
Key Meaning
default Selector for the main model
fast Selector for cheap work (subagents, quick lookups)

First match wins, evaluated before mode logic.

Key Required Meaning
tool ✓ Tool the rule applies to (bash, write, mcpserver.tool, …), or the special loop domain (below)
pattern none Glob on the call’s primary argument; omitted = every call
verdict ✓ allow | ask | deny

A rule with tool = "loop" governs what happens when a call repeats with identical arguments: allow never trips, ask asks at the third repeat, deny denies at three. Without a loop rule, the shipped behavior stands: identical calls auto-error at four.

[[rules]]
tool = "bash"
pattern = "cargo *"
verdict = "allow"
Key Meaning
allow Tool names auto-allowed without asking for the session; “always” answers append here (project layer)
Key Required Meaning
event ✓ pre_tool_use | post_tool_use | stop
tool none Only this tool; omitted = every tool
command ✓ Shell command; tool-call JSON on stdin; exit 2 blocks; clean-exit stdout JSON can steer the mode
Key Meaning
name Server name; tools appear as <name>.<tool>
command + args + env stdio server to spawn
url + headers streamable-HTTP endpoint (SSE fallback)
Key Default Meaning
spend_usd off Ask before the session’s cost crosses this total
context_pct off Ask when the context meter first crosses this percentage
auto_review false The fast-role model pre-screens exec-tier permission asks: auto-allows only the unmistakably safe, never denies, always leaves a note. Inert in --safe-mode
Key Type Default Meaning
max integer 3 Harness continuation rounds when a turn settles while the model’s todo list still has pending items; 0 disables (see the harness loop)
Key Meaning
models Ordered selector list; on provider/auth failure after retries, the turn re-dispatches on the next entry (≤ 2 hops)

Runtime feature toggles: what the model can use, decided at startup. Same spec grammar as the --disable/--enable flags and /features; changes made mid-session are recorded on the strand and restored on resume. Precedence: flags → resumed strand → [features] → defaults (see feature toggles).

Key Default Meaning
disable [] Specs disabled at startup: agents, skills, mcp, hooks, web, lsp, debug, or one item as mcp:<server>, skill:<name>, tool:<hand>, agent:<name>. Strict: an unknown spec is a hard startup error
Key Default Meaning
mode "off" "fs" = bash children write only cwd//tmp/XDG dirs, via bwrap/firejail/landlock, fail-closed
allow_write [] Extra writable directories; a sandbox-expansion “always” grant appends here (project layer)
Key Default Meaning
enable false Append language-server diagnostics to edit/write results (informational, ≤ 20 lines, never tool errors) and register the navigation hands (symbols, definition, references, diagnostics)
write_through false Register the write-tier hands (lsp_rename, lsp_actions, lsp_format); server-proposed edits ride ka’s write path (ledger, snapshots, caps, protected paths)
[lsp.commands] none language → stdio server command, e.g. rust = "rust-analyzer"; only configured languages spawn
Key Default Meaning
enable false Register the debug hand, which drives a DAP adapter: launch/attach, breakpoints, stepping, stack/vars/eval inspection. Inert in --safe-mode
[debug.adapters] none name → stdio launch command, merged over the embedded catalog (gdb, lldb-dap, debugpy, dlv, netcoredbg)
Key Default Meaning
[tools.bash] background_after_ms 30000 Auto-background a still-running bash into a jobs handle; 0 = never
[tools.read] max_image_mb 5 Image cap for read; 0 = unlimited
[tools.web] allow_private_hosts false Let web_fetch reach private/loopback addresses

The aider-style auto-lint / auto-test loop: after a turn that edited files, the test command runs once (test, 15-minute cap) and a failure feeds the output back to the model for one automatic fix round. Lint rules run per edited file, first matching glob wins.

Key Default Meaning
test none Test command run in cwd after an editing turn, e.g. cargo test
[[verify.lints]] pattern none Glob on the edited path (or basename)
[[verify.lints]] command ✓ Lint command; {file} substitutes the edited file, e.g. rustfmt --check {file}
Key Default Meaning
header_glyph ◆ The glyph in the TUI header
mouse "capture" "native" opts out of mouse capture: plain drag selects/pastes with the terminal’s bindings, the wheel scrolls via alternate-scroll, click affordances fall back to their keys (Ctrl+M toggles at runtime and persists)
bell true Ring the terminal bell when a turn finishes or a permission ask appears
notify none Command run when a turn finishes, JSON {event, stop} on stdin, e.g. notify-send ka "turn done"
Key Default Meaning
auto_commit false After each completed turn, git add -A the worktree and commit as ka: <first prompt line>
Key Default Meaning
promote true On context overflow, re-dispatch to a bigger-context sibling model

First entry is the active one.

Key Required Meaning
provider ✓ tavily | brave | bing
api_key_env ✓ Env var holding the API key
base_url none API base override (tests, proxies)
Key Meaning
repo GitHub owner/name releases are fetched from (for self-hosted forks)
check "startup" (default) or "off": the TUI checks availability once per 24 h (cached in ~/.local/state/ka/update/), never installs (ka update stays the only install path), and stays quiet offline; a newer release shows a ⤴ badge in the status bar plus one transcript line
model = "anthropic/claude-sonnet-5@high"
mode = "guarded"
max_steps = 30
[roles]
fast = "groq/llama-3.3-70b"
[[rules]]
tool = "bash"
pattern = "cargo *"
verdict = "allow"
[[hooks]]
event = "pre_tool_use"
tool = "bash"
command = "scripts/guard.sh"
[[mcp]]
name = "fs"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "."]
[guards]
spend_usd = 2.0
context_pct = 90
[sandbox]
mode = "fs"
[lsp]
enable = true
write_through = true
[lsp.commands]
rust = "rust-analyzer"
python = "pyright-langserver --stdio"
[debug]
enable = true