Quality governance inside AI coding sessions
The only quality system that catches issues while the AI agent still has context to fix them.
Installation · Why · Unique Features · Capabilities · Docs
fettle (v.) — a foundry term for trimming and cleaning a rough casting.
AI agents can produce dozens of edits before commit hooks, CI, or PR reviewers see the results. By then, the agent has moved on, lost context, and the feedback loop takes hours or days.
Fettle changes this. It hooks directly into your AI coding agent's tool lifecycle (Claude Code, Codex, Gemini CLI, OpenCode) and runs quality checks in-session — while the agent still knows what it was trying to do.
agent edits code ──▶ Fettle checks immediately ──▶ agent repairs in same session
│ instead of next commit/PR
└── < 1 second └── hours/days later
Installation
For Agent Session Governance
Recommended: Clone and run from the repository (agent hooks require integration assets not in the wheel):
git clone https://github.com/MilindGaharWar/fettle ~/projects/fettle
cd ~/projects/fettle
python3 fettle/cli.py init --install-tools
fettle doctor
This gives you:
- Live agent hooks that check code as your AI assistant writes it
- Workflow commands accessible from your agent (
/fettle:quality,/fettle:review, etc.) - Immediate feedback in the session where context exists
For CI/CLI Automation
Install the wheel for deterministic batch operations:
pipx install finefettle
fettle check --changed
fettle verify
⚙️ pipx installation notes
The PyPI package is named finefettle (the fettle name is taken). The installed command is still fettle.
Important: When using pipx to install from a local clone, use:
pipx install --force /path/to/fettle # Non-editable install
Editable installs (pipx install -e .) bypass the build step that bundles workflow commands, causing "no commands found" errors. Install from PyPI or use --force for non-editable installs.
Why Fettle Exists
The Problem
Most quality tools operate at repository boundaries:
| Check happens | When | Cost of fix |
|---|---|---|
| Editor/linter | While you type | Seconds |
| Commit hooks | After you finish | Minutes |
| CI/PR | After push | Hours to days |
| Fettle | During generation | Seconds |
AI agents amplify this problem. They can make 20 edits in seconds, but commit hooks, CI, and reviews still happen later. When a bug surfaces in CI, the agent has lost the context of why it wrote that code.
The Solution
Fettle integrates directly with AI coding agent platforms:
- Hooks into tool events (Write, Edit, Bash) across Claude Code, Codex, Gemini, OpenCode
- Runs configured checks (lint, security patterns, process gates) before/after each tool call
- Returns findings in-session so the agent can immediately repair
- Preserves evidence in structured traces for audits and learning
Result: A broken pattern caught in-session costs one tool invocation to fix. The same issue in CI costs a context switch, investigation, and rework.
What Makes Fettle Unique
1. One Policy, Five Surfaces
A single .fettle.toml governs all your development surfaces:
- Claude Code — hooks into tool lifecycle
- Codex CLI — PreToolUse/PostToolUse integration
- Gemini CLI — event stream integration
- OpenCode — native plugin transport
- VS Code — Python LSP diagnostics with same rules
Write the rule once, enforce it everywhere your team works.
2. Findings Arrive In-Session
When Fettle catches an issue:
- The agent just made the edit (< 1 second ago)
- The agent still knows the implementation intent
- The agent can repair immediately in the same turn
Traditional approach:
- Agent commits broken code
- Hours later, CI fails
- Developer context-switches to investigate
- Agent re-learns the context to fix it
Fettle cuts the loop from hours to seconds.
3. Zero-Dependency Runtime
The entire engine is pure Python standard library:
- No transitive supply chain to audit
- Fast hook startup (< 50ms)
- No version conflicts with your project's dependencies
- Explicit tools (Ruff, Semgrep, golangci-lint) are optional and user-controlled
4. Workspace-Aware Polyglot Support
Fettle understands modern polyglot repositories:
- Discovers nested workspaces from native markers (
pyproject.toml,go.mod,Cargo.toml,package.json) - Routes edits to the right workspace using longest-prefix matching
- Runs native tools per language:
- Python: Ruff + Semgrep
- JavaScript/TypeScript: ESLint/Biome + Semgrep
- Go: golangci-lint + Semgrep
- Rust: Clippy
- Tracks verification across all affected workspaces
5. Four-State Result Model
Every check returns one of four explicit states:
pass— clean resultviolation— findings detectedtool_error— analysis tool missing/timed outunknown— check not applicable
Missing tools cannot appear clean. A degraded analysis is reported as degraded, not as a pass.
6. Evidence-Based Learning
incident/failure ──▶ fettle learn ──▶ quarantined proposal
│
human review ◀──────┘
│
▼
promoted learned rule ──▶ catches future occurrences
- Rules are drafted from real incidents (not hypothetical patterns)
- Proposals stay quarantined until human promotion
- Every promoted rule carries its origin evidence
- False positives feed back into the learning loop
7. Policy With Provenance
Eight configuration layers resolve deterministically:
- Built-in defaults
- Organization pack
- Team pack
- Digest-pinned central policy
- Repository
.fettle.toml - Directory overrides
- Environment variables
- Delegation capsules
Every value has a source: fettle config --explain shows exactly which layer set each option.
8. Delegation Without Policy Loss
When an orchestrator spawns child agents:
- Policy capsule travels with the child (digest-checked)
- Child receives the full policy context
- Child can tighten but never loosen policy
- Completion report returns to orchestrator
Governance survives delegation without requiring centralized orchestration.
9. Verifiable Claims
- 2,100+ collected tests covering adapters, gates, and integrations
- SLSA build provenance on every release
- CycloneDX SBOM for supply-chain transparency
- PyPI Trusted Publishing (no long-lived credentials)
- No dependencies in the runtime = minimal attack surface
The same evidence discipline Fettle asks of your sessions, it applies to itself.
Capabilities
In-Session Checks
| Category | Examples |
|---|---|
| Code quality | Post-edit lint routed to Python/JS/TS/Go/Rust workspaces |
| Security | Semgrep antipattern rules (SQL injection, unsafe deserialization, credential exposure) |
| Shell safety | Guards on destructive commands (rm -rf /, DROP DATABASE) |
| Process gates | Plan tracking, TDD ordering, complexity budgets, coverage gates |
| Verification | Impacted test discovery, affected-workspace test runs |
All checks:
- Support per-call budgets (timeout = degraded, not failure)
- Return canonical four-state results (no hidden errors)
- Default to advisory mode (non-blocking)
Post-Edit Polyglot Lint
Python:
# After agent edits a .py file:
ruff check --output-format=json # Fast lint
semgrep --config rules/python-antipatterns.yml # Security patterns
JavaScript/TypeScript:
biome check --reporter=json # Or ESLint
semgrep --config rules/ts-antipatterns.yml # Fetch timeout, SQL string templates
Go:
golangci-lint run --out-format=line-number
semgrep --config rules/go-antipatterns.yml # HTTP client timeout, SQL concat
Rust:
cargo clippy --message-format=short
Workspace-Aware Verification
fettle verify # Smart: changed files → impacted tests
fettle verify --full # Full suite across all affected workspaces
- Discovers workspaces from native markers (no manual configuration)
- Maps changed files to tests (Python: name-based; other languages: full suite fallback)
- Records per-workspace results with command, exit code, duration
- Handles deleted files — still mapped to their former workspaces
Guided Workflows
17 agent-invocable workflows bundled with Fettle:
fettle workflows install # Install to all detected agents
fettle workflows list # Show invocation syntax
| Category | Workflows |
|---|---|
| Quality | /fettle:quality, /fettle:pr-review, /fettle:review |
| Security | /fettle:security-review, /fettle:threat-model, /fettle:ops-review |
| Planning | /fettle:plan-activate, /fettle:plan-complete, /fettle:worklog |
| Learning | /fettle:learn, /fettle:mcp-approve, /fettle:mcp-revoke |
| Operations | /fettle:preflight, /fettle:explain, /fettle:report, /fettle:baseline, /fettle:lean-debt |
Cross-platform invocation:
- Claude Code, Gemini CLI:
/fettle:<name> - VS Code, OpenCode:
/fettle-<name> - Codex CLI:
/prompts:fettle-<name>
Session Reliability
For orchestrators and structured audit trails:
fettle plan start --title "Add export feature" --item "Write contract test"
fettle plan check "Write contract test"
fettle verify
fettle brief # Structured session summary
fettle report --days 7 --lineage
Delegation and Worktrees
fettle topology advise # Analyze codebase structure
fettle topology apply # Configure worktree setup
fettle spawn claude --task "Implement the approved item"
fettle brief --json # Child returns structured state
Policy capsules preserve governance across delegation boundaries (digest-checked, capsule can only tighten policy).
Daily Commands
fettle # Status dashboard
fettle check --changed # Lint changed Python files (CLI mode)
fettle verify # Run impacted tests across workspaces
fettle config --validate # Check .fettle.toml
fettle doctor --fix # Verify environment
fettle explain # Recent gate decisions with evidence
fettle report --days 7 # Session history
fettle ratchet show # Quality trend data
All subcommands support --help:
fettle --help
fettle verify --help
Configuration
.fettle.toml in your repository root:
[gates.lint]
enabled = true
mode = "advisory" # advisory | soft | enforce
[gates.plan]
enabled = false # Require active plans in session
threshold = 3
[gates.tdd]
enabled = false # Warn on impl-before-test
mode = "advisory"
[gates.verification]
enabled = true
mode = "advisory"
scope = "impacted" # impacted | full
Advisory by default — promote individual gates after measuring signal/noise in your workflow.
Policy resolves through layered sources with full provenance:
fettle config --explain
See docs/CONFIG.md for all options, precedence rules, environment variables, and policy layering.
Enterprise & Governance
For teams and organizations:
- Central policy distribution via digest-pinned
[extends] - Append-only JSONL traces for audit/compliance
- Organization/lineage reports with structured output
- SARIF + JUnit for existing CI dashboards
- Opt-in aggregate telemetry controlled by central policy
- JSON Schema validation for
.fettle.toml
Note: Each surface (CLI, hooks, CI, editor) supports different check subsets. Validate the exact surface you plan to enforce.
Operational Boundaries
| Boundary | Details |
|---|---|
| Python version | 3.11+ required |
| Agent integrations | Require repository checkout (hooks, transports not in wheel) |
| Language support | Python lint richest; JS/TS/Go/Rust depend on external tools |
| VS Code/LSP | Current path analyzes Python only |
| External tools | Ruff, Semgrep, golangci-lint, clippy, test runners are optional/user-installed |
| Default mode | Advisory (non-blocking) for opinionated gates |
| Error handling | Hooks favor continuity; tool failures reported as degraded, not clean |
| CI role | Independent fail-closed boundary; Fettle is earlier control point |
Evidence
- Test coverage: 2,100+ collected tests
- Build provenance: SLSA on every release
- Supply chain: CycloneDX SBOM
- Publishing: PyPI Trusted Publishing (no long-lived credentials)
- Dependencies: Zero in runtime (Python stdlib only)
Documentation
| Need | Resource |
|---|---|
| Next steps | Documentation index |
| Configuration reference | docs/CONFIG.md |
| OpenCode setup | docs/OPENCODE.md |
| Behavioral evaluations | evals/README.md |
| Roadmap | docs/ROADMAP.md |
| Changelog | CHANGELOG.md |
| Contributing | CONTRIBUTING.md |
| Security | SECURITY.md |
Contributing
See CONTRIBUTING.md for development setup, change verification, and pull request expectations.
Security vulnerabilities: Report via SECURITY.md, not public issues.
License
MIT © Milind
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file finefettle-1.8.0.tar.gz.
File metadata
- Download URL: finefettle-1.8.0.tar.gz
- Upload date:
- Size: 533.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
70ea0a783d18267078d8c22c2b757e67fded611abd1bbeacaa142c4128e70c56
|
|
| MD5 |
c426423dfc8239b901034ba7aa26a718
|
|
| BLAKE2b-256 |
f8e84e64ecbb759322d958bedff3e3db04f8c46d3ce413fc58512096a69d9fc4
|
Provenance
The following attestation bundles were made for finefettle-1.8.0.tar.gz:
Publisher:
release.yml on MilindGaharwar/fettle
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
finefettle-1.8.0.tar.gz -
Subject digest:
70ea0a783d18267078d8c22c2b757e67fded611abd1bbeacaa142c4128e70c56 - Sigstore transparency entry: 2358108491
- Sigstore integration time:
-
Permalink:
MilindGaharwar/fettle@71f4c3623cc06bb98d48c3aaee6c22f2d5321556 -
Branch / Tag:
refs/tags/v1.8.0 - Owner: https://github.com/MilindGaharwar
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@71f4c3623cc06bb98d48c3aaee6c22f2d5321556 -
Trigger Event:
push
-
Statement type:
File details
Details for the file finefettle-1.8.0-py3-none-any.whl.
File metadata
- Download URL: finefettle-1.8.0-py3-none-any.whl
- Upload date:
- Size: 372.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6279bd45d6466f96d2dbd721f97a3821f0963922ac9e768ef16cd2c3ef17aea2
|
|
| MD5 |
59bef736a5c17c3db8c68a745750fb07
|
|
| BLAKE2b-256 |
97c80b121e990f8a3be32d95fb940733cf5672648821011f8672423b199d6fab
|
Provenance
The following attestation bundles were made for finefettle-1.8.0-py3-none-any.whl:
Publisher:
release.yml on MilindGaharwar/fettle
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
finefettle-1.8.0-py3-none-any.whl -
Subject digest:
6279bd45d6466f96d2dbd721f97a3821f0963922ac9e768ef16cd2c3ef17aea2 - Sigstore transparency entry: 2358108586
- Sigstore integration time:
-
Permalink:
MilindGaharwar/fettle@71f4c3623cc06bb98d48c3aaee6c22f2d5321556 -
Branch / Tag:
refs/tags/v1.8.0 - Owner: https://github.com/MilindGaharwar
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@71f4c3623cc06bb98d48c3aaee6c22f2d5321556 -
Trigger Event:
push
-
Statement type: