File capture is the zero-integration path. Point Assay at logs the harness already wrote. No agent change. No daemon required.
assay capture claude-code
assay capture grok
assay capture codex
assay capture opencode
Each adapter is incremental (a high-water mark per file) and idempotent (same producer event, same span). Safe on any schedule.

What each adapter reads

CommandTypical rootWhat you get
claude-code~/.claude/projectsPriced spans + sealed turns
grok~/.grok/sessionsSealed turns (and spans when usage is present)
codex~/.codex/sessionsSealed turns
opencode~/.local/share/opencodeSealed turns
Roots are in the config under capture. Override per run with the adapter’s flags (assay capture claude-code --help). A missing root is skipped when the sweep runs. A direct assay capture <name> against a missing root reports that.

Custom harness

assay capture --adapter ./my-adapter.js
Write a source adapter, check it with the conformance helper, then load it. See the CLI help for --adapter. First-party catalog today: Claude Code, Grok, Codex, OpenCode.

What capture writes

For each new sitting:
  1. Spans — tokens, model, cost when priced.
  2. Turns — scrubbed, sealed conversation lines, joined to spend when the harness supplies the link.
  3. Search postings — messages and reasoning only, on this machine.
  4. On the sweep cadence, retrieve-only attributes: products from path mentions, scopes from writes, openings.
Capture does not call a model. Labelling is a separate switch.

Sweep

assay sweep on     # 30-minute timer
assay sweep off
assay sweep        # run once now
sweep (the once form) does:
  1. Capture each first-party adapter whose root exists.
  2. Retrieve-only attributes. No judge.
  3. If labelling is on: assay labelling run.
See Labelling.

Postgres

Inspection and many writes accept --pg <dsn> or $ASSAY_PG_DSN. File capture of harness logs is the SQLite collector path. A host that already writes to Postgres should embed or ingest instead of scraping local files.