Configuration reference
Every key in emet.config.json, with its default and meaning. The source of truth is emet/schema/emet.config.schema.json. Terms follow GLOSSARY.md. Back to the README.
emet init writes the file. emet preflight and emet doctor validate it. A key marked prose-only is read by the /emet prompts, not by the CLI. A key marked deprecated is still accepted. The schema also allows a free-text "//" key for notes (never read by any tool) and "version", which is always 1.
pr
How a wave’s PR is merged.
{ "pr": { "autoMerge": true, "mergeMethod": "squash", "maxCiFixAttempts": 2 } }autoMerge(defaulttrue): wait for the PR’s checks and merge; with no checks, merge at once. A failing check is fixed and pushed, up tomaxCiFixAttemptstimes, then the PR is left open for a human. A wave with anything flagged is never auto-merged.mergeMethod(defaultsquash):squash,mergeorrebase, passed togh pr merge.maxCiFixAttempts(default2, minimum0): how many times the coordinator may try to fix a failing check before leaving the PR open for a human.
handoff
What happens after a wave closes, and the size limits of a worker’s handoff note. Validated by emet preflight.
{ "handoff": { "autoChain": false, "launcher": "auto", "permissionMode": "bypassPermissions" }}-
maxLines(default60): most lines a.emet/handoff-<ticket>.mdnote may have beforeemet handoff --checkfails it. -
maxChars(default8000, about 2k tokens): most characters a handoff note may have. -
autoChain(defaultfalse): after a clean, merged wave with more waves left, launch the next one withclaude --bginstead of printing/emet:run --dispatch <spec-id>. Inspect it withclaude agentsorclaude attach emet-<spec-id>-w<n>. Requirements:claudeon PATH, with--bgsupport.- A trusted workspace.
--bgruns non-interactively, so the trust dialog never shows; openclaudeinteractively in the repo once and accept it. - The bypass warning accepted once in an interactive session (
skipDangerousModePermissionPrompt), since the next wave runs inhandoff.permissionMode, not in the launching session’s mode.
It launches only when the PR merged and nothing was flagged, and it skips if an
emet-<spec-id>-*session is already live (claude agents --json). If the launch fails, it falls back to printing/emet:run --dispatch <spec-id>. -
launcher(defaultauto, one ofauto,orca,bg): also open the wave in an Orca tab runningclaude attach.autoasks the Orca runtime (orca status), so it works fromclaude --bgsessions too, which have noTERM_PROGRAM;orcaalways tries;bgnever. The wave runs in the background either way, and a tab that fails to open never stops the chain.emet launch <spec-id> --wave <n>does the whole launch; seeemet launch. -
permissionMode(defaultbypassPermissions, one ofbypassPermissions,auto,acceptEdits): permission mode of the chained session. It is not inherited from the launching session, becauseautomode’s classifier can deny a step such asgh pr mergeand leave a wave half-finished. Yourpermissions.denyrules still apply, but the bypass warning must have been accepted once interactively (skipDangerousModePermissionPrompt).
budgets
All optional.
{ "budgets": { "workerAttempts": 2, "reviewRounds": 2, "stallNudgeCap": 6 } }workerAttempts(default2, minimum1): how many times a ticket can failverifybefore the gate answersdefer. The ticket gets the deferred label and the rest of the wave continues. An environment fault, such as the test command exiting 126/127 or a provider outage, pauses the run without spending an attempt.reviewRounds(default2, minimum1): how many review/fix rounds a ticket gets before one escalation to the next model tier. Whatever is still open after that gets a ruling.stallNudgeCap(default6, minimum1): how many times a stalled worker gets nudged. The count never resets.
models
Model and effort per role. Every key is optional; omitting the section keeps worker sonnet/medium and reviewer opus/medium. Effort is one of low, medium, high, xhigh, max.
{ "models": { "worker": { "model": "sonnet", "effort": "medium" }, "reviewer": { "medium": { "model": "opus", "effort": "medium" }, "high": { "model": "opus", "effort": "medium" } }, "triage": "haiku" }}worker.model(defaultsonnet),worker.effort(defaultmedium): the worker. A ticket’sModel:line overridesworkerfor that worker only.reviewer.mediumandreviewer.high(defaultopus,mediumeach): the reviewer for each risk tier returned byemet assess. Raisereviewer.high.effort(for example tohigh) for more scrutiny on risky waves.triage(defaulthaiku): the cheap model for CI-log triage and passive-tier review. A failing check is handed to an agent on this model, which returns at most about 2k tokens withfile:linepointers.escalation(default{ "sonnet": "opus" }): the next model tier per model name, used when a ticket reaches its fix cap.
review
{ "review": { "highRiskPaths": [] } }highRiskPaths(default[]): extra case-insensitive path substrings that force thehighreview tier inemet assess, on top of the built-in set (auth, security, payments, webhooks, CI, the installer, lockfiles, migrations and dangerous sinks such as raw SQL or pipe-to-shell).
landing
mode(defaultpr):propens a pull request (requiresgh).mergemerges the integration branch into local trunk withemet landand never pushes, withcommands.selfCheckstanding in for CI. Independent of the tracker. See ADR-0010.
tracker
Which issue tracker /emet talks to. The CLI reads kind to decide which dependency checks apply; the rest documents the adapter the /emet command follows (see docs/agents/issue-tracker.md).
kind(required):linear,githuborlocal. Forlocal, see Local tracker and ADR-0011.transitions.onStart,transitions.onPrOpen,transitions.onPrMerge: who writes each ticket-state transition:worker,coordinatororautomatic(the tracker integration does it, for example Linear’s GitHub integration on PR open or merge). The coordinator never writes a transition markedautomatic.github.priorityLabels: maps a priority level ("1"= P0 highest to"4"= P3) to a GitHub label name, for example{"1":"P0","2":"P1"}. With none declared, tickets order bycreatedAtascending andemet doctorsays so.github.stateLabels: maps a workflow state (todo,in-progress,in-review) to a GitHub label name, for example{"todo":"status:todo"}.doneandcanceledare inferred from the issue’s closed state andstate_reason.linear: Linear-specific settings (team key, workflow-state names). Read only by the model followingdocs/agents/issue-tracker.md, never by the CLI.local.idPrefix(deprecated): local ticket ids are now<feature-slug>-<NN>.readyLabel,triageLabels,prReference(deprecated): label and PR-reference templates, for exampleCloses #{number}(github) orRefs: {id}(linear).
preflight
requiredFiles(default none): filesemet preflightrequires at the repo root before a wave dispatches, each{ "path", "why" };whyshows in the failure message. Empty means the check does not run.requiredCommands(default none): binaries that must resolve on PATH before dispatch.emet preflightfails with exit 1 naming any that do not, andemet doctorreports them. This is the repo’s own list, separate from the tracker-driven dependency checks;ghalready has a dedicated check, so listing it is optional. Common additions:rgandsg.
specs
dir(defaultdocs/specs): repo-relative directory of living specs, written byemet spec-merge.
map
path(defaultdocs/agents/codebase.md): repo-relative path of the mapemet mapgenerates.
concurrency
waveSize(default4, minimum1): most Agent calls dispatched together in one wave.maxLiveWorkers(defaultauto): global cap shared by every/emetcoordinator running on this host, across every repo. The slot pool lives under~/.local/state/emet/slots, not in any one repo.autoderives the cap from the host’s CPU count and RAM; a positive integer pins it. A separate memory-headroom check (EMET_MEM_RESERVE_GIB, default 8 GiB) denies an acquire when available memory is too low, regardless of this cap. TheEMET_MAX_LIVE_WORKERSenvironment variable overrides this field and also acceptsauto.runIdleThresholdMs(default5400000, 90 minutes): how long a run with no live anchor still classifies as idle rather than dead, based on transcript freshness alone. TheEMET_RUN_IDLE_THRESHOLD_MSenvironment variable overrides it.
ticket
idPattern: anchored regex source a ticket id must match, for example^PROJ-\d+$. An invalid pattern is a hard config error.branchPrefix: lowercase prefix (^[a-z0-9-]+$) for a worker’s local branch. Branches are<branchPrefix>-<number>-<slug>, andcleanupsweeps the glob<branchPrefix>-*.idExample(deprecated, prose-only): one example id matchingidPattern.branchPattern(deprecated, prose-only): full branch-name template.
commands
All prose-only.
selfCheck: commands a worker runs before considering its change done, for example["npm run check"]. Underlanding.modemergeit stands in for CI.workerScopedSuite: command a worker runs to test only the area it touched.emet verifyrequires it to pass.fullSuite.run: command for the repo-wide suite, run once on the integration branch after a wave’s branches merge. A red run blocks the PR andautoChain.fullSuite.singleton:trueif only one worktree may run the suite at a time.fullSuite.runInBackground,fullSuite.reset(deprecated): background flag and state-reset commands.
worktree
lockReason: template for thegit worktree lockreason a worker writes at bootstrap, filled in byemet lock-reason. The default isemet run={runId} ticket={ticket} anchor={anchorPid} slug={coordinatorSlug} at={iso}. Override only to add fields:emet lock-reasonrefuses a template that drops the literalemettoken, any ofrun=,ticket=,anchor=,at=, orslug=.copyFromMain(prose-only): paths copied from the trunk checkout into a fresh worktree before bootstrap, for example untracked env files.bootstrap(prose-only): shell commands run once in a fresh worktree before a worker starts, for example["npm ci"]. Run by/emetPhase 6, never by the CLI.stateDir(deprecated, prose-only): directory for run-local logs, for example.emet.
usage
oversizedReadLines(default400, minimum1): a Read with no offset or limit against a file over this many lines counts as oversized inemet usage.stalledMinutes(default10, minimum1): default--minutesthreshold foremet usage --stalled.
sizing
inlineMaxLines(default100, minimum1): largest ticket body, in lines, kept inline in a worker prompt.
schema
Prose-only. This repo’s data-schema ownership, used by the Phase 3 conflict-avoidance rule when splitting tickets. Empty or omitted skips the rule.
ownedPaths: paths that define shared schema, for example["prisma/schema.prisma"]. At most one worker per wave may touch them.sharedDatabase(deprecated):trueif workers share one physical database.
commit
Prose-only.
trailer: git trailer key a worker appends to commits referencing the ticket, for exampleRefs.trailerPosition:bodyorfooter.
repo
trunk: the branch every worker’s changes merge toward, and the base of every cleanup and preflight git comparison, for examplemain.remote(defaultorigin): the git remotetrunklives on.integrationBranch(deprecated, prose-only): optional long-lived branch a wave integrates onto before trunk.commitTypes(deprecated, prose-only): allowed Conventional Commit types for worker commits.
design
Optional, prose-only. null or omitted skips the design/UI-review step.
canvasIndex(deprecated): path to a design canvas file workers check before UI changes.