awa config — configuration schema, precedence, and when to change it
On this page
Layer precedence
Configuration is layered, lowest precedence first:
product defaults
awa.toml optional shared project config, committable
.awa/config.toml optional local override, ignored/private
--config <path> optional explicit invocation override (above shared/local)
CLI flags highest
A later layer REPLACES a key, and for a list-valued key that means the whole
list, never a merge. A local .awa/config.toml that sets
[scope].extra_excludes discards the shared awa.toml list rather than
adding to it, and the same is true of include, env_allowlist,
default_scope, and extra_effect_roots. To keep a shared list and add to
it, restate the shared entries in the overriding layer. awa config effective shows the resolved list and the layer it came from, which is the
reliable way to catch a list you did not mean to drop.
Each active layer that changes observation, hashing, diff, run cache identity, storage, or output policy is folded into the relevant config identity, so a reused run or checkpoint reflects the config it actually ran under. Invalid config in any active layer fails loudly and names the layer and path.
Shared vs local:
awa.toml— share scan/run policy with all contributors and agents..awa/config.toml— personal overrides that must not be committed..awaignore— committable native ignore patterns.--config <path>— one-off or CI invocation config.
Discover and manage config from the binary
awa config template annotated template (redirect to a file)
awa config init --shared write a committable awa.toml
awa config init --local write a private .awa/config.toml
awa config path show the shared and local paths and which exist
awa config show print a layer's raw contents
awa config effective the composed config plus each value's origin layer
Reference
Defaults are shown; an absent key keeps its default.
[scope] — Scan scope (history/checkpoint family and the shared base)
The common scan boundary shared by awa checkpoint/changes/diff and, through extra_excludes, the run input scan. Only additive user values live here; the product baseline and protected defaults are built in.
include(path list, default:["."])- Directories/files the scan includes; an explicit narrowed scope outranks every configurable and default exclude.
- When to change: Narrow to a subtree, or bring back a path a baseline/ignore rule would otherwise drop.
extra_excludes(path list, default:[])- Additive common excludes applied to both the history family and the run input scan, on top of the built-in baseline.
- When to change: Exclude a project-specific directory from all scans.
use_gitignore(bool, default:false)- Whether .gitignore participates as an ignore source for the history family. Off by default: git ignores answer "what not to commit", not "what can affect a command".
- When to change: Turn on only if your .gitignore genuinely matches what should not be observed.
use_awaignore(bool, default:true)- Whether .awaignore participates for the history family. On by default; .awaignore is awa's committable native ignore file.
- When to change: Turn off to ignore .awaignore files entirely.
follow_symlinks(bool, default:false)- Whether the scanner follows symbolic links.
- When to change: Enable when scoped content lives behind symlinks you trust.
symlink_max_depth(int, default:16)- Maximum symlink chain depth followed when follow_symlinks is on.
- When to change: Raise or lower the guard against deep or cyclic link chains.
allow_symlink_root_escape(bool, default:false)- Whether a followed symlink may resolve outside the project root.
- When to change: Enable only when you deliberately depend on out-of-root linked content.
[history] — History-only excludes
Excludes that affect awa checkpoint/changes/diff but never the run input scan, so a generated artifact can stay out of local history while remaining a real command input. The history family inherits its ignore-source policy from [scope].
extra_excludes(path list, default:[])- Additive history-only excludes, on top of the built-in history defaults (dist, build, coverage).
- When to change: Keep a generated directory out of checkpoints/diffs while runs still key it.
[hashing] — Content hashing and index trust
Local content identity is fixed: awa hashes worktree content with BLAKE3 and persists every local digest with the blake3: prefix followed by lowercase hex. The primitive is product behavior, not a setting — there is no key here to change it, and only the policy governing how it is applied is configurable. The SHA-256 you see in a release checksum file, an exported documentation manifest, or a site asset digest is a separate external integrity convention and takes no part in local evidence identity.
trust_mode(enum: normal | strict | fast, default:normal)- How aggressively the worktree index is trusted to skip rehashing unchanged files. fast compares size and mtime only, which can miss a same-size same-mtime rewrite, so a run observed under it is recorded but never published as reusable.
- When to change: Use strict for integrity-critical work; use fast only where losing run reuse entirely is an acceptable price for scan speed.
max_file_size(byte size (B/KiB/MiB/GiB/TiB), default:50MiB)- Threshold above which large_file_policy applies.
- When to change: Raise to store larger blobs, or lower to keep the store lean.
large_file_policy(enum: hash-only | store | skip, default:hash-only)- What awa does with files above max_file_size: hash-only keeps them in tree hashes without storing blobs.
- When to change: Use store to keep large blob content, or skip to leave them out of hashing entirely.
[checkpoint] — Checkpoint recording
store_file_contents(bool, default:true)- Whether checkpoint blobs are stored (affects checkpoint policy identity).
- When to change: Turn off to record checkpoint hashes without keeping content.
diff_context(int, default:3)- Default number of context lines in checkpoint diffs.
- When to change: Adjust the default hunk context.
rename_detection(bool, default:true)- Whether diffs detect renames.
- When to change: Turn off for pure add/delete diffs.
[run] — Cached command execution
The run cache. extra_excludes is additive run-only; the effective run input
excludes omit the history-only defaults so a build artifact stays a real
command input. extra_effect_roots watches generated-output directories a
command reads but does not produce (see "Effect roots vs excludes"). A wrapped
command never inherits the full ambient environment: it receives the built-in
baseline, whatever env_allowlist adds, and the fixed advisory marker
AWA_RUN=1, and every one of those participates in the cache key. Run awa config effective to see the resolved inherited names and injected facts.
default_scope(path list, default:["."])- The run input scan scope when --scope is not given.
- When to change: Narrow the default set of inputs a run keys on.
extra_excludes(path list, default:[])- Additive run-only excludes, on top of the baseline. Excluding a path weakens what the run can observe, so do it intentionally.
- When to change: Exclude self-generated output a command writes during the run.
use_gitignore(bool, default:false)- Whether .gitignore participates as an ignore source for the run input scan (keyed into the run cache). Off by default.
- When to change: Turn on only if .gitignore matches what should not affect a command.
use_awaignore(bool, default:true)- Whether .awaignore participates for the run input scan. On by default.
- When to change: Turn off to ignore .awaignore for runs.
env_allowlist(name list, default:["CI", "NODE_ENV"])- Environment variable names, on top of the built-in baseline, folded into the run cache key and passed to the child. The baseline already covers execution (PATH, HOME, SHELL, TMPDIR, the Windows equivalents) and the caller's locale (LANG, LANGUAGE, LC_*), so listing one of those is rejected as redundant; AWA_RUN is reserved because awa injects it.
- When to change: Add a variable your commands depend on so it keys the cache.
ttl(duration (d/h/m/s), default:7d)- Freshness window a reusable run entry stays eligible for a hit.
- When to change: Shorten or lengthen how long a cached result is served.
max_stdout_size(byte size, default:100MiB)- Capture limit for stdout; output beyond it is truncated in stored evidence.
- When to change: Raise for commands with very large output.
max_stderr_size(byte size, default:100MiB)- Capture limit for stderr.
- When to change: Raise for commands with very large error output.
capture_output(bool, default:true)- Whether run output is captured and stored for replay/inspection.
- When to change: Turn off to run without recording output.
cache_failed_runs(bool, default:true)- Whether non-zero-exit runs are cached.
- When to change: Turn off to always re-run failed commands.
extra_effect_roots(name/path list, default:[])- Additive watched generated-output selectors on top of the built-ins. Each is either a directory NAME matched wherever it appears ("bin") or an exact project-relative PATH matched only there ("artifacts/bin"). Literal, never globs. Additive only — a built-in cannot be silenced.
- When to change: Watch a generated directory a command reads so later changes to it invalidate reuse.
[gc] — Garbage collection retention
keep_last_checkpoints(int, default:100)- How many recent checkpoints gc retains.
- When to change: Keep more or fewer checkpoints.
keep_runs_for(duration, default:14d)- How long run records are retained by gc.
- When to change: Extend or shorten run history retention.
keep_restores_for(duration, default:14d)- How long a restore's pre-restore recovery observation — the evidence an applied restore can be undone from — is retained by gc. Independent of keep_runs_for.
- When to change: Keep restore undo evidence longer (or shorter) than run history.
[diff] — Content diff rendering
algorithm(enum: histogram | myers, default:histogram)- Text diff engine; histogram anchors on rare lines and falls back to myers locally.
- When to change: Force myers for a stable, classic diff.
[locks] — Writer/collector lock acquisition
timeout(duration, default:5s)- How long any interlock wait may last before the command fails with the lock-timeout exit code — including gc waiting for the exclusive collector lease another gc holds. A writer's lock is the one case that is not a wait: gc does not wait writers out, it suppresses its whole destructive pass, reports the lock as a blocked candidate, deletes nothing, and exits 0. Zero means fail fast; negative is a config error.
- When to change: Raise on busy shared checkouts, or set 0 to never wait.
[ui] — Human presentation
Human output only; JSON always uses machine timestamps and never carries relative prose.
time(enum: relative | local | utc, default:relative)- How human output renders timestamps (log, run history). A --time flag overrides per invocation.
- When to change: Prefer absolute local or utc timestamps over relative ages.
Effect roots vs excludes
The central run-cache decision:
- The command writes or refreshes a generated directory during the run,
and that output is disposable — it may safely be absent after a replay
→
[run].extra_excludesor.awaignore. Otherwise the self-generated output makes every run non-reusable. - The command writes output you actually need on disk afterwards
→
awa run --record. Excluding it would let a replay report success with the output missing. - The command only reads an already-produced generated directory that the
run input scan no longer sees →
[run].extra_effect_roots. Later changes to that generated state should invalidate reuse. - That directory is still visible to the input scan → configure nothing. Its contents already key the run; an effect root would add no coverage.
- The command is a deploy, migration, formatter, live probe, or otherwise
non-reusable →
awa run --record. Keep durable evidence without publishing a reusable hit.
Picking an effect-root selector (literal, never globs):
- The same directory name at any depth, typically repeated across
monorepo packages → a name:
extra_effect_roots = ["bin"]. - Exactly one location → a project-relative path:
extra_effect_roots = ["artifacts/bin"], which watches neitherother/binnorother/artifacts/bin.
Rules:
- Writing to a watched effect root during the run makes the result non-reusable.
- The two lists are separate: the watched set is the built-in effect roots
plus
extra_effect_roots. An exclude you add yourself is NOT watched, so an excluded, unwatched directory is invisible to the cache in both directions. - Excluding a path therefore weakens what
awa runcan observe, so do it intentionally. - awa will not auto-edit config to improve the cache hit rate.
Pattern semantics
.awaignore— gitignore-like: globs, a trailing slash matches a directory, a leading slash anchors to the project root, and later rules override earlier ones. It is on by default;.gitignoreis off by default.[scope].extra_excludesand[run].extra_excludes— gitignore-style patterns, additive on top of the built-in baseline excludes.[run].extra_effect_roots— literal selectors, never globs, in one of two forms. A single segment is a directory NAME matched by basename wherever it appears:"target"watches everytarget/. A slash-separated project-relative PATH matches that one location only:"artifacts/bin"watchesartifacts/binand neitherother/binnorother/artifacts/bin. Matching is case-sensitive and/is the separator on every platform. A backslash, a volume spelling, and a./..component are rejected in either form; a path is also rejected when it begins or ends with a slash, holds an empty component, or names.gitor.awa.
Use awa config effective to see the resolved effective lists and the layer
each value came from.