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
| Location | Who manages | Tracked in git? |
|---|---|---|
.husky/pre-commit, .husky/commit-msg | codi (regenerated by codi generate) | No — gitignored |
.git/hooks/codi-*.mjs | codi (regenerated by codi generate) | No — .git/ is gitignored by git itself |
.pre-commit-config.yaml | codi when the user opts into the pre-commit framework | Yes — you can edit Codi-managed entries; user-pinned rev: values are preserved |
Codi detects the project’s existing hook runner in priority order: husky → pre-commit framework → lefthook → standalone (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 underdocs/,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/*.mdfile that doesn’t matchYYYYMMDD_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.pyto 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,.mdfiles in brand-skill directories.
codi-artifact-validate.mjs
- Purpose: run
codi validate --ciagainst 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.
| Tool | Files matched | What it does |
|---|---|---|
gitleaks protect --staged | all | Blocks 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) | *.py | Lint + format Python; blocks if ruff missing |
Bandit (-lll) | *.py | Security check; blocks if bandit missing |
ShellCheck (-S warning) | *.sh | Shell-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 --amendif 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:
- Don’t bypass the hook.
- Open a separate “WIP” branch, push it without the bypass.
- Skip the hook locally only via
HUSKY=0 git commit ...if the project allows it (codi-cli does not). - 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.
| Command | Trigger label |
|---|---|
codi init (first run) | init-first-time |
codi init --customize | init-customize |
codi update | update |
codi clean (without --all) | clean-reset |
codi preset install | preset-install |
| Add from external source wizard | init-customize |
codi revert | pre-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.