Skip to content

.cadence/config.yaml

.cadence/config.yaml is Cadence’s per-repo settings file. It lives at the repo root under .cadence/ and tells the commands where your designs and plans live, how plans get split and committed, which audits run, and how parallel execution behaves. Every key has a built-in default, so the file only needs to hold the values you want to change.

The canonical default for every key (with inline comments) ships at defaults/config.default.yaml. Your repo’s .cadence/config.yaml overrides only what differs from those defaults. There is no need to copy the whole file.

When a team commits .cadence/config.yaml to share settings, personal preferences need somewhere else to live. That place is .cadence/config.local.yaml: a gitignored sibling file holding only the keys you personally override. Resolution reads three layers in order, and the last layer that defines a key wins for that key:

  1. Plugin defaults (defaults/config.default.yaml)
  2. The repo’s .cadence/config.yaml (the team’s settings)
  3. Your .cadence/config.local.yaml (yours alone, never committed)

The local file is sparse: it contains only overrides, carries no config_version, and the config migrator never touches it. A typical one is a few lines:

.cadence/config.local.yaml
execute:
max_parallel: 2 # this laptop can't take the team default
worktree_confirm: false
authoring:
design_mode: all-at-once

Keys intended for local override are the per-person, per-machine ones: execute.max_parallel, execute.worktree_confirm, authoring.max_parallel, authoring.design_mode, authoring.plan_mode, mockups.dir, and the validate.browser_* and advisors.* keys. Everything else (paths, statuses, audits, plan policy, the whole worktree: section) is team policy: a local override of those still works, but Cadence prints a one-line notice so the divergence is never silent.

A single top-level integer that records which config schema this file was written against. It drives migration detection when Cadence’s schema changes.

KeyControlsDefaultAllowed values
config_versionSchema version of this file; used to detect when a migration is needed.8Integer

Where Cadence reads and writes documents. Paths are relative to the repo root. Commands resolve <paths.designs> / <paths.plans> from here, so changing these moves the whole document tree.

KeyControlsDefaultAllowed values
paths.designsFolder that holds design folders.docs/designsRepo-relative path
paths.plansFolder that holds plan folders.docs/plansRepo-relative path
paths.futureFolder for “future” / parking-lot notes (e.g. thought-partner /c-brainstorm notes).docs/futureRepo-relative path
paths.configFolder that holds this config and Cadence’s working state..cadenceRepo-relative path

Where Cadence keeps its artifacts (brainstorm stubs, designs, and plans). The backend is filesystem by default, exactly today’s behavior; setting backend: notion moves those artifacts into two Notion databases instead, leaving source code and git commits untouched. The whole storage block is team policy: it belongs in the committed .cadence/config.yaml, never in the personal .cadence/config.local.yaml overlay.

KeyControlsDefaultAllowed values
storage.backendWhich backend stores designs, plans, and stubs. filesystem keeps them as markdown folders under paths.*; notion stores them as rows in two Notion databases.filesystemfilesystem | notion
storage.notion.root_pageThe Notion page Cadence provisions the two databases under. A page URL or id you own, shared with the official Notion MCP’s integration. Required when backend is notion."" (empty)Notion page URL or id
storage.notion.designs_dbThe Designs database id. Left empty by you; auto-filled on the first Notion-mode run, then committed so the team shares it."" (empty)Notion database id (auto-filled)
storage.notion.plans_dbThe Plans database id. Left empty by you; auto-filled on the first Notion-mode run, then committed so the team shares it."" (empty)Notion database id (auto-filled)

With backend: filesystem (the default) the notion.* keys are ignored and nothing changes. To opt in, set backend: notion, fill notion.root_page, and leave the two *_db keys empty: the first Notion-mode run creates the databases and writes their ids back into the committed config. See the Notion mode reference for the full setup walkthrough.

Where mockup HTML files are written. A design that opts into the 95-visual-contract slot stores its mockups as local HTML files, on every storage backend, and records each version’s file:// URL in the 95 index.

KeyControlsDefaultAllowed values
mockups.dirThe directory mockup HTML is written to. A relative value resolves against the repo root; an absolute one is taken as given. The directory is created when missing.null (unset)Path, or null

How null resolves depends on the backend:

mockups.dirBackendResolves to
seteither<mockups.dir>/<slug>/
nullfilesystem<paths.designs>/<slug>/mockups/, the design’s own subfolder
nullnotionUnresolvable, so /c-design asks once before writing version 01

How /c-plan shapes the plan it writes.

KeyControlsDefaultAllowed values
plan.tddWhether plans bake in a test-driven workflow (write the test, then the code).truetrue | false
plan.styleWhat a plan’s steps contain. full-code writes out every code step’s code; decisions records only what the implementer can’t decide alone (exact signatures, test assertions, the design’s values) and leaves the code to them; ask asks once per plan. Each plan records its own style, so changing this never affects a plan already written. Never written into your config, by a migration or by /c-brainstorm’s first-run setup, so a future change to the default reaches you unless you set the key yourself.full-codefull-code | decisions | ask
plan.commit_cadenceHow often the plan commits during execution.per-taskper-task (other cadences are judgment-based)
plan.parallel_grainThe finest granularity at which tasks within one plan may run in parallel. per-file keeps each file to one lane; in-file allows lanes to split work within a single file. Not set in the defaults file. Add it under plan to opt in.unset (per-file behaviour)per-file | in-file

There are deliberately no split thresholds. Whether and where to split a plan into phase docs is a judgment call /c-plan makes, not a number you tune. See Parallelism and worktrees for how grain relates to execution lanes.

How /c-execute drives a plan to implemented code, including the parallel-lane machinery. The 01-… / 02-… files inside a single plan are its phases; the keys below govern how those phases run, in lanes that may use git worktrees.

KeyControlsDefaultAllowed values
execute.parallelMaster switch for parallel execution. When false, execution is the legacy sequential path (sub-agents, no worktrees) and execute.mode is ignored.truetrue | false
execute.modePre-flight execution-mode gate: ask presents parallel lanes (recommended) vs inline sequential, parallel runs the lane engine, inline runs every task in the PM session itself — no worktrees, no implementer sub-agents (the completion audit stays a sub-agent).askask | parallel | inline
execute.max_parallelMaximum concurrent implementer lanes (one worktree per lane). Reviewers are uncapped.4Positive integer
execute.worktree_confirmShow a one-time pre-flight confirmation before creating worktrees.truetrue | false

See Parallelism and worktrees for the model behind lanes and the max_parallel cap. Where lane worktrees live and how they merge back is governed by the worktree section below.

The shared git-worktree lifecycle: where worktrees live, how branches go home, the merge lock, and the optional repo-specific hooks. Two commands read this section: /c-worktree (the interactive lifecycle) and /c-execute (its parallel lanes use dir and integrate, and its merge-on-land honors the lock).

KeyControlsDefaultAllowed values
worktree.dirWhere worktrees are created: interactive /c-worktree worktrees and /c-execute lane worktrees alike. Relocated from execute.worktree_dir..cadence/worktreesRepo-relative path
worktree.integrateHistory policy when a worktree branch merges back. Relocated from execute.integrate.rebase-ffrebase-ff | merge-commit
worktree.merge_lockWhether local merges acquire the shared repo-global merge lock, so concurrent merges serialize instead of colliding. Honored by /c-worktree’s local-merge exit and /c-execute’s lane landings; /c-worktree’s PR exit performs no local merge and never takes it.truetrue | false
worktree.lock_stale_thresholdSeconds after which a held lock is reported stale and surfaced as a “steal it?” question. Never auto-stolen.600Positive integer (seconds)

Six optional shell-command hooks let a repo plug its own scripts into fixed lifecycle points. Every hook is null by default, and a null hook means that lifecycle phase simply does not exist; with all hooks empty, /c-worktree runs its generic core only.

KeyControlsDefaultAllowed values
worktree.hooks.provisionRuns after git worktree add (dependency install, env files, similar setup).nullShell command string or null
worktree.hooks.provision_verifyRuns after provision to assert the worktree environment is usable; non-zero surfaces the output and offers repair / remove / keep.nullShell command string or null
worktree.hooks.port_assignAllocates a dev port for the worktree. Must print the port to stdout.nullShell command string or null
worktree.hooks.port_releaseFrees the worktree’s port at cleanup.nullShell command string or null
worktree.hooks.dev_serverStarts the worktree’s dev server.nullShell command string or null
worktree.hooks.deploy_guardExits non-zero when a deploy is not allowed from the current location; the deploy is then refused.nullShell command string or null
  • Environment. Every hook runs with WT_PATH (absolute worktree path), MAIN_ROOT (absolute main-worktree path), and BRANCH (the worktree’s branch) exported. dev_server additionally gets DEV_PORT, captured from port_assign’s stdout or read back from git config branch.<branch>.devPort.
  • Working directory. provision, provision_verify, port_assign, and dev_server run with cwd = $WT_PATH. port_release runs with cwd = $MAIN_ROOT (the worktree may already be removed). deploy_guard runs in the directory the deploy was attempted from: that location is what it judges.
  • Stdout. Only port_assign’s stdout carries meaning (the assigned port, persisted as git config branch.<branch>.devPort). Every other hook’s output is informational and shown to you. provision’s stderr is shown at create time even on a zero exit, so a best-effort provisioner’s warnings surface immediately rather than at the first push.
  • Non-zero exit. provision: surfaced, with an offer to remove the half-created worktree. provision_verify: surfaced, with an offer to repair (re-run provision, then re-verify), remove the worktree, or keep it as-is. port_assign: surfaced; the lifecycle continues without a port, and the dev-server phase is then unavailable. dev_server: surfaced. port_release: surfaced, but cleanup continues. deploy_guard: the deploy is refused, with an explanation of the merge-first-then-deploy-from-main flow.

See the /c-worktree reference for the phase-by-phase lifecycle these keys drive.

How doc-generator agents run when /c-design materializes a design folder. These agents do not use worktrees (they only write docs), so they are cheap to parallelize.

KeyControlsDefaultAllowed values
authoring.max_parallelMaximum concurrent doc-generator agents.6Positive integer
authoring.design_modeStanding default for how /c-design writes child docs: ask prompts you, all-at-once generates in parallel, one-by-one writes sequentially with a review per doc, inline writes every doc in the main session with no sub-agents or pauses.askask | all-at-once | one-by-one | inline
authoring.plan_modeStanding default for how /c-plan writes plan docs: ask prompts you, all-at-once generates in parallel, inline writes every doc in the main session.askask | all-at-once | inline

Opt-in advisor personas that can weigh in during brainstorm and design. Disabled by default.

KeyControlsDefaultAllowed values
advisors.enabledWhether advisors are offered at all.falsetrue | false
advisors.rosterThe set of advisor personas available when enabled.[] (empty)List of advisor entries

See Advisors for what advisors are and how the roster is defined.

Conventions for naming design/plan folders.

KeyControlsDefaultAllowed values
naming.date_formatDate stamp used in folder slugs.YYYY-MM-DDDate format string
naming.slug_caseCasing for the slug portion of folder names.kebabkebab (and similar case styles)

The allowed status values for design and plan documents. The order matters: it is the lifecycle progression Cadence expects.

KeyControlsDefaultAllowed values
status.designValid statuses for a design.[draft, in-review, approved, completed, superseded, on-hold]List of status strings
status.planValid statuses for a plan.[draft, in-progress, implemented, completed, superseded, on-hold]List of status strings

Frontmatter requirements Cadence enforces on documents it writes.

KeyControlsDefaultAllowed values
frontmatter.requiredFrontmatter keys that must be present on every document.[title, created, updated, status, tags]List of key names

Which checks /c-audit (and the completion auditor) run, split into blocking checks, non-blocking warnings, and an optional set. The build_validator sub-block configures the build check. design-intent-alignment, the audit’s name before v0.23.0, still works in a roster as an alias for branch-review.

KeyControlsDefaultAllowed values
audits.defaultAudit checks that run and block on failure.checkbox-completeness, oos-justification, deferred-comment-scan, code-behind-checkbox, branch-review, build-validator, merge-integrityList of audit names
audits.warningsChecks that run but only warn (non-blocking).file-map-honesty, design-plan-consistency, validation-doc-presenceList of audit names
audits.optionalChecks available but off by default.[] (empty)List of audit names
audits.build_validator.commandShell command the build-validator audit runs. null means no build command is run.nullShell command string or null
audits.build_validator.expect_zero_exitTreat a non-zero exit from the build command as a failure.truetrue | false

How Cadence writes the plain-English narrative that accompanies designs.

KeyControlsDefaultAllowed values
plain_english.section_calloutAdd a callout marking the plain-English section.truetrue | false
plain_english.always_write_00aAlways write the 00a plain-English companion doc.truetrue | false
plain_english.length_targetTarget word-count range for the narrative."400-700"Range string

Rules for out-of-scope (OOS) entries in designs and plans.

KeyControlsDefaultAllowed values
oos.require_rationaleRequire a written rationale for each out-of-scope item.truetrue | false
oos.require_wikilinkRequire a wikilink (pointer) for each out-of-scope item.truetrue | false

How /c-validate walks a plan’s 96-validation.md post-deploy, including how it runs browser/automated checks.

KeyControlsDefaultAllowed values
validate.reset_checkboxes_on_rerunClear validation checkboxes when validation is re-run.truetrue | false
validate.browser_driverWhich driver runs browser-based checks. auto detects, playwright forces Playwright, manual walks you through by hand.autoauto | playwright | manual
validate.browser_commandThe CLI test command Cadence delegates browser checks to."npx playwright test"Shell command string
validate.browser_env_preambleOptional shell snippet run before the browser command (e.g. to set env vars). null means none.nullShell snippet string or null

Defaults for /c-find-bugs.

KeyControlsDefaultAllowed values
find_bugs.default_baselineThe git ref bug-finding diffs against by default.mainGit ref
find_bugs.excludePaths excluded from the bug scan.[node_modules, dist, build, __pycache__, target, .next, vendor]List of paths

This repo dogfoods Cadence, and its own .cadence/config.yaml is a good example of the “override only what differs” pattern. It keeps the default paths and audits, bumps execute.max_parallel to 5, and opts into plan.parallel_grain: in-file. The trimmed shape below shows the blocks that have arrived over the last few schema bumps: worktree: (relocated out of execute: in config_version: 4), storage: (new in 5), execute.mode (new in 7), and mockups: (new in 8). Each of those bumps is additive, so scripts/migrate-config.js appends the new block or key verbatim and leaves your values and comments alone:

config_version: 8
paths:
designs: docs/designs
plans: docs/plans
future: docs/future
config: .cadence
plan:
tdd: true
commit_cadence: per-task
parallel_grain: in-file
execute:
max_parallel: 5
parallel: true
worktree_confirm: true
mode: ask
worktree:
dir: .cadence/worktrees
integrate: rebase-ff
merge_lock: true
lock_stale_threshold: 600
advisors:
enabled: false
roster: []
storage:
backend: filesystem
notion:
root_page: ""
designs_db: ""
plans_db: ""
mockups:
dir: null # filesystem backend: the design's own mockups/ subfolder
Built by Sentasity MIT licensed