Skip to content

Configuration

AgentLint reads agentlint.yml (or agentlint.yaml, .agentlint.yml) from the project root. agentlint init writes one with detected defaults. Without a file, AgentLint runs with built-in defaults.

# agentlint.yml — a typical starting point
severity: standard          # strict | standard | relaxed
packs: [python, security]   # universal + quality are always added

rules:
  max-file-size:
    limit: 400
  no-destructive-commands:
    allow_operations:
      - { binary: rm, args_prefix: ["-rf", "build"] }

Every rule and its options are listed in Rules. Commands are in the CLI reference.

Packs

Rules are grouped into packs. universal and quality are always active.

Key Effect
packs: [...] Packs to enable in addition to the core packs. Disables stack detection.
stack: auto Default when packs is absent: enable packs detected from project files.
exclude_packs: [...] Turn a pack off deliberately, including a core pack ([quality]).
drift_ignore_packs: [...] Don't report the listed packs as drift.

Stack detection enables python for pyproject.toml/setup.py, frontend for package.json, react when React is a dependency, and seo for SSR/SSG frameworks. An AGENTS.md can add packs too (see AGENTS.md). security and autopilot are always opt-in.

Custom packs work the same way: name the pack in packs: and point custom_rules_dir at your rule files. See Custom rules. agentlint doctor reports custom rules whose pack isn't enabled.

Pack drift

When packs: is explicit, agentlint status and agentlint doctor compare it with the repository (a bounded scan that skips dependency folders, nested repositories and worktrees) and report packs the code calls for but the configuration omits — for example a "Python-only" config in a repository that contains ui/package.json and React components. Nothing is changed for you. Add the pack, enable it for that directory with projects, or list it under drift_ignore_packs. Workspace baselines are not checked for drift.

Severity

severity changes how findings are reported:

Mode Effect
standard As each rule defines (default).
strict WARNING becomes ERROR, INFO becomes WARNING.
relaxed WARNING becomes INFO.

Only ERROR findings block. Warnings and info are returned to the agent as advice, on every platform.

Rules

Each key under rules: is a rule ID. enabled: false turns a rule off; other keys are rule options (see Rules).

rules:
  no-todo-left:
    enabled: false
  max-file-size:
    limit: 300
  drift-detector:
    threshold: 5

Keys placed directly under rules: are defaults for every rule that reads them; a per-rule value overrides the default (lists are replaced, not merged):

rules:
  strict_mode: true
  allow_paths: ["*.log"]
  no-secrets:
    strict_mode: false

Exempting files

rules:
  ignore_paths:                # skip every rule for these files
    - "**/generated/**"
  max-file-size:
    allow_paths: ["**/legacy_*.py"]   # skip one rule for these files
  no-unnecessary-async:
    ignore_paths: ["app/api/*_routes.py"]
    reason: "FastAPI route consistency"

Patterns use fnmatch globs and match the full path, the project-relative path or the file name.

Inside a file:

# agentlint:ignore-file
# agentlint:ignore max-file-size reason="generated parser"
# agentlint:ignore-next-line

All three forms suppress warnings and errors (except required rules). A reason="..." appears in the session summary (agentlint report --summary).

no-destructive-commands and no-bash-file-write treat /tmp/, /var/folders/ and /private/tmp/ as scratch space. Add prefixes with safe_path_prefixes (values containing $TMPDIR are expanded).

Shell commands

AgentLint splits shell commands joined by &&, ||, ;, |, & or newlines into operations and classifies each one:

  • display — echo, printf;
  • read-only — grep, rg, cat, ls, git status/log/diff/show, gh pr view/list, find without actions, sed without -i, and a short list of cloud and psql read commands;
  • state-changing — everything else.

Operation guards only look at state-changing operations, so grep "rm -rf" build.log is not a destructive command, and git push -u origin feat && gh pr create --base main is not a push to main.

Anything AgentLint can't model exactly — $(...) and backticks, subshells, heredocs, unterminated quotes, or data piped into an interpreter (| bash, | xargs, | ssh) — is checked against the original text, as before. Credential, file-write, custom and organization rules always see the original command.

Allowing specific operations

Use allow_operations to allow one kind of operation for a rule. It applies to the matching operation only; other operations in the same command are still checked.

rules:
  no-destructive-commands:
    allow_operations:
      - binary: rm
        args_prefix: ["-rf", "build"]   # rm -rf build...
      - binary: rm
        args_regex: '-rf dist/\S+'       # full match against the arguments

allow_patterns (regular expressions over the whole command) still work, but exempt the entire command when they match; agentlint doctor points them out. Required rules ignore both.

Exceptions

An exception allows one exact command for one rule in one repository, for at most seven days. Use it for a specific, reviewed operation; for a class of actions use an approval.

exceptions:
  - id: ticket-123
    rule_id: no-force-push
    repository: /absolute/path/to/repository
    operation: git push --force origin maintenance
    created_at: 2026-10-03T10:00:00Z
    expires_at: 2026-10-03T12:00:00Z
    reason: Approved maintenance window

Only literal simple commands qualify (no pipes, expansions or compound commands). Required and organization rules can't be excepted. Each use is recorded first in ~/.cache/agentlint/exception-audit.jsonl (a SHA-256 of the command, not the command); if that write fails, the rule still blocks.

Repeated warnings

Hide a warning rule for the rest of a session with agentlint suppress <rule> (--list, --remove, --clear), or automatically after N consecutive fires:

rules:
  no-dead-imports:
    auto_suppress_after: 2

Errors are never suppressed.

Circuit breaker

If an ERROR rule keeps firing, the circuit breaker lowers it step by step (ERROR → WARNING → INFO → off) so a misfiring rule can't stall a session. Degraded findings are labelled, a notice explains how to re-enable the rule, and agentlint report --summary shows each rule's history. no-secrets, no-env-commit, required rules and organization rules never degrade.

circuit_breaker:
  enabled: true
  degraded_after: 3
  passive_after: 6
  open_after: 10
  reset_after_clean: 5
  reset_after_minutes: 30
  never_degrade: ["my-payment-validator"]

Per rule: rules: {<rule>: {circuit_breaker: {...}}}.

Workspace policy

One policy can cover many repositories. Point the agent's environment at it:

export AGENTLINT_WORKSPACE_CONFIG=/path/to/workspace/agentlint.yml

It applies only to projects inside that file's directory and is combined with each repository's own agentlint.yml: packs are added together, mappings merge, and repository values win for scalars and lists.

packs: [security, autopilot]
workspace:
  required_rules: [no-secrets, no-env-commit, no-force-push, cloud-resource-deletion]

Required rules stay enabled and blocking even if a repository disables them, relaxes severity, ignores paths or uses inline ignores; a failure while evaluating one also blocks. Per-rule path exemptions still apply, so review them as policy decisions. A missing, invalid or shadowed workspace file fails closed. This is local policy, not a tamper-proof sandbox.

agentlint status shows the layers in effect, and each denial names the layer that made the rule active.

Monorepos

projects sets packs per directory. The longest matching prefix wins; other files use the top-level packs.

projects:
  frontend/:
    packs: [frontend, react]
  backend/api/:
    packs: [python, security]

Core packs are added here too. status and list-rules show the top-level configuration. Run CLI commands from the root or pass --project-dir.

Evidence and approvals

evidence:
  receipts_dirs: [~/.local/state/my-tool/receipts]   # receipts from other tools
  max_age: 24h

See Approvals and evidence.

Optional cloud and recording

agentchute: and recording: control the optional AgentChute connection and local session recordings. Both are off unless you enable them.

AGENTS.md import

agentlint import-agents-md turns conventions in an AGENTS.md file into configuration (--dry-run to preview, --merge to add to an existing file). With stack: auto, AGENTS.md keywords can also enable extra packs.

Environment variables

Variable Purpose
AGENTLINT_PROJECT_DIR Project directory, overriding the agent's
AGENTLINT_WORKSPACE_CONFIG Workspace policy file
AGENTLINT_SESSION_ID Session key for state shared between hook calls
AGENTLINT_LOG_LEVEL Log level (default WARNING)
AGENTLINT_CACHE_DIR Session state (default ~/.cache/agentlint/sessions)
AGENTLINT_HEARTBEAT_DIR Hook heartbeats used by status
AGENTLINT_RECEIPTS_DIR Evidence receipts
AGENTLINT_APPROVALS_FILE, AGENTLINT_APPROVAL_AUDIT_FILE Approvals and their audit log
AGENTLINT_EXCEPTION_AUDIT_FILE Exception audit log
AGENTLINT_RECORDING, AGENTLINT_RECORDINGS_DIR Local session recordings
AGENTCHUTE_*, AGENTLINT_AGENTCHUTE_*, AGENTLINT_FEEDS_DIR AgentChute settings and caches

Complete example

severity: standard
packs: [python, security, autopilot]
# exclude_packs: [quality]
# custom_rules_dir: .agentlint/rules/

rules:
  ignore_paths: ["**/generated/**"]
  no-secrets:
    extra_prefixes: ["acme_live_"]
  max-file-size:
    limit: 500
  drift-detector:
    threshold: 15
  token-budget:
    max_tool_invocations: 200
  no-bash-file-write:
    allow_paths: ["*.log"]
  no-network-exfil:
    allowed_hosts: ["internal.example.com"]
  production-guard:
    allowed_projects: ["acme-staging"]
  no-destructive-commands:
    allow_operations:
      - { binary: rm, args_prefix: ["-rf", "build"] }
  cli-integration:
    commands:
      - name: ruff
        on: ["Write", "Edit"]
        glob: "**/*.py"
        command: "ruff check {file.path} --output-format=concise"

projects:
  web/:
    packs: [frontend, react]

evidence:
  max_age: 24h