How Creation Works
How definitions are turned into runtime objects and how plugin onInit hooks run.
Runtime Objects
Each definition type produces a runtime object that wraps the original definition alongside its extracted manifest:
CliDefinition → Cli { manifest, command, plugins }
CommandDefinition → Command { definition, manifest, commands, paths, bequeathOptions }
PluginDefinition → Plugin { definition, manifest }
OptionDefinition → Option { definition, manifest }CLI Creation
createCli() is the main orchestrator. It runs in this order:
- When
metaUrlis set and any ofname,version, ordescriptionare omitted, reads the nearestpackage.json(walking up from that module’s directory) and fills those fields - Extracts the CLI manifest via
getCliManifest() - Creates the root command tree (if a command definition is provided), including bequeath options
- Creates plugins from
plugins(in array order) - Assembles the
Cliobject - Runs
onInithooks for each plugin, passing theCliobject
If any onInit hook throws, creation fails immediately — the error is logged and re-thrown.
Command Tree
createCommand() builds the command tree recursively. For each command definition:
- Reads
commands - Calls
createCommand()for each child definition - Stores children in a
ManifestKeyedMapkeyed bymanifest.name - Extracts the command manifest via
getCommandManifest() - Resolves
paths— defaults to[definition.name]if none provided
createRootCommand() is a thin wrapper that adds name: "root" and delegates to createCommand().
ManifestKeyedMap
Collections of commands, plugins, and bequeath options use ManifestKeyedMap — a Map-backed collection that derives the key from each item via its manifest.name property. It provides:
- Uniqueness enforcement — adding a duplicate key overwrites the previous value
- Key-based lookup via
.get(key) - Iteration via
.values()orfor...of - Convenient
.set(value)method that automatically usesvalue.manifest.nameas the key
This is what allows cli.plugins, command.bequeathOptions, and command.commands to be both iterable and key-addressable.
Plugin onInit Mutation
After the Cli object is assembled, onInit hooks run in insertion order. Hooks receive { cli, plugin } and can mutate the CLI directly:
- Replace
cli.commandwith a new command tree - Add items to
command.bequeathOptions - Modify
cli.plugins
The standard library plugins use this to inject help and version commands and global options. See Creating Plugins.