diff --git a/src/commands/bar/help-subcommand.ts b/src/commands/bar/help-subcommand.ts new file mode 100644 index 00000000..139dd234 --- /dev/null +++ b/src/commands/bar/help-subcommand.ts @@ -0,0 +1,56 @@ +import { color, dim, header, initUI, subheader } from '../../utils/ui'; + +export async function showHelp(): Promise { + await initUI(); + console.log(''); + console.log(header('CCS Bar (macOS Menu Bar App)')); + console.log(''); + console.log(subheader('Usage:')); + console.log(` ${color('ccs bar', 'command')} [command] [options]`); + console.log(''); + + const sections: [string, [string, string][]][] = [ + [ + 'Commands:', + [ + ['launch', 'Start the web-server, write ~/.ccs/bar.json, and open the app (default)'], + ['install', 'Download CCS Bar from the ccs-bar-latest GitHub release into ~/Applications'], + ['uninstall', 'Remove the app and version pin'], + ['version', 'Show CLI and installed app versions'], + ], + ], + [ + 'Options:', + [ + ['--help, -h', 'Show this help message'], + ['--version', 'Show CLI and installed app versions'], + ], + ], + [ + 'Examples:', + [ + ['ccs bar', 'Start the web-server and open CCS Bar (default launch)'], + ['ccs bar install', 'Download and install CCS Bar into ~/Applications'], + ['ccs bar version', 'Show CLI and installed app versions'], + ['ccs bar uninstall', 'Remove CCS Bar and its version pin'], + ], + ], + ]; + + for (const [title, rows] of sections) { + console.log(subheader(title)); + const width = Math.max(...rows.map(([command]) => command.length)); + for (const [command, description] of rows) { + console.log(` ${color(command.padEnd(width + 2), 'command')} ${description}`); + } + console.log(''); + } + + console.log(dim(' macOS only. The app communicates with the CCS web-server on localhost only.')); + console.log( + dim( + ' Ad-hoc signed builds may require right-click > Open or `xattr -dr com.apple.quarantine` on first launch.' + ) + ); + console.log(''); +} diff --git a/src/commands/bar/index.ts b/src/commands/bar/index.ts index 717aaff3..6ae1e57f 100644 --- a/src/commands/bar/index.ts +++ b/src/commands/bar/index.ts @@ -2,12 +2,23 @@ * `ccs bar` command dispatcher * * Mirrors the pattern in src/commands/docker/index.ts. - * Subcommands: launch (default), install, uninstall, version / --version. + * Subcommands: launch (default), install, uninstall, version / --version, help / --help / -h. */ +import { hasAnyFlag } from '../arg-extractor'; + export async function handleBarCommand(args: string[]): Promise { const subcommand = args[0]; + // --help / -h anywhere in args (e.g. `ccs bar install --help`) → show help. + // Mirrors docker/index.ts: hasAnyFlag(normalizedArgs, ['--help', '-h']). + // Also dispatch bare `help` subcommand for symmetry. + if (hasAnyFlag(args, ['--help', '-h']) || subcommand === 'help') { + const { showHelp } = await import('./help-subcommand'); + await showHelp(); + return; + } + // --version / version are aliases for the version subcommand if (subcommand === '--version' || subcommand === 'version') { const { handleBarVersion } = await import('./version-subcommand'); @@ -39,7 +50,7 @@ export async function handleBarCommand(args: string[]): Promise { const handler = commandHandlers[subcommand]; if (!handler) { console.error(`[X] Unknown bar subcommand: ${subcommand}`); - console.error('[i] Usage: ccs bar [launch|install|uninstall|--version]'); + console.error('[i] Usage: ccs bar [launch|install|uninstall|version|--help]'); return; } diff --git a/src/commands/command-catalog.ts b/src/commands/command-catalog.ts index 3f54961e..4043a68e 100644 --- a/src/commands/command-catalog.ts +++ b/src/commands/command-catalog.ts @@ -342,6 +342,7 @@ export const COMMAND_FLAG_SUGGESTIONS: Readonly await showProviderShortcutHelp('cursor', writeLine), proxy: async () => process.exit(await (await import('./proxy-command')).handleProxyCommand(['--help'])), + bar: async () => (await import('./bar/help-subcommand')).showHelp(), docker: async () => (await import('./docker/help-subcommand')).showHelp(), migrate: async () => (await import('./migrate-command')).printMigrateHelp(), setup: async () => (await import('./setup-command')).handleSetupCommand(['--help']),