Generate, audit, and evolve your AI agent's context across the whole project lifecycle. 🏗️
Because an agent without context is an intern with root access — and stale context is an intern reading three-week-old docs.
[English] | Español
Lifecycle: 🚀 Bootstrap · 🧰 Equip · 🔧 Maintain
Jump: Quick Start · Phases at a glance · MCP Server · Language Guides · Architecture · Migrating from v1.x · FAQ · Troubleshooting
Two problems, both real.
The agent improvises. You tell it "Build a payments API in Go with microservices", and:
- Folder structures nobody asked for
- Patterns that contradict your architecture
- Decisions you'll revert in the next session
- Zero continuity between sessions
It's not the agent's fault. Without context, it starts from scratch every session.
Even when context exists, it drifts. Three weeks ago you wrote a beautiful AGENTS.md. Since then go.mod added five deps, the Makefile gained four targets, the README evolved. The AGENTS.md still says what was true on day one. The agent reads it and confidently makes decisions on stale ground.
Codify equips the agent with context AND keeps that context honest as the codebase moves. 🛠️
Codify equips your AI agent with six layers it needs to stop improvising:
┌──────────────┐ ┌──────────────┐ ┌──────────────────────────────┐
│ Context │ │ Specs │ │ Skills │
│ │ │ │ │ │
│ What the │ │ What to │ │ How to do things right — │
│ project is │────▶│ build next │ │ abilities + lifecycle │
│ │ │ │ │ recipes (multi-step) │
│ generate │ │ spec │ │ catalog │
│ analyze │ │ --with-specs│ │ │
└──────────────┘ └──────────────┘ └──────────────────────────────┘
Memory Plan Abilities + Orchestration
┌─────────────────────────────────┐ ┌─────────────────────────────────────┐
│ Hooks │ │ Lifecycle │
│ │ │ │
│ Deterministic guardrails │ │ Maintain artifacts over time │
│ on tool calls (Edit/Bash) │ │ │
│ │ │ config / init │
│ hooks │ │ check / update / audit / usage │
└─────────────────────────────────┘ └─────────────────────────────────────┘
Determinism Custodianship
- Context gives the agent architectural memory — stack, patterns, conventions, domain knowledge
- Specs give the agent an implementation plan — features, acceptance criteria, task breakdowns
- Skills give the agent reusable abilities — how to commit, version, design entities, review code — plus lifecycle recipes, the multi-step orchestrations (bug fixing, releases, the SDD lifecycle) that ship as a
lifecycleskills category - Hooks add deterministic guardrails — shell scripts on Claude Code lifecycle events, no LLM in the loop
- Lifecycle keeps everything in sync —
config,init,check,update,audit,usage,watch— drift detection, selective regen, commit auditing, cost transparency, foreground watching
It follows the AGENTS.md standard — an open specification backed by the Linux Foundation for providing AI agents with project context. Files work out of the box with Claude Code, Cursor, Codex, and any agent that reads the standard.
Codify groups its commands into three phases that map naturally to how a developer adopts and uses it:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Bootstrap │ ──▶ │ Equip │ ──▶ │ Maintain │
└─────────────┘ └─────────────┘ └─────────────┘
config generate check
init analyze update
spec audit
catalog watch
usage
resolve
- Bootstrap (one-time) — set up the workstation (
codify config) or a project (codify init). - Equip (per need) — generate context, install skills (incl. lifecycle recipes) and hooks via
codify catalog, write specs. - Maintain (ongoing) — detect drift, regenerate, audit commits, track usage.
The same diagram is available in codify --help. For the full matrix of which command applies to workstation vs project and greenfield vs brownfield, see docs/lifecycle-matrix.md.
Day 1
You: "Create a payments API in Go"
Agent: *creates main.go with everything in one file*
You: "No, use Clean Architecture"
Agent: *creates structure but mixes domain with infra*
You: "Repositories go in infrastructure"
Agent: *refactors for the third time*
You: "What about the BDD tests I asked for yesterday?"
Agent: "BDD tests? This is the first time you've mentioned that"
You: "At least commit this properly"
Agent: *writes "update code" as commit message*
Day 22 (after AGENTS.md was written and never updated)
You: "Add the new circuit-breaker dep we added last week"
Agent: *uses go-retry — never heard of go-resilience because AGENTS.md is stale*
Result: 45 minutes correcting the agent on day 1, two hours on day 22. 😤
Day 1
You: "Create a payments API in Go"
Agent: *reads AGENTS.md, CONTEXT.md, DEVELOPMENT_GUIDE.md*
Agent: "I see you use DDD with Clean Architecture, PostgreSQL,
BDD testing with Godog, and idiomatic Go patterns.
I'll create the payments endpoint in internal/domain/payment/
following your patterns and concurrency conventions."
Agent: *reads SKILL.md for conventional commits*
Agent: "Done. Here's the commit following Conventional Commits:
feat(payment): add payment domain entity with Stripe integration"
Day 22 (you've been editing in the background; AGENTS.md auto-stayed in sync)
You: "Add the new circuit-breaker dep we added last week"
Agent: *reads current AGENTS.md — knows go-resilience is the project's choice*
Agent: "Adding go-resilience following the wrap-with-context pattern from
IDIOMS.md. Note that codify check ran clean before this session."
Result: Coherent code from the first line, AND from line 1,000. ✨
Behind the scenes on day 22, codify watch has been quietly running, codify check flagged the go.mod change, codify update refreshed AGENTS.md, and codify usage shows it cost $0.04 in tokens.
The recommended sequence for a first-time user. Each step maps to a lifecycle phase (see diagram above). For a full walk-through with expected outputs see docs/getting-started.md.
# 1. Install (Homebrew / go install / GitHub Releases)
brew tap jorelcb/tap && brew install codify
# 2. Bootstrap — workstation defaults (one time)
codify config
# 3. Bootstrap — your project (greenfield or brownfield)
cd my-project && codify init
# 4. Equip — install only what you need (each is skippable)
codify spec <name> --from-context ./output/<name>/ # SDD specs
codify catalog # Skills (incl. lifecycle recipes) + hooks + plugins
# 5. Maintain — keep artifacts honest as the code evolves
codify check # Drift detection — no LLM, zero cost
codify update # Selective regen when input signals drift
codify audit # Review commits against conventions
codify watch # Foreground watcher
codify usage # LLM token + cost summary
codify resolve # Fill [DEFINE: ...] markersAPI keys (ANTHROPIC_API_KEY or GEMINI_API_KEY) are required only for LLM-backed commands — see the table in docs/getting-started.md.
The first-run auto-launch of codify config is soft (TTY only, never blocks CI). Opt out via --no-auto-config, CODIFY_NO_AUTO_CONFIG=1, or ~/.codify/.no-auto-config.
One-time setup for the workstation and per project. After this, you move to the Equip phase.
Two complementary commands shape how Codify behaves: codify config at the user level and codify init at the project level. Both compose on top of the existing standalone commands; they are smart entry points, not replacements.
codify config manages your global preferences at ~/.codify/config.yml. The first time you run any interactive Codify command in a TTY without that file existing, you'll be offered the option to launch the wizard. Three answers: Yes (run wizard), No (use defaults this run), Skip permanently (creates ~/.codify/.no-auto-config so the prompt never appears again).
| Subcommand | Action |
|---|---|
codify config |
Wizard if no config exists; print current config if it does |
codify config get <key> |
Read a single value |
codify config set <key> <value> |
Update a single value |
codify config unset <key> |
Clear a single value |
codify config edit |
Open ~/.codify/config.yml in $EDITOR |
codify config list |
Print the effective config (with merge applied) |
Valid keys: preset, locale, language, model, target, provider, project_name.
codify init asks one question first: is this project new or existing? Based on the answer it routes you to the right flow:
| Answer | Internal flow | What you provide |
|---|---|---|
| new | invokes generate |
project name + description (inline or path to a file) |
| existing | invokes analyze |
project name (auto-detected from cwd, override if you want) |
After that, both branches collect: architectural preset (override of global default), language, locale, output directory, model. Result:
.codify/config.yml— project-scoped defaults that persist for everyone with the repo.codify/state.json— snapshot of generation state (consumed by lifecycle commands)- Generated
AGENTS.mdandcontext/*.mdwritten tooutput/
Skills and hooks are NOT bundled — init prints recommended next-step commands to keep responsibilities focused. Run codify catalog (skills — including the lifecycle recipes — hooks, and plugins) separately when you want them.
When any command resolves a value (preset, locale, model, etc.):
flags > .codify/config.yml > ~/.codify/config.yml > built-in defaults
Setting --preset hexagonal on the command line wins regardless of what's in either config file. Project-level config wins over user-level. Built-ins fill the gaps.
Install only what you need. Each command below is independent and skippable. After equipping, the Maintain phase keeps everything honest as the project evolves.
The foundation. Generates files following the AGENTS.md standard that give your agent deep project memory.
| Situation | Use | Why |
|---|---|---|
| Greenfield project (no code yet) | codify generate |
You provide the description; the LLM generates context against it |
| Existing repo with code in it | codify analyze |
The scanner extracts factual signals (deps, build targets, CI, frameworks) and feeds them as ground truth — much higher accuracy than a manual description |
| Existing repo + you want to override what the scanner detects | codify analyze first, then edit, then codify reset-state |
Scan-first, hand-tune second |
| You have a detailed design doc | codify generate --from-file ./docs/design.md |
Treat the file's content as the description |
| In doubt | codify init |
Asks "new or existing?" and routes you to the right flow internally |
codify generate payment-service \
--description "Payment microservice in Go with gRPC and PostgreSQL" \
--language goScans an existing codebase and generates context files from what it finds. Uses a differentiated prompt that treats scan data as factual ground truth, producing more accurate output than a manual description.
What the scanner detects:
- Language, framework, and dependencies (Go, JS/TS, Python, Rust, Java, Ruby)
- Directory structure (3 levels deep)
- README content (filtered: badges, HTML comments, ToC removed)
- Existing context files (18+ patterns: AGENTS.md, .claude/CLAUDE.md, ADRs, OpenAPI specs, etc.)
- Build targets from Makefile/Taskfile (exact commands for AGENTS.md)
- Testing patterns (frameworks, BDD scenarios, coverage config)
- CI/CD pipelines (GitHub Actions triggers and jobs, GitLab CI)
- Infrastructure signals (Docker, Terraform, Kubernetes, Helm)
codify analyze /path/to/my-project| File | What it does |
|---|---|
AGENTS.md |
Root file: tech stack, commands, conventions, structure |
CONTEXT.md |
Architecture, components, data flow, design decisions |
INTERACTIONS_LOG.md |
Session log and ADRs |
DEVELOPMENT_GUIDE.md |
Work methodology, testing practices, security, delivery expectations |
IDIOMS.md |
Language-specific concurrency, error handling, conventions (requires --language) |
CLAUDE.md |
Bridge for Claude Code: imports @AGENTS.md + room for Claude-specific notes |
AGENTS.md is the canonical root that compatible agents (Cursor, Codex, Gemini
CLI, …) read automatically; the generated CLAUDE.md bridges it into Claude
Code, which reads CLAUDE.md rather than AGENTS.md natively (an existing
CLAUDE.md is never overwritten). See ADR-0014.
Idiomatic guides ship for Go, TypeScript, JavaScript, Python, Rust, and Java
(--language <name>); analyze auto-detects the language, distinguishing
TypeScript from JavaScript via tsconfig.json.
codify generate [project-name] [flags]All flags are optional in a terminal — interactive menus prompt for missing values.
| Flag | Short | Description | Default |
|---|---|---|---|
--description |
-d |
Project description (required unless --from-file) |
(interactive) |
--from-file |
-f |
Read description from file (alternative to -d) |
— |
--preset |
-p |
Template preset (neutral, clean-ddd, hexagonal, event-driven) |
(interactive) |
--model |
-m |
LLM model (claude-* or gemini-*) |
auto-detected |
--language |
-l |
Language (activates idiomatic guides) | — |
--locale |
Output language (en, es) |
en |
|
--with-specs |
Also generate SDD specs after context | false |
|
--type |
-t |
Project type hint (api, cli, lib...) | — |
--architecture |
-a |
Architecture hint | — |
From existing context, generates implementation-ready specifications. This enables AI Spec-Driven Development (AI SDD): your agent implements a spec, not an improvisation.
Your idea → generate (context) → spec (specifications) → Agent writes code with full context
codify spec payment-service \
--from-context ./output/payment-service/Available on both generate and analyze. Chains context generation + spec generation + AGENTS.md update in a single run:
codify generate my-api \
--description "REST API in Go with PostgreSQL" \
--language go \
--with-specsDefault standard is GitHub Spec-Kit (per-feature, under specs/<feature-id>/):
| File | What it does |
|---|---|
spec.md |
Prioritized user stories (P1/P2/P3), FR-XXX, measurable SC-XXX |
plan.md |
Technical context, Constitution Check, project structure |
tasks.md |
Tasks by user story (T001, [P], [US1]), MVP-first phases |
.specify/memory/constitution.md |
Project principles — the gate plan.md's Constitution Check checks |
--sdd-standard openspec instead writes the real OpenSpec tree (openspec/project.md + openspec/specs/<capability>/spec.md with ### Requirement: / #### Scenario: blocks).
Skills are reusable Agent Skills (SKILL.md files) that teach your agent how to perform specific tasks — following Conventional Commits, applying DDD patterns, doing code reviews, versioning releases. They complement context files: context tells the agent what your project is, skills tell it how to do things right.
Skills install through codify catalog — the unified surface for ecosystem packages (skills + hooks).
| Mode | What it does | API key | Cost | Speed |
|---|---|---|---|---|
| Static | Delivers pre-built skills from the embedded catalog. Production-ready, Claude frontmatter. | Not needed | Free | Instant |
| Personalized | LLM adapts the skill to your project — examples use your domain, language, and stack. | Required | ~pennies | ~10s |
Run codify catalog and a rich selector opens — horizontal tabs per package
type (Skills · Hooks · Plugins), a tree grouped by each package's
source-declared category, and checkboxes with a tri-state parent
([ ] none / [~] some / [x] all). Your selection accumulates across
tabs, so you equip skills + hooks + plugins in a single pass:
codify catalog
# → Ecosystem: claude (pre-step)
# → Scope: project (pre-step)
# → Rich selector opens:
# ⇥ switch tab · ↑↓ move · → expand · space mark · a mark-all · ⏎ install
# marks persist across tabs; ⏎ installs everything selected, in one passThe same selector is reused by codify init (project scope) and codify config (workstation scope), so you can equip your agent during bootstrap
(ADR-0010 Decision 6). Terminals without Unicode get an ASCII fallback (force it
with CODIFY_ASCII=1); non-TTY / CI environments fall back to the flags below.
# Static: instant delivery, no API key. Install to the current project (.claude/skills/).
codify catalog --type skill --package ddd-entity,hexagonal-port --scope project
# Install at workstation scope — available from any project (~/.claude/skills/).
codify catalog --type skill --package conventional-commit,semantic-versioning --scope workstation
# Personalized: LLM-adapts each skill to your project.
codify catalog --type skill --package ddd-entity,cqrs-command --scope project \
--mode personalized --context "Go microservice with DDD, Godog BDD, PostgreSQL"
# Browse everything available, with source badges and installed markers.
codify catalog --list --type skill| Scope | Path | Use case |
|---|---|---|
project |
./.claude/skills/ |
Committed to git, shared with team |
workstation |
~/.claude/skills/ |
Available from any project |
Skills also install for Antigravity CLI: codify catalog --ecosystem antigravity --type skill --package <id> --scope project|workstation writes them (with Antigravity frontmatter) flat to ~/.gemini/antigravity-cli/skills/ (workstation) or .agents/skills/ (project). Gemini CLI is deprecated and unsupported (ADR-0012 §4).
Every interactive install also records your picks to a committable, per-scope
desired-state file — .codify/project.catalog.yml (project) and
~/.codify/workstation.catalog.yml (workstation). It is the user-authored
intent (distinct from the lockfile, which is codify's install record). Commit
it and a teammate reproduces your exact setup with one command:
codify catalog --apply --scope project # install everything the file declares# .codify/project.catalog.yml
version: 1
scope: project
packages:
- { ecosystem: claude, id: ddd-entity, type: skill }
- { ecosystem: claude, id: conventional-commit, type: hook }
- {
ecosystem: claude,
id: spec-driven-change,
type: plugin,
source: anthropics/claude-plugins-official,
}YAML (not TOML) to add no new dependency — codify already uses YAML for config.
--status/--syncoperate on the separate lockfile (codify's install record).
Packages are installed individually by ID (--package <id,...>). Browse the live list with codify catalog --list --type skill. The 23 skills, grouped by theme:
| Theme | Package IDs |
|---|---|
| Neutral | code-review, test-strategy, refactor-safely, api-design |
| Clean + DDD | ddd-entity, clean-arch-layer, bdd-scenario, cqrs-command, hexagonal-port |
| Hexagonal | port-definition, adapter-pattern, dependency-inversion, hex-integration-test |
| Event-Driven | command-handler, domain-event, event-projection, saga-orchestrator, event-idempotency |
| Testing | test-foundational, test-tdd, test-bdd |
| Conventions | conventional-commit, semantic-versioning |
The architecture themes mirror the four --preset options for context generation, so skills installed for hexagonal-port/adapter-pattern line up with AGENTS.md/CONTEXT.md generated under --preset hexagonal.
Personal / team packages: drop your own under
~/.codify/sources/<id>/— acodify-package.yamlmanifest plus the content (SKILL.md, orhooks.json+ scripts for hooks). They appear incodify catalogbadged[local-fs], alongside the built-ins, and override a built-in of the same ID. (Track D — git/marketplace sources land next; see ADR-0012.)
codify catalog --type skill [flags]| Flag | Description | Default |
|---|---|---|
--package |
Comma-separated package IDs to install | (interactive) |
--scope |
Install scope: project or workstation (alias: global) |
project |
--mode |
static (embedded template) or personalized (LLM-adapted) |
static |
--context |
Project description for personalized mode | — |
--model |
LLM model for personalized mode | auto-detected |
--list |
Browse available packages instead of installing | false |
Lifecycle recipes are multi-step orchestrations that AI agents execute on demand — from branch creation to PR merge, from bug report to fix deployment. Where an ordinary skill teaches how to do a single task, a lifecycle recipe orchestrates a sequence of tasks.
They are skills now. Lifecycle recipes used to be a separate
codify workflowscommand. As of v4.0.0 they are alifecyclecategory inside the unified skills catalog — installed throughcodify cataloglike any other skill, on Claude and Antigravity (both deliver them as native skills). The standalonecodify workflowscommand, the MCPgenerate_workflowstool, and the old Antigravity annotated-workflow format (// turbo,// capture, …) were removed. See ADR-0015 for the rationale (Antigravity 2.0 dropped its distinct workflow primitive and converged on Claude's skills/hooks/plugins model).
Each lifecycle skill is delivered as a native SKILL.md whose frontmatter carries:
name— Skill name (kebab-case, used as/slash-command)description— What the recipe doesdisable-model-invocation: true— Only the user invokes it (these recipes have side effects)allowed-tools: Bash(*)— Auto-approves shell commands for uninterrupted execution
Lifecycle skills are static and English-only, like the rest of the catalog — no LLM personalization, no API key, no cost.
# Interactive: open the catalog, switch to the Skills tab, expand the "lifecycle" category
codify catalog
# Install the SDD lifecycle (Spec-Kit) at project scope
codify catalog --type skill --package spec-kit --scope project
# Install bug-fix + release-cycle recipes at workstation scope
codify catalog --type skill --package bug-fix,release-cycle --scope workstation
# Install the OpenSpec lifecycle (propose → apply → archive)
codify catalog --type skill --package openspec --scope project
# Antigravity — same recipes, installed as native Antigravity skills
codify catalog --ecosystem antigravity --type skill --package spec-kit --scope project
# Browse the lifecycle recipes (and every other skill) with installed markers
codify catalog --list --type skill| Package | Recipe | Description |
|---|---|---|
spec-kit |
SDD lifecycle (Spec-Kit) | Bundle of 5 skills: speckit-specify → speckit-clarify → speckit-plan → speckit-tasks → speckit-analyze — the full Spec-Kit SDD lifecycle |
openspec |
SDD lifecycle (OpenSpec) | Bundle of 3 skills: spec-propose → spec-apply → spec-archive — full SDD lifecycle with formal spec deltas, branch creation, and merge cleanup |
bug-fix |
Bug Fix | Reproduce → diagnose → fix → test → PR |
release-cycle |
Release Cycle | Version bump → changelog → tag → deploy |
The SDD lifecycle ships under both standards —
spec-kit(the default) andopenspec. The standard is a selection, not a packaging primitive: both deliver the same recipe content as skills (ADR-0011 / ADR-0015).
The SDD lifecycle (spec-kit / openspec) is the recommended recipe for adding features and making non-trivial changes. It implements Spec-Driven Development (SDD): a methodology where formal planning artifacts precede code, and where every change to the system is a tracked, reviewable evolution of specifications — not just a code diff. The OpenSpec flavor (/spec-propose → /spec-apply → /spec-archive) is shown below; the Spec-Kit flavor (/speckit-specify → … → /speckit-analyze) follows the same intent-first discipline.
The problem with chat-driven AI development:
- Plans disappear when the chat session ends
- Code reviews see what changed but not why it changed
- AI agents lose context between sessions and re-litigate decisions
- Specs (when they exist) get out of sync with the code
The SDD answer:
- Specs live in the repository, organized by capability under
openspec/specs/<capability>/spec.md - Each change is a self-contained workspace under
openspec/changes/<change-id>/ - Deltas (ADDED / MODIFIED / REMOVED requirements) describe how specs evolve, not just final state
- Reviewers approve intent first (proposal + deltas) before approving code
- Archived changes preserve audit trail indefinitely
Each phase is a separate cognitive mode with a clear hand-off:
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ /spec- │ │ /spec- │ │ /spec- │
│ propose │ ──▶ │ apply │ ──▶ │ archive │
│ │ │ │ │ │
│ Plan the │ │ Execute the │ │ Consolidate │
│ change │ │ plan │ │ & cleanup │
└──────────────┘ └──────────────┘ └──────────────┘
Intent Implementation Truth
| Phase | What it produces | Cognitive mode |
|---|---|---|
| Propose | proposal.md (motivation), design.md (technical decisions), tasks.md (atomic checklist), specs/<capability>/spec.md (deltas with ADDED/MODIFIED/REMOVED) — plus a feature branch with the proposal committed |
"What should change and why" — no code yet |
| Apply | Sequential task execution, atomic commits per task, tests, self-review, pull request | "How to make it real" — focused on implementation, deltas already approved |
| Archive | Spec deltas merged into openspec/specs/<capability>/spec.md, change moved to openspec/changes/archive/YYYY-MM-DD-<id>/, feature branch merged and deleted |
"Make the truth durable" — close the loop |
$ /spec-propose Add two-factor authentication via TOTP
✓ Read openspec/specs/auth-login/spec.md
✓ Created change-id: add-2fa
✓ Created openspec/changes/add-2fa/
├── proposal.md (motivation, scope, impact)
├── design.md (TOTP library choice, schema changes)
├── tasks.md (8 atomic tasks across 3 phases)
└── specs/auth-login/spec.md (ADDED: 2FA requirements with G/W/T scenarios)
✓ Created branch feature/add-2fa
✓ Committed proposal artifacts
→ Request intent review before implementation
$ /spec-apply add-2fa
✓ Implementing task 1.1: add 2FA columns to user table
✓ Test: migration up/down
✓ Commit: "feat: add 2FA schema columns"
... (8 tasks, atomic commits)
✓ Full test suite passes
✓ PR opened: "add-2fa: Add two-factor authentication via TOTP"
$ /spec-archive add-2fa
✓ Merged deltas into openspec/specs/auth-login/spec.md
✓ Moved to openspec/changes/archive/2026-04-27-add-2fa/
✓ Squash-merged feature branch
✓ Deleted local + remote feature/add-2fa
codify generate ─────────────▶ AGENTS.md, CONTEXT.md (project memory)
codify spec ─────────────────▶ specs/<feature>/spec.md... (Spec-Kit specs, default)
codify catalog --type skill ─▶ /spec-propose, /spec-apply, /spec-archive
--package openspec (SDD lifecycle skills)
generate and spec create the initial state. The SDD lifecycle skills then govern every subsequent change, keeping the system's specs in lockstep with its code.
For brownfield projects (mature codebases without formal specs), the adoption path is different — specs should emerge from the real behavior of the code, not from aspirations. Follow this sequence:
1. codify analyze ./my-project → AGENTS.md, CONTEXT.md, ... (factual context from scan)
2. openspec init → empty openspec/ workspace
3. codify catalog --type skill → /spec-propose, /spec-apply, /spec-archive
--package openspec --scope project
4. From your agent, prompt:
"Read AGENTS.md and CONTEXT.md, then reverse-engineer OpenSpec specs
from the source code under a change named 'baseline'. Identify
capability boundaries from the codebase structure. Use ADDED
requirements with GIVEN/WHEN/THEN scenarios derived from real
behavior, not aspirational design."
5. /spec-archive baseline → consolidate baseline specs into openspec/specs/
This pattern (the OpenSpec retrofitting mode) produces factual specs validated against existing code rather than projections from a description. After the baseline is archived, every new change goes through the standard /spec-propose → /spec-apply → /spec-archive lifecycle. Codify's role here is to provide the context (analyze) and the lifecycle skills (catalog --type skill --package openspec); the baseline retrofit itself is a one-shot prompt against your agent, not a separate Codify command — keeping responsibilities clean and avoiding overlap with OpenSpec's tooling.
The output structure (openspec/specs/, openspec/changes/, delta format with ADDED/MODIFIED/REMOVED, GIVEN/WHEN/THEN scenarios) follows the OpenSpec convention. The lifecycle skills Codify installs are designed to operate on OpenSpec workspaces seamlessly.
Codify's value-add over installing OpenSpec directly:
- Multi-target: same SDD methodology delivered as native skills for Claude Code or Antigravity
- Curated, production-ready content: the recipes ship with embedded examples, not scaffolding
- Integrated pipeline: combined with
codify generate+codify spec, you get end-to-end SDD bootstrap
Both live in the same codify catalog skills surface; the difference is scope and how the agent invokes them:
| Ordinary skills | Lifecycle recipes (lifecycle category) |
|
|---|---|---|
| Purpose | Teach how to do a specific task | Orchestrate a sequence of tasks |
| Scope | Single concern (e.g., "write a commit") | End-to-end process (e.g., "evolve a spec from proposal to merged change") |
| Invocation | Agent reads when relevant | User invokes via /command (disable-model-invocation: true) |
| Examples | Conventional Commits, DDD entity, code review | SDD lifecycle (spec-kit / openspec), bug fix, release cycle |
Both install the same way — see Agent Skills → Options (codify catalog, skill type). Lifecycle recipes use the package IDs from the lifecycle recipe catalog above (spec-kit, openspec, bug-fix, release-cycle).
Hooks are deterministic guardrails for Claude Code. Where skills (prompts, including the lifecycle recipes) rely on the LLM doing the right thing, hooks are shell scripts that always run on lifecycle events (PreToolUse, PostToolUse, etc.) — they enforce rules every single time, by exit code.
Hooks install through codify catalog (the unified packages surface). They are catalog-driven (no LLM personalization) and English-only by design.
The artifact layers complement each other:
| Layer | Mechanism | When does it run? | Determinism |
|---|---|---|---|
| Skills | Prompt loaded into context | When agent or user invokes | Depends on LLM |
| Lifecycle recipes | Multi-skill lifecycle (a lifecycle-category skill bundle) |
User invokes via slash command | Depends on LLM |
| Hooks | Shell scripts on events | Every matching tool call | 100% (exit codes) |
| Preset | Event | Purpose |
|---|---|---|
linting |
PostToolUse (Edit|Write) |
Auto-format and lint files using the right tool per language (Prettier/ESLint, ruff/black, gofmt/gofumpt, rustfmt, rubocop, shfmt). Tools detected via command -v — skipped silently if not installed. |
security-guardrails |
PreToolUse (Bash, Edit|Write) |
Block dangerous Bash commands (rm -rf /, git push --force to main, curl | bash, fork bombs, fs-formatting) and protect sensitive files (.env*, secrets/, .git/, lockfiles, private keys, CI configs). |
convention-enforcement |
PreToolUse (Bash with if) |
Validate commit messages against Conventional Commits 1.0.0 (header ≤72 chars, valid type, no trivial placeholders) and block direct/force pushes to protected branches (main, master, develop, production, release/*). Requires Claude Code v2.1.85+. |
all |
(combined) | Pass all three package IDs to install the full bundle |
Each preset above is a catalog package:
linting,security-guardrails,convention-enforcement. Install them by ID with--package.
| Scope | Target | Behavior |
|---|---|---|
project |
.claude/settings.json + .claude/hooks/ |
Merge handlers + copy scripts for this repo. Backs up the existing settings file first; idempotent — re-running adds nothing new. |
workstation |
~/.claude/settings.json + ~/.claude/hooks/ |
Same, for all your projects. Script command paths are rewritten to $HOME. |
~/.claude/ OR ./.claude/
├── settings.json (merged) ├── settings.json (merged)
├── settings.json.codify-backup-… ├── settings.json.codify-backup-…
└── hooks/ └── hooks/
├── lint.sh ├── lint.sh
├── block-dangerous-commands.sh ├── block-dangerous-commands.sh
├── protect-sensitive-files.sh ├── protect-sensitive-files.sh
├── validate-commit-message.sh ├── validate-commit-message.sh
└── check-protected-branches.sh └── check-protected-branches.sh
codify catalog
# → Ecosystem: claude
# → Package type: Hooks
# → Install scope: project or workstation
# → Multi-select the hook bundles to install# Activate everything for the current project
codify catalog --type hook --package linting,security-guardrails,convention-enforcement --scope project
# Just linting, at workstation scope (all your projects)
codify catalog --type hook --package linting --scope workstation
# Browse available hook bundles with installed markers
codify catalog --list --type hookclaude
> /hooksEvery install backs up the previous settings.json to settings.json.codify-backup-<timestamp>. To roll back:
mv .claude/settings.json.codify-backup-<timestamp> .claude/settings.json- Bash + jq (Linux/macOS native; Windows requires Git Bash or WSL)
- Claude Code v2.1.85+ (only for the
convention-enforcementpreset, which uses theiffield on hook handlers)
The bash scripts use regex patterns, not AST parsing. They stop careless agent commands, not motivated adversaries — sophisticated obfuscation (e.g. eval $(echo b3JtIC1yZiAv | base64 -d)) can bypass detection. For stronger guarantees use a dedicated tool like bash-guardian. The scripts are short and deliberately editable: extend the pattern arrays to match your project's specific risk model.
codify catalog --type hook [flags]| Flag | Description | Default |
|---|---|---|
--package |
Hook bundle IDs: linting, security-guardrails, convention-enforcement (comma-separated) |
(interactive) |
--scope |
Install scope: project or workstation (alias: global) |
project |
--list |
Browse available hook bundles instead of installing | false |
Plugins are Claude Code plugins — native bundles (skills + hooks + agents + MCP servers + commands) distributed through a plugin marketplace. codify catalog browses a marketplace and delegates install to Claude Code's own plugin CLI (the agent owns the plugin cache, namespacing and versioning — codify doesn't re-implement it), so claude must be on your PATH.
# Browse the Anthropic-managed directory (default marketplace)
codify catalog --list --type plugin
# Install a plugin at workstation scope
codify catalog --type plugin --package gopls-lsp --scope workstation
# Point at another marketplace (owner/repo or a marketplace.json URL)
codify catalog --type plugin --marketplace acme/claude-plugins --list| Flag | Description | Default |
|---|---|---|
--package |
Plugin IDs to install (comma-separated) | (interactive) |
--scope |
Install scope: project or workstation (alias: global) |
project |
--marketplace |
Marketplace: owner/repo or a marketplace.json URL |
anthropics/claude-plugins-official |
--list |
Browse available plugins instead of installing | false |
Plugins are installed by shelling out to
claude plugin marketplace add+claude plugin install; ifclaudeis not found, codify prints the exact manual commands. (See ADR-0012 for the standards/mechanic rationale.)
Ongoing. These commands operate on an already-equipped project. They detect drift, regenerate stale artifacts, audit commits, and keep cost transparent. Apply equally to greenfield and brownfield projects.
Once Codify generates artifacts, the world keeps moving. Dependencies change, README evolves, someone hand-edits AGENTS.md. Without active checking, the artifacts drift silently out of sync with the project.
codify check and its companion codify reset-state solve this without an LLM: SHA256 hashes of artifacts and input signals, captured at generation time and compared at check time. Zero LLM cost. Zero network. Fully deterministic.
codify check # human-readable report; exit 1 on significant drift
codify check --strict # any drift (including minor) triggers exit 1
codify check --json # machine-readable JSON for CI pipelines
codify check -o ./output/my-project # if artifacts live elsewhere than cwdWhat it detects:
| Drift kind | Severity | What it means |
|---|---|---|
artifact_modified |
significant | A generated file (e.g. AGENTS.md) was edited after generation |
artifact_missing |
significant | A file present in the snapshot is gone from disk |
signal_changed |
significant | An input signal (go.mod, Makefile, README.md, etc.) changed — your context may be stale |
signal_removed |
significant | A tracked signal is no longer on disk |
artifact_new |
minor | A new artifact appeared since the snapshot |
signal_added |
minor | A new signal appeared (informational) |
Exit codes:
0— no significant drift (or no drift at all)1— significant drift (default) or any drift (with--strict)2— no.codify/state.jsonexists (project not bootstrapped)
CI usage example (GitHub Actions):
- name: Verify Codify artifacts are in sync
run: codify check --strictA non-zero exit fails the job, so PRs that change dependencies without regenerating context are caught automatically.
When you intentionally edit AGENTS.md (e.g. you tightened a constraint by hand) and want Codify to consider that the new truth:
codify reset-state # recompute state.json from current FS, atomic write
codify reset-state --dry-run # preview only, no changesThe command is read-only over your artifacts — it never modifies AGENTS.md or context files. It only updates state.json (with backup at .bak). Subsequent check runs compare against the new baseline.
Every successful codify generate / codify analyze / codify init writes .codify/state.json containing:
- Project metadata (name, preset, language, locale, target)
- Git context (commit, branch, remote, dirty status)
- Artifacts: SHA256 + size + generation timestamp for each generated file
- Input signals: SHA256 of well-known files (
go.mod,Makefile,README.md, etc.)
codify check recomputes this snapshot from the current FS and diffs the two. The whole operation is local, fast (<100ms typical), and fully reproducible.
Three commands build on drift detection to close the gap between "Codify generated artifacts once" and "Codify maintains them as the project evolves": update regenerates selectively, audit reviews commits against documented conventions, usage exposes LLM cost.
Once codify check flags drift, codify update does the actual refresh:
codify update # detect drift, regenerate via analyze if needed
codify update --dry-run # show what would change without LLM cost
codify update --force # regenerate even on minor drift
codify update --accept-current # keep current FS as new baseline (alias for reset-state)
codify update --no-tracking # skip usage recording for this invocationBehavior matrix:
| Drift state | Without --force |
With --force |
|---|---|---|
| No drift | no-op, exit 0, no LLM call | no-op, exit 0 |
Only minor drift (artifact_new, signal_added) |
report and exit 0 | regenerate |
Significant drift in signals (e.g. go.mod changed) |
regenerate via analyze | regenerate via analyze |
| Only hand-edits to artifacts (no signal changes) | refuses with exit 1; suggests --accept-current |
regenerate (loses edits) |
The "hand-edit refusal" exists deliberately — if you tightened a constraint in AGENTS.md by hand, regenerating would silently lose it.
audit evaluates recent git commits against project conventions:
codify audit # last 20 commits, rules-only (zero LLM cost)
codify audit --since main~50 # all commits since main~50
codify audit --strict # any finding (incl. minor) fails the run
codify audit --json # machine-readable for CI pipelines
codify audit --with-llm # heuristic mode — sends commits + AGENTS.md to LLM (records usage)Rules-only checks (deterministic, zero cost):
| Finding | Severity | Description |
|---|---|---|
commit_invalid_type |
significant | Header doesn't match type[scope][!]: subject or uses an unknown type |
commit_trivial |
significant | Message is a placeholder (wip, fix, update, etc.) |
commit_header_too_long |
minor | Header exceeds 72 characters |
protected_branch_direct |
significant | Direct commit on main / master / develop / production (no merge commit detected) |
Recognized commit types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert.
Every successful and failed LLM call (from generate, analyze, update, spec, etc.) is automatically recorded with token counts and cost. Read the log with:
codify usage # current project's spending
codify usage --global # aggregate across all your projects
codify usage --since 7d # last 7 days only
codify usage --by command # break down by command name
codify usage --by model # break down by model name
codify usage --json # full JSON for scripting
codify usage --reset # archive current log and start freshSample output:
Codify Usage — project scope (.codify/usage.json)
════════════════════════════════════════════════════════════
Total cost: $0.42 (42 cents)
Total calls: 17
Total input: 142.3K tokens
Total output: 31.8K tokens
By command:
generate $0.12 2 calls
audit $0.18 8 calls
update $0.10 6 calls
spec $0.02 1 call
Pricing transparency: the cost is computed using a public list-price table embedded at internal/domain/usage/pricing.go (version 2026-05). It reflects what Anthropic and Google publish on their pricing pages. If you have negotiated discounts, the figure shown is an upper bound — useful for comparison, not for invoicing.
Disabling tracking — three options, any one suffices:
# 1. Per-invocation: skip just for this run
codify update --no-tracking
# 2. Per-shell: env variable
export CODIFY_NO_USAGE_TRACKING=1
# 3. Permanently: marker file
touch ~/.codify/.no-usage-trackingWhen tracking is disabled, no entries are written. The codify usage command will report zero (because nothing was recorded), but works fine.
A drop-in workflow that runs codify check + codify audit on every pull request:
# .github/workflows/codify.yml
name: Codify drift + audit
on: [pull_request]
jobs:
codify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 50 # codify audit needs commit history
- name: Install Codify
run: |
go install github.com/jorelcb/codify/cmd/codify@latest
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
- name: Verify generated artifacts are in sync
run: codify check --strict
- name: Audit recent commits
run: codify audit --since origin/main --strictBoth check and audit (rules-only mode, the default) are deterministic and free — no API key required. update and audit --with-llm require ANTHROPIC_API_KEY or GEMINI_API_KEY.
codify resolve is the standalone surface for filling in [DEFINE: ...] markers — the placeholders the LLM emits in generated context files when the project description didn't cover something. v2.1.0 promoted it from an inline post-generate hook to a first-class command you can run any time on existing files.
- You shipped
AGENTS.md/CONTEXT.mdwith markers left intact (declined the inline prompt duringgenerate, or generated before v2.0.5). - You added a new section to a context file by hand and want to re-resolve any markers introduced.
- Your CI flagged unresolved
[DEFINE]markers and you want to fix them in a single pass without re-generating.
codify resolve AGENTS.md CONTEXT.md # explicit list
codify resolve --all # walk cwd, every file with a marker
codify resolve --since=HEAD~5 # files changed in git since <ref>The --all walk skips .git, node_modules, vendor, .codify, and binary files (NUL byte in first 4KB).
For each file with markers, Codify makes one LLM enrichment call to translate the raw [DEFINE: hint] into a friendly prompt with grounded suggestions:
── AGENTS.md (2 markers) ──
40 ## Currency Configuration
41
▸ 42 The supported currency is [DEFINE: ISO 4217 currency code], using two
What currency does the application use?
(fintech context inferred from line 12)
Suggestions:
1) USD [default]
2) EUR
3) MXN
Your answer (1-N, text, Enter for default, s to skip)
Input parser:
- integer 1-N → pick the suggestion
- free text → use as the answer
- Enter → use the default if present, otherwise skip
sorskip→ explicit skip (case-insensitive)
When enrichment fails (no API key, provider error, malformed response, sanitizer rejected everything), the prompt degrades to the legacy form (Your input for L42 (Enter to skip)) — never a hard failure.
By default, skipping a marker replaces it with a date-stamped TODO comment in the file's native syntax — so the gap stays visible in IDE TODO panels and grep:
| Extension | Replacement |
|---|---|
.md, .html, .htm, .xml |
<!-- TODO 2026-05-06: ISO 4217 code --> |
.go, .js, .ts, .java, .rs, .c, .cpp, .swift, .cs, ... |
// TODO 2026-05-06: ISO 4217 code |
.py, .rb, .sh, .yml, .yaml, .toml, .ini, ... |
# TODO 2026-05-06: ISO 4217 code |
| Other / unknown | Marker preserved verbatim (safe default) |
Pass --skip-mode=verbatim to keep raw [DEFINE: ...] markers in the file.
After the rewrite, before the file is touched on disk, you see a small unified diff and choose:
About to rewrite AGENTS.md:
line 41
- The supported currency is [DEFINE: ISO 4217 currency code], using two
+ The supported currency is USD, using two
line 43
Apply changes? Apply / Discard (keep file as-is) / Edit before applying
- Apply — write the proposed content
- Discard — file untouched, contributes to the
FilesDiscardedcounter in the summary - Edit — open the proposed content in
$EDITOR(falling back tovim/vi/nano); the saved bytes are written
Skip the preview entirely with --no-preview.
Two layers protect against the LLM doing more than it was asked:
-
Suggestion sanitizer. Before the user sees them, suggestions returned by the enricher are filtered: URLs, file paths, multi-line strings, markdown-fenced text, and values longer than 50 chars are dropped. Suggestions are deduplicated case-insensitively and capped at 3 kept entries; the LLM-proposed default must match one of the survivors or it's discarded.
-
Post-rewrite validator. After the LLM rewrites the file with the user's answers, Codify re-scans the output and classifies markers by frequency (line numbers shift, text counts don't):
Lost— user skipped this marker but the LLM removed it anywayNotApplied— user answered but the marker is still in the fileSpurious— markers that did not exist in the input but appear in the output
Any of those triggers a transparent fallback to deterministic literal substitution, preserving every user answer. A WARNING goes to stderr explaining the downgrade.
codify resolve [files...] [flags]| Flag | Description | Default |
|---|---|---|
--all, -a |
Walk cwd recursively for files containing [DEFINE] markers |
false |
--since |
Only resolve files changed in git since this ref (e.g. HEAD~5) |
— |
--no-enrich |
Skip the LLM-driven question/suggestions step (cheaper, less friendly) | false |
--no-preview |
Skip the diff preview before writing files | false |
--skip-mode |
todo (default, TODO comment in file syntax) or verbatim |
todo |
--dry-run |
Walk markers and report what would change without writing files | false |
--locale |
Output locale for the LLM rewrite/enrichment prompts | en |
--model, -m |
LLM model | auto-detected |
The enrichment call uses Anthropic prompt caching (5-minute ephemeral TTL). For a typical 3-file generation, the same system prompt is reused across files — the second and third calls hit cache. Gemini callers pay full input-token cost per call (its caching API has a 4096-token minimum that resolver prompts don't meet). Without any provider configured, the resolver falls through to the legacy UI + literal substitution — no LLM cost, less polished UX.
The same flow runs automatically at the tail of codify generate / analyze / init, so most users never invoke codify resolve by hand. Use it when you want to revisit existing files or when you want one of the opt-out flags (--no-enrich, --skip-mode=verbatim, --dry-run).
codify watch keeps drift detection running in the background of your editor session. It re-runs check automatically when any file registered in .codify/state.json changes — input signals (e.g. go.mod, Makefile, README.md) and generated artifacts (AGENTS.md, context/*.md).
codify watch # default 2s debounce, report-only
codify watch --debounce 500ms # tighter debounce for fast feedback
codify watch --auto-update --strict # aggressively keep artifacts in syncBehavior:
- Loads
.codify/state.jsononce at startup; exits 2 if missing - Subscribes via
fsnotifyto the parent dirs of registered paths (no recursive walk) - Debounces events (default 2s) — five rapid saves trigger one drift check, not five
- Prints drift reports to stdout and keeps watching
--auto-updaterunscodify updatewhen significant drift is detected (records LLM usage)Ctrl+Cexits cleanly
codify watch is intentionally a foreground process, not a system daemon. It has no --detach, no PID file, no signal-driven reload. This decision is documented in ADR-008. The summary:
- PID file management, signal handling, log rotation, OS service integration are all hard problems and out of scope for a single-maintainer project. Users who need persistence can wrap with
tmux/nohup/systemd/ their preferred process supervisor. - The realistic use case is short-lived — you start
watchwhen you start coding, you stop it when you stop. Hours, not weeks. - Scope is naturally bounded — only the ~20 paths in
state.jsonare watched.
If you do want long-running watch:
# tmux session that survives terminal close
tmux new-session -d -s codify-watch "cd $(pwd) && codify watch"
tmux attach -t codify-watch # to inspect; Ctrl+B then D to detach
# systemd user unit (~/.config/systemd/user/codify-watch.service)
[Unit]
Description=Codify watch for %i
[Service]
WorkingDirectory=%h/projects/%i
ExecStart=/usr/local/bin/codify watch --debounce 5s
Restart=on-failure
[Install]
WantedBy=default.target
# nohup for a quick session-survival
nohup codify watch > codify-watch.log 2>&1 &For users whose mental model is "validate at git commit" rather than "validate while editing", codify check is the right tool — it's a one-shot deterministic check designed for CI and git hooks. Integrate via your preferred hook manager:
lefthook (lefthook.yml):
pre-commit:
commands:
codify-check:
run: codify check --strictpre-commit (.pre-commit-config.yaml):
repos:
- repo: local
hooks:
- id: codify-check
name: Codify drift detection
entry: codify check --strict
language: system
pass_filenames: falsewatchexec (foreground alternative on the same FS-event basis):
watchexec -w go.mod -w Makefile -w README.md -- codify checkCodify itself doesn't generate these configs — the integration is short and project-specific enough that copy-paste is the right primitive (per ADR-008).
Use Codify as an MCP server — your AI coding agent calls the tools directly, no manual CLI needed.
go install github.com/jorelcb/codify/cmd/codify@latestAdd to your project's .mcp.json:
{
"mcpServers": {
"codify": {
"command": "codify",
"args": ["serve"],
"env": {
"ANTHROPIC_API_KEY": "sk-ant-...",
"GEMINI_API_KEY": "AI..."
}
}
}
}# Register the MCP server
codex mcp add codify -- codify serve
codify servespeaks standard MCP, so any MCP-capable client can connect. (Gemini CLI setup was dropped — it is being deprecated in favor of Antigravity; ADR-0012 §4.)
Set the API key(s) for the provider(s) you want to use. The provider is auto-detected from the
modelparameter. If the binary is not in your PATH, use the full path (e.g.,/Users/you/go/bin/codify).
| Tool | Description |
|---|---|
generate_context |
Generate context files from a project description |
generate_specs |
Generate SDD specs from existing context files |
analyze_project |
Scan an existing project and generate context from its structure |
generate_skills |
Deliver curated Agent Skills (multi-file: SKILL.md + reference/examples), including the lifecycle category (bug-fix, release-cycle, spec-kit, openspec). Instant, offline — no API key |
generate_hooks |
Generate Claude Code hook bundles (deterministic guardrails). Static-only, Claude-only. Outputs hooks.json + .sh scripts for manual merge into settings.json |
All generative tools support locale (en/es) and model parameters (skills and hooks are English-only and ignore locale). generate_context and analyze_project also accept with_specs (and sdd_standard). generate_specs accepts from_context, output (defaults to from_context), and sdd_standard (spec-kit/openspec) — full parity with the codify spec CLI. generate_skills accepts category (including lifecycle), preset, and target (claude/antigravity) — static-only, no API key. generate_hooks accepts preset (linting/security-guardrails/convention-enforcement/all) and output — no model, context, or locale (hooks are English-only, static-only). The lifecycle recipes that were the removed generate_workflows tool are now obtained via generate_skills with category=lifecycle (ADR-0015).
| Tool | Description |
|---|---|
commit_guidance |
Conventional Commits spec and behavioral context for generating proper commit messages |
version_guidance |
Semantic Versioning spec and behavioral context for determining version bumps |
get_usage |
Read LLM cost tracking from local .codify/usage.json (project) or ~/.codify/usage.json (global). Pure file read, no LLM call. Parameters: scope (project/global), since (e.g. 7d/24h), by (command/model/provider) |
Knowledge tools inject behavioral context into the calling agent — the agent receives the spec and instructions, then applies them to the current task. Supports locale (en/es).
"Generate context for a payment microservice in Go with gRPC and PostgreSQL"
→ Agent calls generate_context
"Analyze my project at /path/to/my-app and generate specs"
→ Agent calls analyze_project with with_specs=true
"Generate convention skills for my project"
→ Agent calls generate_skills with category=conventions, preset=all
"Install the SDD lifecycle recipe for Claude Code"
→ Agent calls generate_skills with category=lifecycle, preset=spec-kit, target=claude
"Give me the bug-fix and release-cycle lifecycle recipes"
→ Agent calls generate_skills with category=lifecycle, preset=all, target=claude
"Generate Claude Code hooks to block dangerous commands and enforce conventional commits"
→ Agent calls generate_hooks with preset=all (or security-guardrails + convention-enforcement)
"Help me commit these changes following conventional commits"
→ Agent calls commit_guidance, receives the spec, crafts the message
"What version should I release based on recent changes?"
→ Agent calls version_guidance, receives semver rules, analyzes commits
When you pass --language, the tool generates an additional IDIOMS.md file with patterns and conventions specific to that language. This is one of the most impactful features — it gives your agent deep knowledge of idiomatic patterns instead of generic advice.
| Language | What IDIOMS.md covers |
|---|---|
go |
Goroutines, channels, WaitGroups, context.Context, error wrapping with %w, table-driven tests |
javascript |
async/await, Promise.all, AbortController, worker threads, TypeScript, ESM, Jest patterns |
python |
asyncio, multiprocessing, type hints, pydantic, pytest fixtures, ruff |
# Go project with idiomatic guides
codify generate my-api -d "REST API in Go" --language go
# TypeScript SDK with JS idioms
codify generate my-sdk -d "SDK in TypeScript" --language javascript
# Python service with async patterns
codify generate my-service -d "FastAPI service" --language pythonWithout --language, the tool generates 4 files. With it, you get 5 — and significantly richer output.
Choose the architectural philosophy for your context. Codify ships 4 presets:
| Preset | Focus | When to use |
|---|---|---|
neutral (default) |
No architectural opinion — structure adapts to the project | Greenfield exploration, scripts, tools, anywhere you want minimal opinion baked in |
clean-ddd |
DDD + Clean Architecture + BDD + Layered domain | Long-lived business systems, domain-rich logic, teams comfortable with layered architecture |
hexagonal |
Ports & Adapters — lighter than clean-ddd | Apps with strong external integration concerns, swappable infra, simpler than full DDD |
event-driven |
CQRS + Event Sourcing + Sagas | Async systems, multi-service coordination, event-first domains, audit trails |
# Default — no architectural opinion
codify generate my-api -d "Inventory REST API in Go"
# Clean + DDD
codify generate my-api -d "Inventory REST API in Go" --preset clean-ddd
# Hexagonal — ports & adapters
codify generate my-payments -d "Payment service" --preset hexagonal
# Event-driven — CQRS + ES + sagas
codify generate my-orders -d "Order processing" --preset event-drivenFor detailed project descriptions (design docs, RFCs, 6-pagers), use --from-file instead of --description:
codify generate my-api \
--from-file ./docs/project-description.md \
--language goThe file content becomes the project description. Supports any text format — markdown, plain text, etc. Mutually exclusive with --description.
Codify v2.0 has one breaking change. Everything else (multi-target support for Claude/Codex/Antigravity, all commands, all flags, all config keys) keeps working identically.
| v1.x | v2.0 |
|---|---|
--preset default (deprecated alias resolving to clean-ddd with warning) |
Removed — returns a clear error with migration instructions |
Default value of --preset flag: clean-ddd |
neutral (no architectural opinion baked in) |
default accepted in ~/.codify/config.yml |
Returns the same error at config load |
The change in default reflects a project decision documented in ADR-001: Codify's "default" used to be DDD/Clean — opinionated. v2.0 makes the default architecturally neutral, so the agent gets a clean baseline unless you explicitly choose a stance.
If you used --preset default explicitly:
# Before (v1.x):
codify generate my-api -d "..." --preset default
# After (v2.0): use clean-ddd (same behavior as v1.x default)
codify generate my-api -d "..." --preset clean-ddd
# OR adopt the new default explicitly:
codify generate my-api -d "..." --preset neutralIf you ran codify generate without --preset and want to keep v1.x behavior:
Two options:
# Option A — pass --preset clean-ddd on every invocation
codify generate my-api -d "..." --preset clean-ddd
# Option B — set it as your global default (recommended for CI/scripts)
codify config set preset clean-dddIf your ~/.codify/config.yml has preset: default:
# Edit the file or use the CLI:
codify config set preset clean-ddd # to keep v1.x behavior
codify config set preset neutral # to adopt v2.0 default- All targets remain supported:
claude,codex,antigravity(per ADR-009, reversing the v1.26 deprecation plan) - All commands work identically —
generate,analyze,spec,catalog(skills incl. lifecycle, hooks, plugins),config,init,check,update,audit,usage,watch,reset-state - All other flags, all output formats, all MCP tools (9 total)
- Config schema, state.json schema, usage.json schema — unchanged
- Pricing table version, locale options, language options — unchanged
If you don't pass --preset explicitly anywhere, the only observable difference is that newly-generated AGENTS.md/CONTEXT.md will be architecture-agnostic instead of DDD-flavored. Existing artifacts are not affected; codify check won't flag drift just because the version changed.
Built in Go with what it preaches — DDD/Clean Architecture:
internal/
├── domain/ 💎 Pure business logic
│ ├── project/ Project entity (aggregate root)
│ ├── catalog/ Declarative skill catalogs (incl. the lifecycle category) and metadata registries
│ ├── shared/ Value objects, domain errors
│ └── service/ Interfaces: LLMProvider, FileWriter, TemplateLoader
│
├── application/ 🔄 Use cases (CQRS)
│ ├── command/ GenerateContext, GenerateSpec, GenerateSkills
│ └── query/ ListProjects
│
├── infrastructure/ 🔧 Implementations
│ ├── llm/ LLM providers (Claude, Gemini) + prompt builder
│ ├── template/ Template loader (locale + preset + language-aware)
│ ├── scanner/ Project scanner (language, deps, framework, build targets, testing, CI/CD)
│ └── filesystem/ File writer, directory manager, context reader
│
└── interfaces/ 🎯 Entry points
├── cli/commands/ generate, analyze, spec, catalog, serve, list
└── mcp/ MCP server (stdio + HTTP transport, 9 tools)
templates/
├── en/ English locale
│ ├── neutral/ Default preset — no architectural opinion
│ │ ├── agents.template
│ │ ├── context.template
│ │ ├── interactions.template
│ │ └── development_guide.template
│ ├── clean-ddd/ DDD + Clean Architecture + BDD
│ │ └── (same files)
│ ├── hexagonal/ Ports & Adapters
│ │ └── (same files)
│ ├── event-driven/ CQRS + Event Sourcing + Sagas
│ │ └── (same files)
│ ├── spec/ Specification templates (AI SDD)
│ │ ├── constitution.template
│ │ ├── spec.template
│ │ ├── plan.template
│ │ └── tasks.template
│ ├── skills/ Agent Skills templates (static, English-only)
│ │ ├── neutral/ Architecture: review, testing, API design, refactoring
│ │ ├── clean-ddd/ Architecture: DDD entity, layer, BDD, CQRS, Hexagonal port
│ │ ├── hexagonal/ Architecture: port, adapter, dependency inversion, integration test
│ │ ├── event-driven/ Architecture: command handler, domain event, projection, saga, idempotency
│ │ ├── testing/ Testing: Foundational, TDD, BDD
│ │ ├── conventions/ Conventions (conventional commits, semver)
│ │ └── lifecycle/ Lifecycle recipes: bug-fix, release-cycle, spec-kit, openspec (ADR-0015)
│ ├── hooks/ Hook bundle templates
│ │ ├── linting/
│ │ ├── security-guardrails/
│ │ └── convention-enforcement/
│ └── languages/ Language-specific idiomatic guides
│ ├── go/idioms.template
│ ├── javascript/idioms.template
│ └── python/idioms.template
└── es/ Spanish locale (same structure)
The golden rule: Infrastructure → Application → Domain. Nothing in domain depends on anything external.
See context/CONTEXT.md for full architectural details.
# All tests
go test ./...
# BDD with Godog
go test ./tests/...v3.0.0
The full surface in one snapshot — anything checked here is shipped, tested, and behaves as documented above.
Context layer
- ✅
generate— context from a description (4 files, +1 with--language) - ✅
analyze— context from an existing repo via project scanner (18+ context-file patterns, build-target parsing, CI/CD detection, framework + dependency parsing for 8 languages) - ✅
spec+--with-specsflag — SDD specs (Spec-Kit default: user stories + SC-XXX; OpenSpec alt.) - ✅ Streaming output, anti-hallucination grounding rules, output validators (
[DEFINE]markers, frontmatter, code-fence balance) - ✅ Anthropic prompt caching across per-file generation loop
Behavior layer
- ✅
catalog— unified install surface for skills + hooks (ADR-0010). Interactive wizard,--listbrowsing with source badges + installed markers, non-interactive--type/--package/--scope. Claude ecosystem (others return later) - ✅
skills(via catalog) — architecture (neutral/clean-ddd/hexagonal/event-driven) + testing + conventions + lifecycle (bug-fix, release-cycle, spec-kit, openspec); curated multi-file skills (SKILL.md + reference.md + examples.md), static-only and English-only since v4.0.0 - ✅
hooks(via catalog) — linting, security-guardrails, convention-enforcement; auto-install with settings.json backup + idempotent merge - ✅ lifecycle recipes (the
lifecycleskills category) — installed as native skills on Claude and Antigravity; the standaloneworkflowscommand and the Antigravity annotated-workflow format were removed in v4.0.0 (ADR-0015)
Bootstrap layer
- ✅
config— user-level config wizard with auto-launch SOFT (TTY-gated, triple opt-out);get/set/unset/edit/listsubcommands - ✅
init— project-level smart router (new vs existing) that delegates togenerateoranalyze
Lifecycle layer
- ✅
check— drift detection (artifact_modified, signal_changed, etc.) — deterministic, no LLM - ✅
update— selective regeneration viaanalyze; refuses to overwrite hand-edits without--force - ✅
audit— Conventional Commits + protected branches (rules-only, free) +--with-llmheuristic mode (records usage) - ✅
usage— local LLM cost tracking (.codify/usage.json+~/.codify/usage.json);--global,--since,--by,--json,--reset - ✅
watch— foreground file watcher with debounce, optional--auto-update - ✅
reset-state— recompute snapshot without touching artifacts - ✅
resolve— interactive[DEFINE]marker resolution with LLM-driven prompts (grounded suggestions + default), TODO-anchor skip mode, post-rewrite validator (anti-hallucination), diff preview,--all/--since/ explicit file selection,--no-enrich/--no-preview/--skip-mode=verbatim/--dry-runopt-outs
MCP server
- ✅ 9 tools: 6 generative (context/specs/analyze/skills/hooks/usage) + 3 read-only (commit_guidance/version_guidance/get_usage)
- ✅ stdio + HTTP transports; parameter enums for stricter agent validation; no API key needed for read-only tools
Distribution
- ✅ Homebrew tap (
brew install jorelcb/tap/codify) - ✅
go install github.com/jorelcb/codify/cmd/codify@latest - ✅ Pre-built binaries in GitHub Releases
Quality
- ✅ 9 BDD packages with 30+ scenarios; pure unit tests across domain + infrastructure
- ✅ DDD/Clean Architecture internal layout (the project eats its own dog food)
Known boundaries (intentional, not roadmap):
- No daemon mode for
watch— wrap with tmux/nohup/systemd if needed (per ADR-008) - No
pkg/codifyGo library — embedding via process boundary (CLI/MCP) is the contract (per ADR-003) - Hooks are Claude Code-only (the underlying primitive doesn't exist for codex/antigravity)
Which LLM providers are supported?
Anthropic Claude (default) and Google Gemini. Set ANTHROPIC_API_KEY for Claude or GEMINI_API_KEY for Gemini. The provider is auto-detected from the --model flag: claude-* models use Anthropic, gemini-* models use Google.
How much does each generation cost?
4-5 API calls for generate (depending on --language), 4 for spec. Skills are free (no API calls — curated content delivered from the embedded catalog). Each generation costs pennies with either provider.
Do I need an API key for skills? No. Skills are curated, production-ready content delivered instantly from the embedded catalog — no LLM, no API key, no cost. (The LLM personalization mode was removed in v4.0.0: well-authored static skills with embedded examples proved strictly better.)
Are the templates fixed? They're structural guides, not renderable output. The LLM generates intelligent, project-specific content following the template structure.
Can I customize the templates?
You can create your own presets in templates/<locale>/. Each preset needs 4 files: agents.template, context.template, interactions.template, and development_guide.template. Language-specific templates go in templates/<locale>/languages/<lang>/idioms.template.
Which agents support the generated files? Any agent compatible with the AGENTS.md standard: Claude Code, Cursor, GitHub Copilot Workspace, Codex, and more.
What's the difference between ordinary skills and lifecycle recipes?
Ordinary skills teach your agent how to do a single task (e.g., write a commit message, design a DDD entity). Lifecycle recipes — the lifecycle skills category — orchestrate a sequence of tasks into an end-to-end process (e.g., the full SDD lifecycle from proposal to merged change). Ordinary skills are passive (read when relevant); lifecycle recipes are active (invoked via /command, with disable-model-invocation: true). Both install through codify catalog.
Do I need an API key for lifecycle recipes? No. Like all skills, the lifecycle recipes are static, English-only, curated content delivered instantly — no LLM, no API key, no cost.
Which ecosystems support lifecycle recipes?
Claude Code and Antigravity — both install them as native skills (SKILL.md with frontmatter). As of v4.0.0 the codify workflows command, the MCP generate_workflows tool, and the old Antigravity annotated-workflow format (// turbo, // capture, …) were removed; Antigravity 2.0 converged on Claude's skills/hooks/plugins model (ADR-0015).
What's AI Spec-Driven Development?
A methodology where you generate context and specifications before writing code. Your agent implements a spec, not an improvisation. generate creates the blueprint, spec creates the implementation plan, and the SDD lifecycle recipe (the spec-kit / openspec package in the lifecycle skills category) governs every subsequent change as a tracked spec evolution (propose → apply → archive) with formal deltas, isolated change workspaces, and audit trails.
Why three phases (propose / apply / archive) instead of one workflow? Each phase is a different cognitive mode. Propose answers "what should change and why?" without writing code — the LLM stays focused on intent. Apply answers "how to make it real?" with the deltas already approved, eliminating spec ambiguity from the implementation context. Archive closes the loop deterministically: merge deltas into source-of-truth specs, archive the change for audit, merge the branch. Mixing these phases dilutes attention and produces vague plans + sloppy code.
Does Codify replace OpenSpec?
No — it complements it. The openspec lifecycle recipe installs skills that operate on OpenSpec-format workspaces (openspec/specs/, openspec/changes/, ADDED/MODIFIED/REMOVED deltas with G/W/T scenarios). If you already use OpenSpec, Codify gives you curated lifecycle skills that drive the workflow. If you don't, Codify is your zero-config entry point to the methodology — combined with codify generate and codify spec, you get the full pipeline from blank repo to governed iteration.
Common errors and quick fixes are now consolidated in docs/troubleshooting.md. The most frequent ones:
ANTHROPIC_API_KEY or GEMINI_API_KEY environment variable is required— set the key for LLM-backed commands; read-only commands (check,audit --rules-only,usage) don't need one.No snapshot at .codify/state.json...— project not bootstrapped: runcodify init,generate, oranalyzefirst; orcodify reset-stateif the file was deleted.Codify isn't configured globally yet. Run interactive setup now?prompt blocks scripts — pass--no-auto-config, setCODIFY_NO_AUTO_CONFIG=1, ortouch ~/.codify/.no-auto-config.
If your symptom is not listed in docs/troubleshooting.md, open an issue with: command run, exit code, and stderr. The CHANGELOG and ADRs document most design decisions.
Start here:
- 📘 Getting Started — 5-minute end-to-end tour with expected outputs
- 📋 Lifecycle Matrix — Which command applies to workstation vs project, greenfield vs brownfield
- 📖 Command Reference — Cheatsheet of every command, grouped by phase
- 🆘 Troubleshooting — Common errors and fixes
Reference:
- 📐 ADRs — Architectural Decision Records
- 📋 AGENTS.md — Project context for AI agents
- 🏛️ Architecture — DDD/Clean Architecture details
- 📝 Changelog — Change history
- 🧪 Specs — Technical specifications (SDD)
Apache License 2.0 — see LICENSE.
Context. Specs. Skills. Hooks. Lifecycle. Your agent, fully equipped — and kept honest. 🧠
"An agent without context is an intern with root access — and stale context is an intern reading three-week-old docs"
⭐ If this helped you, give it a star — it keeps us building