Files
ccs/src/commands/help-command.ts
T
Tam Nhu Tran bf5fcfc034 docs(help): add kiro idc flag guidance
- add a dedicated 'ccs help kiro' topic with IDC and paste-callback examples

- link the providers help topic to the new Kiro-specific help surface
2026-04-05 02:17:50 -04:00

303 lines
10 KiB
TypeScript

import packageJson from '../../package.json';
import { color, dim, header, initUI, subheader } from '../utils/ui';
import {
BUILTIN_PROVIDER_SHORTCUTS,
ROOT_COMMAND_CATALOG,
ROOT_COMPATIBLE_ALIAS_EXAMPLES,
ROOT_HELP_TOPICS,
ROOT_PROFILE_EXAMPLES,
getPublicRootCommands,
type HelpTopicName,
type RootCommandEntry,
} from './command-catalog';
type HelpWriter = (line: string) => void;
function getTopicSummary(name: HelpTopicName): string {
return ROOT_HELP_TOPICS.find((topic) => topic.name === name)?.summary || '';
}
function writeCommandTable(
title: string,
entries: readonly { name: string; summary: string }[],
writeLine: HelpWriter
): void {
writeLine(subheader(title));
const maxWidth = Math.max(...entries.map((entry) => entry.name.length));
for (const entry of entries) {
writeLine(` ${color(entry.name.padEnd(maxWidth + 2), 'command')} ${entry.summary}`);
}
writeLine('');
}
function writeGroupedCommands(group: RootCommandEntry['group'], writeLine: HelpWriter): void {
const entries = getPublicRootCommands()
.filter((entry) => entry.group === group)
.map((entry) => ({ name: entry.name, summary: entry.summary }));
const titles: Record<RootCommandEntry['group'], string> = {
start: 'Start Here',
manage: 'Profile Management',
operations: 'Operations',
runtime: 'Compatible Runtimes',
};
writeCommandTable(titles[group], entries, writeLine);
}
async function showProfilesHelp(writeLine: HelpWriter): Promise<void> {
await initUI();
writeLine(header('CCS Profiles Help'));
writeLine('');
writeCommandTable(
'Profile Types',
[
{ name: 'ccs auth create <name>', summary: 'Concurrent Claude account profile' },
{ name: 'ccs api create', summary: 'API-backed settings profile' },
{ name: 'ccs cliproxy create <name>', summary: 'Named CLIProxy variant profile' },
{ name: 'ccs env <profile>', summary: 'Export an existing profile for other tools' },
],
writeLine
);
writeCommandTable('Examples', ROOT_PROFILE_EXAMPLES, writeLine);
writeLine(` ${dim('Deep help: ccs auth --help | ccs api --help | ccs cliproxy --help')}`);
writeLine('');
}
async function showProvidersHelp(writeLine: HelpWriter): Promise<void> {
await initUI();
writeLine(header('CCS Providers Help'));
writeLine('');
writeCommandTable('Built-in OAuth Providers', BUILTIN_PROVIDER_SHORTCUTS, writeLine);
writeCommandTable(
'Common Setup Paths',
[
{
name: 'ccs <provider> --auth',
summary: 'Authenticate a provider account without launching',
},
{ name: 'ccs api create --preset <id>', summary: 'Create an API-backed provider profile' },
{ name: 'ccs config', summary: 'Use the dashboard for provider and model setup' },
{ name: 'ccs help kiro', summary: 'Kiro-specific auth methods and IDC flags' },
],
writeLine
);
writeLine(` ${dim('Deep help: ccs cliproxy --help | ccs api --help')}`);
writeLine('');
}
async function showKiroHelp(writeLine: HelpWriter): Promise<void> {
await initUI();
writeLine(header('CCS Kiro Help'));
writeLine('');
writeLine(' Kiro supports Builder ID, IDC, and management-only social OAuth flows.');
writeLine('');
writeCommandTable(
'Authentication Methods',
[
{ name: 'ccs kiro --auth', summary: 'Default AWS Builder ID device-code flow' },
{
name: 'ccs kiro --auth --kiro-auth-method aws-authcode',
summary: 'AWS Builder ID auth-code flow via local callback server',
},
{
name: 'ccs kiro --auth --kiro-auth-method idc',
summary: 'IAM Identity Center flow; requires IDC start URL',
},
{
name: 'ccs config',
summary: 'Dashboard flow for GitHub OAuth and account management',
},
],
writeLine
);
writeCommandTable(
'Kiro Flags',
[
{
name: '--kiro-auth-method <aws|aws-authcode|google|github|idc>',
summary: 'Select the Kiro auth method',
},
{ name: '--kiro-idc-start-url <url>', summary: 'Required IDC start URL when using `idc`' },
{ name: '--kiro-idc-region <region>', summary: 'Optional IDC region override' },
{ name: '--kiro-idc-flow <authcode|device>', summary: 'IDC flow type; defaults to authcode' },
{
name: '--paste-callback',
summary: 'Paste the final callback URL for callback-based CLI auth flows',
},
{ name: '--import', summary: 'Import an existing Kiro IDE token instead of starting OAuth' },
],
writeLine
);
writeCommandTable(
'Examples',
[
{ name: 'ccs kiro --auth', summary: 'Start the default Builder ID device flow' },
{
name: 'ccs kiro --auth --kiro-auth-method aws-authcode --paste-callback',
summary: 'Use auth-code flow and paste the callback URL manually',
},
{
name: 'ccs kiro --auth --kiro-auth-method idc --kiro-idc-start-url https://d-xxx.awsapps.com/start',
summary: 'Start IDC auth with the default authcode flow',
},
{
name: 'ccs kiro --auth --kiro-auth-method idc --kiro-idc-start-url https://d-xxx.awsapps.com/start --kiro-idc-flow device',
summary: 'Use IDC device-code flow instead of authcode',
},
],
writeLine
);
writeLine(
` ${dim('GitHub OAuth is dashboard-only: ccs config -> Accounts -> Add Kiro account')}`
);
writeLine('');
}
async function showTargetsHelp(writeLine: HelpWriter): Promise<void> {
await initUI();
writeLine(header('CCS Targets Help'));
writeLine('');
writeCommandTable('Target Routing', ROOT_COMPATIBLE_ALIAS_EXAMPLES, writeLine);
writeCommandTable(
'Examples',
[
{ name: 'ccs glm --target droid', summary: 'Run a profile on Droid instead of Claude' },
{
name: 'ccs --target codex',
summary: 'Open a native Codex session with your current setup',
},
{ name: 'ccs codex-api --target codex', summary: 'Run a routed API bridge on native Codex' },
],
writeLine
);
}
export async function handleHelpCommand(writeLine: HelpWriter = console.log): Promise<void> {
await initUI();
writeLine(header(`CCS CLI v${packageJson.version}`));
writeLine('');
writeLine(' Claude profile switching, provider routing, and compatible runtime bridges.');
writeLine('');
writeLine(subheader('Usage'));
writeLine(` ${color('ccs <profile> [claude-args...]', 'command')}`);
writeLine(` ${color('ccs <command> [options]', 'command')}`);
writeLine(` ${color('ccs help <topic>', 'command')}`);
writeLine('');
writeGroupedCommands('start', writeLine);
writeGroupedCommands('manage', writeLine);
writeGroupedCommands('runtime', writeLine);
writeGroupedCommands('operations', writeLine);
writeCommandTable(
'OAuth Provider Shortcuts',
BUILTIN_PROVIDER_SHORTCUTS.map((entry) => ({
name: `ccs ${entry.name}`,
summary: entry.summary,
})),
writeLine
);
writeCommandTable('Examples', ROOT_PROFILE_EXAMPLES, writeLine);
writeCommandTable('Targets and Aliases', ROOT_COMPATIBLE_ALIAS_EXAMPLES, writeLine);
writeCommandTable(
'More Help',
[
{ name: 'ccs help profiles', summary: getTopicSummary('profiles') },
{ name: 'ccs help providers', summary: getTopicSummary('providers') },
{ name: 'ccs help completion', summary: getTopicSummary('completion') },
{ name: 'ccs help targets', summary: getTopicSummary('targets') },
{ name: 'ccs api --help', summary: 'Deep help for API profile lifecycle commands' },
{ name: 'ccs cliproxy --help', summary: 'Deep help for variants, quota, and lifecycle' },
{ name: 'ccs docker --help', summary: 'Deep help for Docker deployment commands' },
{ name: 'ccs cursor --help', summary: 'Deep help for Cursor runtime/admin commands' },
{ name: 'ccs copilot --help', summary: 'Deep help for GitHub Copilot commands' },
],
writeLine
);
writeLine(` ${dim('Flags: -h/--help, -v/--version, -sc/--shell-completion, --target <cli>')}`);
writeLine('');
}
function listHelpTargets(): string {
return ROOT_HELP_TOPICS.map((topic) => topic.name).join(', ');
}
export async function handleHelpRoute(
args: string[],
writeLine: HelpWriter = console.log
): Promise<void> {
const topic = args[0] as HelpTopicName | undefined;
if (!topic) {
await handleHelpCommand(writeLine);
return;
}
if (topic === 'profiles') {
await showProfilesHelp(writeLine);
return;
}
if (topic === 'providers') {
await showProvidersHelp(writeLine);
return;
}
if (topic === 'kiro') {
await showKiroHelp(writeLine);
return;
}
if (topic === 'targets') {
await showTargetsHelp(writeLine);
return;
}
if (topic === 'completion') {
const { showShellCompletionHelp } = await import('./shell-completion-command');
showShellCompletionHelp(writeLine);
return;
}
const commandHandlers: Partial<Record<string, () => Promise<void>>> = {
api: async () => (await import('./api-command/help')).showApiCommandHelp(writeLine),
auth: async () => {
const authModule = await import('../auth/auth-commands');
const AuthCommands = authModule.default;
await new AuthCommands().showHelp();
},
cleanup: async () => (await import('./cleanup-command')).handleCleanupCommand(['--help']),
cliproxy: async () => (await import('./cliproxy/help-subcommand')).showHelp(),
copilot: async () =>
process.exit(await (await import('./copilot-command')).handleCopilotCommand(['--help'])),
cursor: async () =>
process.exit(await (await import('./cursor-command')).handleCursorCommand(['--help'])),
docker: async () => (await import('./docker/help-subcommand')).showHelp(),
migrate: async () => (await import('./migrate-command')).printMigrateHelp(),
setup: async () => (await import('./setup-command')).handleSetupCommand(['--help']),
tokens: async () =>
process.exit(await (await import('./tokens-command')).handleTokensCommand(['--help'])),
};
const handler = commandHandlers[topic];
if (handler) {
await handler();
return;
}
await initUI();
writeLine(color(`Unknown help topic or command: ${topic}`, 'error'));
writeLine('');
writeLine(` ${dim(`Available help topics: ${listHelpTargets()}`)}`);
writeLine('');
process.exitCode = 1;
}
export function getRootHelpVisibleCommands(): string[] {
return getPublicRootCommands().map((entry) => entry.name);
}
export function getRootHelpCatalogEntries(): readonly RootCommandEntry[] {
return ROOT_COMMAND_CATALOG;
}