In-session quality governance for Claude Code, Codex CLI, Gemini CLI, and OpenCode
Project description
Quality governance inside AI coding sessions
Catch risky code and broken engineering process while the agent still has the context to fix them.
Quick start · Why Fettle · Capabilities · Multi-agent · Docs
fettle (v.) — a foundry term for trimming and cleaning a rough casting.
AI coding agents can produce dozens of edits before commit hooks, CI, or a pull request reviewer sees the result. Fettle connects to the agent's tool lifecycle, normalizes events from Claude Code, Codex CLI, Gemini CLI, and OpenCode, and runs configured checks before, after, and at the end of a session.
agent edits ──▶ Fettle checks ──▶ finding returns in-session ──▶ agent repairs
Status: v1.7.0 "Workflows Everywhere"
Quick Start
Agent integrations currently run from a Git checkout:
git clone https://github.com/MilindGaharwar/fettle ~/projects/fettle
cd ~/projects/fettle
python3 fettle/cli.py init --install-tools
fettle doctor
fettle init detects installed agents, creates project configuration, and wires
supported integrations without replacing unrelated settings. Preview changes
with --dry-run, or generate a fitted configuration explicitly:
fettle init --interactive
fettle init --profile solo # also: team, enterprise
For the standalone CLI only:
pipx install finefettle
fettle check --changed
The PyPI package is named finefettle because the fettle package name is
unrelated. The installed command remains fettle.
Why Fettle
Most quality tools act at a repository boundary. Fettle adds an earlier control point: the session where code is being generated.
| Control point | Typical feedback time | Fettle's role |
|---|---|---|
| Editor or linter | While a human edits | Invoke analysis from agent events too |
| Commit hook | At commit | Catch selected issues before they accumulate |
| CI / PR review | After push | Keep CI as independent evidence, not first feedback |
| Agent session | During generation | Enforce code and process policy with current context |
Fettle is not a replacement for tests, review, or CI. It connects those forms of evidence into the agent workflow and records what happened.
What Makes Fettle Different
- One policy, five surfaces. A single
.fettle.tomlgoverns Claude Code, Codex CLI, Gemini CLI, OpenCode, and VS Code diagnostics through one event model and one dispatcher — write the rule once, enforce it everywhere your agents work. - Zero-dependency runtime. The entire engine is Python standard library. Nothing to vendor-audit, no transitive supply chain, hooks start fast.
- Findings arrive while the agent can still act. Feedback lands in the same session that produced the code, when repair costs one tool call instead of a review round-trip.
- Policy with provenance. Eight configuration layers (defaults, org,
team, digest-pinned central, repository, directory, environment, capsule)
resolve deterministically, and
fettle config --explainshows exactly which layer set every value. - Rules that learn — under human control.
fettle learndrafts detection rules from real incidents; proposals stay quarantined until a human promotes them, and every promoted rule carries its evidence. - Delegation without policy loss. Policy capsules travel with spawned sub-agents and are digest-checked on arrival; children can tighten policy but never loosen it.
- Claims you can check. 2,000+ tests, SLSA build provenance, a CycloneDX SBOM, and PyPI Trusted Publishing on every release — the same evidence discipline Fettle asks of your sessions.
Capabilities
In-session checks
- Runs
ruffand optionalsemgrepafter Python edits. - Guards destructive shell commands and protected configuration before use.
- Supports opt-in gates for plans, TDD ordering, complexity, coverage, BDD links, verification stamps, remote CI, claims, worklogs, and session reports.
- Uses per-check budgets and records tool/config failures instead of presenting them as clean analysis.
- Returns advisories by default; blocking behavior is enabled per gate.
One event model for four agents
Claude Code, Codex CLI, Gemini CLI, and native OpenCode events pass through agent-specific translators into one dispatcher. This lets a repository express policy once while using different agent clients. Integration transport and installation still differ by client; see the documentation index.
Evidence loop
incident or repeated failure
│
▼
quarantined rule proposal ── human review ──▶ promoted learned rule
▲ │
└──────── fire / false-positive evidence ────────┘
fettle learndrafts Semgrep proposals from incidents or trace signatures.- Proposed rules remain outside active rule directories until a human runs
fettle rules promote. fettle ratchetuses recorded evidence to support advisory/enforce changes.- Suppressions can carry an owner, reason, and expiry.
Session reliability
fettle plan start --title "Add export" --item "Write contract test"
fettle plan check "Write contract test"
fettle verify
fettle brief
Session plans, worklogs, verification stamps, CI verdicts, and completion reports give an orchestrator structured state instead of requiring transcript reconstruction. These gates are opt-in unless selected by a setup profile.
Multi-Agent Work
Fettle can govern delegated work through isolated worktrees, claims, topology advice, and policy capsules:
orchestrator ── fettle spawn ──▶ child in worktree
│ │
├── policy capsule ├── claim + plan + checks
└── topology manifest ◀────────└── completion report
fettle topology advise
fettle topology apply
fettle topology status
fettle spawn claude --task "Implement the approved work item"
fettle brief --json
fettle report --lineage
Capsules are intended to preserve effective policy across delegation and are digest-checked by the child session. Treat this as an additional application control, not a sandbox or substitute for operating-system isolation. Review the current security notes and enable strict gates only after validating them in your environment.
Enterprise Controls
- Digest-pinned central policy through
[extends], synchronized outside hooks. - Append-only JSONL decision traces and org/lineage/compliance reports.
- SARIF and JUnit output for existing CI dashboards.
- Opt-in aggregate telemetry controlled by central policy.
- JSON Schema validation for
.fettle.toml. - SLSA provenance and CycloneDX SBOM in the release workflow.
Repository policy, hook policy, CLI scans, CI, and editor diagnostics share configuration, but each surface supports a different subset of checks. Validate the exact surface you plan to enforce; do not assume perfect output parity.
Daily Commands
fettle # local status dashboard
fettle check --changed # changed Python files
fettle config --validate
fettle doctor --fix
fettle explain # explain recent gate decisions
fettle verify [--full]
fettle ci status
fettle report --days 7
Discover all commands with fettle --help and command-specific options with
fettle <command> --help.
Guided Agent Workflows
Fettle bundles 17 user-invocable guided workflows. These are agent workflows rather than CLI subcommands: they combine Fettle checks with structured review, explanation, and artifact creation. They work in every supported agent environment — install them with:
fettle workflows install # all detected agents (also runs during fettle init)
fettle workflows list # names + per-host invocation
| Workflow | Commands (Claude Code / Gemini naming) |
|---|---|
| Quality and review | /fettle:quality, /fettle:pr-review, /fettle:review, /fettle:explain, /fettle:report |
| Security and operations | /fettle:security-review, /fettle:threat-model, /fettle:preflight, /fettle:ops-review |
| Planning and evidence | /fettle:plan-activate, /fettle:plan-complete, /fettle:worklog, /fettle:baseline |
| Policy and learning | /fettle:learn, /fettle:mcp-approve, /fettle:mcp-revoke, /fettle:lean-debt |
Per-host invocation: Claude Code and Gemini CLI use /fettle:<name>; VS Code
and OpenCode use /fettle-<name>; Codex CLI uses /prompts:fettle-<name>.
Use these when you want the agent to interpret results or guide a review. Use
the fettle CLI for deterministic automation and CI. The canonical sources in
commands/ are bundled into the PyPI wheel, so fettle workflows install
works from any install mode.
Configuration
Fettle reads .fettle.toml from the project root. Start advisory and promote
individual gates after measuring noise:
[gates.lint]
enabled = true
mode = "advisory" # advisory | soft | enforce
[gates.plan]
enabled = false
threshold = 3
session_plans = true
[gates.tdd]
enabled = false
mode = "advisory"
[gates.session_report]
enabled = false
Policy resolves through layered sources — built-in defaults, org and team
packs, digest-pinned central policy, the repository file, per-directory
overrides, environment variables, and delegation capsules — with full
provenance via fettle config --explain. See the
configuration reference for defaults, supported modes,
precedence, environment variables, and state locations.
Operational Boundaries
- Python 3.11 or newer is required.
- Agent integrations and the OpenCode transport require a repository checkout; the wheel contains the CLI and Python package, not every integration asset.
- Hook-time lint is richest for Python. Other language adapters depend on their external tools and configured surface.
- The current LSP/VS Code diagnostic path analyzes Python files only.
- Ruff, Semgrep, test runners, agent CLIs, and GitHub tooling are external and optional unless the enabled workflow requires them.
- Opinionated and potentially blocking gates mostly default off or advisory.
- Hooks favor continuity and visible degradation for environment/tool errors; use CI for an independent fail-closed boundary.
Documentation
| Need | Guide |
|---|---|
| Choose the next setup step | Documentation index |
| Configure gates and policy | Configuration |
| Install OpenCode integration | OpenCode |
| Run behavioral evaluations | Evals |
| Track future direction | Roadmap |
| Review release history | Changelog |
Contributing and Testing
Match verification effort to the changed surface. Documentation-only changes do not require the full test suite unless they alter a tested contract such as version metadata or executable examples.
# Documentation or metadata only
git diff --check
fettle config --validate
# Behavior-changing Python code
python -m pytest tests -q
fettle check --changed
Fettle dogfoods its own hooks and CI controls. Rules include positive and clean fixtures; behavioral evals separately test whether feedback changes agent behavior.
License
MIT (c) Milind
Project details
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.7.0.tar.gz.
File metadata
- Download URL: finefettle-1.7.0.tar.gz
- Upload date:
- Size: 517.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
470a72bdf0d40a98bc8c379b85606a2313d177b6ee25bea85baee77e28036c94
|
|
| MD5 |
52cc61530c8f4ea51d0e2668ff6e2b9f
|
|
| BLAKE2b-256 |
b379265ab865b13caf68693b9ed6dee94b20f7eb21f590274218ba1322d3e230
|
Provenance
The following attestation bundles were made for finefettle-1.7.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.7.0.tar.gz -
Subject digest:
470a72bdf0d40a98bc8c379b85606a2313d177b6ee25bea85baee77e28036c94 - Sigstore transparency entry: 2339200521
- Sigstore integration time:
-
Permalink:
MilindGaharwar/fettle@c7acb0f2f7ee0c1f61ba58fe7b456f962545e0ce -
Branch / Tag:
refs/tags/v1.7.0 - Owner: https://github.com/MilindGaharwar
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c7acb0f2f7ee0c1f61ba58fe7b456f962545e0ce -
Trigger Event:
push
-
Statement type:
File details
Details for the file finefettle-1.7.0-py3-none-any.whl.
File metadata
- Download URL: finefettle-1.7.0-py3-none-any.whl
- Upload date:
- Size: 365.4 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 |
4b9c77720e628d3da09ebff5fbbda7a44718ef17a4685db21277562799a7d5ab
|
|
| MD5 |
77eda727c18988d9a4dc6589311d5f33
|
|
| BLAKE2b-256 |
8f03516f2e9ec417d990afb1fce4a5e20a2a1dbf3a57b316a3968fd60e22b684
|
Provenance
The following attestation bundles were made for finefettle-1.7.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.7.0-py3-none-any.whl -
Subject digest:
4b9c77720e628d3da09ebff5fbbda7a44718ef17a4685db21277562799a7d5ab - Sigstore transparency entry: 2339200524
- Sigstore integration time:
-
Permalink:
MilindGaharwar/fettle@c7acb0f2f7ee0c1f61ba58fe7b456f962545e0ce -
Branch / Tag:
refs/tags/v1.7.0 - Owner: https://github.com/MilindGaharwar
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c7acb0f2f7ee0c1f61ba58fe7b456f962545e0ce -
Trigger Event:
push
-
Statement type: