Skip to main content

Fettle

Quality governance inside AI coding sessions

The only quality system that catches issues while the AI agent still has context to fix them.

PyPI CI Python 3.11+ MIT license 2100+ tests

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:

  1. The agent just made the edit (< 1 second ago)
  2. The agent still knows the implementation intent
  3. The agent can repair immediately in the same turn

Traditional approach:

  1. Agent commits broken code
  2. Hours later, CI fails
  3. Developer context-switches to investigate
  4. 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 result
  • violation — findings detected
  • tool_error — analysis tool missing/timed out
  • unknown — 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:

  1. Built-in defaults
  2. Organization pack
  3. Team pack
  4. Digest-pinned central policy
  5. Repository .fettle.toml
  6. Directory overrides
  7. Environment variables
  8. 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:

  1. Policy capsule travels with the child (digest-checked)
  2. Child receives the full policy context
  3. Child can tighten but never loosen policy
  4. 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

finefettle-1.8.0.tar.gz (533.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

finefettle-1.8.0-py3-none-any.whl (372.2 kB view details)

Uploaded Python 3

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

Hashes for finefettle-1.8.0.tar.gz
Algorithm Hash digest
SHA256 70ea0a783d18267078d8c22c2b757e67fded611abd1bbeacaa142c4128e70c56
MD5 c426423dfc8239b901034ba7aa26a718
BLAKE2b-256 f8e84e64ecbb759322d958bedff3e3db04f8c46d3ce413fc58512096a69d9fc4

See more details on using hashes here.

Provenance

The following attestation bundles were made for finefettle-1.8.0.tar.gz:

Publisher: release.yml on MilindGaharwar/fettle

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for finefettle-1.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6279bd45d6466f96d2dbd721f97a3821f0963922ac9e768ef16cd2c3ef17aea2
MD5 59bef736a5c17c3db8c68a745750fb07
BLAKE2b-256 97c80b121e990f8a3be32d95fb940733cf5672648821011f8672423b199d6fab

See more details on using hashes here.

Provenance

The following attestation bundles were made for finefettle-1.8.0-py3-none-any.whl:

Publisher: release.yml on MilindGaharwar/fettle

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page