How to Set Up Project Governance
This is the single, start-to-finish walkthrough for creating your project's Charter: from a project with no governance configured, through the interview, generation, validation, and synthesis, to a charter that is active and automatically injected into every governed mission action.
- For the conceptual model behind these steps — the DRG, bootstrap vs. compact context, governed profile invocation — see How Charter Works.
- If a step below fails, see Troubleshooting Charter Failures.
- For the full doctrine-synthesis workflow (partial resynthesis, provenance, recovery from a stale bundle) beyond the quick version in Step 4 below, see How to Synthesize and Maintain Doctrine.
- For the faster, pack-driven alternative to this interview-driven walkthrough —
charter pack applyplus the requiredcharter generatefollow-up, and how the dispatch fallback behaves at each step — see Charter Pack Usage Journey.
Prerequisites
- Spec Kitty 3.x installed — verify with
uv run spec-kitty --version - A git repository (new or existing). Charter requires a git working tree.
- A Spec Kitty project scaffold. For a fresh repository, run
uv run spec-kitty init --ai claude --non-interactivebefore continuing.initis idempotent, so rerunning it in an already-initialized project exits cleanly.
The governance model, briefly
Two files matter, and they are not peers:
.kittify/charter/charter.yamlis the single git-tracked, authoritative, structured charter. Itsgovernance,directives,catalog, activation, andoverridessections all live here. You authorgovernance,directives, activation, andoverrides(directly, or via the interview);charter generaterefreshescatalogandmetadatadeterministically from the current doctrine selection, without touching your authored sections..kittify/charter/charter.mdis a curated companion: a human-readable narrative the runtime never parses, scrapes, or resolves policy from. Editing it has no effect on governed mission behavior.charter generateseeds a startercharter.mdonly when one is absent, and never overwrites an existing one.
.kittify/config.yaml carries a single charter: pointer that resolves the active
charter.yaml. When spec-kitty next invokes an agent profile for a mission action, the runtime
reads charter.yaml directly and injects the relevant governance context into the prompt
automatically — that is what "governed" means throughout this guide.
Step 1: Run the Interview
The interview captures your project's policy decisions and saves them as structured answers to
.kittify/charter/interview/answers.yaml.
Quick path (non-interactive)
Use --defaults to accept deterministic defaults without prompts. Good for bootstrapping or CI:
spec-kitty charter interview \
--profile minimal \
--defaults \
--json
Full interactive path
For a thorough setup, use the comprehensive profile, which asks 11 questions:
spec-kitty charter interview \
--profile comprehensive
What the interview asks
Minimal profile (8 questions):
| Question | What it controls |
|---|---|
| Project intent | Policy summary in the charter preamble |
| Languages and frameworks | Styleguide selection (e.g., Python) |
| Testing requirements | Test framework, minimum coverage |
| Quality gates | Linting, type checking, pre-commit hooks |
| Review policy | Required PR approvals, branch strategy |
| Performance targets | CLI timeout thresholds |
| Deployment constraints | Branch naming and protection rules |
Comprehensive profile adds 4 more:
| Question | What it controls |
|---|---|
| Documentation policy | Added as a project directive |
| Risk boundaries | Added as a project directive |
| Amendment process | How the charter itself can be changed |
| Exception policy | How to handle one-off policy exceptions |
Override selections
You can override doctrine selections on the command line:
spec-kitty charter interview \
--profile minimal \
--defaults \
--selected-paradigms "test-first" \
--selected-directives "TEST_FIRST" \
--available-tools "spec-kitty,git,python,pytest,ruff,mypy,uv" \
--json
Step 2: Generate the Charter Bundle
Generate (or refresh) the charter bundle from your interview answers:
spec-kitty charter generate --from-interview --json
This refreshes charter.yaml's catalog and metadata sections from your doctrine selection,
seeds a starter charter.md companion if one is not already present (an existing charter.md is
left untouched), and auto-stages the produced files via git add --force so the immediately
following charter bundle validate succeeds without a manual git add. It also ensures
.gitignore carries the required entries for derived charter artifacts.
Note:
charter generaterequires a git working tree. If you run it outside a git repo it exits non-zero with an error directing you to rungit initfirst.
Overwrite an existing charter
To force a full regeneration from your interview answers:
spec-kitty charter generate --from-interview --force --json
Choose a template set
Override the doctrine template set if your project needs a different workflow shape:
spec-kitty charter generate \
--from-interview \
--template-set plan-default \
--json
Available template sets: software-dev-default, plan-default, documentation-default,
research-default.
Point at an existing public constitution
If your repository already publishes governance outside .kittify/ — for example
spec/constitution.md — keep that document in place and reference it from charter.yaml rather
than duplicating it. Declare it under governance.charter.governance_references (the
interview's equivalent question writes into this same section):
governance:
charter:
governance_references:
- spec/constitution.md
spec-kitty charter context --action ... renders these paths as required governance reading, and
spec-kitty charter status reports missing or unsafe references so you can fix stale paths. All
referenced paths must be repository-relative and stay inside the repo root. Spec Kitty does not
require the public document and charter.yaml to be byte-for-byte equal — charter.yaml is the
only one the runtime resolves.
Step 3: Validate the Bundle
Before promoting doctrine, verify the bundle is internally consistent.
3a. Check for graph-native decay
spec-kitty charter lint
charter lint detects orphaned directives (referenced in the DRG but without a backing tactic),
contradictions between directives, and staleness (directives whose provenance points to a deleted
or superseded built-in directive).
3b. Validate the bundle schema
spec-kitty charter bundle validate
This validates the charter bundle against the CharterBundleManifest v2.0.0 schema — the
structured-charter.yaml manifest — checking that all required files are present, correctly
structured, and consistent.
3c. Check status
spec-kitty charter status --json
charter status reports the bundle's freshness (charter → bundle → DRG), synthesis state,
org-layer state, and the health of any declared governance_references. If lint and validate
both pass and status shows no drift, you are ready to synthesize.
Step 4: Synthesize Doctrine
Synthesis promotes agent-generated project-local doctrine artifacts into .kittify/doctrine/,
making them available for runtime context injection.
# Preview first
spec-kitty charter synthesize --dry-run
# Apply
spec-kitty charter synthesize
# Confirm
spec-kitty charter status
On a fresh project where .kittify/charter/generated/ is missing or empty (the agent harness has
not yet written candidate artifacts), synthesize creates the minimal artifact set — a
.kittify/doctrine/ directory marker and a PROVENANCE.md record — and the runtime falls back to
built-in doctrine until a full synthesis run with agent-generated content completes. For partial
resynthesis, provenance inspection, and recovery from a stale bundle, see
How to Synthesize and Maintain Doctrine.
Quick baseline via a starter pack
If you'd rather start from a small curated baseline than write directives from scratch, apply a built-in charter pack instead of running the full interview:
spec-kitty charter pack apply minimal
charter pack apply merges the pack's activation keys into .kittify/config.yaml. This is
additive by default — a key already present (even one you deliberately set empty) is left
untouched; pass --force to overwrite it. Two honest caveats: activating config entries does not
by itself guarantee an unmatched spec-kitty dispatch routes to a specialist profile — you may
still need --profile <profile-id> to be explicit — and the activations need a compile step
(spec-kitty charter generate --no-from-interview, or apply --compile to chain it
automatically) before they fully render into .kittify/charter/charter.yaml (see issue #3105 in
the project issue tracker; check that issue for current resolution status). That same compile
step is also what resolves the "routed to the generic agent" symptom in
Troubleshooting Charter Failures: the generic-agent
fallback only checks whether the compiled bundle exists, not what it activates, so apply --compile (not plain apply) is required to clear it — minimal still activates no
agent_profiles, so --profile may still be needed to resolve ambiguity.
Step 5: Confirm Governance Is Active
Your charter is active once spec-kitty charter status reports no drift after synthesis. From
here, governance context loads automatically — you don't call anything manually in normal use.
How context loading works
When spec-kitty next builds a prompt for a mission action, the runtime traverses the DRG from
that action's entry point and renders the relevant governance context into the prompt. The same
resolution is exposed for debugging as:
spec-kitty charter context --action <action> --json
| Mode | When it fires | What the agent sees |
|---|---|---|
| Bootstrap | First time an action loads context (or a freshly generated charter) | Full relevant DRG subgraph — all applicable directives and tactics |
| Compact | Subsequent loads, or when the DRG payload is too large to include in full | Resolved paradigms, directives, tools, and template set only — a known limitation, see issue #787 |
| Missing | No charter exists | Instructions telling the agent to create one |
First-load state is tracked per action in .kittify/charter/context-state.json. Each action
(specify, plan, implement, review, ...) has an independent first-load timestamp.
Verify with a real mission action
spec-kitty charter context --action implement --json
This is useful when diagnosing unexpected agent behavior during a workflow step, or simply to confirm governance context is flowing before you start real mission work.
Anti-Patterns to Avoid
Editing derived sections directly
charter.yaml's catalog and metadata sections, plus references.yaml, runtime state, and
synthesis outputs, are owned by CLI commands. Manual edits there can be overwritten or make bundle
validation misleading. Edit charter.yaml's governance: and directives: sections (or run the
interview) instead, then re-run charter generate and synthesis as needed.
Skipping the interview
Running generate without an interview produces generic defaults. The charter is most valuable
when it contains your project's actual policy decisions — testing thresholds, review
requirements, branching rules. Take the time to answer the questions.
Enforcing public-charter equality
Do not require spec/constitution.md and .kittify/charter/charter.yaml to be equivalent unless
your project explicitly chooses that mirror policy. Spec Kitty treats external governance docs as
supporting reading declared via governance_references, not an alternate authoritative source.
Keeping constitution-era paths
Do not use .kittify/memory/constitution.md, .kittify/constitution/constitution.md, or
.kittify/constitution/{governance,directives,metadata}.yaml as current runtime paths. Migrate
current policy into .kittify/charter/charter.yaml; move any still-useful public document to a
normal repo path such as spec/constitution.md and declare it in governance_references.
Complete Workflow Example
Set up governance for a new project from scratch:
# 1. Create the Spec Kitty project scaffold
uv run spec-kitty init --ai claude --non-interactive
# 2. Run the interview
uv run spec-kitty charter interview --profile comprehensive
# 3. Generate the charter bundle
uv run spec-kitty charter generate --from-interview --json
# 4. Validate
uv run spec-kitty charter lint
uv run spec-kitty charter bundle validate
# 5. Synthesize doctrine
uv run spec-kitty charter synthesize --dry-run
uv run spec-kitty charter synthesize
# 6. Confirm everything is current
uv run spec-kitty charter status --json
# 7. Start working — governance context loads automatically
uv run spec-kitty specify "Build user authentication module"
Later, after updating your charter, edit .kittify/charter/charter.yaml directly (its
governance:/directives: sections), then re-run status/lint/synthesize as needed — there is no
separate sync step; the next charter context call reads the file as-is.
What's Next
You now have an active, governed charter. From here:
- How to Synthesize and Maintain Doctrine — partial resynthesis, provenance, recovery from stale bundles
- How to Run a Governed Mission — composed steps, prompt resolution, blocked decisions
- How to Use Retrospective Learning — preview and apply synthesis proposals after a mission completes
- Charter-Governed Workflow — a guided tour connecting this setup flow to a full mission run
- How Charter Works — the DRG, bootstrap/compact context, and governed profile invocation in depth
Command Reference
- CLI Commands — full CLI reference including charter subcommands
See Also
- How Charter Works — Charter mental model and the DRG
- Troubleshooting Charter Failures — fixes for stale bundles, missing doctrine, compact-context limits, retrospective gate failures, and synthesizer rejections
- Create a Specification — start a mission with governance active
- Switch Missions — how missions interact with governance
- Non-Interactive Init — automated project setup including charter
- Charter Pack Usage Journey — the pack-apply onboarding alternative and the dispatch safety net
Background
- Mission System — how missions use governance context