Docs

Configuration

The file and its keys

Every top-level key of vinaya.config.json: who owns it, what it sets, its fields and what happens when you leave it out.

Reference
23 keys
All optional

An example

A config that spells out several documented defaults:

vinaya.config.json
{
  "dispatch": {
    "agent": "claude",
    "timeoutMs": 14400000,
    "reviewerTimeoutMs": 1200000,
    "killGraceMs": 5000
  },
  "reviewPolicy": {
    "codeReviewThreshold": "BLOCKER",
    "securityThreshold": "HIGH",
    "maxRounds": 3,
    "maxTaskMinutes": 180
  },
  "planning": { "collisionThreshold": 3 },
  "rings": {
    "ring1_forgeWriteInterception": true,
    "ring2_asyncAudits": true
  },
  "checks": {},
  "report": { "commandTimeoutMs": 900000 }
}

vinaya init seeds a starter: rings (both true), an empty checks, a starter briefSchema, then managed. See Setup commands.

All keys at a glance

KeyOwnerSetsWhen absent
logsHarnessWhere Log events go; custom event typesA folder under the runtime directory
runtimeDirHarnessWhere a run's local files live~/.vinaya/runtime/<repository segment>
dispatchHarnessAgent runtime and dispatch time limitsAgent from --agent; 4 h / 20 min / 5 s
principalsHarnessWho holds Principal authorityNo default: unset, every Principal-deciding check and command refuses
releaseActorHarnessWho may author the release pull requestgithub-actions[bot]
managedHarnessWhat Vinaya installed and ownsWritten by init; absent means not installed
ciHarnessSetup command CI runs before checksNo setup step
tokensHarnessA second usage-collection routeClaude Code transcript adapter only
rolesVinayaRole contract overrides and additionsCore roles
briefSchemaVinayaSections a pull request, Issue or Milestone body must carryNo sections required
reviewPolicyVinayaBlocking severities, round cap, task time budgetBLOCKER, HIGH, 3 rounds, 180 min
planningVinayaPlan-time collision threshold3 files
projectsVinayaProject metadataNone
blastRadiusVinayaExtra high-impact pathsDerived domains only
checksVinayaCustom checks and their scopeOnly the core checks
ringsVinayaTwo ring opt-out flagsBoth slices run
prePushVinayaTests that always run on pushImport-graph selection only
securityScanVinayaAgent-configuration scanner commandNo scanner
gateCutoversVinayaIssue or pull-request number below which a gate does not applyNo cutover: every gate applies from #1
proseGatesVinayaInputs of the writing checksVinaya's own prior defaults
decisionRecordsVinayaFolder for decision recordsOff
reportVinayavinaya pr report command budget15 min
logPublishRemovedNothing; kept so a config still carrying it fails loudlyMust be absent

General rules

  • An unknown top-level key is dropped. logPublish is the one removed key kept, as a loud refusal.
  • decisionRecords.path may not sit inside proseGates.doctrineRoot.
  • In reviewPolicy, an unknown or invalid value refuses; it never falls back to a default. Three of its values are typed loosely on purpose, so a typo refuses that one setting instead of voiding the whole config.

Harness keys

logs

Where events are delivered, live, one at a time. Set exactly one of folder or url.

FieldMeaning
folderAbsolute path. A relative path is refused
urlServer ingest URL
headersIngest headers. Values may reference ${VAR_NAME}, resolved at delivery. Requires url
readHeadersRead credential for vinaya log selftest and vinaya sync. Same ${VAR} rule. Requires url. Not read from the default branch
eventsYour team's own event types: name → { fields: { <name>: type } }, where a type is text, number, boolean or a listed set of words. Refused at load if malformed. Not read from the default branch

When absent, events go to a folder under the per-repository runtime directory. A CI job never falls back to a folder. For unattended runs, the destination must match the default branch; see Trust.

runtimeDir

The one directory that holds every file a run writes: the driver lock, control records and agent output. It is not the telemetry outbox.

  • Must be an absolute path. A value inside the repository falls back to the default.
  • Ignored in the global file.
  • For unattended runs, honoured only when the default branch declares the same value.

dispatch

FieldMeaningDefault
agentDefault vendor: claude or codex. --agent overrides itNone
timeoutMsDeveloper wall-time ceiling before SIGTERM14 400 000 (4 h)
reviewerTimeoutMsCode-reviewer and security ceiling1 200 000 (20 min)
killGraceMsTime between SIGTERM and SIGKILL5 000

principals

An array of GitHub logins, at least one. These logins are trusted to author review verdicts and to apply the waiver labels vinaya/waiver:docs and vinaya/waiver:review. Read from the default branch. Ignored in the global file.

releaseActor

The GitHub login expected to author the Changesets release pull request (changeset-release/main). It decides the release exemption on the body-bare-digits check. Read from the default branch. Ignored in the global file.

managed

The ownership manifest. init writes it and eject reads it. You do not edit it by hand.

FieldMeaning
versionManifest version. Current is 3
filesWhole files Vinaya owns, repository-relative, no ..
blocksMarker-delimited regions inside your own files: path (under .git/, .husky/, .vinaya/hooks/ or .claude/hooks/), marker, comment (hash or html)
labelsForge labels Vinaya created because they did not exist
agentsThe --agents selection: skills, claude, gemini. Absent means every vendor

ci

{ setup }: a shell command added, word for word, as a step in the generated workflows that run vinaya check. Read when workflows are generated (init, upgrade, doctor), and only from the file at the repository root.

tokens

{ collect }: exactly "<interpreter> <repo-relative-script-path>", for a host other than Claude Code. The script prints { inputTokens, outputTokens, cacheCreationInputTokens, cacheReadInputTokens, model }.

vinaya tokens refuses to run the script until you approve it with vinaya tokens --trust-collect. Approval is per declaration, repository and machine, and pins the script's blob hash. Ignored in the global file.

Vinaya keys

roles

A map of role key → { contract }, where contract is a path containing /, resolved relative to the config file. An entry overrides a core role or adds a new one, and the contract is validated. Ignored in the global file.

briefSchema

The sections a body must carry.

  • pr, issue, milestone: each { sections: [...] }. A section is one of { builtin }, { heading, name? }, { field, name? } or { phrase, name? }. Absent for a kind means no sections are required.
  • ack: builtins you dropped on purpose. This only silences doctor's divergence report.
  • init seeds a starter; upgrade never rewrites it.

reviewPolicy

FieldMeaningDefault
codeReviewThresholdLowest blocking code-review severity (BLOCKER > MAJOR > MINOR)BLOCKER
securityThresholdLowest blocking security severity (CRITICAL > HIGH > MEDIUM > LOW)HIGH
maxRoundsRound cap, a positive integer3
maxTaskMinutesTask wall-clock budget. 0 turns it off180

An unknown or invalid value refuses; it never falls back. Read from the default branch.

planning

{ collisionThreshold }: how many files two open tasks may share before the new one must declare Conflicts-with. Default 3. 0 turns the refusal off and leaves a warning only.

projects

An array of { name, description?, path? }. Display metadata only; no gate reads it. vinaya init product <name> appends one, alongside a row in .vinaya/projects.md.

blastRadius

{ extraDomains: [paths] }: collision domains beyond the ones derived from package.json workspaces and the built-in set (lockfile, monorepo config, CI, git hooks).

checks

A map of check name → entry. An entry has the same shape as a core check, with no privileged field. There are no conditionals (if or unless). Ignored in the global file. init seeds {}.

FieldMeaning
runThe executable
scopediff or full
includeGlobs for scoping
args, timeoutMsArguments and time limit
envVariable allowlist: true, { optional: true }, { anyOf: [≥2 names including the key] }, or a literal string
requiresOpenPr, ownWorkflowRuns only with an open pull request; reported by your own workflow
principalOwedtrue when only the Principal can clear it
validatesbody or issue: runs on the pull-request or Issue write path

See Gates for adding, replacing and silencing checks.

rings

{ ring1_forgeWriteInterception, ring2_asyncAudits }. Both are booleans, and both are required when the block is present.

  • true or absent runs the slice.
  • false opts out of brief-schema validation on the write path (ring 1) or dead-branch-push bookkeeping (ring 2).
  • It never disables a ring or the detection of a direct push to main.

prePush

{ alwaysRun: [globs] }: test files that run on every push, whether or not the import graph reaches them. Additive only.

securityScan

{ command: [argv] }: a scanner run once per round before the security pass. It runs only when the pull request touches .claude/**, .mcp.json or .agents/**, on the head-verified candidate copy, with no forge credential.

When absent, the security pass is told no scanner is configured; it never pauses. Read from the default branch.

gateCutovers

Non-negative integers: objectivesSinceIssue, briefSectionsSinceIssue, documentationSinceIssue, briefRulesSincePr, agentBoxesRefusedSincePr. Below the number, that gate passes unconditionally. Read from the working tree, not the default branch.

proseGates

Inputs of the reader-resolvable-prose and retired-vocabulary checks, read when the check runs.

FieldMeaning
doctrineRootDoctrine folder, swept in full. Default aeg-root
readerFacingPrefix, readerFacingSuffixThe reader-facing surface. Set both or neither; neither is a declared no-op
legacySlugDirArchived-tranche folder. Default <doctrineRoot>/tranches/completed
sourceComments{ globs, allowlist, severity: warning|error }. Unset leaves this class dormant
specGrandfatherSpec files exempted, as a list or as file → maximum finding count
specPathsFiles or folders added to the spec class. Defaults: root SPEC.md, CONTEXT.md, docs/adr/**, apps/<app>/specs/**
productPathsReplaces the product class's file set
published{ allow: [literals] }, masked before the published pass
rulesexempt, defaults (per rule "off" or an override), custom rules

decisionRecords

{ path }: a repository-relative folder, outside the repository root and the doctrine tree. Setting it:

  • turns on vinaya new adr,
  • adds the folder to the spec scope,
  • enables the decision-record-citation rule.

When absent, none of that happens.

report

{ commandTimeoutMs }: the time budget per [agent] Test Plan command in vinaya pr report. Default 900 000 (15 min); maximum 3 600 000.

Removed

logPublish

Removed: telemetry is never posted to a tracker or code host. If present, validation fails and names logs as the replacement.

What's next