Configuration
git-paw uses TOML configuration files at two levels, with repo-level settings overriding global ones.
Config File Locations
| Level | Path | Purpose |
|---|---|---|
| Global | ~/.config/git-paw/config.toml | Default CLI, custom CLIs, global presets |
| Per-repo | .git-paw/config.toml (in repo root) | Repo-specific overrides |
Both files are optional. git-paw works with sensible defaults when no config exists.
Full Config Example
# Default CLI used when --cli flag is not provided
default_cli = "my-cli"
# Default CLI for spec-mode launches (--from-all-specs, --specs); bypasses picker when set
# default_spec_cli = "my-cli"
# Prefix for spec-derived branch names (default: "spec/")
# branch_prefix = "spec/"
# Enable mouse mode in tmux sessions (default: true)
mouse = true
# Custom CLI definitions
[clis.my-agent]
command = "/usr/local/bin/my-agent"
display_name = "My Agent"
[clis.local-llm]
command = "ollama-code"
display_name = "Local LLM"
# Named presets for quick launch
[presets.backend]
branches = ["feature/api", "fix/db"]
cli = "claude"
[presets.frontend]
branches = ["feature/ui", "feature/styles"]
cli = "codex"
# Spec scanning configuration
# [specs]
# dir = "specs"
# type = "openspec" # "openspec", "markdown", or "speckit"
# Session logging
# [logging]
# enabled = false
# Agent coordination broker
# [broker]
# enabled = false
# port = 9119
# bind = "127.0.0.1"
# Pointers to user-maintained governance docs (all optional)
# [governance]
# adr = "docs/adr"
# test_strategy = "docs/test-strategy.md"
# security = "docs/security-checklist.md"
# dod = "docs/definition-of-done.md"
# constitution = ".specify/memory/constitution.md"
Settings Reference
default_cli
The AI CLI to use when --cli is not passed and you want to skip the CLI picker.
default_cli = "my-cli"
default_spec_cli
The AI CLI to use by default when launching with --from-all-specs or --specs. When set, skips the CLI picker for any specs that don’t have a paw_cli override.
default_spec_cli = "my-cli"
See Spec-Driven Launch for the full CLI resolution chain.
branch_prefix
Prefix prepended to spec-derived branch names. Defaults to "spec/".
branch_prefix = "spec/"
For example, a spec with ID add-auth produces branch spec/add-auth.
mouse
Enable or disable tmux mouse mode for git-paw sessions. When enabled, you can click panes to switch, drag borders to resize, and scroll with the mouse wheel. This is set per-session and does not affect your other tmux sessions.
mouse = true # default
Custom CLIs
Register custom AI CLIs that aren’t in git-paw’s built-in detection list.
Via config file
[clis.my-agent]
command = "/usr/local/bin/my-agent" # absolute path
display_name = "My Agent" # optional, shown in prompts
[clis.local-llm]
command = "ollama-code" # binary name (resolved via PATH)
display_name = "Local LLM"
Via command line
# Add with absolute path
git paw add-cli my-agent /usr/local/bin/my-agent
# Add with binary name on PATH
git paw add-cli my-agent my-agent
# Add with display name
git paw add-cli my-agent my-agent --display-name "My Agent"
# Remove
git paw remove-cli my-agent
The add-cli and remove-cli commands modify the global config at ~/.config/git-paw/config.toml.
Listing CLIs
git paw list-clis
Shows both auto-detected and custom CLIs with their source:
Name Path Source
claude /usr/local/bin/claude detected
codex /usr/local/bin/codex detected
my-agent /usr/local/bin/my-agent custom
Presets
Presets save branch + CLI combinations for one-command launch.
Defining presets
[presets.backend]
branches = ["feature/api", "fix/db-migration"]
cli = "claude"
[presets.full-stack]
branches = ["feature/api", "feature/ui", "feature/styles"]
cli = "gemini"
Using presets
git paw start --preset backend
This skips all interactive prompts and launches with the preset’s branches and CLI.
Specs
Configure spec file scanning for --from-all-specs and --specs mode.
[specs]
dir = "specs" # Directory containing spec files (relative to repo root)
type = "openspec" # "openspec" (OpenSpec changes), "markdown" (flat .md files), or "speckit" (GitHub Spec Kit)
| Field | Default | Description |
|---|---|---|
dir | "specs" | Directory to scan for spec files |
type | "openspec" | Spec backend: "openspec" (directory-based OpenSpec changes), "markdown" (flat .md files with YAML frontmatter), or "speckit" (GitHub Spec Kit .specify/specs/<feature>/) |
When [specs] is omitted and .specify/specs/ exists at the repo root, the
spec backend auto-detects to type = "speckit" with
dir = ".specify/specs". Use the --specs-format CLI flag to override both
the config value and the auto-detection for a single launch.
See Spec-Driven Launch for format details.
Logging
Configure session output logging.
[logging]
enabled = true
| Field | Default | Description |
|---|---|---|
enabled | false | Whether to capture pane output to log files |
When enabled, logs are written to .git-paw/logs/<session>/ using tmux pipe-pane. See Session Logging for details.
Broker
Configure the HTTP broker for agent coordination. When enabled, git-paw starts a lightweight HTTP server that lets agents share status updates, artifacts, and blocked requests.
[broker]
enabled = true
port = 9119
bind = "127.0.0.1"
| Field | Default | Description |
|---|---|---|
enabled | false | Whether to start the coordination broker |
port | 9119 | HTTP port for the broker server |
bind | "127.0.0.1" | Bind address – never bind to 0.0.0.0 on shared machines |
When the broker is enabled, git-paw injects the GIT_PAW_BROKER_URL environment variable into each agent pane, pointing to http://<bind>:<port>. Agents use this URL to communicate with the broker.
Multi-repo port assignment
If you run git-paw sessions for multiple repositories at the same time, each session needs a different port. Set a unique port in each repo’s .git-paw/config.toml:
# Repo A
[broker]
enabled = true
port = 9119
# Repo B (in its own .git-paw/config.toml)
[broker]
enabled = true
port = 9120
See Agent Coordination for usage details.
Supervisor
Configure the supervisor agent for orchestrating parallel coding sessions. When enabled, the supervisor monitors agents, runs tests, verifies work, and coordinates merges.
[supervisor]
enabled = true
cli = "claude"
test_command = "just check"
lint_command = "cargo clippy -- -D warnings"
build_command = "cargo build"
fmt_check_command = "cargo fmt --check"
doc_build_command = "mdbook build docs/"
spec_validate_command = "openspec validate {{CHANGE_ID}} --strict"
security_audit_command = "cargo audit"
agent_approval = "auto"
| Field | Default | Description |
|---|---|---|
enabled | false | Whether to use supervisor mode by default (can also use --supervisor flag, or override with --no-supervisor for a single session) |
cli | (uses default_cli) | CLI binary for the supervisor agent |
test_command | (none) | Test runner — gate 1 (e.g. "just check", "cargo test", "npm test", "pytest") |
lint_command | (none) | Lint check — gate 1 (e.g. "cargo clippy -- -D warnings", "npm run lint", "ruff check .", "golangci-lint run") |
build_command | (none) | Compile step — gate 1 when build is distinct from test (e.g. "cargo build", "npm run build", "mvn package", "go build ./...") |
fmt_check_command | (none) | Formatter check — gate 1 (e.g. "cargo fmt --check", "prettier --check .", "gofmt -l .", "black --check .") |
doc_build_command | (none) | Documentation build — gate 4 (e.g. "mdbook build docs/", "sphinx-build", "mkdocs build") |
spec_validate_command | (none) | Spec validator — gate 3 (e.g. "openspec validate {{CHANGE_ID}} --strict" for OpenSpec). {{CHANGE_ID}} is substituted by the supervisor agent at verification time with the change name being audited; it is not expanded at config load |
security_audit_command | (none) | Security audit tooling — gate 5 (e.g. "cargo audit", "npm audit", "bandit -r .", "gosec ./...") |
agent_approval | "auto" | Permission level for coding agents: "manual", "auto", or "full-auto" |
Gate-command templating. The seven *_command keys feed the supervisor
skill’s five verification gates (testing, regression analysis, spec audit, doc
audit, security audit). For each key set on this section, the supervisor skill
substitutes the matching {{...}} placeholder at session boot and the
supervisor agent runs the literal command during that gate. For each key
omitted, the placeholder renders as (not configured) and the supervisor
agent skips that tooling step — the gate’s manual review still applies (e.g.
the OWASP-category diff scan for the security gate, the spec scenario
coverage check for the spec gate). Pre-v0.5.x configs that did not name any
of the six new keys continue to work; they just run a less-rigorous
verification cycle until the keys are filled in. A user wanting to explicitly
opt out of a single gate’s tooling can set the field to "(not configured)"
verbatim — the supervisor agent recognises that as the same skip token.
Resolution chain — git-paw picks supervisor mode using the first matching rule:
--no-supervisor→ off (highest precedence; overrides everything below).--supervisor→ on.[supervisor] enabled = true→ on.[supervisor] enabled = false→ off.- No
[supervisor]section +--dry-run→ off. - No
[supervisor]section + interactive TTY → prompts you. - No
[supervisor]section + non-TTY → off.
--supervisor and --no-supervisor are mutually exclusive — passing both produces a parse error.
Approval levels:
| Level | Behavior |
|---|---|
manual | Agents prompt for every action (safest, slowest) |
auto | CLI default behavior — some prompts, some auto-approved |
full-auto | Skip all permission prompts (fastest, agents run unattended) |
The supervisor translates the approval level into CLI-specific flags at launch (e.g. --dangerously-skip-permissions for Claude in full-auto mode).
Auto-approve safe permission prompts
When supervisor mode is enabled, git-paw can automatically approve common,
known-safe permission prompts (cargo test, git commit, broker curl calls, etc.)
in stalled agent panes so the supervisor does not have to dismiss every prompt by hand.
[supervisor.auto_approve]
enabled = true
safe_commands = ["just lint", "just test"]
stall_threshold_seconds = 30
approval_level = "safe"
| Field | Default | Description |
|---|---|---|
enabled | true | Master switch for auto-approval. Set to false to disable. |
safe_commands | [] | Project-specific command prefixes appended to the built-in defaults. |
stall_threshold_seconds | 30 | Seconds an agent’s last_seen must lag before its pane is polled (minimum 5). |
approval_level | "safe" | Coarse preset: "off", "conservative", or "safe". |
Built-in safe commands: cargo fmt, cargo clippy, cargo test, cargo build,
git commit, git push, curl http://127.0.0.1:.
Approval-level presets:
| Preset | Behavior |
|---|---|
off | Forces enabled = false. No detection or approval runs. |
conservative | Drops git push and curl from the effective whitelist. |
safe (default) | Approve every entry in the built-in whitelist plus configured extras. |
How it works: when an agent’s status is non-terminal (done, verified, blocked,
committed are skipped) and its last_seen exceeds the threshold, git-paw runs
tmux capture-pane, classifies the pending command, and either dispatches
BTab Down Enter (if safe) or publishes an agent.question to the supervisor inbox
(if not).
git-paw also seeds .claude/settings.json::allowed_bash_prefixes with the broker
endpoints (/publish, /status, /poll, /feedback) so the first broker call
never hits a permission prompt. Existing entries in that file are preserved.
Common dev-command allowlist
On every supervisor session start, git-paw seeds a curated preset of dev-loop
prefix patterns into .claude/settings.json::allowed_bash_prefixes so agents
do not hit a permission prompt for each variant of cargo build, git commit,
just check, mdbook build, etc. The mechanism is the same one Claude uses
for its “Yes, don’t ask again” flow — but seeded up-front rather than approved
one-by-one.
[supervisor.common_dev_allowlist]
enabled = true
extra = ["pnpm test", "deno fmt"]
| Field | Default | Description |
|---|---|---|
enabled | true | Master switch for the seeder. Set to false to skip seeding entirely. |
extra | [] | Additional project-specific prefix patterns appended to the built-in preset. |
Built-in preset (all v0.5.0 entries):
- Cargo:
cargo build,cargo test,cargo clippy,cargo fmt,cargo check,cargo tree,cargo deny,cargo update - Git (read):
git status,git log,git diff,git show,git fetch - Git (write, non-destructive):
git commit,git push,git pull,git merge,git stash,git add,git restore,git rm - Just:
just(any recipe) - mdBook:
mdbook build - OpenSpec:
openspec validate,openspec new,openspec archive,openspec list,openspec status,openspec instructions - Search (read-only):
find,grep,sed -n
Intentional exclusions: cargo install, cargo run, cargo bench,
git rebase, git reset, git checkout, git push --force, sed without
-n, and non-cargo package managers (npm, pnpm, yarn, deno, bun,
uv, pip, pipx, gem). Add them via extra if you accept the wider
surface for your project.
Behaviour:
- Independent of broker status — non-broker supervisor sessions still benefit.
- Idempotent: re-seeding on session re-attach never duplicates entries.
- Non-fatal: write failures log a warning to stderr and session start continues.
- Targets
<repo>/.claude/settings.jsonalways; also writes~/.claude-oss/settings.jsonwhen that directory pre-exists (the alt-config dogfood pattern) but never creates the directory. - Entries persist after
git paw stop— prune.claude/settings.jsonmanually if you want a clean slate.
Conflict detector tuning
When supervisor mode is enabled, the broker runs an in-process conflict
detector that auto-emits agent.feedback (and optionally agent.question)
on forward, in-flight, and ownership conflicts. See
Agent Coordination § Automatic Conflict Detection for the runtime semantics; the table below
documents the configuration surface.
[supervisor.conflict]
window_seconds = 120
warn_on_intent_overlap = true
escalate_on_violation = true
| Field | Default | Description |
|---|---|---|
window_seconds | 120 | Seconds the detector waits before escalating an unresolved in-flight conflict to the supervisor inbox via agent.question. |
warn_on_intent_overlap | true | Master switch for forward-conflict feedback. When false, two agents declaring overlapping agent.intent files no longer trigger agent.feedback, but the intent tracker still records them (so in-flight and ownership detection continue to work). |
escalate_on_violation | true | Whether ownership violations escalate to the supervisor inbox. When false, the violator still receives agent.feedback, but no follow-up agent.question lands in the supervisor inbox. |
The [supervisor.conflict] table is fully optional. A v0.4 config with
[supervisor] and no [supervisor.conflict] loads cleanly with every field
at the defaults above. Setting [supervisor] enabled = false (or omitting
the section) disables the detector subsystem entirely — no auto-emitted
warnings fire regardless of the values here.
Learnings mode tuning
When supervisor mode is active, the parent [supervisor] learnings = true
flag (default false) activates the learnings subsystem. Entries are
appended to .git-paw/session-learnings.md covering the five deterministic
categories tracked in v0.5.0 (stuck duration, recovery-cycle count, forward
conflicts, in-flight conflicts, ownership violations). The
[supervisor.learnings_config] sub-table tunes the flush cadence; the
master switch lives on the parent table.
[supervisor]
learnings = true
[supervisor.learnings_config]
flush_interval_seconds = 60
| Field | Default | Description |
|---|---|---|
flush_interval_seconds | 60 | How often the learnings aggregator flushes accumulated entries from memory to .git-paw/session-learnings.md. The file is append-only across sessions; a longer interval batches more entries per write. |
See the Learnings Mode chapter for the
category-by-category walkthrough, the output-file format, and the v0.6.0
roadmap for programmatic access via the agent.learning broker variant.
Governance
Point git-paw at your project’s existing governance documents so the supervisor can read them as context. All fields are optional — list only the docs you have.
[governance]
adr = "docs/adr" # directory of ADR files
test_strategy = "docs/test-strategy.md" # single Markdown file
security = "docs/security-checklist.md" # single Markdown file
dod = "docs/definition-of-done.md" # single Markdown file
constitution = ".specify/memory/constitution.md" # single Markdown file
| Field | Kind | Description |
|---|---|---|
adr | directory | Architecture Decision Records. git-paw does not care which convention (Nygard, MADR, adr-tools) — point at the folder where they live. |
test_strategy | file | The team’s test-strategy document. |
security | file | Security checklist (OWASP-style, project-specific, whatever the team uses). |
dod | file | Definition of Done for completed work. |
constitution | file | Project constitution. Spec Kit users normally let this auto-wire (see below). |
git-paw does not dictate the structure, format, or rubric of any of these documents. The supervisor LLM reads them as context and applies judgment during its existing audit flow. There is no [governance.gates] table and no per-doc enforcement switch — gating-per-doc would require git-paw to define “failure” for each doc type, and that is a process choice your team owns.
Paths are stored verbatim and resolved against the repository root at use time. Relative paths point at files inside the repo; absolute paths are accepted as-is. A path that does not exist still loads cleanly — git-paw does not stat the filesystem at config-load. If you point at a missing file, the runtime consumer flags it.
Spec Kit constitution auto-wiring
When governance.constitution is unset AND [specs] type = "speckit", git-paw probes for <specs_dir>/../memory/constitution.md and, if present, populates governance.constitution automatically. This means a typical Spec Kit project (with .specify/specs/ and .specify/memory/constitution.md) gets the constitution wired up without any [governance] entry.
Explicit values always win. If governance.constitution is set to anything — including a path that does not exist or an empty string — auto-wiring is skipped:
[governance]
constitution = "" # disables auto-wiring without deleting the slot
Auto-wiring only runs for the Spec Kit backend. With [specs] type = "openspec", type = "markdown", or no [specs] section, governance.constitution stays whatever the TOML says (defaulting to None).
What the supervisor does with these paths
This [governance] table is the storage slot. The runtime consumer — boot-prompt injection so the supervisor can read each doc and apply it to its audit — lives in the parallel governance-context capability. See the Governance chapter of the user guide for what that looks like end-to-end.
Dashboard
Configure the dashboard TUI rendered in pane 0 when the broker is enabled.
[dashboard]
show_message_log = true
| Field | Default | Description |
|---|---|---|
show_message_log | false | When true, the dashboard renders a scrolling broker-message panel above the prompts section. Useful for watching live agent traffic; leave false for a more compact layout. |
See Dashboard for details.
Multi-repo configuration
Each repository can have its own dashboard settings in .git-paw/config.toml. The repo-level config overrides the global config.
Merging Rules
When both global and repo configs exist, they merge with these rules:
| Field | Merge behavior |
|---|---|
default_cli | Repo wins |
default_spec_cli | Repo wins |
branch_prefix | Repo wins |
mouse | Repo wins |
clis | Maps merge (repo overrides per-key) |
presets | Maps merge (repo overrides per-key) |
specs | Repo wins |
logging | Repo wins |
broker | Repo wins |
supervisor | Repo wins |
dashboard | Repo wins |
governance | Per-field merge (repo wins on each set field, unset fields fall back to global) |
Example: If global config defines [clis.my-agent] and repo config defines [clis.my-agent] with a different command, the repo version wins. But a [clis.other-tool] in global config still appears — maps are merged, not replaced.
Graceful Absence
If no config files exist, git-paw uses defaults:
- No default CLI (prompts for selection)
- Mouse mode enabled
- No custom CLIs
- No presets