nils-agent-docs 0.4.8

CLI crate for nils-agent-docs in the nils-cli workspace.
Documentation

agent-docs

Overview

agent-docs is a deterministic policy-document discovery CLI for Codex/agent workflows.

It resolves required Markdown documents by context and scope, with explicit precedence rules for:

  • startup policy files (AGENTS.override.md > AGENTS.md)
  • home vs project extension config (AGENT_DOCS.toml)
  • strict vs non-strict missing-doc behavior

The CLI does not replace runtime AGENTS.md loading. It provides a testable resolution contract.

Non-goals

  • Replacing or bypassing how any runtime natively loads AGENTS.md.
  • Auto-editing arbitrary existing policy files in-place.
  • Discovering non-markdown policy files without explicit AGENT_DOCS.toml entries.
  • Remote policy sync or network-backed policy lookups.

Path Resolution Precedence

Path resolution is deterministic and applies to all commands.

AGENT_HOME

  1. --agent-home <path> (command flag)
  2. AGENT_HOME environment variable
  3. $HOME/.agents

PROJECT_PATH

  1. --project-path <path> (command flag)
  2. PROJECT_PATH environment variable
  3. git rev-parse --show-toplevel from current working directory
  4. current working directory

Normalization Rules

  • Paths are normalized lexically (. removed, duplicate separators collapsed).
  • Relative document paths in AGENT_DOCS.toml are resolved from their declared scope root.
  • Absolute document paths are kept absolute and ignore scope root joining.

Scope and Context Model

Scopes

  • home: rooted at effective AGENT_HOME
  • project: rooted at effective PROJECT_PATH

Built-in contexts

  • startup
  • skill-dev
  • task-tools
  • project-dev

Built-in required docs by context

Context Scope Required document contract Required
startup home Use AGENTS.override.md when present; else AGENTS.md true
startup project Use AGENTS.override.md when present; else AGENTS.md true
skill-dev home DEVELOPMENT.md true
task-tools home CLI_TOOLS.md true
project-dev project DEVELOPMENT.md true

AGENTS.override.md precedence is evaluated per scope independently.

Command Surface

Usage:
  agent-docs <command> [options]

Commands:
  resolve            Resolve required docs for a context
  contexts           List supported contexts
  add                Upsert one AGENT_DOCS.toml entry
  scaffold-agents    Scaffold default AGENTS.md template
  baseline           Check baseline doc coverage
  scaffold-baseline  Scaffold missing baseline docs

Use agent-docs --help (or agent-docs <command> --help) for CLI help text.

Commands and Flags

contexts

Print supported context names.

Flags:

  • --format text|json (default: text)
  • --agent-home <path>
  • --project-path <path>

resolve

Resolve effective required/optional docs for one context.

Flags:

  • --context startup|skill-dev|task-tools|project-dev (required)
  • --format text|json|checklist (default: text)
  • --strict (missing required docs become exit code 1)
  • --agent-home <path>
  • --project-path <path>

Format guidance:

  • text: human-readable output for manual inspection and debugging.
  • json: machine-readable output for structured parsing/integration.
  • checklist: line-oriented required-doc contract for shell verification and CI guards.

add

Create/update one AGENT_DOCS.toml entry in home or project scope.

Flags:

  • --target home|project (required)
  • --context startup|skill-dev|task-tools|project-dev (required)
  • --scope home|project (required; target root for path resolution)
  • --path <doc-path> (required)
  • --required (set required=true; omitted means required=false)
  • --when <condition> (default: always)
  • --notes <text>
  • --agent-home <path>
  • --project-path <path>

Copy-pastable resolve + add flow

# 1) Resolve built-in project-dev requirements
agent-docs resolve --context project-dev --format text

# 2) Register BINARY_DEPENDENCIES.md as required for project-dev
agent-docs add \
  --target project \
  --context project-dev \
  --scope project \
  --path BINARY_DEPENDENCIES.md \
  --required \
  --when always \
  --notes "External runtime tools required by the repo"

add stdout shape:

add: target=project action=<inserted|updated> config=<PROJECT_PATH>/AGENT_DOCS.toml entries=<N>

Verify both built-in and extension docs are present:

agent-docs resolve --context project-dev --format checklist \
  | rg "REQUIRED_DOCS_BEGIN|REQUIRED_DOCS_END|DEVELOPMENT\\.md|BINARY_DEPENDENCIES\\.md"

scaffold-agents

Scaffold default AGENTS.md template.

Flags:

  • --target home|project (required)
  • --output <path> (optional explicit output file path)
  • --force (overwrite when file exists)
  • --agent-home <path>
  • --project-path <path>

Semantics:

  • Default output: <target-root>/AGENTS.md
  • Without --force, existing target file is not modified.

baseline

Audit minimum baseline documents.

Flags:

  • --check (required in Sprint contract)
  • --target home|project|all (default: all)
  • --format text|json (default: text)
  • --strict (missing required docs become exit code 1)
  • --agent-home <path>
  • --project-path <path>

scaffold-baseline

Scaffold baseline docs from deterministic templates/inputs.

Flags:

  • --target home|project|all (default: all)
  • --missing-only (create only missing baseline docs)
  • --force (overwrite existing files)
  • --dry-run (print planned writes only)
  • --format text|json (default: text)
  • --agent-home <path>
  • --project-path <path>

Exit Codes

  • 0: success (or non-strict missing-doc report)
  • 1: strict policy failure (--strict and one or more required docs missing)
  • 2: usage error (invalid flags, invalid command, missing required argument)
  • 3: config/schema error (AGENT_DOCS.toml invalid)
  • 4: runtime error (I/O failure, git probe failure not recoverable)

Strict Semantics

resolve --strict

  • Required docs are evaluated after built-ins + TOML merge.
  • If any required doc is missing on disk, command exits 1.
  • Without --strict, missing required docs are reported but exit code remains 0.

baseline --strict

  • Evaluates baseline required docs for selected target scope(s).
  • Missing required baseline docs cause exit 1 only when --strict is set.

Worktree fallback

Worktree fallback is deterministic and applies only to project-scope required docs when running from a linked worktree in auto mode.

Fallback order (project scope)

startup project policy:

  1. <PROJECT_PATH>/AGENTS.override.md
  2. <PROJECT_PATH>/AGENTS.md
  3. <PRIMARY_WORKTREE_PATH>/AGENTS.override.md (fallback)
  4. <PRIMARY_WORKTREE_PATH>/AGENTS.md (fallback)

project-dev required project docs (built-ins and required project-scope extension entries):

  1. <PROJECT_PATH>/<doc-path>
  2. <PRIMARY_WORKTREE_PATH>/<doc-path> (fallback)

Strict and compatibility semantics

  • --strict exits 1 only when all candidates in the deterministic order are missing.
  • local-only mode disables <PRIMARY_WORKTREE_PATH> fallback candidates and enforces local project paths only.
  • Non-worktree repositories are unchanged: only <PROJECT_PATH> candidates are evaluated.

Output disclosure and local-only operation

When fallback is used, output must disclose fallback provenance in addition to required-doc presence.

  • text/json: include a fallback source marker and the resolved fallback path.
  • checklist: keep required-doc status lines and include fallback provenance in the same report.

To disable fallback, run resolve/baseline in local-only mode.

agent-docs --worktree-fallback local-only resolve --context startup --strict --format checklist
agent-docs --worktree-fallback local-only baseline --check --target project --strict --format text

Output Contract

resolve text example

$ agent-docs resolve --context startup
CONTEXT: startup
AGENT_HOME: /Users/example/.agents
PROJECT_PATH: /Users/example/work/nils-cli

[required] startup home /Users/example/.agents/AGENTS.override.md source=builtin status=present why="startup home policy (AGENTS.override.md preferred over AGENTS.md)"
[required] startup project /Users/example/work/nils-cli/AGENTS.md source=builtin-fallback status=present why="startup project policy (AGENTS.override.md missing, fallback AGENTS.md)"

summary: required_total=2 present_required=2 missing_required=0 strict=false

resolve JSON example

{
  "context": "startup",
  "strict": false,
  "agent_home": "/Users/example/.agents",
  "project_path": "/Users/example/work/nils-cli",
  "documents": [
    {
      "context": "startup",
      "scope": "home",
      "path": "/Users/example/.agents/AGENTS.override.md",
      "required": true,
      "status": "present",
      "source": "builtin",
      "why": "startup home policy (AGENTS.override.md preferred over AGENTS.md)"
    },
    {
      "context": "startup",
      "scope": "project",
      "path": "/Users/example/work/nils-cli/AGENTS.md",
      "required": true,
      "status": "present",
      "source": "builtin-fallback",
      "why": "startup project policy (AGENTS.override.md missing, fallback AGENTS.md)"
    }
  ],
  "summary": {
    "required_total": 2,
    "present_required": 2,
    "missing_required": 0
  }
}

resolve checklist example

Checklist mode is designed for copy-paste verification. The required-doc section is delimited by REQUIRED_DOCS_BEGIN and REQUIRED_DOCS_END, with one required document per line: <filename> status=<present|missing> path=<absolute-path>.

$ agent-docs resolve --context project-dev --format checklist
REQUIRED_DOCS_BEGIN context=project-dev mode=non-strict
DEVELOPMENT.md status=present path=/Users/example/work/nils-cli/DEVELOPMENT.md
BINARY_DEPENDENCIES.md status=present path=/Users/example/work/nils-cli/BINARY_DEPENDENCIES.md
REQUIRED_DOCS_END required=2 present=2 missing=0 mode=non-strict context=project-dev

resolve checklist strict + missing required example

When --strict is set and any required doc is missing, checklist output is still emitted and the process exits with code 1.

$ agent-docs resolve --context skill-dev --format checklist --strict
REQUIRED_DOCS_BEGIN context=skill-dev mode=strict
DEVELOPMENT.md status=missing path=/Users/example/.agents/DEVELOPMENT.md
REQUIRED_DOCS_END required=1 present=0 missing=1 mode=strict context=skill-dev
$ echo $?
1

baseline --check text example

$ agent-docs baseline --check --target all
BASELINE CHECK: all
AGENT_HOME: /Users/example/.agents
PROJECT_PATH: /Users/example/work/nils-cli

[home] startup policy /Users/example/.agents/AGENTS.md required present source=builtin-fallback why="startup home policy (AGENTS.override.md missing, fallback AGENTS.md)"
[home] skill-dev /Users/example/.agents/DEVELOPMENT.md required missing source=builtin why="skill development guidance from AGENT_HOME/DEVELOPMENT.md"
[home] task-tools /Users/example/.agents/CLI_TOOLS.md required present source=builtin why="tool-selection guidance from AGENT_HOME/CLI_TOOLS.md"
[project] startup policy /Users/example/work/nils-cli/AGENTS.md required present source=builtin-fallback why="startup project policy (AGENTS.override.md missing, fallback AGENTS.md)"
[project] project-dev /Users/example/work/nils-cli/DEVELOPMENT.md required present source=builtin why="project development guidance from PROJECT_PATH/DEVELOPMENT.md"

missing_required: 1
missing_optional: 0
suggested_actions:
  - agent-docs scaffold-baseline --missing-only --target home

baseline --check JSON example

{
  "target": "all",
  "strict": false,
  "agent_home": "/Users/example/.agents",
  "project_path": "/Users/example/work/nils-cli",
  "items": [
    {
      "scope": "home",
      "context": "skill-dev",
      "label": "skill-dev",
      "path": "/Users/example/.agents/DEVELOPMENT.md",
      "required": true,
      "status": "missing",
      "source": "builtin",
      "why": "skill development guidance from AGENT_HOME/DEVELOPMENT.md"
    }
  ],
  "missing_required": 1,
  "missing_optional": 0,
  "suggested_actions": [
    "agent-docs scaffold-baseline --missing-only --target home"
  ]
}

baseline extension merge order (deterministic)

baseline --check applies extension documents with explicit, deterministic merge rules:

  1. Start with built-in baseline items for selected --target.
  2. Load extension configs in fixed order: $AGENT_HOME/AGENT_DOCS.toml then $PROJECT_PATH/AGENT_DOCS.toml.
  3. Consider only extension entries with required = true and scope included by --target.
  4. Resolve each extension path, then de-dup by key: (context, scope, normalized_path).
  5. Same-key override order:
    • within one config file, later [[document]] wins (last-write-wins)
    • across files, project config wins over home config (loaded later)
  6. Output order is stable:
    • built-ins stay in built-in declaration order
    • extension items keep first-seen key order; when overridden, the item is replaced in place

This ensures baseline output is reproducible while still honoring later overrides.

AGENT_DOCS.toml Schema

Each scope may define AGENT_DOCS.toml at:

  • $AGENT_HOME/AGENT_DOCS.toml
  • $PROJECT_PATH/AGENT_DOCS.toml

Schema uses repeated [[document]] tables.

[[document]]
context = "project-dev"
scope = "project"
path = "BINARY_DEPENDENCIES.md"
required = true
when = "always"
notes = "Track required external CLIs for this project"

Field contract

Field Type Required Rules
context string yes One of: startup, skill-dev, task-tools, project-dev
scope string yes One of: home, project
path string yes Relative or absolute path to markdown doc
required bool no Default false
when string no Default always; supported values: always
notes string no Free text, default empty string

Deterministic merge contract

For resolve --context <ctx>:

  1. Start with built-in entries for <ctx>.
  2. Load entries from $AGENT_HOME/AGENT_DOCS.toml (if file exists).
  3. Load entries from $PROJECT_PATH/AGENT_DOCS.toml (if file exists).
  4. Filter entries by exact context == <ctx>.
  5. Normalize each entry path:
    • absolute path: keep as-is
    • relative path: join with root selected by entry scope
  6. De-dup with merge key: (context, scope, normalized_path).
  7. Conflict resolution order:
    • built-in keys are immutable and cannot be removed or downgraded.
    • for non-built-in duplicates, later source wins (project config overrides home config).
    • within one file, later table wins (last-write-wins).
  8. Final output order is stable:
    • built-ins in built-in declaration order
    • merged extension entries in load order after de-dup replacement

This merge behavior is deterministic and test-friendly.

De-dup examples

  • Same key appears twice in $PROJECT_PATH/AGENT_DOCS.toml: second entry wins.
  • Same key appears in both home and project configs: project entry wins.
  • Key matches built-in required doc (for example project DEVELOPMENT.md in project-dev): built-in contract remains required and present in output.

Invalid Schema Behavior

If any AGENT_DOCS.toml entry is invalid, command exits 3 and prints actionable error.

Error example: invalid context

error[AGENT_DOCS_SCHEMA]: /Users/example/work/nils-cli/AGENT_DOCS.toml:4:11
invalid value for `context`: "project"
allowed: startup, skill-dev, task-tools, project-dev

Error example: missing required field

error[AGENT_DOCS_SCHEMA]: /Users/example/.agents/AGENT_DOCS.toml:1:1
missing required key `path` in [[document]]

Error example: unsupported when

error[AGENT_DOCS_SCHEMA]: /Users/example/work/nils-cli/AGENT_DOCS.toml:7:8
invalid value for `when`: "if-env:CI"
allowed: always

Explicit BINARY_DEPENDENCIES.md Support Example

Add required BINARY_DEPENDENCIES.md for project-dev context.

CLI command:

agent-docs add \
  --target project \
  --context project-dev \
  --scope project \
  --path BINARY_DEPENDENCIES.md \
  --required \
  --when always \
  --notes "External runtime tools required by the repo"

Equivalent TOML entry:

[[document]]
context = "project-dev"
scope = "project"
path = "BINARY_DEPENDENCIES.md"
required = true
when = "always"
notes = "External runtime tools required by the repo"

resolve --context project-dev must include this document after merge, without removing built-in project DEVELOPMENT.md.

Verification command:

agent-docs resolve --context project-dev --format checklist \
  | rg "REQUIRED_DOCS_BEGIN|REQUIRED_DOCS_END|DEVELOPMENT\\.md|BINARY_DEPENDENCIES\\.md"

Snapshot Fixture Maintenance

The add command has golden/snapshot fixtures under tests/fixtures/add.

  • Run snapshot-related tests:

    scripts/ci/agent-docs-snapshots.sh
    
  • Re-generate expected snapshots (--bless) and immediately verify:

    scripts/ci/agent-docs-snapshots.sh --bless
    

Docs