import type { Command } from "commander"; import { applyCommandHelp, subcommand } from "../lib/cli-command-help.js"; import { registerCommand } from "../lib/register-command.js"; import { log } from "../logger.js"; import { appsHelp } from "./apps.help.js"; interface AppListEntry { name: string; source: string; } export function registerAppsCommand(program: Command): void { registerCommand(program, { name: appsHelp.name, transport: "local", description: appsHelp.description, build: (apps) => { applyCommandHelp(apps, appsHelp); subcommand(apps, "list").action(async (opts: { json?: boolean }) => { // Lazy-import the app store so the daemon module graph loads only when // this command runs (cli/no-daemon-internals). const { listAllApps } = await import("../../apps/app-store.js"); const entries: AppListEntry[] = listAllApps() .map(({ name, sourcePath }) => ({ name, source: sourcePath })) .sort((a, b) => a.name.localeCompare(b.name)); if (opts.json) { console.log(JSON.stringify({ ok: true, apps: entries })); return; } if (entries.length === 0) { log.info("No apps found."); return; } // Name and source lead; align the name into a column so the source // path (which also identifies the app's origin) stays scannable. const nameWidth = Math.max(4, ...entries.map((e) => e.name.length)); log.info(`Apps (${entries.length}):\n`); log.info(` ${"NAME".padEnd(nameWidth)} SOURCE`); for (const e of entries) { log.info(` ${e.name.padEnd(nameWidth)} ${e.source}`); } }); }, }); }