Forge – Code-Quality Guardrails for AI Agents
Forge is a pip-installable Python package providing deterministic CLI tools to enforce code quality standards in repositories. It works independently with pre-commit hooks and optionally integrates with Claude Code for AI agents, preventing quality drift in AI-generated code.
Notifications You must be signed in to change notification settings
Fork 1
Star 1
BranchesTags
Open more actions menu
Folders and files
NameName
Last commit message
Last commit date
Latest commit
History
12 Commits
12 Commits
.badges
.badges
.claude-plugin
.claude-plugin
.claude
.claude
.githooks
.githooks
.github/workflows
.github/workflows
agents
agents
claude-hooks
claude-hooks
dev
dev
docs
docs
skills
skills
src/forge
src/forge
tests
tests
.conda_env_name.example
.conda_env_name.example
.gitignore
.gitignore
CHANGELOG.md
CHANGELOG.md
CLAUDE.md
CLAUDE.md
CONTRIBUTING.md
CONTRIBUTING.md
FOUNDATION.md
FOUNDATION.md
LICENSE
LICENSE
README.md
README.md
REPO_STRUCTURE.md
REPO_STRUCTURE.md
cli_wiring_exempt.toml
cli_wiring_exempt.toml
pyproject.toml
pyproject.toml
pyrefly.toml
pyrefly.toml
ruff.toml
ruff.toml
Repository files navigation
AI agents write more code, faster — but without guardrails, quality drifts: lint rules silently disabled, docstrings half-written, standards left as prose nobody runs. Good output needs hard guardrails, not good intentions.
Forge ships those guardrails as deterministic tools that run the same way whether a human or an agent invokes them:
A pip-installable Python package (forge-scripts) with CLIs that codify a repo's quality standards (lint, docstrings, test naming, GitHub labels, env diagnostics).
A drop-in pre-commit hook that runs those CLIs in order on every commit, with no per-repo wiring.
An optional Claude Code plugin (agents, skills, hooks) that wires the same CLIs into an agent session — an add-on, not a prerequisite.
Everything mechanical is a plain CLI or shell hook. The Claude Code plugin is a thin orchestrator on top — the gate is the CLI, never the model.
At a glance: adopting forge
Adopting forge is three steps, roughly 1 minute of work. Step 3 is optional. The numbered Quickstart below has the full detail; docs/adopting.md breaks it into three independent install tracks (CLIs only / + git hooks / + plugin) so you can take exactly the layer(s) you want.
Install forge-scripts — pip install "git+https://github.com/misnaej/forge.git@main" puts every forge CLI on PATH. (~30s)
Run install-forge-bootstrap — one-shot umbrella: wires git hooks, scaffolds FOUNDATION.md / CLAUDE.md, installs the canonical GitHub label schema, generates docs/api-digest.md + docs/cli-reference.md + code_health/audit_deps_tree.log, and runs forge-doctor. Idempotent — safe to re-run after every forge upgrade. (~30s)
(Optional) Install the Claude Code plugin — only if your team uses Claude Code. (~30s)
Steps 1–2 are Claude-independent. After step 2, forge-doctor reports the install status automatically.
Why this exists
Most teams accumulate the same scaffolding in every repo — a ruff config, a pre-commit hook, a gh label setup script, a doctor command — and it drifts. Repo A runs strict ruff while repo B silently disabled three rules. Contributors set up their env differently in each repo. Standards live as stale prose nobody runs against.
Forge collapses that scaffolding into one pip-installable package and one drop-in pre-commit hook. Adopt forge and you get:
A canonical ruff configuration philosophy (select = ["ALL"] strict, per-file ignores only).
A verify-forge-docstrings checker that validates Google-style Args/Returns against actual function signatures.
A consistent set of GitHub labels installed by one command (install-forge-labels).
A forge-doctor CLI that tells a contributor exactly what's wrong with their local install.
A pre-commit hook running all of the above on every commit. New checks are added in forge and propagate to every consumer on the next version bump. (Pytest is deliberately NOT in the default sequence — too slow for pre-commit; run it in CI or wire it into .githooks/pre-commit yourself.)
Need something forge doesn't ship (custom mypy step, secret scan)? See docs/customizing-precommit.md — edit .githooks/pre-commit directly. No plugin system, no config file.
What you get today
Category Items
CLIs (pip package, no Claude required) install-forge-bootstrap (one-shot umbrella), forge-upgrade (two-phase upgrade flow), forge-precommit (full sequence dispatcher), fix-forge-ruff (ruff phase), verify-forge-docstrings, verify-forge-docstring-coverage, verify-forge-repo-structure, verify-forge-test-naming, verify-forge-manifest, verify-forge-plugin-version, verify-forge-cli-wiring, forge-continuation-append, forge-next-prep, forge-config (config reference + setup advisor — see docs/configuration.md), install-forge-labels, forge-doctor, install-forge-githooks, install-forge-claude-md
Audit-pack CLIs (pip package, optional [audit] extras) forge-audit-dup, forge-audit-deps, forge-audit-suppressions, forge-audit-orphans, forge-audit-data, forge-audit-claims, forge-audit-agents (non-blocking template-conformance audit), forge-audit-all — see docs/audit-pack.md
Git hooks (drop-in, no Claude required) .githooks/pre-commit (dispatcher), .githooks/post-merge + .githooks/post-checkout (auto-warn on FOUNDATION.md drift)
Process docs docs/security.md, docs/audit-pack.md, docs/cli-reference.md (generated CLI reference), docs/api-digest.md (generated index of all top-level functions/classes, public API + internal helpers); foundation engineering principles at FOUNDATION.md
Claude Code plugin (optional) Agents (pr-manager, precommit-fixer, git-commit-push, design-checker, docs-types-checker, security-checker, issue-triage, perf-optimizer, weekly-summary, knowledge-search, test-advisor, test-writer); skills (commit, pr, next, triage, weekly, fix, review, test); Claude Code hooks (block_protected_branches, block_force_push, block_pr_merge, block_branch_deletion, block_no_verify, block_install_deps, block_claude_attribution, block_continuation_delete, block_protected_files, check_commit_format, check_foundation_sync, warn_pr_checks, block_raw_ruff, block_raw_git)
Everything in the first three rows is Claude-independent — works from any shell, CI, or IDE.
The audit-pack CLIs are gated behind extras: pip install forge-scripts[audit] pulls in vulture, jsonschema, and PyYAML; [audit-tach] adds tach for dependency-graph checks. See docs/audit-pack.md for what each audit detects and how findings land in code_health/audit_*.log.
Quickstart: adopt forge in your repo
The full tutorial for the three steps in At a glance.
- Install forge-scripts
Forge is a public repo, so no auth setup is needed. Install directly from GitHub:
pip install --upgrade "git+https://github.com/misnaej/forge.git@main"
Pin to a specific version or channel:
Pin Cadence
@main Slow channel — minor versions only
@dev Fast channel — every patch
@v1.3.0 Frozen at a specific tag
For a project's pyproject.toml:
[project.optional-dependencies] dev = [ "forge-scripts @ git+https://github.com/misnaej/forge.git@main",
... your other dev deps
]
Then install editably:
pip install -e ".[dev]"
The forge CLIs are now on your PATH:
forge-precommit --help forge-doctor
- Run install-forge-bootstrap (recommended)
install-forge-bootstrap
One-shot umbrella that runs every installer + generator in dependency order. Idempotent — re-run safely after every forge upgrade.
Source of truth: the STEPS tuple in src/forge/install_bootstrap.py. The table below is rendered documentation; update the tuple, not this table, when adding or reordering steps.
Step CLI What lands on disk
1 install-forge-githooks .githooks/pre-commit, .githooks/post-merge, .githooks/post-checkout + core.hooksPath
2 install-forge-claude-md FOUNDATION.md + scaffolded CLAUDE.md (if absent) + .claude/
3 install-forge-labels Canonical GitHub label schema (skipped when gh missing or no remote)
4 forge-gen-api-digest docs/api-digest.md (index of top-level functions / classes)
5 forge-gen-cli-reference docs/cli-reference.md (generated from each CLI's --help)
6 forge-audit-deps --tree code_health/audit_deps_tree.log (dependency tree)
7 forge-doctor Verifies the install
8 forge-config Post-install nudge: what [tool.forge.*] config forge reads + what to set (docs/configuration.md)
Flags: --check (dry-run), --skip (repeatable; slugs are githooks, claude-md, labels, api-digest, cli-reference, audit-deps, doctor, config), --strict (abort on first failure; default is continue-on-fail).
Want to run an installer on its own? Each step is also a standalone CLI — see docs/standalone-installers.md.
Self-updating hooks (wrapper pattern). Each managed git hook is a one-line wrapper that calls a forge-shipped CLI:
#!/usr/bin/env bash
forge:githook-managed v2 body-sha=
set -euo pipefail
(staleness preamble — advisory warning when installed forge is newer)
forge-post-merge "$@"
forge-precommit, forge-post-merge, and forge-post-checkout carry the actual logic. The hook file is yours — you can add repo-specific steps after the forge CLI call:
#!/usr/bin/env bash
forge:githook-managed v2 body-sha=
set -euo pipefail forge-post-merge "$@" ./scripts/install-editable.sh # consumer step — survives forge upgrades
The marker embeds a SHA of the canonical body. On every git pull, the forge-post-merge CLI backgrounds an install-forge-githooks --refresh --quiet so consumers pick up new forge hook content automatically — but auto-refresh leaves modified wrappers alone (your repo-specific lines survive). Use install-forge-githooks --force to override and rewrite a modified wrapper; the previous content is saved as .githooks/.before-forge-vX.Y.Z.bak so nothing is lost.
Cleaner: drop-in extension directories. Rather than editing the managed wrapper at all, drop an executable script into .githooks/post-merge.d/ (or .githooks/post-checkout.d/). After its own work, forge-post-merge / forge-post-checkout runs every executable *.sh in that directory in sorted filename order (10-, 20-, … the cron.d convention). The subdirectory is one install-forge-githooks never writes, so your scripts survive every refresh with no body-sha bookkeeping:
.githooks/post-merge.d/10-refresh-deps.sh (yours — remember chmod +x)
#!/usr/bin/env bash ./scripts/install-editable.sh
A failing extension logs a warning and is skipped — it never breaks your git pull / git checkout. Extensions run only in interactive contexts (skipped in CI, same posture as the drift check). Each script needs a shebang and the executable bit; it runs with the repo root as its working directory and inherits your shell environment. Because a .d/ script is committed and runs automatically, review it with the same care as any executable hook — the directory is intentionally outside forge's refresh cycle, so forge never inspects or rewrites it.
git commit now runs the canonical pre-commit sequence:
Step What it does When it runs
ruff fix-forge-ruff — runs ruff format (in-place) + ruff check --fix --unsafe-fixes, re-stages modified tracked files via git add, writes code_health/ruff.log. PASSes iff ruff cleared every violation; residue (rules without autofix) lands in the log. Always (skipped if no src/ or tests/)
docstrings verify-forge-docstrings — validates Google-style Args/Returns against signatures Always (CLI picks files via staged + unstaged + branch diff vs main; reports cleanly when nothing matches)
docstring_coverage verify-forge-docstring-coverage — interrogate-based aggregate coverage %, per-file table, and a MISSING: symbol list for forge:precommit-fixer. When pyproject.toml + a src/ tree exist (self-skips otherwise). No [tool.interrogate] section required — forge defaults apply when it's absent. Non-blocking: reports only, never refuses the commit.
test_naming verify-forge-test-naming — validates test file / function naming conventions Always (CLI selects modified test files from the diff vs main). Warning-only: al
[truncated for AI cost control]