# agentnative
[](https://anc.dev/score/anc)
[](https://crates.io/crates/agentnative)
[](#license)
The agent-native CLI linter. Checks whether your CLI follows the 7 agent-readiness principles.
`anc` dogfoods the spec it enforces — the badge above is its own live score.
## Install
The crate is published as `agentnative`. The binary is called `anc`.
```bash
# Homebrew (installs anc)
brew install brettdavies/tap/agentnative
# From crates.io
cargo install agentnative
# Pre-built binary via cargo-binstall
cargo binstall agentnative
# Pre-built binaries from GitHub Releases
# https://github.com/brettdavies/agentnative-cli/releases
```
## Install the skill
`anc` ships a companion skill bundle (`agentnative-skill`) that teaches AI coding agents how to operate the linter and
where to apply the principles. Install it with one command per host:
```bash
anc skill install claude_code # ~/.claude/skills/agent-native-cli
anc skill install codex # ~/.codex/skills/agent-native-cli
anc skill install cursor # ~/.cursor/skills/agent-native-cli
anc skill install factory # ~/.factory/skills/agent-native-cli (Factory Droid)
anc skill install kiro # ~/.kiro/skills/agent-native-cli (Kiro)
anc skill install opencode # ~/.config/opencode/skills/agent-native-cli
```
Inspect the resolved command before running it:
```bash
anc skill install --dry-run claude_code
# git clone --depth 1 https://github.com/brettdavies/agentnative-skill.git /home/you/.claude/skills/agent-native-cli
```
JSON output (mode `dry-run` and `install`, success and error) is uniform — agents can rely on the same envelope shape
across every outcome:
```bash
anc skill install --dry-run claude_code --output json
```
If the site adds a host before this `anc` release knows about it, fall back to a manual `git clone`:
```bash
git clone --depth 1 https://github.com/brettdavies/agentnative-skill.git <host-skills-dir>/agent-native-cli
```
The host map is hardcoded in this binary; new hosts ship via patch release after the site updates `skill.json`.
## Quick Start
```bash
# Check the current project (`check` is the default subcommand)
anc .
# Check a specific binary
anc ./target/release/mycli
# Resolve a command on PATH and run behavioral checks against it
anc --command ripgrep
# JSON output for CI
anc . --output json
# Filter by principle
anc . --principle 3
# Quiet mode (warnings and failures only)
anc . -q
```
## The 7 Principles
agentnative checks your CLI against seven agent-readiness principles:
| P1 | Non-Interactive by Default | No prompts, no browser popups, stdin from `/dev/null` works |
| P2 | Structured Output | `--output json` exists and produces valid JSON |
| P3 | Progressive Help | `--help` has examples, `--version` works |
| P4 | Actionable Errors | Structured error types, named exit codes, no `.unwrap()` |
| P5 | Safe Retries | `--dry-run` for write operations |
| P6 | Composable Structure | SIGPIPE handled, NO_COLOR respected, shell completions, AGENTS.md |
| P7 | Bounded Responses | `--quiet` flag, no unbounded list output, clamped pagination |
## Example Output
```text
P1 — Non-Interactive by Default
[PASS] Non-interactive by default (p1-non-interactive)
[PASS] Flags advertise env-var bindings in --help (p1-env-hints)
[PASS] TTY detection for color output (p1-tty-detection-source)
[PASS] No interactive prompt dependencies (p1-non-interactive-source)
P3 — Progressive Help
[PASS] Help flag produces useful output (p3-help)
[PASS] Version flag works (p3-version)
P4 — Actionable Errors
[PASS] Rejects invalid arguments (p4-bad-args)
[PASS] Structured error types (p4-error-types)
[PASS] Exit codes use named constants (p4-exit-codes)
[PASS] No process::exit outside main (p4-process-exit)
[PASS] Dedicated error module exists (p4-error-module)
P6 — Composable Structure
[PASS] Handles SIGPIPE gracefully (p6-sigpipe)
[PASS] Respects NO_COLOR (p6-no-color-behavioral)
[PASS] Shell completions support (p6-completions)
Code Quality
[PASS] No .unwrap() in source (code-unwrap)
33 checks: 28 pass, 1 warn, 0 fail, 4 skip, 0 error
🏆 Score: 97% — your tool qualifies for the agent-native badge.
Embed in your README:
[](https://anc.dev/score/anc)
Convention: https://anc.dev/badge
```
The badge hint appears in `text` output when a tool scores at or above the 80% eligibility floor. Below the floor, `anc`
prints nothing badge-related — the convention is to surface the embed only when earned.
## Three Check Layers
agentnative uses three layers to analyze your CLI:
- **Behavioral** — runs the compiled binary, checks `--help`, `--version`, `--output json`, SIGPIPE, NO_COLOR, exit
codes. Language-agnostic.
- **Source** — ast-grep pattern matching on source code. Detects `.unwrap()`, missing error types, naked `println!`, and
more. Currently supports Rust.
- **Project** — inspects files and manifests. Checks for AGENTS.md, recommended dependencies, dedicated error/output
modules.
## CLI Reference
When the first non-flag argument is not a recognized subcommand, `check` is inserted automatically. `anc .`, `anc -q .`,
and `anc --command ripgrep` all resolve to `anc check …`. Bare `anc` (no arguments) still prints help and exits 2 — this
is deliberate fork-bomb prevention when agentnative dogfoods itself.
```text
Usage: anc check [OPTIONS] [PATH]
Arguments:
[PATH] Path to project directory or binary [default: .]
Options:
--command <NAME> Resolve a command from PATH and run behavioral checks against it
--binary Run only behavioral checks (skip source analysis)
--source Run only source checks (skip behavioral)
--principle <PRINCIPLE> Filter checks by principle number (1-7)
--output <OUTPUT> Output format [default: text] [possible values: text, json]
-q, --quiet Suppress non-essential output [env: AGENTNATIVE_QUIET=]
--include-tests Include test code in source analysis
--audit-profile <CATEGORY> Exemption category for the target [possible values:
human-tui, file-traversal, posix-utility, diagnostic-only]
-h, --help Print help
```
`--command` and `[PATH]` are mutually exclusive — pick one. `--command` runs behavioral checks only; source and project
checks are skipped because there is no source tree to analyze.
`--audit-profile` suppresses checks that legitimately do not apply to a class of tool (e.g., `human-tui` for TUI apps
like `lazygit` whose contract IS the TTY, `posix-utility` for stdin-primary tools like `cat`/`sed`/`awk`,
`diagnostic-only` for read-only tools like `nvidia-smi`, `file-traversal` reserved for upcoming subcommand-structure
relaxations on `fd`/`find`-class tools). Suppressed checks emit `Skip` with structured evidence. The full per-category
mapping lives in `coverage/matrix.json` under `audit_profiles[]` — agents should read it rather than scrape `--help`.
### Exit Codes
| 0 | All checks passed |
| 1 | Warnings present (no failures) |
| 2 | Failures, errors, or usage errors |
Exit 2 covers both check failures (a real `[FAIL]` or `[ERROR]` result) and usage errors (bare `anc`, unknown flag,
mutually exclusive flags). Agents distinguishing the two should parse `stderr` (usage errors print `Usage:`) or call
`anc --help` first to validate the invocation shape.
### Shell Completions
```bash
# Bash
anc completions bash > ~/.local/share/bash-completion/completions/anc
# Zsh (writes to the first directory on your fpath)
anc completions zsh > "${fpath[1]}/_anc"
# Fish
anc completions fish > ~/.config/fish/completions/anc.fish
# PowerShell
anc completions powershell > anc.ps1
# Elvish
anc completions elvish > anc.elv
```
Pre-generated scripts are also available in `completions/`.
## JSON Output
```bash
anc check . --output json
```
Produces a self-describing scoring run record (`schema_version: "0.5"`) with results, summary, coverage against the 7
principles, plus contextual metadata identifying which tool was scored, by which `anc` build, on which platform, and
how:
```json
{
"schema_version": "0.5",
"results": [
{
"id": "p3-help",
"label": "Help flag produces useful output",
"group": "P3",
"layer": "behavioral",
"status": "pass",
"evidence": null,
"confidence": "high"
}
],
"summary": {
"total": 33,
"pass": 28,
"warn": 1,
"fail": 0,
"skip": 4,
"error": 0
},
"coverage_summary": {
"must": { "total": 23, "verified": 17 },
"should": { "total": 16, "verified": 2 },
"may": { "total": 7, "verified": 0 }
},
"audience": "agent-optimized",
"audit_profile": null,
"spec_version": "0.3.0",
"tool": { "name": "ripgrep", "binary": "rg", "version": "ripgrep 15.1.0" },
"anc": { "version": "0.3.0", "commit": "abc1234" },
"run": {
"invocation": "anc check --command rg --output json",
"started_at": "2026-04-29T16:00:00Z",
"duration_ms": 412,
"platform": { "os": "linux", "arch": "x86_64" }
},
"target": { "kind": "command", "path": null, "command": "rg" },
"badge": {
"eligible": true,
"score_pct": 97,
"embed_markdown": "[](https://anc.dev/score/ripgrep)",
"scorecard_url": "https://anc.dev/score/ripgrep",
"badge_url": "https://anc.dev/badge/ripgrep.svg",
"convention_url": "https://anc.dev/badge"
}
}
```
- `coverage_summary` — how many MUSTs/SHOULDs/MAYs the checks that ran actually verified, against the spec registry's
totals. See `docs/coverage-matrix.md` for the per-requirement breakdown. Checks suppressed by `--audit-profile` do
**not** count toward `verified` — suppression means the requirement was not verified, even if the check is skipped
rather than run.
- `audience` — derived classification from 4 signal behavioral checks (`p1-non-interactive`, `p2-json-output`,
`p7-quiet`, `p6-no-color-behavioral`). Emits `agent-optimized` (0-1 Warns), `mixed` (2 Warns), or `human-primary` (3-4
Warns). Returns `null` when any signal check failed to run (source-only mode, missing runner, or `--audit-profile`
suppression). Informational only — never gates totals or exit codes. Values serialize as kebab-case to match
`audit_profile`'s format within the same JSON document.
- `audience_reason` — present only when `audience` is `null`. Values: `suppressed` (at least one signal check was masked
by `--audit-profile`) or `insufficient_signal` (signal check never produced, e.g. source-only run). Additive to schema
`0.2`; older consumers feature-detect.
- `audit_profile` — echoes the applied `--audit-profile <category>` flag value (`human-tui`, `file-traversal`,
`posix-utility`, or `diagnostic-only`). `null` when no profile is set. See `coverage/matrix.json` under
`audit_profiles` for the committed per-category mapping of which check IDs each profile suppresses.
- `tool` — identifies what was scored. `name` is always present (deterministic from path or command). `binary` is the
executable basename when one is located; `null` for project-mode runs without a built artifact. `version` is
best-effort: project-mode prefers the manifest version (`Cargo.toml`/`pyproject.toml`), command/binary mode probes
`<bin> --version` then `-V`. `null` when probing failed or was declined by the self-spawn guard. The site's
`registry.yaml` `version_extract` snippets remain authoritative for tools whose self-report is unreliable. Schema
`0.4` addition.
- `anc` — identifies the `anc` build that produced the scorecard. `version` is the crate version at compile time.
`commit` is the short Git SHA at compile time, or `null` for builds outside a Git checkout (e.g., `cargo install` from
crates.io). Informational, not a signed provenance signal — pair with a Sigstore-signed release artifact if provenance
is required. Schema `0.4` addition.
- `run` — run-level facts. `invocation` is the user's argv joined with shell-safe quoting, captured **before**
default-subcommand injection so it reflects what the user typed (`anc .`, not `anc check .`). `started_at` is RFC 3339
UTC. `duration_ms` is wall-clock milliseconds. `platform.os` / `platform.arch` come from `std::env::consts`. Schema
`0.4` addition.
- `target` — what `anc` was pointed at. `kind` is `"project"` (directory), `"binary"` (executable file), or `"command"`
(PATH-resolved name from `--command`). `path` is the **basename** of the resolved target (project directory name or
binary file name) — never the absolute path, so home-dir usernames and employer directory layouts don't leak into
scorecards committed to repos or posted by agents. `command` carries the user-supplied name for command mode. The
unused field is always `null`, never missing — consumer code can access both unconditionally. Schema `0.4` addition.
- `badge` — agent-native badge derivation from the live run. `score_pct` is `pass / (pass + warn + fail)` rounded (Skips
and Errors excluded from both sides of the ratio). `eligible` is true iff `score_pct >= 80` **and** a tool slug was
derivable. `embed_markdown` is `null` below the floor — the convention is "do not nag" until earned; `scorecard_url`
and `badge_url` are populated whenever a slug exists, even below the floor, so the site renders an SVG for every
scored tool (a regression below the floor shifts color rather than 404s). `convention_url` always points at
`https://anc.dev/badge`. Schema `0.5` addition.
> Publishing a scorecard? `run.invocation` may carry usernames or absolute paths from the machine that produced the
> scorecard. `target.path` is intentionally the basename only and is safe to commit. Review `run.invocation` before
> publishing — `anc` does not silently redact, since that would surprise users debugging their own runs.
## Contributing
```bash
git clone https://github.com/brettdavies/agentnative-cli
cd agentnative-cli
git config core.hooksPath scripts/hooks # mirror CI locally on every push
cargo test
cargo run -- check .
```
### Reporting issues
Open an issue at
[github.com/brettdavies/agentnative-cli/issues/new/choose](https://github.com/brettdavies/agentnative-cli/issues/new/choose).
The chooser surfaces three structured templates plus a blank fallback for everything else:
| Blank issue | Anything outside the structured templates below. |
| False positive | A check flagged your CLI but you believe your CLI is doing the right thing. |
| Scoring bug | Results don't match what the check should be doing (wrong status, miscategorized group/layer, evidence pointing at the wrong line). |
| Feature request | Missing capability, flag, or output format in the checker itself. |
Spec questions, principle pressure-tests, and CLI grading live on the spec repo —
[brettdavies/agentnative](https://github.com/brettdavies/agentnative/issues/new/choose). The chooser config redirects
those automatically. Site bugs (rendering, performance) go to
[brettdavies/agentnative-site](https://github.com/brettdavies/agentnative-site/issues/new/choose). See
[CONTRIBUTING.md on the spec repo](https://github.com/brettdavies/agentnative/blob/main/CONTRIBUTING.md) for the full
cross-repo routing table.
## License
MIT OR Apache-2.0