Skip to content

jorelcb/codify

Repository files navigation

🧠 Codify

Version MCP Go License Claude Gemini AGENTS.md

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


🎯 The Problem

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. 🛠️

💡 The Solution

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 lifecycle skills 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.

🗺️ Lifecycle phases at a glance

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.

✨ Before and after

😱 Without Codify

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. 😤

🚀 With Codify

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.

⚡ Quick Start

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: ...] markers

API 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.


🚀 Bootstrap phase (one-time setup)

One-time setup for the workstation and per project. After this, you move to the Equip phase.

⚙️ Configuration & Bootstrap

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 — user-level defaults

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 — project-level bootstrap

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.md and context/*.md written to output/

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.

Merge precedence

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.


🧰 Equip phase (install context, skills, hooks, specs)

Install only what you need. Each command below is independent and skippable. After equipping, the Maintain phase keeps everything honest as the project evolves.

📋 Context Generation

The foundation. Generates files following the AGENTS.md standard that give your agent deep project memory.

When to use generate vs analyze

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

generate command — Context from a description

codify generate payment-service \
  --description "Payment microservice in Go with gRPC and PostgreSQL" \
  --language go

analyze command — Context from an existing project

Scans 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

Generated files

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.

Options

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

📐 Spec-Driven Development

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

spec command

codify spec payment-service \
  --from-context ./output/payment-service/

--with-specs — Full pipeline in one command

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-specs

Generated spec files

Default 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).


🧩 Agent Skills

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).

Two modes

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

Interactive mode

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 pass

The 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.

CLI mode

# 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

Install scopes

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).

Declarative mode (catalog-as-code)

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 / --sync operate on the separate lockfile (codify's install record).

Skill catalog

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>/ — a codify-package.yaml manifest plus the content (SKILL.md, or hooks.json + scripts for hooks). They appear in codify catalog badged [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.)

Options (codify catalog, skill type)

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 (the lifecycle skills category)

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 workflows command. As of v4.0.0 they are a lifecycle category inside the unified skills catalog — installed through codify catalog like any other skill, on Claude and Antigravity (both deliver them as native skills). The standalone codify workflows command, the MCP generate_workflows tool, 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 does
  • disable-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.

Install via codify catalog

# 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

Lifecycle recipe catalog

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) and openspec. The standard is a selection, not a packaging primitive: both deliver the same recipe content as skills (ADR-0011 / ADR-0015).

Spec-driven Change: the philosophy

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

The three phases

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

Concrete example

$ /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

How it fits with the rest of Codify

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.

Adopting SDD on an existing codebase

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.

OpenSpec compatibility

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

Ordinary skills vs lifecycle recipes

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

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 catalog

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.

Install scopes

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.

Output layout

~/.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

Interactive mode

codify catalog
# → Ecosystem: claude
# → Package type: Hooks
# → Install scope: project or workstation
# → Multi-select the hook bundles to install

CLI mode

# 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 hook

Verify activation

claude
> /hooks

Rollback

Every 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

Requirements

  • Bash + jq (Linux/macOS native; Windows requires Git Bash or WSL)
  • Claude Code v2.1.85+ (only for the convention-enforcement preset, which uses the if field on hook handlers)

Honest limitations

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.

Options

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

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; if claude is not found, codify prints the exact manual commands. (See ADR-0012 for the standards/mechanic rationale.)


🔧 Maintain phase (ongoing lifecycle)

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.

🔍 Lifecycle: Drift Detection

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 — detect drift in CI or locally

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 cwd

What 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.json exists (project not bootstrapped)

CI usage example (GitHub Actions):

- name: Verify Codify artifacts are in sync
  run: codify check --strict

A non-zero exit fails the job, so PRs that change dependencies without regenerating context are caught automatically.

codify reset-state — accept current FS as the new baseline

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 changes

The 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.

How drift detection works under the hood

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.


🔄 Lifecycle: Update, Audit & Usage Tracking

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.

codify update — selective regeneration

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 invocation

Behavior 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.

codify audit — review commits against conventions

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.

codify usage — LLM cost transparency

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 fresh

Sample 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-tracking

When tracking is disabled, no entries are written. The codify usage command will report zero (because nothing was recorded), but works fine.

CI integration — GitHub Actions pattern

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 --strict

Both 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.


✏️ Lifecycle: Marker Resolution (codify resolve)

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.

When to use

  • You shipped AGENTS.md / CONTEXT.md with markers left intact (declined the inline prompt during generate, 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.

File selection

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).

Interactive flow (LLM-driven by default)

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
  • s or skip → 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.

Skip mode

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.

Diff preview

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 FilesDiscarded counter in the summary
  • Edit — open the proposed content in $EDITOR (falling back to vim / vi / nano); the saved bytes are written

Skip the preview entirely with --no-preview.

Anti-hallucination guardrails

Two layers protect against the LLM doing more than it was asked:

  1. 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.

  2. 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 anyway
    • NotApplied — user answered but the marker is still in the file
    • Spurious — 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.

Flags

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

Cost notes

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).


👁️ Lifecycle: Foreground Watcher (codify watch)

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 sync

Behavior:

  • Loads .codify/state.json once at startup; exits 2 if missing
  • Subscribes via fsnotify to 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-update runs codify update when significant drift is detected (records LLM usage)
  • Ctrl+C exits cleanly

Why foreground (not daemon)

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 watch when you start coding, you stop it when you stop. Hours, not weeks.
  • Scope is naturally bounded — only the ~20 paths in state.json are watched.

Wrapping in a process supervisor

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 &

Alternative — git-hook integration with codify check

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 --strict

pre-commit (.pre-commit-config.yaml):

repos:
  - repo: local
    hooks:
      - id: codify-check
        name: Codify drift detection
        entry: codify check --strict
        language: system
        pass_filenames: false

watchexec (foreground alternative on the same FS-event basis):

watchexec -w go.mod -w Makefile -w README.md -- codify check

Codify itself doesn't generate these configs — the integration is short and project-specific enough that copy-paste is the right primitive (per ADR-008).


🔌 MCP Server

Use Codify as an MCP server — your AI coding agent calls the tools directly, no manual CLI needed.

Install

go install github.com/jorelcb/codify/cmd/codify@latest

Claude Code

Add to your project's .mcp.json:

{
  "mcpServers": {
    "codify": {
      "command": "codify",
      "args": ["serve"],
      "env": {
        "ANTHROPIC_API_KEY": "sk-ant-...",
        "GEMINI_API_KEY": "AI..."
      }
    }
  }
}

Codex CLI

# Register the MCP server
codex mcp add codify -- codify serve

codify serve speaks 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 model parameter. If the binary is not in your PATH, use the full path (e.g., /Users/you/go/bin/codify).

Available MCP Tools

Generative tools (require LLM API key)

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).

Read-only tools (no API key needed)

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).

Example prompts

"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

🌐 Language-Specific Guides

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 python

Without --language, the tool generates 4 files. With it, you get 5 — and significantly richer output.

🎭 Presets

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-driven

--from-file — Rich descriptions from files

For 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 go

The file content becomes the project description. Supports any text format — markdown, plain text, etc. Mutually exclusive with --description.

🚀 Migrating from v1.x

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.

What changed

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.

Migration steps

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 neutral

If 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-ddd

If 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

What did NOT change

  • 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.

🏗️ Architecture

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)

Template system

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.

🧪 Tests

# All tests
go test ./...

# BDD with Godog
go test ./tests/...

📊 Project status

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-specs flag — 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, --list browsing 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 lifecycle skills category) — installed as native skills on Claude and Antigravity; the standalone workflows command 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 / list subcommands
  • init — project-level smart router (new vs existing) that delegates to generate or analyze

Lifecycle layer

  • check — drift detection (artifact_modified, signal_changed, etc.) — deterministic, no LLM
  • update — selective regeneration via analyze; refuses to overwrite hand-edits without --force
  • audit — Conventional Commits + protected branches (rules-only, free) + --with-llm heuristic 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-run opt-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/codify Go 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)

💡 FAQ

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.

🆘 Troubleshooting

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: run codify init, generate, or analyze first; or codify reset-state if the file was deleted.
  • Codify isn't configured globally yet. Run interactive setup now? prompt blocks scripts — pass --no-auto-config, set CODIFY_NO_AUTO_CONFIG=1, or touch ~/.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.

📚 Documentation

Start here:

Reference:

📄 License

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

🐛 Report bug · 💡 Request feature

About

Give your AI agent the blueprint it needs. MCP server & CLI that generates context, specs, and Agent Skills from project descriptions — powered by Claude & Gemini.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors