Files
stack/packages/macp/src/cli.ts
jason.woltje df460d5a49
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
feat(macp): mosaic macp CLI surface (#410)
2026-04-05 06:33:52 +00:00

93 lines
4.2 KiB
TypeScript

import type { Command } from 'commander';
/**
* Register macp subcommands on an existing Commander program.
* This avoids cross-package Commander version mismatches by using the
* caller's Command instance directly.
*/
export function registerMacpCommand(parent: Command): void {
const macp = parent.command('macp').description('MACP task and gate management');
// ─── tasks ───────────────────────────────────────────────────────────────
const tasks = macp.command('tasks').description('Manage MACP tasks');
tasks
.command('list')
.description('List MACP tasks')
.option(
'--status <status>',
'Filter by task status (pending|running|gated|completed|failed|escalated)',
)
.option(
'--type <type>',
'Filter by task type (coding|deploy|research|review|documentation|infrastructure)',
)
.action((opts: { status?: string; type?: string }) => {
// not yet wired — task persistence layer is not present in @mosaicstack/macp
console.log('[macp] tasks list: not yet wired — use macp package programmatically');
if (opts.status) {
console.log(` status filter: ${opts.status}`);
}
if (opts.type) {
console.log(` type filter: ${opts.type}`);
}
process.exitCode = 0;
});
// ─── submit ──────────────────────────────────────────────────────────────
macp
.command('submit <path>')
.description('Submit a task from a JSON/YAML spec file')
.action((specPath: string) => {
// not yet wired — task submission requires a running MACP server
console.log('[macp] submit: not yet wired — use macp package programmatically');
console.log(` spec path: ${specPath}`);
console.log(' task id: (unavailable — no MACP server connected)');
console.log(' status: (unavailable — no MACP server connected)');
process.exitCode = 0;
});
// ─── gate ────────────────────────────────────────────────────────────────
macp
.command('gate <spec>')
.description('Run a gate from a spec string or file path (wraps runGate/runGates)')
.option('--fail-on <mode>', 'Gate fail-on mode: ai|fail|both|none', 'fail')
.option('--cwd <path>', 'Working directory for gate execution', process.cwd())
.option('--log <path>', 'Path to write gate log output', '/tmp/macp-gate.log')
.option('--timeout <seconds>', 'Gate timeout in seconds', '60')
.action((spec: string, opts: { failOn: string; cwd: string; log: string; timeout: string }) => {
// not yet wired — gate execution requires a task context and event sink
console.log('[macp] gate: not yet wired — use macp package programmatically');
console.log(` spec: ${spec}`);
console.log(` fail-on: ${opts.failOn}`);
console.log(` cwd: ${opts.cwd}`);
console.log(` log: ${opts.log}`);
console.log(` timeout: ${opts.timeout}s`);
process.exitCode = 0;
});
// ─── events ──────────────────────────────────────────────────────────────
const events = macp.command('events').description('Stream MACP events');
events
.command('tail')
.description('Tail MACP events from the event log (wraps event emitter)')
.option('--file <path>', 'Path to the MACP events NDJSON file')
.option('--follow', 'Follow the file for new events (like tail -f)')
.action((opts: { file?: string; follow?: boolean }) => {
// not yet wired — event streaming requires a live event source
console.log('[macp] events tail: not yet wired — use macp package programmatically');
if (opts.file) {
console.log(` file: ${opts.file}`);
}
if (opts.follow) {
console.log(' mode: follow');
}
process.exitCode = 0;
});
}