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:memoryURNs (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 prefixedurn: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 lsand innode get --json). Cross-memory edges are allowed. - Null/omitted flags mean "unset" — update commands only change the fields you pass.
Write semantics¶
memory setcreates when called without a positional argument (requires--organd--name) and updates when given one.node addfails if the loc already exists;node updatepreserves 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--yeswhen 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
00under a feature (msg:010:00), feature000under a module (msg:000), and — in a product-rooted corpus — modulegenunder a product (api:gen). Scaffold any of them withspec new … --contract. Introducing a contract into a tier that already has siblings is retroactive:lintthen 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;specrefuses to renumber an existing citation. - The register is advisory. Next-free numbers come from the live nodes;
specnever writes the register node. Usespec register --checkto catch a stale ledger. spec findis 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 supersederequires--yeswhen 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.
| 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
--agentcontributes — sibling agents installed in the same App are not consulted. - Output is masked. It never carries key material — only
hasApiKeyand the shortapiKeyPreview.--jsonemits the full masked record:id,name,ownerType,ownerId,provider,model,hasApiKey,apiKeyPreview,params,enabled,createdAt,updatedAt. --appdefaults to the configured App context (hadron app useor the global--appflag);--agentnarrows to one agent. Both accept an ID or a URN.- You must be a member of the App, and — when
--agentis 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