assay init writes a config so later verbs need no repeated flags.

Which file

--config-file$ASSAY_CONFIG./assay.config.json~/.config/assay/config.json → none. Each value: flag > env > config > built-in default.

Shape after init

{
  "db": "~/.local/state/assay/assay.sqlite",
  "keyFile": "~/.config/assay/transcript.key",
  "principal": "user:you",
  "mode": "corpus",
  "capture": {
    "claudeCodeRoot": "~/.claude/projects",
    "grokRoot": "~/.grok/sessions",
    "codexRoot": "~/.codex/sessions",
    "opencodeRoot": "~/.local/share/opencode"
  }
}
~ is expanded.

Mode

Value
corpusYour own work with AI. Labelling is in scope.
observabilitySomeone else’s agent loop. Labelling optional.

Products

Optional. See Products.
{
  "products": {
    "workspaceRoots": ["~/code"],
    "groups": {
      "website": ["marketing-site", "docs-site"]
    }
  }
}
A component in two groups is a load error.

Labelling

Used when you run assay labelling on. Name a harness CLI, or an API:
{
  "labelling": {
    "api": {
      "url": "https://api.example.com/v1/chat/completions",
      "model": "your-model",
      "keyEnv": "YOUR_API_KEY"
    }
  }
}
keyEnv is the name of an environment variable. Never the secret. Optional search.kinds if you want tool traffic in the index. Default is messages and reasoning only. See Search.

Forward compatibility

Unknown top-level section: warning, ignored. Unknown key inside a section this build owns: fail loud. --strict-config / $ASSAY_STRICT_CONFIG=1: unknown top-level section is an error. Use in CI. When you add a section a newer Assay understands, upgrade the binary. assay --version is the check. A section the installed build ignores is silence of a different kind.

Postgres

$ASSAY_PG_DSN or --pg. Do not also pass --db. A config db key is the SQLite path. It is not a second name for Postgres.