mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 12:15:57 +00:00
feat(ui): enhance help and profile commands with new ui layer
- Redesign help command with hero box and styled sections - Add table formatting for profile list with status indicators - Use semantic colors consistently (command, path, success, warning) - Profile create shows info box on success - Maintain NO_COLOR compliance for all output
This commit is contained in:
+1
-1
@@ -204,7 +204,7 @@ async function main(): Promise<void> {
|
||||
|
||||
// Special case: help command
|
||||
if (firstArg === '--help' || firstArg === '-h' || firstArg === 'help') {
|
||||
handleHelpCommand();
|
||||
await handleHelpCommand();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+119
-115
@@ -1,142 +1,146 @@
|
||||
import { colored } from '../utils/helpers';
|
||||
import { initUI, box, header, color, dim } from '../utils/ui';
|
||||
|
||||
// Version is read from VERSION file during build
|
||||
const VERSION = '5.3.0';
|
||||
|
||||
/**
|
||||
* Print a section with header and items
|
||||
*/
|
||||
function printSection(title: string, subtitle: string, items: [string, string][]): void {
|
||||
// Header with optional subtitle
|
||||
const headerText = subtitle ? `${title} ${dim(subtitle)}` : title;
|
||||
console.log(header(headerText));
|
||||
|
||||
// Calculate max command length for alignment
|
||||
const maxCmdLen = Math.max(...items.map(([cmd]) => cmd.length));
|
||||
|
||||
for (const [cmd, desc] of items) {
|
||||
const paddedCmd = cmd.padEnd(maxCmdLen + 2);
|
||||
console.log(` ${color(paddedCmd, 'command')} ${desc}`);
|
||||
}
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display comprehensive help information for CCS (Claude Code Switch)
|
||||
*/
|
||||
export function handleHelpCommand(): void {
|
||||
console.log(colored('CCS (Claude Code Switch) - Profile switching for Claude CLI', 'bold'));
|
||||
console.log('');
|
||||
export async function handleHelpCommand(): Promise<void> {
|
||||
// Initialize UI (if not already)
|
||||
await initUI();
|
||||
|
||||
console.log(colored('Usage:', 'cyan'));
|
||||
console.log(` ${colored('ccs', 'yellow')} [profile] [claude-args...]`);
|
||||
console.log(` ${colored('ccs', 'yellow')} [flags]`);
|
||||
console.log('');
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// SECTION 1: API KEY MODELS + PROFILE MANAGEMENT
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
console.log(colored('═══ API Key Profiles ═══', 'cyanBold'));
|
||||
console.log(' Configure in ~/.ccs/*.settings.json');
|
||||
console.log('');
|
||||
console.log(` ${colored('ccs', 'yellow')} Use default Claude account`);
|
||||
console.log(` ${colored('ccs glm', 'yellow')} GLM 4.6 (API key required)`);
|
||||
console.log(` ${colored('ccs glmt', 'yellow')} GLM with thinking mode`);
|
||||
console.log(` ${colored('ccs kimi', 'yellow')} Kimi for Coding (API key)`);
|
||||
console.log(` ${colored('ccs profile create', 'yellow')} Create custom API profile`);
|
||||
console.log(` ${colored('ccs profile remove', 'yellow')} Remove a profile`);
|
||||
console.log(` ${colored('ccs profile list', 'yellow')} List all profiles`);
|
||||
console.log('');
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// SECTION 2: ACCOUNT MANAGEMENT
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
console.log(colored('═══ Account Management ═══', 'cyanBold'));
|
||||
console.log(' Run multiple Claude accounts concurrently');
|
||||
console.log('');
|
||||
// Hero box with title
|
||||
console.log(
|
||||
` ${colored('ccs auth --help', 'yellow')} Show account management commands`
|
||||
);
|
||||
console.log(` ${colored('ccs auth create <name>', 'yellow')} Create new account profile`);
|
||||
console.log(` ${colored('ccs auth list', 'yellow')} List all account profiles`);
|
||||
console.log('');
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// SECTION 3: CLI PROXY (OAUTH PROVIDERS)
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
console.log(colored('═══ CLI Proxy (OAuth Providers) ═══', 'cyanBold'));
|
||||
console.log(' Zero-config OAuth authentication via CLIProxyAPI');
|
||||
console.log(' First run: Browser opens for authentication');
|
||||
console.log(' Settings: ~/.ccs/{provider}.settings.json (created after auth)');
|
||||
console.log('');
|
||||
console.log(
|
||||
` ${colored('ccs gemini', 'yellow')} Google Gemini (gemini-2.5-pro)`
|
||||
);
|
||||
console.log(
|
||||
` ${colored('ccs codex', 'yellow')} OpenAI Codex (gpt-5.1-codex-max)`
|
||||
);
|
||||
console.log(
|
||||
` ${colored('ccs agy', 'yellow')} Antigravity (gemini-3-pro-preview)`
|
||||
);
|
||||
console.log(` ${colored('ccs qwen', 'yellow')} Qwen Code (qwen3-coder)`);
|
||||
console.log('');
|
||||
console.log(` ${colored('ccs <provider> --auth', 'yellow')} Authenticate only`);
|
||||
console.log(` ${colored('ccs <provider> --logout', 'yellow')} Clear authentication`);
|
||||
console.log(` ${colored('ccs <provider> --headless', 'yellow')} Headless auth (for SSH)`);
|
||||
console.log(` ${colored('ccs codex "explain code"', 'yellow')} Use with prompt`);
|
||||
console.log('');
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// DELEGATION
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
console.log(colored('Delegation (inside Claude Code CLI):', 'cyan'));
|
||||
console.log(
|
||||
` ${colored('/ccs "task"', 'yellow')} Delegate task (auto-selects profile)`
|
||||
);
|
||||
console.log(
|
||||
` ${colored('/ccs --glm "task"', 'yellow')} Force GLM-4.6 for simple tasks`
|
||||
);
|
||||
console.log(` ${colored('/ccs --kimi "task"', 'yellow')} Force Kimi for long context`);
|
||||
console.log(
|
||||
` ${colored('/ccs:continue "follow-up"', 'yellow')} Continue last delegation session`
|
||||
box(`CCS v${VERSION}\nClaude Code Profile & Model Switcher`, {
|
||||
padding: 1,
|
||||
borderStyle: 'round',
|
||||
titleAlignment: 'center',
|
||||
})
|
||||
);
|
||||
console.log('');
|
||||
|
||||
console.log(colored('Diagnostics:', 'cyan'));
|
||||
console.log(
|
||||
` ${colored('ccs doctor', 'yellow')} Run health check and diagnostics`
|
||||
);
|
||||
console.log(
|
||||
` ${colored('ccs sync', 'yellow')} Sync delegation commands and skills`
|
||||
);
|
||||
console.log(` ${colored('ccs update', 'yellow')} Update CCS to latest version`);
|
||||
// Usage section
|
||||
console.log(header('USAGE'));
|
||||
console.log(` $ ${color('ccs', 'command')} <profile> [flags] [-- claude-args...]`);
|
||||
console.log(` $ ${color('ccs', 'command')} [flags]`);
|
||||
console.log('');
|
||||
|
||||
console.log(colored('Flags:', 'cyan'));
|
||||
console.log(` ${colored('-h, --help', 'yellow')} Show this help message`);
|
||||
console.log(
|
||||
` ${colored('-v, --version', 'yellow')} Show version and installation info`
|
||||
);
|
||||
console.log(
|
||||
` ${colored('-sc, --shell-completion', 'yellow')} Install shell auto-completion`
|
||||
);
|
||||
// API Key Profiles section
|
||||
printSection('API KEY PROFILES', 'Configure: ~/.ccs/*.settings.json', [
|
||||
['ccs', 'Use default Claude account'],
|
||||
['ccs glm', 'GLM-4.6 via Zhipu AI'],
|
||||
['ccs glmt', 'GLM-4.6 (Turbo mode)'],
|
||||
['ccs kimi', 'Kimi via Moonshot AI'],
|
||||
]);
|
||||
|
||||
// Profile management section
|
||||
printSection('PROFILE MANAGEMENT', '', [
|
||||
['ccs profile create', 'Create custom API profile'],
|
||||
['ccs profile list', 'List all profiles'],
|
||||
['ccs profile remove', 'Remove a profile'],
|
||||
]);
|
||||
|
||||
// Account management section
|
||||
printSection('ACCOUNT MANAGEMENT', 'Multiple Claude accounts', [
|
||||
['ccs auth create <name>', 'Create new account'],
|
||||
['ccs auth list', 'List all accounts'],
|
||||
['ccs auth default <name>', 'Set default account'],
|
||||
]);
|
||||
|
||||
// OAuth section
|
||||
printSection('OAUTH PROVIDERS', 'Zero config, browser auth', [
|
||||
['ccs gemini', 'Google Gemini (gemini-2.5-pro)'],
|
||||
['ccs codex', 'OpenAI Codex (gpt-5.1-codex-max)'],
|
||||
['ccs agy', 'Antigravity (gemini-3-pro-preview)'],
|
||||
['ccs qwen', 'Qwen Code (qwen3-coder)'],
|
||||
]);
|
||||
|
||||
// OAuth flags
|
||||
console.log(header('OAUTH FLAGS'));
|
||||
console.log(` ${color('ccs <provider> --auth', 'command')} Authenticate only`);
|
||||
console.log(` ${color('ccs <provider> --logout', 'command')} Clear authentication`);
|
||||
console.log(` ${color('ccs <provider> --headless', 'command')} Headless auth (for SSH)`);
|
||||
console.log('');
|
||||
|
||||
console.log(colored('Configuration:', 'cyan'));
|
||||
console.log(' Config File: ~/.ccs/config.json');
|
||||
console.log(' Profiles: ~/.ccs/profiles.json');
|
||||
console.log(' Instances: ~/.ccs/instances/');
|
||||
console.log(' Settings: ~/.ccs/*.settings.json');
|
||||
// Delegation section
|
||||
printSection('DELEGATION', 'Inside Claude Code CLI', [
|
||||
['/ccs "task"', 'Delegate (auto-select profile)'],
|
||||
['/ccs --glm "task"', 'Force GLM-4.6'],
|
||||
['/ccs --kimi "task"', 'Force Kimi'],
|
||||
['/ccs:continue', 'Continue last delegation'],
|
||||
]);
|
||||
|
||||
// Diagnostics section
|
||||
printSection('DIAGNOSTICS', '', [
|
||||
['ccs doctor', 'Run health check'],
|
||||
['ccs sync', 'Sync delegation commands'],
|
||||
['ccs update', 'Update to latest version'],
|
||||
]);
|
||||
|
||||
// Flags section
|
||||
console.log(header('FLAGS'));
|
||||
console.log(` ${color('-h, --help', 'command')} Show this help`);
|
||||
console.log(` ${color('-v, --version', 'command')} Show version`);
|
||||
console.log(` ${color('-sc, --shell-completion', 'command')} Install shell completion`);
|
||||
console.log('');
|
||||
|
||||
console.log(colored('CLI Proxy:', 'cyan'));
|
||||
console.log(' Binary: ~/.ccs/cliproxy/bin/cli-proxy-api');
|
||||
console.log(' Config: ~/.ccs/cliproxy/config.yaml');
|
||||
console.log(' Auth: ~/.ccs/cliproxy/auth/');
|
||||
console.log(' Port: 8317 (default)');
|
||||
// Configuration paths
|
||||
console.log(header('CONFIGURATION'));
|
||||
console.log(` Config: ${color('~/.ccs/config.json', 'path')}`);
|
||||
console.log(` Profiles: ${color('~/.ccs/profiles.json', 'path')}`);
|
||||
console.log(` Settings: ${color('~/.ccs/*.settings.json', 'path')}`);
|
||||
console.log(` CLIProxy: ${color('~/.ccs/cliproxy/', 'path')}`);
|
||||
console.log('');
|
||||
|
||||
console.log(colored('Shared Data:', 'cyan'));
|
||||
console.log(' Commands: ~/.ccs/shared/commands/');
|
||||
console.log(' Skills: ~/.ccs/shared/skills/');
|
||||
console.log(' Agents: ~/.ccs/shared/agents/');
|
||||
console.log(' Note: Symlinked across all profiles');
|
||||
// Shared Data
|
||||
console.log(header('SHARED DATA'));
|
||||
console.log(` Commands: ${color('~/.ccs/shared/commands/', 'path')}`);
|
||||
console.log(` Skills: ${color('~/.ccs/shared/skills/', 'path')}`);
|
||||
console.log(` Agents: ${color('~/.ccs/shared/agents/', 'path')}`);
|
||||
console.log(` ${dim('Note: Symlinked across all profiles')}`);
|
||||
console.log('');
|
||||
|
||||
console.log(colored('Examples:', 'cyan'));
|
||||
console.log(` ${colored('$ ccs', 'yellow')} # Use default account`);
|
||||
console.log(
|
||||
` ${colored('$ ccs gemini', 'yellow')} # OAuth (browser opens first time)`
|
||||
);
|
||||
console.log(` ${colored('$ ccs glm "implement API"', 'yellow')} # API key model`);
|
||||
// Examples
|
||||
console.log(header('EXAMPLES'));
|
||||
console.log(` ${dim('# Use default account')}`);
|
||||
console.log(` $ ${color('ccs', 'command')}`);
|
||||
console.log('');
|
||||
console.log(` Docs: ${colored('https://github.com/kaitranntt/ccs', 'cyan')}`);
|
||||
console.log(` ${dim('# OAuth provider (browser auth first time)')}`);
|
||||
console.log(` $ ${color('ccs gemini', 'command')}`);
|
||||
console.log('');
|
||||
console.log(` ${dim('# API key model with prompt')}`);
|
||||
console.log(` $ ${color('ccs glm "implement the API"', 'command')}`);
|
||||
console.log('');
|
||||
|
||||
console.log(colored('Uninstall:', 'yellow'));
|
||||
// Footer
|
||||
console.log(dim('Docs: https://github.com/kaitranntt/ccs'));
|
||||
console.log(dim('License: MIT'));
|
||||
console.log('');
|
||||
|
||||
// Uninstall
|
||||
console.log(color('Uninstall:', 'warning'));
|
||||
console.log(' npm uninstall -g @kaitranntt/ccs');
|
||||
console.log('');
|
||||
|
||||
console.log(`${colored('License:', 'cyan')} MIT`);
|
||||
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
+123
-62
@@ -7,7 +7,19 @@
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { colored } from '../utils/helpers';
|
||||
import {
|
||||
initUI,
|
||||
header,
|
||||
subheader,
|
||||
color,
|
||||
dim,
|
||||
ok,
|
||||
fail,
|
||||
warn,
|
||||
info,
|
||||
table,
|
||||
infoBox,
|
||||
} from '../utils/ui';
|
||||
import { InteractivePrompt } from '../utils/prompt';
|
||||
import { getCcsDir, getConfigPath, loadConfig } from '../utils/config-manager';
|
||||
|
||||
@@ -148,9 +160,10 @@ function updateConfig(name: string, _settingsPath: string): void {
|
||||
* Handle 'ccs profile create' command
|
||||
*/
|
||||
async function handleCreate(args: string[]): Promise<void> {
|
||||
await initUI();
|
||||
const parsedArgs = parseArgs(args);
|
||||
|
||||
console.log(colored('Create API Profile', 'bold'));
|
||||
console.log(header('Create API Profile'));
|
||||
console.log('');
|
||||
|
||||
// Step 1: Profile name
|
||||
@@ -162,15 +175,15 @@ async function handleCreate(args: string[]): Promise<void> {
|
||||
} else {
|
||||
const error = validateProfileName(name);
|
||||
if (error) {
|
||||
console.error(`[X] ${error}`);
|
||||
console.log(fail(error));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if exists
|
||||
if (profileExists(name) && !parsedArgs.force) {
|
||||
console.error(`[X] Profile '${name}' already exists`);
|
||||
console.log(` Use ${colored('--force', 'yellow')} to overwrite`);
|
||||
console.log(fail(`Profile '${name}' already exists`));
|
||||
console.log(` Use ${color('--force', 'command')} to overwrite`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -183,7 +196,7 @@ async function handleCreate(args: string[]): Promise<void> {
|
||||
} else {
|
||||
const error = validateUrl(baseUrl);
|
||||
if (error) {
|
||||
console.error(`[X] ${error}`);
|
||||
console.log(fail(error));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -193,7 +206,7 @@ async function handleCreate(args: string[]): Promise<void> {
|
||||
if (!apiKey) {
|
||||
apiKey = await InteractivePrompt.password('API Key');
|
||||
if (!apiKey) {
|
||||
console.error('[X] API key is required');
|
||||
console.log(fail('API key is required'));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -210,33 +223,57 @@ async function handleCreate(args: string[]): Promise<void> {
|
||||
|
||||
// Create files
|
||||
console.log('');
|
||||
console.log('[i] Creating profile...');
|
||||
console.log(info('Creating profile...'));
|
||||
|
||||
try {
|
||||
const settingsPath = createSettingsFile(name, baseUrl, apiKey, model);
|
||||
updateConfig(name, settingsPath);
|
||||
|
||||
console.log(colored('[OK] Profile created successfully', 'green'));
|
||||
console.log('');
|
||||
console.log(` Profile: ${name}`);
|
||||
console.log(` Settings: ~/.ccs/${name}.settings.json`);
|
||||
console.log(` Base URL: ${baseUrl}`);
|
||||
console.log(` Model: ${model}`);
|
||||
console.log(
|
||||
infoBox(
|
||||
`Profile: ${name}\n` +
|
||||
`Settings: ~/.ccs/${name}.settings.json\n` +
|
||||
`Base URL: ${baseUrl}\n` +
|
||||
`Model: ${model}`,
|
||||
'Profile Created'
|
||||
)
|
||||
);
|
||||
console.log('');
|
||||
console.log(colored('Usage:', 'cyan'));
|
||||
console.log(` ${colored(`ccs ${name} "your prompt"`, 'yellow')}`);
|
||||
console.log(header('Usage'));
|
||||
console.log(` ${color(`ccs ${name} "your prompt"`, 'command')}`);
|
||||
console.log('');
|
||||
} catch (error) {
|
||||
console.error(`[X] Failed to create profile: ${(error as Error).message}`);
|
||||
console.log(fail(`Failed to create profile: ${(error as Error).message}`));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if profile has real API key (not placeholder)
|
||||
*/
|
||||
function isProfileConfigured(profileName: string): boolean {
|
||||
try {
|
||||
const ccsDir = getCcsDir();
|
||||
const settingsPath = path.join(ccsDir, `${profileName}.settings.json`);
|
||||
if (!fs.existsSync(settingsPath)) return false;
|
||||
|
||||
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
||||
const token = settings?.env?.ANTHROPIC_AUTH_TOKEN || '';
|
||||
// Check if it's a placeholder or empty
|
||||
return token.length > 0 && !token.includes('YOUR_') && !token.includes('your-');
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle 'ccs profile list' command
|
||||
*/
|
||||
async function handleList(): Promise<void> {
|
||||
console.log(colored('CCS Profiles', 'bold'));
|
||||
await initUI();
|
||||
|
||||
console.log(header('CCS Profiles'));
|
||||
console.log('');
|
||||
|
||||
try {
|
||||
@@ -244,38 +281,52 @@ async function handleList(): Promise<void> {
|
||||
const profiles = Object.keys(config.profiles);
|
||||
|
||||
if (profiles.length === 0) {
|
||||
console.log(colored('No profiles configured', 'yellow'));
|
||||
console.log(warn('No profiles configured'));
|
||||
console.log('');
|
||||
console.log('To create a profile:');
|
||||
console.log(` ${colored('ccs profile create', 'yellow')}`);
|
||||
console.log(` ${color('ccs profile create', 'command')}`);
|
||||
console.log('');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(colored('Settings-based Profiles:', 'cyan'));
|
||||
// Calculate max name length for alignment
|
||||
const maxNameLen = Math.max(...profiles.map((n) => n.length));
|
||||
profiles.forEach((name) => {
|
||||
// Build table data with status indicators
|
||||
const rows: string[][] = profiles.map((name) => {
|
||||
const settingsPath = config.profiles[name];
|
||||
const paddedName = name.padEnd(maxNameLen);
|
||||
console.log(` ${colored(paddedName, 'yellow')} ${settingsPath}`);
|
||||
const status = isProfileConfigured(name) ? color('[OK]', 'success') : color('[!]', 'warning');
|
||||
|
||||
return [name, settingsPath, status];
|
||||
});
|
||||
|
||||
// Print table
|
||||
console.log(
|
||||
table(rows, {
|
||||
head: ['Profile', 'Settings File', 'Status'],
|
||||
colWidths: [15, 35, 10],
|
||||
})
|
||||
);
|
||||
console.log('');
|
||||
|
||||
// Also show CLIProxy profiles if any
|
||||
// Show CLIProxy variants if any
|
||||
if (config.cliproxy && Object.keys(config.cliproxy).length > 0) {
|
||||
console.log(colored('CLIProxy Variants:', 'cyan'));
|
||||
Object.entries(config.cliproxy).forEach(([name, variant]) => {
|
||||
const v = variant as { provider: string; settings: string };
|
||||
console.log(` ${colored(name, 'yellow')} → ${v.provider} (${v.settings})`);
|
||||
console.log(subheader('CLIProxy Variants'));
|
||||
const cliproxyRows = Object.entries(config.cliproxy).map(([name, v]) => {
|
||||
const variant = v as { provider: string; settings: string };
|
||||
return [name, variant.provider, variant.settings];
|
||||
});
|
||||
|
||||
console.log(
|
||||
table(cliproxyRows, {
|
||||
head: ['Variant', 'Provider', 'Settings'],
|
||||
colWidths: [15, 15, 30],
|
||||
})
|
||||
);
|
||||
console.log('');
|
||||
}
|
||||
|
||||
console.log(`Total: ${profiles.length} profile(s)`);
|
||||
console.log(dim(`Total: ${profiles.length} profile(s)`));
|
||||
console.log('');
|
||||
} catch (error) {
|
||||
console.error(`[X] Failed to list profiles: ${(error as Error).message}`);
|
||||
console.log(fail(`Failed to list profiles: ${(error as Error).message}`));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -284,6 +335,7 @@ async function handleList(): Promise<void> {
|
||||
* Handle 'ccs profile remove' command
|
||||
*/
|
||||
async function handleRemove(args: string[]): Promise<void> {
|
||||
await initUI();
|
||||
const parsedArgs = parseArgs(args);
|
||||
|
||||
// Load config first to get available profiles
|
||||
@@ -291,20 +343,20 @@ async function handleRemove(args: string[]): Promise<void> {
|
||||
try {
|
||||
config = loadConfig();
|
||||
} catch {
|
||||
console.error('[X] Failed to load config');
|
||||
console.log(fail('Failed to load config'));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const profiles = Object.keys(config.profiles);
|
||||
if (profiles.length === 0) {
|
||||
console.log(colored('No profiles to remove', 'yellow'));
|
||||
console.log(warn('No profiles to remove'));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Interactive profile selection if not provided
|
||||
let name = parsedArgs.name;
|
||||
if (!name) {
|
||||
console.log(colored('Remove Profile', 'bold'));
|
||||
console.log(header('Remove Profile'));
|
||||
console.log('');
|
||||
console.log('Available profiles:');
|
||||
profiles.forEach((p, i) => console.log(` ${i + 1}. ${p}`));
|
||||
@@ -320,7 +372,7 @@ async function handleRemove(args: string[]): Promise<void> {
|
||||
}
|
||||
|
||||
if (!(name in config.profiles)) {
|
||||
console.error(`[X] Profile '${name}' not found`);
|
||||
console.log(fail(`Profile '${name}' not found`));
|
||||
console.log('');
|
||||
console.log('Available profiles:');
|
||||
profiles.forEach((p) => console.log(` - ${p}`));
|
||||
@@ -332,7 +384,7 @@ async function handleRemove(args: string[]): Promise<void> {
|
||||
|
||||
// Confirm deletion
|
||||
console.log('');
|
||||
console.log(`Profile '${colored(name, 'yellow')}' will be removed.`);
|
||||
console.log(`Profile '${color(name, 'command')}' will be removed.`);
|
||||
console.log(` Settings: ${settingsPath}`);
|
||||
console.log('');
|
||||
|
||||
@@ -340,7 +392,7 @@ async function handleRemove(args: string[]): Promise<void> {
|
||||
parsedArgs.yes || (await InteractivePrompt.confirm('Delete this profile?', { default: false }));
|
||||
|
||||
if (!confirmed) {
|
||||
console.log('[i] Cancelled');
|
||||
console.log(info('Cancelled'));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
@@ -356,37 +408,45 @@ async function handleRemove(args: string[]): Promise<void> {
|
||||
fs.unlinkSync(expandedPath);
|
||||
}
|
||||
|
||||
console.log(colored('[OK] Profile removed', 'green'));
|
||||
console.log(` Profile: ${name}`);
|
||||
console.log(ok(`Profile removed: ${name}`));
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show help for profile commands
|
||||
*/
|
||||
function showHelp(): void {
|
||||
console.log(colored('CCS Profile Management', 'bold'));
|
||||
async function showHelp(): Promise<void> {
|
||||
await initUI();
|
||||
|
||||
console.log(header('CCS Profile Management'));
|
||||
console.log('');
|
||||
console.log(colored('Usage:', 'cyan'));
|
||||
console.log(` ${colored('ccs profile', 'yellow')} <command> [options]`);
|
||||
console.log(subheader('Usage'));
|
||||
console.log(` ${color('ccs profile', 'command')} <command> [options]`);
|
||||
console.log('');
|
||||
console.log(colored('Commands:', 'cyan'));
|
||||
console.log(` ${colored('create [name]', 'yellow')} Create new API profile (interactive)`);
|
||||
console.log(` ${colored('list', 'yellow')} List all profiles`);
|
||||
console.log(` ${colored('remove <name>', 'yellow')} Remove a profile`);
|
||||
console.log(subheader('Commands'));
|
||||
console.log(` ${color('create [name]', 'command')} Create new API profile (interactive)`);
|
||||
console.log(` ${color('list', 'command')} List all profiles`);
|
||||
console.log(` ${color('remove <name>', 'command')} Remove a profile`);
|
||||
console.log('');
|
||||
console.log(colored('Options:', 'cyan'));
|
||||
console.log(` ${colored('--base-url <url>', 'yellow')} API base URL (create)`);
|
||||
console.log(` ${colored('--api-key <key>', 'yellow')} API key (create)`);
|
||||
console.log(` ${colored('--model <model>', 'yellow')} Default model (create)`);
|
||||
console.log(` ${colored('--force', 'yellow')} Overwrite existing (create)`);
|
||||
console.log(` ${colored('--yes, -y', 'yellow')} Skip confirmation prompts`);
|
||||
console.log(subheader('Options'));
|
||||
console.log(` ${color('--base-url <url>', 'command')} API base URL (create)`);
|
||||
console.log(` ${color('--api-key <key>', 'command')} API key (create)`);
|
||||
console.log(` ${color('--model <model>', 'command')} Default model (create)`);
|
||||
console.log(` ${color('--force', 'command')} Overwrite existing (create)`);
|
||||
console.log(` ${color('--yes, -y', 'command')} Skip confirmation prompts`);
|
||||
console.log('');
|
||||
console.log(colored('Examples:', 'cyan'));
|
||||
console.log(` ${colored('ccs profile create', 'yellow')} # Interactive wizard`);
|
||||
console.log(` ${colored('ccs profile create myapi', 'yellow')} # Create with name`);
|
||||
console.log(` ${colored('ccs profile remove myapi', 'yellow')} # Remove profile`);
|
||||
console.log(` ${colored('ccs profile list', 'yellow')} # Show all profiles`);
|
||||
console.log(subheader('Examples'));
|
||||
console.log(` ${dim('# Interactive wizard')}`);
|
||||
console.log(` ${color('ccs profile create', 'command')}`);
|
||||
console.log('');
|
||||
console.log(` ${dim('# Create with name')}`);
|
||||
console.log(` ${color('ccs profile create myapi', 'command')}`);
|
||||
console.log('');
|
||||
console.log(` ${dim('# Remove profile')}`);
|
||||
console.log(` ${color('ccs profile remove myapi', 'command')}`);
|
||||
console.log('');
|
||||
console.log(` ${dim('# Show all profiles')}`);
|
||||
console.log(` ${color('ccs profile list', 'command')}`);
|
||||
console.log('');
|
||||
}
|
||||
|
||||
@@ -397,7 +457,7 @@ export async function handleProfileCommand(args: string[]): Promise<void> {
|
||||
const command = args[0];
|
||||
|
||||
if (!command || command === '--help' || command === '-h' || command === 'help') {
|
||||
showHelp();
|
||||
await showHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -414,10 +474,11 @@ export async function handleProfileCommand(args: string[]): Promise<void> {
|
||||
await handleRemove(args.slice(1));
|
||||
break;
|
||||
default:
|
||||
console.error(`[X] Unknown command: ${command}`);
|
||||
await initUI();
|
||||
console.log(fail(`Unknown command: ${command}`));
|
||||
console.log('');
|
||||
console.log('Run for help:');
|
||||
console.log(` ${colored('ccs profile --help', 'yellow')}`);
|
||||
console.log(` ${color('ccs profile --help', 'command')}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user