xPulse
πŸ‡¬πŸ‡§ EN

COMP_cli_adr-001 – Command Registration via Autodiscovery

Status: ACCEPTED Date: 2026-03-16 Author: xPulse


Context

@xpulse/cli needs a mechanism to aggregate commands from various xParts without having to depend on them – and without boilerplate in every xPart.

Additionally, a command should be fully abstracted from CLI internals: no import of @xpulse/event, no manual emission of cli:done, no knowledge of timeout mechanisms.

Decision

@xpulse/cli is a runner – not a command owner.

@xpulse/cli discovers β†’ @xpulse/doc/src/commands/FetchCommand.js
β†’ @xpulse/config/src/commands/ConfigShowCommand.js

Command Contract

import { Command } from '@xpulse/cli/command';
export class FetchCommand extends Command {
configure() {
this
.setName('doc:fetch')
.setAlias('df')
.setDescription('Fetch docs via git archive')
.addArgument('tool', null, 'Tool name')
.addOption('tag', null, 'Git tag')
.addFlag('dry-run', false, 'Dry run');
}
async run(input, output) {
while (!done) {
await doWork();
this.keepAlive(); // ← no event import required
}
output.success('Done!');
return 0; // ← exit code instead of cli:done event
}
}

Full Abstraction

A command imports nothing from @xpulse/event and knows nothing about CLI internals. @xpulse/cli handles everything:

Task Who does it
Autodiscovery @xpulse/cli
Build input @xpulse/cli
Build output @xpulse/cli
Inject keepAlive function @xpulse/cli
Start + stop timer @xpulse/cli
process.exit(code) @xpulse/cli
Implement logic xPart

Exit Codes

run() returns a numeric exit code – the well-known Unix scheme:

Code Meaning
0 Success
1 Error
2 Misuse – wrong or missing arguments

@xpulse/cli calls process.exit(exitCode) after run(). No cli:done event – run() resolves and the process ends.

`cli:keepalive` – internal

cli:keepalive continues to exist as an internal event in @xpulse/cli. xParts do not see it – they call this.keepAlive(), and the base class emits the event internally via an injected function.

`--help` + `--list`

xpulse --help # all commands with name, alias, description
xpulse --help doc:fetch # command detail with arguments, options, flags, example
xpulse --list # names only, machine-readable – for autocomplete/scripting

Dependencies

@xpulse/cli β†’ @xpulse/event ← internal for keepAlive

Rationale

Consequences

Alternatives Rejected

en/adr/adr-001-command-registration.md 2026-03-27