Rename the CLI binary, socket path, container wrapper, error prefixes, and all references from `nc` to `ncl`. Add ~/.local/bin symlink during setup and pnpm script alias. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
39 lines
1.3 KiB
TypeScript
39 lines
1.3 KiB
TypeScript
/**
|
|
* Command registry — single source of truth for what `ncl` can do.
|
|
*
|
|
* Each command file under `commands/` calls `register()` at top level,
|
|
* and `commands/index.ts` imports them all for side effects so the
|
|
* registry is populated before the host's CLI server accepts connections.
|
|
*/
|
|
import type { CallerContext } from './frame.js';
|
|
|
|
export type Access = 'open' | 'approval' | 'hidden';
|
|
|
|
export type CommandDef<TArgs = unknown, TData = unknown> = {
|
|
name: string;
|
|
description: string;
|
|
access: Access;
|
|
/** Resource this command belongs to (for help grouping). */
|
|
resource?: string;
|
|
/** Validates `frame.args` and produces the typed handler input. Throws on invalid. */
|
|
parseArgs: (raw: Record<string, unknown>) => TArgs;
|
|
handler: (args: TArgs, ctx: CallerContext) => Promise<TData>;
|
|
};
|
|
|
|
const registry = new Map<string, CommandDef>();
|
|
|
|
export function register<TArgs, TData>(def: CommandDef<TArgs, TData>): void {
|
|
if (registry.has(def.name)) {
|
|
throw new Error(`CLI command "${def.name}" already registered`);
|
|
}
|
|
registry.set(def.name, def as CommandDef);
|
|
}
|
|
|
|
export function lookup(name: string): CommandDef | undefined {
|
|
return registry.get(name);
|
|
}
|
|
|
|
export function listCommands(): CommandDef[] {
|
|
return [...registry.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
}
|