Skip to content

hadron CLI

Command surface and stable contracts of the hadron command-line interface. Installation and sign-in live in Install the hadron CLI. The CLI also documents itself: hadron agentic-usage prints the complete agent-facing contract, and hadron <command> --help covers every flag.

Source: hadron-memory/hadron-cli.

Command surface (v1)

hadron auth login | logout | whoami | status
hadron memory ls | get <id-or-urn> | set [<id-or-urn>] | rm <id-or-urn>
hadron node ls [-m <memory>] | get <urn> | add | update <urn> | rm <urn>
hadron edge ls <node-urn> | add | update <edge-id> | rm <edge-id>
hadron spec ls [-m <memory>] | get <citation> | register | find <query> | new | lint | supersede <citation> | import
hadron app ls --org <org> | install | uninstall <id> | use <urn>
hadron ai-config ls [--app <id-or-urn>] [--agent <id-or-urn>]
hadron config get | set | list
hadron api <query-or-mutation>      # raw GraphQL escape hatch
hadron version
hadron completion <shell>
hadron agentic-usage                # prints the agent contract

Global flags

Flag Effect
--json Machine-readable output on stdout; progress/errors on stderr. Field names are stable: new fields may be added, existing ones are never renamed or removed without a major version bump.
--server <url> Hadron server base URL for this invocation (default https://srv.hadronmemory.com; persist with hadron config set server).
--app <urn> App URN context for this invocation (persist with hadron app use). Most calls need none.

With --json, errors are emitted on stderr as {"error":{"code":<exit-code>,"message":"..."}}.

Exit codes (stable contract)

Code Meaning
0 success
1 generic failure
2 usage error (bad flags/arguments, missing --yes)
3 authentication required or rejected
4 not found (or not visible to this principal)
5 conflict (e.g. duplicate install)
6 cancelled / timed out waiting for the user

Scripts and agents should branch on exit codes, not parse error text.

Reference conventions

  • Memory references are org:memory URNs (e.g. acme.com:kb) or IDs — every command that takes an ID also accepts the URN.
  • Node references are always fully-qualified URNs: <org>:<memory>:<loc> (e.g. acme.com:kb:findings:flaky-ci), optionally prefixed urn:node:. Bare locs are rejected with exit 2 — the same loc can exist in several memories. See URN composition.
  • Edges are directed and labeled; endpoints are node URNs at creation, and the edge is addressed by its edge ID afterwards (shown by edge ls and in node get --json). Cross-memory edges are allowed.
  • Null/omitted flags mean "unset" — update commands only change the fields you pass.

Write semantics

  • memory set creates when called without a positional argument (requires --org and --name) and updates when given one.
  • node add fails if the loc already exists; node update preserves unset fields. Content comes from --content "<text>", --content - (stdin), or --content-file <path>.
  • Destructive commands (memory rm, node rm, edge rm, app uninstall) prompt on a terminal and require --yes when run non-interactively. Without it they exit 2.

Product specs

hadron spec maintains product-spec nodes in a memory that follows the loc-as-citation convention: a spec's loc is its citation number — a legal-code-style address where each colon level is a real parent/child node. A memory uses one of two schemes:

  • flat<module>:<feature>:<rule>[:<flow>] (e.g. msg:010:02).
  • product-rooted<product>:<module>:<feature>:<rule>[:<flow>] (e.g. api:cha:010:01), for a memory that spans several products.

The scheme is self-describing — the second segment is alpha (a module) when product-rooted, numeric (a feature) when flat — and a memory should use only one. A register node holds the frozen module-code table and the number ledger. Every subcommand takes -m <org::memory>; specs are addressed by a bare citation, not a full node URN.

Command Purpose
spec describe [--declare flat\|product] Report the memory's scheme (flat/product), products, modules, and counts. --declare records the scheme in the memory's data.
spec ls [--prefix <loc>] List specs, optionally under a citation prefix.
spec get <citation> Show one spec: abstract, edges, body, and a lint summary.
spec register [--check] Print the number ledger derived from live nodes. --check reports drift against the register node and exits 5 if any is found.
spec find <query> [--match-exactly] Find specs by meaning (hybrid keyword + vector). --match-exactly switches to literal keyword search.
spec new [--product <ppp>] [--module <mmm>] --title <t> … Allocate the next citation and scaffold the rubric plus edges. --new-product / --new-module / --new-feature mint their respective tiers; --contract scaffolds the tier's general-provisions contract; --dry-run previews.
spec lint [<citation>] [--product <ppp>] [--module <mmm>] [--all] [--strict] Validate one spec, a product, a module, or the corpus against the rubric and stability rules. Exits 5 on errors.
spec supersede <old> --title <t> [--copy-body] --yes Retire a spec and mint its replacement with a superseded-by edge.
spec import spec-kit\|code <path> Planned extractors — not yet implemented (exit 2).

Numbering and stability:

  • Features are numbered in tens (010, 020, …); rules and flows increment by one. Allocation is monotonic — strictly above the current maximum — so a retired number is never recycled.
  • General-provisions contracts. Each tier has a reserved contract its siblings inherit: rule 00 under a feature (msg:010:00), feature 000 under a module (msg:000), and — in a product-rooted corpus — module gen under a product (api:gen). Scaffold any of them with spec new … --contract. Introducing a contract into a tier that already has siblings is retroactive: lint then requires each existing sibling to be back-wired with an inheritance edge before it passes.
  • Citations are never renumbered. To relocate or replace a spec, use spec supersede; spec refuses to renumber an existing citation.
  • The register is advisory. Next-free numbers come from the live nodes; spec never writes the register node. Use spec register --check to catch a stale ledger.
  • spec find is semantic by default and relies on the memory's vector index; without one it falls back to keyword and prints a note. Like the other destructive commands, spec supersede requires --yes when non-interactive.
hadron spec describe -m acme.com::platform-specs   # which scheme?
hadron spec new -m acme.com::specs --module msg --feature 010 \
  --title "W4 — 7-day check-in" --dry-run     # preview the allocation
hadron spec lint --all -m acme.com::specs       # check the corpus
hadron spec find "re-engage idle users" -m acme.com::specs

See Maintain product specs for the end-to-end workflow.

AI service configs

hadron ai-config ls lists the masked set of AI service configs resolvable in an App's chat context — every distinct config name a chat could select. It is the config picker an app or UI presents; each row is the one resolveAIConfig would pick for that name.

hadron ai-config ls [--app <id-or-urn>] [--agent <id-or-urn>] [--json]
Column Meaning
NAME Config name, unique per owner (e.g. default, fast, frontier).
OWNER Tier that owns the winning row: HADRON_SERVER, ORGANIZATION, APP, or AGENT.
PROVIDER / MODEL Provider id (anthropic, openai, glm, bedrock) and model identifier.
ENABLED Whether the config is enabled.
KEY Key preview (ellipsis + last 4 characters), or when no key is set.

Resolution and masking:

  • Resolution walks App → Agent → Org → HadronServer, deduped by name with the innermost owner winning, enabled-only. Only the agent you name with --agent contributes — sibling agents installed in the same App are not consulted.
  • Output is masked. It never carries key material — only hasApiKey and the short apiKeyPreview. --json emits the full masked record: id, name, ownerType, ownerId, provider, model, hasApiKey, apiKeyPreview, params, enabled, createdAt, updatedAt.
  • --app defaults to the configured App context (hadron app use or the global --app flag); --agent narrows to one agent. Both accept an ID or a URN.
  • You must be a member of the App, and — when --agent is given — the agent must be installed in it. App membership, not org-admin, is the bar because the result is masked. Platform admins may omit --app.
hadron ai-config ls --app acme.com:juno-app
hadron ai-config ls --app acme.com:juno-app --agent acme.com:juno --json

To create or rotate the underlying provider keys (the App/Agent/Org-owned rows this picker resolves over), see Configure your LLM provider.

Authentication

Mechanism Use
hadron auth login Interactive browser OAuth; token stored in the OS keychain.
printf '%s\n' "$TOKEN" \| hadron auth login --with-token Store a portal-minted hdr_user_* personal access token.
HADRON_TOKEN env var Overrides stored tokens — CI and agent contexts.

hadron auth status answers "am I signed in?" via exit code (0 yes / 3 no).

The escape hatch: hadron api

Anything the curated commands don't cover is reachable as raw GraphQL (see the GraphQL API reference):

hadron api 'query { me { id email } }'
hadron api 'query($id: ID!) { memory(id: $id) { urn name } }' -F id=mem_123
cat op.graphql | hadron api -

-F key=value binds variables — values that parse as JSON are sent as JSON, otherwise as strings. The verbatim GraphQL response envelope prints to stdout; GraphQL errors are reflected in the exit code.

Recipes

# Inspect a memory and its nodes
hadron memory get acme.com:kb --json
hadron node ls -m acme.com:kb --json

# Read one node's content and edges
hadron node get acme.com:kb:findings:flaky-ci --json

# Create a node from stdin
cat finding.md | hadron node add -m acme.com:kb --loc findings:flaky-ci \
  --name "Flaky CI" --content -

# Connect two nodes
hadron edge add --from acme.com:kb:findings:flaky-ci \
  --to acme.com:kb:start-here --label routes-to

# Delete non-interactively (agents must pass --yes)
hadron node rm acme.com:kb:findings:flaky-ci --yes