Skip to content

Configuration

Beetl reads two configs: a project config committed under .beetl/, and a user config in your home directory that holds identity and never leaves your machine. Every key is optional and has a default, so a fresh beetl init writes a minimal file and everything below falls back to the values shown here.

Lives at .beetl/config.json or .beetl/config.toml. beetl init asks which format to write; beetl adopt writes one into a config-less (legacy) store. Exactly one config file may exist — Beetl never resolves multiple by silent precedence, and a missing config is an error rather than a silent revert to committed-mode defaults (both would be surprising for a project that had chosen privacy). See Formats & discovery.

Full file with defaults:

{
"schemaVersion": 1,
"idPrefix": "BTL",
"strictness": "strict",
"autoFile": true,
"requireActor": false,
"privacy": {
"mode": "committed",
"redactPatterns": [],
"scrubPaths": false,
},
"agent": {
"runner": null,
"model": null,
"apiKeyEnv": "ANTHROPIC_API_KEY",
},
"taxonomy": { "extends": "builtin", "categories": [], "surfaces": [] },
"nudges": {
"enabled": true,
"rules": [{ "scope": "file", "count": 3, "days": 60 }],
},
"global": { "enabled": false },
"attribution": { "inCommittedReports": false },
"integrations": { "github": { "enabled": false } },
}
Key Type / values Default Meaning
schemaVersion 1 1 Config schema version. Only 1 is valid today; present so future migrations are explicit.
idPrefix string ^[A-Z][A-Z0-9]{1,7}$ BTL Prefix for session IDs (BTL-20260724-a8q6). 2–8 uppercase alphanumerics, must start with a letter.
strictness strict | loose strict strict enforces the full lifecycle-gate set on transitions; loose relaxes non-critical gates for lightweight use.
autoFile boolean true Whether agents may auto-create sessions (e.g. via the stop hook). false → sessions only from an explicit beetl new / file-complete.
requireActor boolean false When true, reject any store write with no resolvable Actor — agents must pass --actor agent:<tool>:<model> on every call.

Controls what sensitive data is written and where. See the Privacy page for the classification and scrub model.

Key Type / values Default Meaning
mode committed | private-split | local-only committed committed: sessions committed as-is. private-split: sensitive artifacts split into a gitignored *.private.json. local-only: the whole .beetl/ is gitignored.
redactPatterns string[] (regex) [] Extra regexes redacted from session text, on top of the built-in secret detectors.
scrubPaths boolean false Rewrite absolute filesystem paths to repo-relative before writing.

Selects the runner used for LLM-backed work (beetl diagnose, patterns --synthesize). See Agent integration and Patterns.

Key Type / values Default Meaning
runner claude-cli | codex-cli | api | none | null null Which runner to use. null auto-detects: claude on PATH → claude-cli, else codexcodex-cli, else none. api is explicit-only.
model string | null null Runner-specific model override. null uses the runner’s own default.
apiKeyEnv string ANTHROPIC_API_KEY Env var read for the API key. Only used when runner is api.

Extends the built-in category/surface vocabulary used when filing sessions.

Key Type / values Default Meaning
extends builtin | none builtin builtin keeps the shipped categories and adds yours; none uses only your categories.
categories string[] [] Project-specific categories in addition to (or instead of) the built-ins.
surfaces string[] [] Project-specific surfaces (free-form area labels, e.g. cli/interactive). No built-in surface list.

Built-in categories: logic-error, race-condition, state-management, null-safety, type-error, resource, integration, config-environment, data, ui-rendering, performance, security, regression.

Threshold rules that fire at beetl new time and in pattern reports to flag churn hotspots (e.g. “3 sessions touched this file in 60 days”).

Key Type Default Meaning
enabled boolean true Master switch for nudges.
rules rule[] [{ "scope": "file", "count": 3, "days": 60 }] The threshold rules to evaluate.

Each rule:

Field Type / values Constraint Meaning
scope file | surface | category What the repeated sessions must share to trip the nudge.
count integer ≥ 2 Number of sessions in the window that trips the nudge.
days integer ≥ 1 Rolling window, in days, ending at the newest session.
Key Type Default Meaning
enabled boolean false Opt into the cross-project global layer. Set by the beetl init prompt; non-interactive init leaves it false so nothing leaves a repo without a human choice.
Key Type Default Meaning
inCommittedReports boolean false Whether beetl blame author/agent attribution may appear in committed reports. Local-only by default.
Key Type Default Meaning
github.enabled boolean false Enable GitHub issue/PR links. Designed-in, shipped incrementally.

Human identity lives in the user-level config at ~/.beetl/config.json, not the project config — so it’s consistent across every repo and never committed. beetl init establishes it on first run: it defaults username from git config user.name and records your git emails so store entries can be matched to commits.

{
"identity": {
"username": "mike",
"gitEmails": ["mikeweberbusiness@gmail.com"],
},
}
Key Type Default Meaning
identity.username string Your handle, used in human:<username> actors. Optional.
identity.gitEmails string[] [] Git author emails you commit under, used to attribute sessions to commits.
  • Beetl looks for config.json, then config.toml, under .beetl/. Both formats parse to the same schema. YAML was accepted through v0.1 and dropped in ADR-0011 — the parser was 39% of the shipped bundle, and TOML covers the same ground.
  • Exactly one config must exist. Two or more is an error (CONFIG_AMBIGUOUS) — Beetl will not pick one by precedence. Zero is an error (CONFIG_MISSING) rather than a silent fallback to defaults; run beetl adopt to write one explicitly.
  • A config.* file in an unsupported format (e.g. config.ini, or a config.yaml left over from v0.1) is reported, with beetl adopt --format <fmt> suggested to write a supported one. It is never silently ignored — that would revert a local-only store to committed defaults.
Command What it does
beetl init Create .beetl/ and write the initial config (asks format + global opt-in).
beetl adopt Write a config into an existing config-less store (--format json|toml).
beetl global Manage the cross-project global layer (gated by global.enabled).
beetl doctor Diagnose store/config problems, including ambiguous or missing config.