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.
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.
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
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
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}
"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"
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