Codi installs git hooks that run on every commit, every push, and every commit message. This page maps each hook to its purpose, when it triggers, what it blocks, and how to handle failures.

If you want the high-level model (pre-commit ⇢ pre-push ⇢ CI), see Architecture: Hook System. If you’re contributing to codi-cli itself, see the Quality gates policy.

Where hooks live

LocationWho managesTracked in git?
.husky/pre-commit, .husky/commit-msgcodi (regenerated by codi generate)No — gitignored
.git/hooks/codi-*.mjscodi (regenerated by codi generate)No — .git/ is gitignored by git itself
.pre-commit-config.yamlcodi when the user opts into the pre-commit frameworkYes — you can edit Codi-managed entries; user-pinned rev: values are preserved

Codi detects the project’s existing hook runner in priority order: huskypre-commit frameworklefthookstandalone (raw .git/hooks/pre-commit).

Layer A — codi-managed structural checks (pre-commit)

These run on every commit, scoped to staged files. Each one is a small Node.js script in .git/hooks/codi-*.mjs.

codi-version-bump.mjs

  • Purpose: when artifact files change, ensure their version: frontmatter is bumped.
  • Triggers on: any staged file under .codi/rules/, .codi/skills/, .codi/agents/.
  • Blocks the commit when: artifact content changed but version stayed the same.
  • Fix: bump the version: field in the artifact’s frontmatter.

codi-staged-junk-check.mjs

  • Purpose: catch accidentally-staged developer junk.
  • Blocks: .DS_Store, node_modules/, dist/, IDE state files (.idea/workspace.xml, etc.).
  • Fix: git rm --cached <file> and add the path to .gitignore.

codi-conflict-marker-check.mjs

  • Purpose: catch unresolved git merge markers.
  • Blocks: lines beginning with <<<<<<<, =======, >>>>>>>, or ||||||| (diff3).
  • Fence-aware (since v2.14.2): markers inside fenced code blocks (``` or ~~~) and inside <example>...</example> regions are ignored — they’re documentation, not real conflicts.
  • Fix: resolve the merge conflict properly and re-stage.

codi-file-size-check.mjs

  • Purpose: enforce the 800-LOC ceiling for source files.
  • Blocks: any source file over 800 lines.
  • Excludes: .md, .mdx, .txt, .rst, anything under docs/, references/, assets/.
  • Fix: extract helpers into sibling files. Don’t bypass with --no-verify — the cap exists because oversized files become unreadable.

codi-import-depth-check.mjs

  • Purpose: prevent fragile ../../../ deep relative imports.
  • Blocks: any TS/JS import path with two or more ../ segments.
  • Fix: use a path alias (#src/* for Node subpath imports, @/* for Vite/Next-style bundler aliases).

codi-doc-naming-check.mjs

  • Purpose: enforce the documentation naming convention.
  • Blocks: any docs/*.md file that doesn’t match YYYYMMDD_HHMMSS_[CATEGORY]_*.md.
  • Allowed categories: ARCHITECTURE, AUDIT, GUIDE, REPORT, ROADMAP, RESEARCH, SECURITY, TESTING, BUSINESS, TECH, PLAN.
  • Fix: rename the file to match. Run python3 scripts/validate-docs.py to verify (in codi-cli’s own repo).

codi-secret-scan.mjs

  • Purpose: codi-specific secret-pattern check (in addition to gitleaks).
  • Blocks: tokens matching codi’s heuristic patterns.
  • Fix: revoke the credential, rewrite the commit, and never commit secrets — use .env* (gitignored) for local config.

codi-skill-yaml-validate.mjs, codi-skill-resource-check.mjs, codi-skill-path-wrap-check.mjs

  • Purpose: validate that skill content is well-formed.
  • Blocks: malformed YAML frontmatter in SKILL.md; broken [[/path]] resource references; unwrapped paths missing ${CLAUDE_SKILL_DIR}[[...]].
  • Fix: correct the SKILL.md content. Most issues are visible in the error output.

codi-brand-skill-validate.mjs

  • Purpose: validate brand skills (asset structure, token files).
  • Triggers on: staged .json, .css, .html, .svg, .md files in brand-skill directories.

codi-artifact-validate.mjs

  • Purpose: run codi validate --ci against staged artifact changes.
  • Blocks: rule/skill/agent schema breaks, frontmatter parse errors, unknown agent references.

codi-template-wiring-check.mjs

  • Purpose (codi contributors only): every skill template referenced in code must exist on disk.
  • Triggers on: source-file changes that touch skill registries.
  • Fix: add the missing template, or remove the reference.

Layer B — third-party scanners and formatters (pre-commit)

Codi wires these only when the relevant file types are staged.

ToolFiles matchedWhat it does
gitleaks protect --stagedallBlocks if a real secret pattern matches
ESLint (--fix)*.{ts,tsx,js,jsx}Auto-fixes; re-stages on success
Prettier (--write)*.{ts,tsx,js,jsx,mjs,cjs,json,md,mdx,yaml,yml,css,scss,html}Auto-formats; re-stages on success
Ruff (check --fix + format)*.pyLint + format Python; blocks if ruff missing
Bandit (-lll)*.pySecurity check; blocks if bandit missing
ShellCheck (-S warning)*.shShell-script lint; blocks if shellcheck missing

Missing tools produce a clear “install with: <command>” error rather than silently skipping.

Layer C — commit-msg validator

Runs once per git commit -m "...". A custom Node.js validator embedded directly in .husky/commit-msg (not the upstream commitlint package, which would be heavier and require a separate config file).

  • Format: type(scope): description (scope optional). Allowed types: feat, fix, docs, refactor, test, chore, perf, ci, build, style, revert.
  • First-line cap: 72 characters.
  • Fix: rewrite the commit message. git commit --amend if you’ve just made the bad commit.

pre-push (codi-cli’s own repo)

Codi-cli installs a pre-push hook on its own repo via scripts/setup-husky-hooks.mjs (run automatically by pnpm install’s prepare step). This is not generated by codi for downstream users — it runs pnpm test:coverage against codi-cli’s own test suite, which only makes sense for contributors.

For your own project’s pre-push checks, configure them via the pre-commit framework’s pre-push stage or directly in .husky/pre-push (which codi will leave alone if you create it).

When you absolutely cannot bypass a hook

The codi-cli repo’s policy is never use --no-verify — diagnose and fix the underlying issue.

If you genuinely need to commit broken state for an emergency hotfix:

  1. Don’t bypass the hook.
  2. Open a separate “WIP” branch, push it without the bypass.
  3. Skip the hook locally only via HUSKY=0 git commit ... if the project allows it (codi-cli does not).
  4. Document the bypass in the PR description with the reason and the follow-up plan.

Customizing or disabling individual hooks

Most hook behavior is flag-controlled via .codi/flags.yaml. Run codi doctor --hooks to see which hooks are wired in your project and which underlying tools are installed. To disable a flag-controlled hook:

# .codi/flags.yaml
test_before_commit:
  mode: enabled
  value: false

Then run codi generate to refresh the hook scripts.

For codi-managed structural checks (Layer A above), there’s no per-hook toggle — they enforce repository-wide invariants. If a check is genuinely wrong for your project, open an issue.

Backups

Codi takes a backup before every destructive operation that mutates .codi/ or generated agent files. Backups live under .codi/backups/<ISO-timestamp>/ and are capped at 50. The manifest (backup-manifest.json) is written LAST as a commit marker, so a crash mid-snapshot leaves a partial dir that the next operation auto-sweeps.

CommandTrigger label
codi init (first run)init-first-time
codi init --customizeinit-customize
codi updateupdate
codi clean (without --all)clean-reset
codi preset installpreset-install
Add from external source wizardinit-customize
codi revertpre-revert

codi clean --all skips the snapshot — it wipes .codi/ entirely (including .codi/backups/), so a backup there cannot survive. Users who want pre-clean safety should run codi backup --list first.

Manage backups with the codi backup command:

codi backup --list           # list sealed backups, newest first
codi backup --delete <ts...> # remove specific backups by timestamp
codi backup --prune          # interactive TUI to select backups to delete

Restore with codi revert (interactive picker), codi revert --last (most recent), codi revert <ts> (specific), or codi revert --dry-run (preview without writing). See Backups & Recovery for the full guide.