Skip to content

Command Registry

github-actions[bot] edited this page Oct 9, 2026 · 3 revisions

Command Registry

← Architecture · JSON-Output · Commands · Compat-V15


The command registry is one machine-readable description of every nSelf command: its path, summary, flags, arguments, side effects, output kind, JSON support and canon status. Agents, the MCP server, docs and CI read it instead of scraping --help.

There is no commands verb. The registry is published two ways.

nself help --json                 # the whole registry
nself help --json config          # only `nself config` and its subcommands
nself help --json config get      # only `nself config get`

nself help --json works from any directory and needs no project. It prints one v1 JSON envelope (JSON-Output) with "command": "help"; the registry is the envelope's data. A path that names no command fails with E401, exit 1, nothing on stdout. Without --json, nself help [command] is cobra's usual help, unchanged.

The committed copy is .github/command-registry.json. It is the same document plus a first key _generated, and it documents the v1.5 contract. nself help --json reports the mode it runs in: the exit codes and the JSON support of the v1.5-only pilots follow NSELF_V15 (Compat-V15). With NSELF_V15=1, nself help --json | jq -S .data equals the committed file without _generated.

How a command moves

A move changes data, not the command's source. Edit the Ticket's fragment under internal/canon/domains/ (a moves, shims, retired_hubs, breakouts or removed row), then regenerate everything the move touches:

make canon cmd-inventory wiki-commands parity

make canon rewrites the engine's move table (cmd/commands/canon_moves_gen.go). The three generators (tools/cmdinventory, tools/wikigen, tools/parity) set NSELF_V15=1 in their own process and build from commands.PrepareTreeForGeneration(), so the committed registry, inventory, wiki pages and parity matrix always describe the v1.5 surface with builtin families only; an installed plugin is never mounted and canon plugin entries are left out of the inventory. Command-Canon (generated by cmdinventory -format canon) lists every old spelling and where it went. A moved top-level command keeps its cmd-<old>.md page as a stub: it says where the command went and keeps the old prose under Previous content. Everything in v1.5 applies from v1.5.0; the old spelling works until v1.6.0.

Counts

Counts are computed, never typed. Ask the binary:

nself help --json | jq .data.counts
Field Meaning
commands every command except the root, hidden ones and help included
top_level visible depth-1 commands, help excluded (the number the surface budget and the inventory use)
core commands that are one of the ADR 0016 verbs
pending top-level commands outside the canon whose disposition is still open
deprecated_shims hidden aliases kept for the deprecation window
core_missing verbs with no command yet
json_envelope, json_legacy commands by JSON support

Document

Fields are in this order. Consumers must ignore fields they do not know: new fields and enum values are additive and keep schema_version at "1"; a rename, removal or change of meaning is v2.

Field Type Meaning
schema_version string "1"
verbs string[] the canonical verbs (at most 20, ADR 0016), in ADR order, from internal/canon/canon.yaml
root.summary string the root command's short text
root.flags Flag[] root flags, sorted by name
commands Command[] every command except the root, sorted by path
counts object see above

Command

Field Type Meaning
path string full path, for example nself config get
name string last word of the path
parent string parent path (nself for top level)
summary string short description
hidden bool hidden from --help
deprecated string or null cobra deprecation message
aliases string[] alternative names, sorted
group string or null the --help group
runnable bool has a body; a hub that only prints help is not runnable
args Arg[] positional arguments parsed from the usage line: {name, required, variadic, secret}
flags Flag[] flags declared on this command, sorted by name. Inherited flags appear on the command that declares them. cobra's own --help is never listed
canon enum canon status, below
target string or null for deprecated-shim: the canonical path to use instead
side_effect enum highest effect of a default run, below
output enum document, stream or interactive
json enum envelope, legacy or none
data_schema string or null schema file for the envelope data when json is envelope
exit_codes object state exit codes this command documents beyond the exit classes, {} when none
confirm object or null {flags: [bool flag names], plan: {flag: bool flag, id_flag: string flag} or null}; null when no confirmation is declared
surface enum all by default, or cli-only when the whole command is unavailable to machine surfaces

Flag

name, shorthand, type (bool, string, int, stringSlice, duration, ...), default (the flag's default text, parse it by type), usage, hidden, deprecated, required, persistent, env (always null in v1), and three optional escalations that apply when the flag is set: side_effect, json and output. cli_only keeps the flag off machine surfaces; secret marks its value for redaction. Both booleans are printed even when false. Positional arguments have the same secret marker.

Surface declarations

Declare confirm, surface: cli-only, and secret_args on the command row in its canon fragment. confirm.flags lists local or inherited boolean flags; an empty list is valid for nonce confirmation. A plan form names its boolean flag and string id_flag. A flag override may declare cli_only: true or secret: true, alongside the existing output: stream override for a follow-style flag. A deprecated shim receives none of these declarations. Installed plugin commands carry the same facts through their mount annotations. Invalid plugin confirmation is omitted with one E437 warning per plugin.

cmdregistry.ToolName(path) replaces spaces and hyphens with underscores and prefixes nself_; names must be unique, at most 64 characters, and contain only lowercase letters, digits, and underscores. RoutePath(path) separates path words under /v1/commands/. EffectiveSideEffect takes the highest class from the command and set flag overrides. EffectiveOutput returns stream when a set flag declares output: stream, otherwise the command output.

Canon status

Value Meaning
core one of the canonical verbs
subcommand a command at depth 2 or deeper
deprecated-shim a hidden alias kept for the deprecation window; target names the replacement
plugin mounted from a plugin (no built-in command carries it)
pending a top-level command outside the canon; its disposition is still to be decided
builtin provided by the framework and not counted against the canon (help)

Side effects

One class per command, the highest effect of running it with default flags. The order is read < write < remote < destructive.

Class Meaning
read changes no persistent state anywhere. A remote read is still read. A hub with no body is read
write changes local state (files, containers, the local database) in a way a re-run or the inverse command restores
remote changes state on another system: deploy targets, servers, cloud APIs, registries, GitHub, licence writes
destructive deletes or overwrites data that no command can restore: volumes, rows, files, backups, servers, keys

A flag can raise the class (doctor --fix is write); no flag lowers it.

Output kinds and JSON support

  • document is one bounded result; stream runs until stopped (follow, tail, serve); interactive needs a terminal or prompts. A flag of a document command may escalate the output to stream; there is no other flag-level output value.
  • envelope commands print the v1 envelope. legacy commands print their own bare JSON. none commands refuse --json with E402. A flag may override this to legacy or none when it is set.

Rules the build enforces

The registry is built from the live cobra tree and one declared file, internal/canon/canon.yaml, keyed by command path. The build fails, naming the path, when a command has no entry, an entry names no command, an enum value is invalid, a top-level canon is not allowed at its depth, core and the verb list disagree, a shim has no valid target, a runnable command has no side_effect, a flag override does not exist or does not escalate, or YAML claims json: envelope. Envelope support is derived from the Go data-type map in cmd/commands/registry_types.go, never declared in YAML.

go test ./... also fails when .github/command-registry.json is stale (TestRegistryGolden), when canon and internal/deprecation/registry.yaml disagree about shims, or when the counts disagree with .github/command-inventory.json.

Adding a command

  1. Add the command as usual.
  2. Add one line for its path to internal/canon/canon.yaml: canon (top level only), side_effect, and output or json when they are not the defaults.
  3. Run make cmd-inventory (alias: make registry). It rewrites .github/command-registry.json, .github/command-inventory.json and the generated block of Commands. Commit all three.

The inventory is a projection of the registry, so the two cannot disagree. Its shape is unchanged.

See also

Home


Getting Started


Commands


Features


Configuration


Plugins (87 + 10 monitoring)

Free (25)
Pro (62)
Planned (26)
  • plugin-audit
  • plugin-blog
  • plugin-checkout
  • plugin-commerce
  • plugin-drm
  • plugin-export
  • plugin-flow
  • plugin-import
  • plugin-ldap
  • plugin-mailgun
  • plugin-media
  • plugin-oauth-providers
  • plugin-pages
  • plugin-postmark
  • plugin-rate-limit
  • plugin-reports
  • plugin-saml
  • plugin-scheduler
  • plugin-sendgrid
  • plugin-sso
  • plugin-subscription
  • plugin-thumb
  • plugin-transcoder
  • plugin-twilio
  • plugin-waf
  • plugin-watermark

Guides


Architecture


Reference


Machine interface


Licensing


Security


Brand


Operations


Contributing


Admin


Changelog


All commands (21)

Clone this wiki locally