Agentic-native linting tool to enforce deterministic quality gates
> /plugin marketplace add ironlint/ironlint> /plugin install ironlint@ironlint-marketplace
FAQ
ironlint is a Claude Code plugin with 3 hand-picked skills for development work, indexed on Flowy. Install it with the command on its page. It includes ironlint-init, ironlint-review, ironlint. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
Repo: ironlint/ironlint
IronLint is a local policy gate for agentic coding harnesses. GitHub Actions runs your checks in the cloud after you push; IronLint runs the same kind of checks locally, on every edit your agent makes, before the code lands on disk, and it can refuse. A check is a file glob plus a shell command. IronLint hands that command your proposed content on stdin and reads one thing back: the exit code. Any nonzero exit (1โ125) blocks the write. No engines, no severities, no output parsing.
One YAML file at .ironlint.yml in your repo root. A map of checks; each names what to match, where it applies, and the command that decides.
# .ironlint.yml
checks:
no-console:
files: "**/*.ts"
run: "! grep -n 'console.log'" # proposed content arrives on stdin
lint-and-format:
files: "src/**/*.py"
run: "ruff check --quiet --stdin-filename \"$IRONLINT_FILE\" -"
New here? Start with Getting started.
Prebuilt binaries for macOS (Apple Silicon and Intel), Linux (x86-64), and Windows (x86-64). The installer downloads the right binary, drops it in ~/.cargo/bin, and puts it on your PATH โ no Rust toolchain required:
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/ironlint/ironlint/releases/latest/download/ironlint-cli-installer.sh | sh
Windows (PowerShell):
powershell -ExecutionPolicy Bypass -c "irm https://github.com/ironlint/ironlint/releases/latest/download/ironlint-cli-installer.ps1 | iex"
Or build from source (needs a Rust toolchain):
cargo install --git https://github.com/ironlint/ironlint ironlint-cli
Then run ironlint --version. Update any time with ironlint update (installer-based installs; source builds update with cargo install โฆ --force).
ironlint init takes you from clone to gated in one command. It scaffolds a starter .ironlint.yml, trusts that new config, detects your coding agents, and wires IronLint's edit hook into each โ so policy runs on every edit without you calling ironlint check by hand:
ironlint init
It detects Claude Code, Codex, pi, and OpenCode, asks before touching anything, and installs the hook. Target one explicitly, wire them all, or patch your user account instead of the project:
ironlint init --harness opencode # just one agent
ironlint init --harness all # every supported agent
ironlint init --global # wire user-level agent settings (the config remains project-local)
It also installs an ironlint-config authoring skill so the agent knows how to write checks; run ironlint schema to read the format yourself. ironlint doctor verifies the wiring (one row per agent); ironlint init --uninstall --harness <name> removes it.
Sharing checks across repos:
extends: ["../shared/ironlint-base.yml"]
checks:
# project-specific overrides + additions
Local checks override inherited checks of the same id. Full format: ironlint schema or Configuration.
steps:). IronLint reads one thing back โ the exit code. 0 passes, 1โ125 blocks, and your command's stdout/stderr becomes the block message. No engines, no severities, no output parsing.ruff, eslint, tsc, clippy, biome โ the same checks CI runs, wired in as-is. No per-tool integration to write.on: [write] fires per edit; on: [pre-commit] fires once over the selected matching file set. A single check can do both โ IronLint keys by check, not by event.ironlint trust blesses it; any change to the config or its check scripts revokes trust until you re-bless. check fails closed on untrusted input..ironlint/log.jsonl; the directory ignores itself. The optional standalone Claude Code plugin provides the /ironlint-review skill for reviewing noisy and dead checks; it is not a CLI command or part of the standard init integration.An LLM catches its own slop poorly, but fixes it well once something reliable points at the problem. IronLint is the deterministic half of that loop: a check runs on every edit and hands back a signal the model can't talk its way around โ a nonzero exit. The agent writes, the check judges, the agent fixes. Push every fixed-rule quality gate onto deterministic checks, and leave prompts and skills for the judgment calls that genuinely need them.
That ethos has a name and a longer argument โ Determinism-in-the-loop.
A check fires on write (default), pre-commit, or both.
| Event | Trigger | stdin | $IRONLINT_FILE | $IRONLINT_FILES |
|---|---|---|---|---|
write | Every agent edit | proposed content | the edited file | same, single entry |
pre-commit | Once for the selected matching file set | empty | not set | selected matching files, newline-joined |
Use on: [write, pre-commit] to fire at both โ no duplication. This is the inversion that separates IronLint from lefthook, whose earliest reach is pre-commit, after the agent already wrote the file.
Every check receives, on its environment:
$IRONLINT_FILE โ absolute path of the file under check (set for write; not set for pre-commit).$IRONLINT_FILES โ newline-joined list of all selected files (single entry for write; the matching file set for pre-commit).$IRONLINT_ROOT โ project root (the check's cwd).$IRONLINT_EVENT โ write or pre-commit.$IRONLINT_BIN โ absolute path to the ironlint binary, so a check can invoke it without PATH resolution.$IRONLINT_TMPFILE โ a materialized temp file holding the proposed content, set only when your run/steps reference it.$IRONLINT_PROPOSED_MANIFEST โ optional tab-separated manifest of sibling proposed files in the same atomic patch; absent unless an adapter supplies it.write) or empty (pre-commit).Read proposed content from stdin, not from $IRONLINT_FILE. On harnesses that gate before the write lands (codex, pi), the file on disk still holds the old content.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Agent Edit / Write (or git pre-commit) โ
โ โ โ
โ harness adapter hook โ
โ โ โ
โ ironlint check โ
โ โ โ
โ match touched file โ checks whose `files:` glob hits โ
โ โ โ
โ for each check: sh -c <run> โ
โ env: $IRONLINT_FILE $IRONLINT_ROOT $IRONLINT_EVENT โฆ โ
โ stdin: proposed post-edit content โ
โ โ โ
โ read only the exit code โ
โ 0 โ pass 1โ125 โ BLOCK the write โ
โ 126 / 127 / timeout / signal โ InternalError (never a โ
โ silent pass) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Each adapter collapses one harness's edit hook into the ABI above and runs ironlint check. The runner matches the touched file to checks, dispatches each (once per file on write, once per check on pre-commit), and folds the exit codes into a single verdict.
| Code | Meaning |
|---|---|
| 0 | Pass โ every matched check passed |
| 1 | Config or load error โ parse failure, missing file |
| 2 | Block โ at least one check exited nonzero (1โ125) |
| 3 | InternalError โ at least one check crashed (not found, timeout, killed by signal) |
| 4 | Untrusted config/checks โ run ironlint trust |
Adapters fail-open on exit 3 by default. Opt-in fail-closed: IRONLINT_FAIL_CLOSED_ON_INTERNAL=1. Exit 4 is different: adapters must surface it loudly, and pre-write adapters (every shipped adapter) treat it as fail-closed and block the tool call outright โ an untrusted config is never silently allowed through.
The codex adapter reads these same exit codes but doesn't block through its own exit code โ it translates them into a permissionDecision:"deny" JSON object on stdout, because that's how Codex's PreToolUse hook contract blocks a tool call. See adapters/codex/README.md.
Never run a check or write telemetry. Exit 0 on success, 1 on a config error โ never 2.
ironlint explain <file> # which checks are in scope for a file, and their run commands
ironlint show-resolved-config # the post-extends: merged check set, annotated by source
ironlint schema # the check-authoring guide
All honor --config <path> (default .ironlint.yml).
Add # ironlint-disable: <check-id> anywhere in a file to suppress that check for the whole file.
adapters/claude-code/. PreToolUse hook for edits, plus three skills. See docs/adapters/claude-code.md.adapters/opencode/. tool.execute.before gates proposed edits. See docs/adapters/opencode.md.adapters/codex/. PreToolUse hook for apply_patch, blocking via a permissionDecision JSON on stdout rather than an exit code; requires a one-time review+trust step inside Codex. See adapters/codex/README.md.adapters/pi/. tool_call hook gates proposed edits before they're written. See adapters/pi/README.md.At the pre-commit boundary, IronLint is a near line-for-line swap for lefthook's gate role:
# lefthook.yml # .ironlint.yml
pre-commit: checks:
commands: prettier:
prettier: files: '**/*.{ts,css,md}'
glob: "*.{ts,css,md}" on: [pre-commit]
run: prettier --check {staged_files} run: prettier --check $IRONLINT_FILES
Absorbed: the gate role. Declined: parallel, stage_fixed, and the fixer/restager half. Added: the write lifecycle โ lefthook's earliest reach is pre-commit, after the agent already wrote the file; IronLint fires on the write itself.
cargo build --release
./target/release/ironlint --version
Full docs live in docs/ โ start with Getting started or the Architecture page.
Issues and PRs welcome. Good places to start: a new adapter under adapters/, a check pack under tests/fixtures/, or docs under docs/. See AGENTS.md for build, test, and coverage conventions.
Apache 2.0. See LICENSE.
.agents/
skills/
adapter-drift-audit/
references/
claude-code.md
SKILL.md
cleanup-build-artifacts/
assets/
.gitkeep
references/
.gitkeep
scripts/
.gitkeep
SKILL.md
.claude-plugin/
marketplace.json
.codex/
hooks.json
.dockerignore
.github/
workflows/
ci.yml
release.yml
.gitignore
.ironlint.yml
adapters/
claude-code/
.claude-plugin/
plugin.json
hooks/
hook.sh
hooks.json
README.md
skills/
ironlint/
ironlint-init/
SKILL.md
ironlint-review/
SKILL.md
SKILL.md
codex/
hooks/
hook.sh
README.md
opencode/
.gitignore
bun.lock
package.json
README.md
src/
index.ts
tests/
plugin.test.ts
tsconfig.json
pi/
package-lock.json
package.json
README.md
src/
index.ts
test/
index.test.ts
tsconfig.json
shared/
ironlint-config/
SKILL.md
AGENTS.md
Cargo.lock
Cargo.toml
CHANGELOG.md
CLAUDE.md
clippy.toml
crates/
ironlint-bash-gate/
Cargo.toml
src/
lib.rs
ironlint-cli/
Cargo.toml
src/
cli.rs
commands/
check.rs
config.rs
doctor/
adapters.rs
config.rs
mod.rs
tests/
adapters.rs
config.rs
mod.rs
report.rs
error_report.rs
explain.rs
gate_bash.rs
init/
mod.rs
onboard.rs
render.rs
select.rs
mod.rs
schema.rs
show_resolved_config.rs
sweep.rs
trust.rs
update.rs
validate.rs
watch/
mod.rs
render.rs
runtime.rs
state.rs
tests/
mod.rs
render.rs
runtime.rs
state.rs
main.rs
tests/
cli_check_external_paths.rs
cli_check_single_load.rs
cli_check_sweep.rs
cli_config_walk_up.rs
cli_diff_read_error.rs
cli_diff_skips_unreadable_file.rs
cli_e2e_check_quiet_stderr.rs
cli_e2e_doctor.rs
cli_e2e_explain.rs
cli_e2e_gate_bash.rs
cli_e2e_gates.rs
cli_e2e_show_resolved_config.rs
cli_e2e_trust_worktree.rs
cli_e2e_trust.rs
cli_e2e_update.rs
cli_e2e_watch.rs
cli_error_voice.rs
cli_event_validation.rs
cli_format_output.rs
cli_init_dry_run_isolation.rs
cli_init_onboarding.rs
cli_init.rs
cli_internal_error_detail.rs
cli_pass_no_match.rs
cli_runner_telemetry_failure.rs
cli_schema.rs
cli_timeout_floor_log.rs
cli_usage_errors_exit_1.rs
cli_validate_json.rs
cli_validate.rs
cli_version.rs
common/
mod.rs
hook_contract_claude_code.rs
hook_contract_codex.rs
skills_gates_model.rs
ironlint-core/
Cargo.toml
src/
adapter/
json_settings.rs
materialize.rs
mod.rs
ops.rs
plan.rs
registry.rs
config/
extends.rs
mod.rs
parser.rs
scope.rs
types.rs
diff/
mod.rs
parser.rs
disable.rs
engine/
gate.rs
mod.rs
lib.rs
runner/
engine.rs
mod.rs
path.rs
tests/
mod.rs
tmpfile.rs
timeout.rs
tmpfile.rs
types.rs
snapshots/
ironlint_core__verdict__tests__verdict_json_wire_shape.snap
telemetry.rs
trust/
decision.rs
mod.rs
policy_hash.rs
store.rs
summary.rs
tests/
decision.rs
policy_hash.rs
store.rs
summary.rs
worktree.rs
verdict.rs
watch.rs
tests/
diff_parse.rs
disable.rs
extends_origin.rs
extends.rs
fixtures/
baseline_v1.json
baseline_v3.json
log_legacy.jsonl
resolve_paths.rs
scope.rs
snapshots/
telemetry__snapshot_check_skip_pattern.snap
telemetry__snapshot_check_with_rules.snap
telemetry.rs
trust_extends.rs
trust_worktree.rs
verdict_internal_error.rs
verdict_schema_version.rs
deny.toml
docs/
adapters/
claude-code.md
opencode.md
README.md
architecture.md
audits/
2026-05-12-bug-audit.md
2026-05-23-first-run-dx-audit.md
2026-05-24-check-end-to-end-audit.md
2026-05-29-launch-readiness-audit.md
configuring/
disabling.md
inheritance.md
targeting-files.md
getting-started.md
operating/
diagnostics.md
inspecting-config.md
running-checks.md
telemetry.md
watching-checks.md
README.md
reference/
cli.md
config-schema.md
show-resolved-config.md
verdict-json.md
security/
trust.md
superpowers/
plans/
2026-05-28-adapter-drift-audit-skill.md
2026-05-28-ironlint-core-resilience-hardening.md
2026-05-28-pi-adapter.md
2026-05-29-script-engine-prewrite-content.md
2026-07-01-init-onboarding-clarity.md
2026-07-05-repo-wide-check-sweep.md
2026-07-06-bash-gate-self-trust-prevention.md
2026-07-08-gates-to-scripts-rename.md
2026-07-11-git-worktree-trust-inheritance.md
2026-07-11-svelte-sellsheet-component.md
2026-07-15-doctor-module-split-completion.md
2026-07-15-watch-runtime-test-seam.md
2026-07-30-secret-scanner-corpus-extraction.md
specs/
2026-05-25-audit-orchestration-design.md
2026-05-28-adapter-drift-audit-skill-design.md
2026-05-28-pi-adapter-design.md
2026-07-01-init-onboarding-clarity-design.md
2026-07-04-phase-5-code-heavy-design.md
2026-07-05-init-harness-toggle-select-design.md
2026-07-06-bash-gate-self-trust-prevention-design.md
2026-07-07-gates-to-scripts-rename-design.md
2026-07-11-git-worktree-trust-inheritance-design.md
2026-07-11-svelte-sellsheet-component-design.md
2026-07-15-watch-runtime-test-seam-design.md
2026-07-30-secret-scanner-corpus-extraction-design.md
visual-elevator-pitch.md
writing-checks/
README.md
recipes.md
iron-lint.png
ironlint-demo.gif
LICENSE
llms.txt
plans/
2026-06-11-remove-llm-evaluation.md
2026-06-15-ironlint-gates-redesign-core.md
2026-06-27-ironlint-init-onboarding.md
2026-06-28-ironlint-checks-pipeline.md
2026-06-28-ironlint-config-skill.md
2026-06-28-ironlint-watch-tui.md
2026-06-29-tmpfile-force-init.md
2026-07-02-eval-bench-spec-fixes.md
2026-07-02-zcode-adapter.md
2026-07-03-drop-reasonix-add-codex-adapter.md
2026-07-03-phase-5-correctness-abi-fixes.md
2026-07-04-watch-motion-polish.md
2026-07-07-bash-gate-sh-c-and-bare-env-bypasses.md
archive/
2026-05-11-ironlint-0.1a-foundation.md
2026-05-11-ironlint-0.1b-engines.md
2026-05-11-ironlint-0.1c-claude-code-adapter.md
2026-05-12-bug-audit-remediation.md
2026-05-12-ironlint-a1-prompt-injection.md
2026-05-12-ironlint-a2-skip-patterns.md
2026-05-12-ironlint-a3-diff-prefilter.md
2026-05-12-ironlint-b1-parallel-rules.md
2026-05-12-ironlint-c4-check-flags.md
2026-05-12-ironlint-e1-baseline-checksum.md
2026-05-12-ironlint-opencode-adapter.md
2026-05-13-ironlint-c1-doctor.md
2026-05-13-ironlint-c2-explain-guide.md
2026-05-13-ironlint-c3-show-resolved-config.md
2026-05-13-ironlint-d1-typed-telemetry.md
2026-05-14-ironlint-h1-emit-semantic-payload.md
2026-05-14-ironlint-h2-record-verdict.md
2026-05-14-ironlint-h3-adapter-subagent-mode.md
2026-05-25-audit-remediation.md
2026-06-24-ironlint-trust-store.md
readiness-review/
phase-1-stop-silent-bypass.md
phase-2-process-and-trust-hardening.md
phase-2-review-followups.md
phase-3-enforcement-integrity-and-supply-chain.md
phase-4-close-the-promise.md
phase-5-docs-and-polish.md
README.md
README.md
README.md
scripts/
ci-coverage.sh
ci-dogfood.sh
specs/
2026-05-11-ironlint-plan-and-0.1-design.md
2026-05-12-bully-parity-closures.md
2026-05-14-subagent-semantic-eval.md
2026-05-25-reasonix-adapter.md
2026-05-29-deferred-gating.md
2026-05-29-script-engine-prewrite-content.md
2026-06-11-remove-llm-evaluation.md
2026-06-15-ironlint-gates-redesign-design.md
2026-06-27-ironlint-init-onboarding-design.md
2026-06-28-ironlint-checks-pipeline-design.md
2026-06-28-ironlint-config-skill-design.md
2026-06-28-ironlint-watch-tui-design.md
2026-06-29-ironlint-tmpfile-force-init-design.md
2026-07-01-init-interactive-onboarding-design.md
2026-07-01-ironlint-govern-portable-governance-design.md
2026-07-01-performance-dx-audit.md
2026-07-02-determinism-eval-bench-design.md
2026-07-02-drop-reasonix-add-codex-adapter-design.md
2026-07-02-zcode-adapter-design.md
2026-07-04-ironlint-watch-motion-polish-design.md
overview.md
tests/
e2e/
init/
Dockerfile
drive.sh
README.md
run.sh
fixtures/
codex/
apply_patch_add.json
apply_patch_update.json
README.md
valid_v1.bully.yml
valid_v2.ironlint.yml
with_extends/
base.ironlint.yml
child.ironlint.ymlยฉ 2026 Flowy ยท Free and open source
Built for Claude Code ยท Not affiliated with Anthropic