CLI

The qualifier crate installs a binary called qualifier.

cargo install qualifier

Commands

Write records:

qualifier record   <kind> <location> [message]   Record an annotation
qualifier reply    <target> <message>            Reply to an existing record
qualifier resolve  <target> [message]            Resolve (close) an existing record
qualifier emit     <type> <subject> --body JSON  Emit a raw record of any type

<kind> accepts the built-in kinds (pass, fail, blocker, concern, comment, praise, suggestion, waiver, resolve) or any custom string. <location> is a path with an optional span (e.g., src/auth.rs:42). <target> is an id-prefix (≥4 chars) or a <location>.

Inspect:

qualifier show     <artifact>              Show annotations for an artifact
qualifier ls       [--kind K]              List artifacts (optionally by kind)
qualifier praise   <artifact>              Show who annotated and why (alias: blame)
qualifier review   [subject]               Check freshness of span-bound annotations

Maintain:

qualifier compact  <artifact> [options]    Compact a .qual file

All commands that produce output accept --format json for machine-readable output.

Typical workflows

Record and resolve an issue

# Record a concern at a specific line
qualifier record concern src/parser.rs:42 "Panics on malformed input"

# See it
qualifier show src/parser.rs

# Reply (id-prefix, min 4 chars — or a location)
qualifier reply a1b2 "Good catch, fixed in latest commit"
qualifier reply src/parser.rs:42 "Good catch, fixed in latest commit"

# Close it
qualifier resolve a1b2

Threaded conversations

qualifier show src/parser.rs

  src/parser.rs

  Records (4):
    concern  L42 "Panics on malformed input"          alice  2026-03-01  a1b2c3d4
    ├── comment  "Good catch, fixed in latest commit" bob    2026-03-01  b2c3d4e5
    └── resolve  "Resolved"                           alice  2026-03-01  c3d4e5f6
    praise       "Excellent property-based test coverage"  bob  2026-02-24  e5f6a7b8

Replies and resolves are threaded under their parent with tree-drawing characters.

Show details for one artifact

qualifier show src/parser.rs

  src/parser.rs

  Records (3):
    concern     L42–58 "Panics on malformed UTF-8 input"  alice  2026-02-24  a1b2c3d4
    praise      "Excellent property-based test coverage"   bob    2026-02-24  e5f6a7b8
    suggestion  "Consider adding fuzzing targets"          carol  2026-02-24  f1f2f3f4

Use --all to include resolved/superseded records. Use --pretty to force colored output.

Record a quality concern with full options

qualifier record concern src/parser.rs "Panics on malformed UTF-8 input" \
  --suggested-fix "Replace .unwrap() on line 42 with error propagation" \
  --tag robustness --tag error-handling \
  --issuer "mailto:alice@example.com" \
  --span 42:58

--span overrides any span parsed from <location>. When the source file is readable, content_hash is auto-computed.

Emit a raw record (raw or non-annotation types)

# A SPDX license record
qualifier emit license src/lib.rs --body '{"spdx":"MIT"}'

# A custom URI-typed record (round-trips via Record::Unknown)
qualifier emit https://example.com/lint/v1 src/parser.rs \
  --body '{"rule":"no-panic","matches":3}'

emit is a low-level passthrough: the body is preserved verbatim. For --type annotation, the body is validated against the annotation schema; other types are not validated.

Compact old annotations

# Preview what compaction would do
qualifier compact src/parser.rs --dry-run

# Prune superseded annotations
qualifier compact src/parser.rs

# Collapse everything to a single epoch annotation
qualifier compact src/parser.rs --snapshot

# Compact every .qual file in the repo
qualifier compact --all

List artifacts

qualifier ls --kind blocker
qualifier ls --unqualified   # artifacts with no annotations

Batch annotation (for agents)

# Pipe overrides JSONL from stdin: {kind, location, message, ...}
cat overrides.jsonl | qualifier record --stdin

# Or pipe complete records (envelope + body)
cat records.jsonl | qualifier emit --stdin

Configuration

Qualifier uses layered configuration (highest wins):

Priority Source Example
1 CLI flags --issuer mailto:me@example.com
2 Environment QUALIFIER_ISSUER
3 Project config .qualifier.toml
4 User config ~/.config/qualifier/config.toml
5 Built-in defaults