Real-time quality guardrails for AI coding agents
Project description
agentlint
Real-time quality guardrails for AI coding agents.
AI coding agents drift during long sessions — they introduce API keys into source, skip tests, force-push to main, and leave debug statements behind. AgentLint catches these problems as they happen, not at review time.
What it catches
AgentLint ships with 10 universal rules that work with any tech stack:
| Rule | Severity | What it does |
|---|---|---|
no-secrets |
ERROR | Blocks writes containing API keys, tokens, passwords |
no-env-commit |
ERROR | Blocks writing .env and credential files |
no-force-push |
ERROR | Blocks git push --force to main/master |
no-destructive-commands |
WARNING | Warns on rm -rf, DROP TABLE, git reset --hard |
dependency-hygiene |
WARNING | Warns on ad-hoc pip install / npm install |
max-file-size |
WARNING | Warns when a file exceeds 500 lines |
drift-detector |
WARNING | Warns after many edits without running tests |
no-debug-artifacts |
WARNING | Detects console.log, print(), debugger left in code |
test-with-changes |
WARNING | Warns if source changed but no tests were updated |
no-todo-left |
INFO | Reports TODO/FIXME comments in changed files |
ERROR rules block the agent's action. WARNING rules inject advice into the agent's context. INFO rules appear in the session report.
Quick start
pip install agentlint
cd your-project
agentlint setup
That's it! AgentLint hooks are now active in Claude Code.
When AgentLint blocks a dangerous action, the agent sees:
⛔ [no-secrets] Possible secret token detected (prefix 'sk_live_')
💡 Use environment variables instead of hard-coded secrets.
The agent's action is blocked before it can write the secret into your codebase.
The setup command:
- Installs hooks into
.claude/settings.json - Creates
agentlint.ymlwith auto-detected settings (if it doesn't exist)
To remove AgentLint hooks:
agentlint uninstall
Installation options
# Install to project (default)
agentlint setup
# Install to user-level settings (~/.claude/settings.json)
agentlint setup --global
Claude Code marketplace
Add the AgentLint marketplace and install the plugin:
/plugin marketplace add mauhpr/agentlint
/plugin install agentlint@agentlint
Local plugin (development)
claude --plugin-dir /path/to/agentlint/plugin
Manual hook configuration
Add to your project's .claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash|Edit|Write",
"hooks": [{ "type": "command", "command": "agentlint check --event PreToolUse" }]
}
],
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [{ "type": "command", "command": "agentlint check --event PostToolUse" }]
}
],
"Stop": [
{
"hooks": [{ "type": "command", "command": "agentlint report" }]
}
]
}
}
Configuration
Create agentlint.yml in your project root (or run agentlint init):
# Auto-detect tech stack or list packs explicitly
stack: auto
# strict: warnings become errors
# standard: default behavior
# relaxed: warnings become info
severity: standard
packs:
- universal
rules:
max-file-size:
limit: 300 # Override default 500-line limit
drift-detector:
threshold: 5 # Warn after 5 edits without tests (default: 10)
no-secrets:
enabled: false # Disable a rule entirely
# Load custom rules from a directory
# custom_rules_dir: .agentlint/rules/
Custom rules
Create a Python file in your custom rules directory:
# .agentlint/rules/no_direct_db.py
from agentlint.models import Rule, RuleContext, Violation, Severity, HookEvent
class NoDirectDB(Rule):
id = "custom/no-direct-db"
description = "API routes must not import database layer directly"
severity = Severity.WARNING
events = [HookEvent.POST_TOOL_USE]
pack = "custom"
def evaluate(self, context: RuleContext) -> list[Violation]:
if not context.file_path or "/routes/" not in context.file_path:
return []
if context.file_content and "from database" in context.file_content:
return [Violation(
rule_id=self.id,
message="Route imports database directly. Use repository pattern.",
severity=self.severity,
file_path=context.file_path,
)]
return []
Then set custom_rules_dir: .agentlint/rules/ in your config.
See docs/custom-rules.md for the full guide.
How it works
AgentLint hooks into Claude Code's lifecycle events:
- PreToolUse — Before Write/Edit/Bash calls. Can block the action (exit code 2).
- PostToolUse — After Write/Edit. Injects warnings into the agent's context.
- Stop — End of session. Generates a quality report.
Each invocation loads your config, evaluates matching rules, and returns JSON that Claude Code understands. Session state persists across invocations so rules like drift-detector can track cumulative behavior.
Comparison with alternatives
| Project | How AgentLint differs |
|---|---|
| guardrails-ai | Validates LLM I/O. AgentLint validates agent tool calls in real-time. |
| claude-code-guardrails | Uses external API. AgentLint is local-first, no network dependency. |
| Custom hooks | Copy-paste scripts. AgentLint is a composable engine with config + plugins. |
| Codacy Guardrails | Commercial, proprietary. AgentLint is fully open source. |
FAQ
Does AgentLint slow down Claude Code? No. Rules evaluate in <10ms. AgentLint runs locally as a subprocess — no network calls, no API dependencies.
What if a rule is too strict for my project?
Disable it in agentlint.yml: rules: { no-secrets: { enabled: false } }. Or switch to severity: relaxed to downgrade warnings to informational.
Is my code sent anywhere? No. AgentLint is fully offline. It reads stdin from Claude Code's hook system and evaluates rules locally. No telemetry, no network requests.
Can I use AgentLint outside Claude Code?
The CLI works standalone — you can pipe JSON to agentlint check in any CI pipeline. However, the hook integration (blocking actions in real-time) is specific to Claude Code.
Contributing
See CONTRIBUTING.md for development setup and guidelines.
License
MIT
Project details
Release history Release notifications | RSS feed
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 agentlint-0.1.1.tar.gz.
File metadata
- Download URL: agentlint-0.1.1.tar.gz
- Upload date:
- Size: 80.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4c0d60bbc3d34dffe27312d367a40a5387f8abd902d8b2f365de21626b5ca9c8
|
|
| MD5 |
f55acbeaaf205d1c821863a31ee8d3d4
|
|
| BLAKE2b-256 |
fbb7c22d4aa4ec17ab9c0b1c17f45d9147be66630c39140bfe6bc78bea776c9d
|
Provenance
The following attestation bundles were made for agentlint-0.1.1.tar.gz:
Publisher:
publish.yml on mauhpr/agentlint
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agentlint-0.1.1.tar.gz -
Subject digest:
4c0d60bbc3d34dffe27312d367a40a5387f8abd902d8b2f365de21626b5ca9c8 - Sigstore transparency entry: 970398295
- Sigstore integration time:
-
Permalink:
mauhpr/agentlint@7dce55605fa4367ceb2a17259e5255d4fbf44556 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/mauhpr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7dce55605fa4367ceb2a17259e5255d4fbf44556 -
Trigger Event:
release
-
Statement type:
File details
Details for the file agentlint-0.1.1-py3-none-any.whl.
File metadata
- Download URL: agentlint-0.1.1-py3-none-any.whl
- Upload date:
- Size: 28.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ad6443c7a4e94e7f1940539608c63cf6e8b3ab5267b97b0720c2c6345bf98b7f
|
|
| MD5 |
5a729e75203f84c1736df80a18a3c62a
|
|
| BLAKE2b-256 |
1da4662d332e1fca486d84334e6f4623f167da7e99d3355f1f762f2acfd7041b
|
Provenance
The following attestation bundles were made for agentlint-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on mauhpr/agentlint
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agentlint-0.1.1-py3-none-any.whl -
Subject digest:
ad6443c7a4e94e7f1940539608c63cf6e8b3ab5267b97b0720c2c6345bf98b7f - Sigstore transparency entry: 970398299
- Sigstore integration time:
-
Permalink:
mauhpr/agentlint@7dce55605fa4367ceb2a17259e5255d4fbf44556 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/mauhpr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7dce55605fa4367ceb2a17259e5255d4fbf44556 -
Trigger Event:
release
-
Statement type: