mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 12:15:57 +00:00
333 lines
12 KiB
TypeScript
333 lines
12 KiB
TypeScript
/**
|
|
* Auth Commands (Facade)
|
|
*
|
|
* CLI interface for CCS multi-account management.
|
|
* Commands: create, list, show, remove, default, reset-default
|
|
*
|
|
* Login-per-profile model: Each profile is an isolated Claude instance.
|
|
* Users login directly in each instance (no credential copying).
|
|
*
|
|
* Implementation Note: This is a facade that delegates to modular command handlers.
|
|
* See ./commands/ for individual command implementations.
|
|
*/
|
|
|
|
import ProfileRegistry from './profile-registry';
|
|
import { InstanceManager } from '../management/instance-manager';
|
|
import { initUI, header, subheader, color, dim, warn, fail } from '../utils/ui';
|
|
import { MAX_CONTEXT_GROUP_LENGTH } from './account-context';
|
|
import packageJson from '../../package.json';
|
|
|
|
// Import command handlers from modular structure
|
|
import {
|
|
type CommandContext,
|
|
handleCreate,
|
|
handleBackup,
|
|
handleList,
|
|
handleShow,
|
|
handleResources,
|
|
handleRemove,
|
|
handleDefault,
|
|
handleResetDefault,
|
|
} from './commands';
|
|
|
|
/**
|
|
* Auth Commands Class (Facade)
|
|
*
|
|
* Maintains class API for backward compatibility while delegating
|
|
* to modular command handlers.
|
|
*/
|
|
class AuthCommands {
|
|
private registry: ProfileRegistry;
|
|
private instanceMgr: InstanceManager;
|
|
private readonly version: string = packageJson.version;
|
|
|
|
constructor() {
|
|
this.registry = new ProfileRegistry();
|
|
this.instanceMgr = new InstanceManager();
|
|
}
|
|
|
|
/**
|
|
* Get command context for handlers
|
|
*/
|
|
private getContext(): CommandContext {
|
|
return {
|
|
registry: this.registry,
|
|
instanceMgr: this.instanceMgr,
|
|
version: this.version,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Show help for auth commands
|
|
*/
|
|
async showHelp(): Promise<void> {
|
|
await initUI();
|
|
|
|
console.log(header('CCS Concurrent Account Management'));
|
|
console.log('');
|
|
console.log(subheader('Usage'));
|
|
console.log(` ${color('ccs auth', 'command')} <command> [options]`);
|
|
console.log('');
|
|
console.log(subheader('Commands'));
|
|
console.log(` ${color('create <profile>', 'command')} Create new profile and login`);
|
|
console.log(
|
|
` ${color('backup <profile>', 'command')} Backup local continuity for an account`
|
|
);
|
|
console.log(` ${color('list', 'command')} List all saved profiles`);
|
|
console.log(` ${color('show <profile>', 'command')} Show profile details`);
|
|
console.log(
|
|
` ${color('resources <profile>', 'command')} Show or change shared resource mode`
|
|
);
|
|
console.log(` ${color('remove <profile>', 'command')} Remove saved profile`);
|
|
console.log(` ${color('default <profile>', 'command')} Set default profile`);
|
|
console.log(
|
|
` ${color('reset-default', 'command')} Clear default (restore original CCS)`
|
|
);
|
|
console.log('');
|
|
console.log(subheader('Examples'));
|
|
console.log(` ${dim('# Create two isolated accounts and choose one explicitly at runtime')}`);
|
|
console.log(` ${color('ccs auth create work', 'command')}`);
|
|
console.log(` ${color('ccs auth create personal', 'command')}`);
|
|
console.log(` ${color('ccs work "review code"', 'command')}`);
|
|
console.log(` ${color('ccs personal "write tests"', 'command')}`);
|
|
console.log('');
|
|
console.log(
|
|
` ${dim('# Optional: share local project history while credentials stay isolated')}`
|
|
);
|
|
console.log(` ${color('ccs auth create work2 --share-context', 'command')}`);
|
|
console.log('');
|
|
console.log(` ${dim('# Share context only within a specific group')}`);
|
|
console.log(
|
|
` ${color('ccs auth create backup --share-context --context-group sprint-a', 'command')}`
|
|
);
|
|
console.log('');
|
|
console.log(` ${dim('# Advanced: deeper shared continuity for session history artifacts')}`);
|
|
console.log(
|
|
` ${color('ccs auth create backup --share-context --context-group sprint-a --deeper-continuity', 'command')}`
|
|
);
|
|
console.log('');
|
|
console.log(` ${dim('# Create clean profile without shared commands/skills/agents')}`);
|
|
console.log(` ${color('ccs auth create sandbox --bare', 'command')}`);
|
|
console.log('');
|
|
console.log(` ${dim('# Change shared resources for an existing account')}`);
|
|
console.log(` ${color('ccs auth resources work --mode profile-local', 'command')}`);
|
|
console.log(` ${color('ccs auth resources work --mode shared', 'command')}`);
|
|
console.log('');
|
|
console.log(` ${dim('# Set work as default')}`);
|
|
console.log(` ${color('ccs auth default work', 'command')}`);
|
|
console.log('');
|
|
console.log(` ${dim('# Backup the local continuity lane for an account or plain ccs')}`);
|
|
console.log(` ${color('ccs auth backup work', 'command')}`);
|
|
console.log(
|
|
` ${color('ccs auth backup default', 'command')} ${dim('# backup plain ccs lane')}`
|
|
);
|
|
console.log('');
|
|
console.log(` ${dim('# Restore original CCS behavior')}`);
|
|
console.log(` ${color('ccs auth reset-default', 'command')}`);
|
|
console.log('');
|
|
console.log(` ${dim('# List all profiles')}`);
|
|
console.log(` ${color('ccs auth list', 'command')}`);
|
|
console.log('');
|
|
console.log(subheader('Options'));
|
|
console.log(
|
|
` ${color('--force', 'command')} Allow overwriting existing profile (create)`
|
|
);
|
|
console.log(
|
|
` ${color('--share-context', 'command')} Share project workspace context across accounts`
|
|
);
|
|
console.log(
|
|
` ${color('--context-group <name>', 'command')} Share context only within a named group`
|
|
);
|
|
console.log(
|
|
` ${color('--deeper-continuity', 'command')} Advanced shared mode: sync additional continuity artifacts`
|
|
);
|
|
console.log(
|
|
` ${color('--bare', 'command')} Create clean profile without shared symlinks (no CK/commands/skills)`
|
|
);
|
|
console.log(
|
|
` ${color('--mode <mode>', 'command')} Shared resource mode for resources: shared|profile-local`
|
|
);
|
|
console.log(
|
|
` ${color('--yes, -y', 'command')} Skip confirmation prompts (remove)`
|
|
);
|
|
console.log(
|
|
` ${color('--json', 'command')} Output in JSON format (list, show)`
|
|
);
|
|
console.log(
|
|
` ${color('--verbose', 'command')} Show additional details (list)`
|
|
);
|
|
console.log('');
|
|
console.log(subheader('Note'));
|
|
console.log(
|
|
` By default, ${color('ccs', 'command')} uses Claude CLI defaults from ~/.claude/`
|
|
);
|
|
console.log(
|
|
` Recommended two-account route: create ${color('work', 'command')} and ${color('personal', 'command')}, then run the profile you want.`
|
|
);
|
|
console.log(
|
|
` Use ${color('ccs auth default <profile>', 'command')} to change the default profile.`
|
|
);
|
|
console.log(` Account logins, tokens, and .anthropic stay isolated for every profile.`);
|
|
console.log(
|
|
` Non-bare account profiles share basic ${color('settings.json', 'path')} with ${color('~/.claude/settings.json', 'path')}; ${color('ccs auth show <profile>', 'command')} shows the link state.`
|
|
);
|
|
console.log(
|
|
` Shared Resources control plugins/commands/skills/agents/settings.json; History Sync controls project/session continuity only.`
|
|
);
|
|
console.log(
|
|
` History sync is opt-in: both accounts need shared mode and the same ${color('context_group', 'path')}.`
|
|
);
|
|
console.log(
|
|
` ${color('--deeper-continuity', 'command')} requires shared mode and syncs session-env/file-history/todos/shell-snapshots.`
|
|
);
|
|
console.log(
|
|
` To make future plain ${color('ccs', 'command')} resume with an account, set ${color('ccs auth default <profile>', 'command')}; back up the current native lane first with ${color('ccs auth backup default', 'command')}.`
|
|
);
|
|
console.log(
|
|
` Existing history sync: open ${color('ccs config', 'command')} -> Accounts -> Edit Context.`
|
|
);
|
|
console.log(
|
|
` Existing shared resources: use ${color('ccs auth resources <profile> --mode shared|profile-local', 'command')}.`
|
|
);
|
|
console.log(` Shared context groups are normalized (trim + lowercase) and spaces become "-".`);
|
|
console.log(
|
|
` ${color('context_group', 'path')} must be non-empty and <= ${MAX_CONTEXT_GROUP_LENGTH} chars in shared mode.`
|
|
);
|
|
console.log('');
|
|
}
|
|
|
|
/**
|
|
* Create new profile - delegates to create-command.ts
|
|
*/
|
|
async handleCreate(args: string[]): Promise<void> {
|
|
return handleCreate(this.getContext(), args);
|
|
}
|
|
|
|
async handleBackup(args: string[]): Promise<void> {
|
|
return handleBackup(this.getContext(), args);
|
|
}
|
|
|
|
/**
|
|
* List all profiles - delegates to list-command.ts
|
|
*/
|
|
async handleList(args: string[]): Promise<void> {
|
|
return handleList(this.getContext(), args);
|
|
}
|
|
|
|
/**
|
|
* Show profile details - delegates to show-command.ts
|
|
*/
|
|
async handleShow(args: string[]): Promise<void> {
|
|
return handleShow(this.getContext(), args);
|
|
}
|
|
|
|
async handleResources(args: string[]): Promise<void> {
|
|
return handleResources(this.getContext(), args);
|
|
}
|
|
|
|
/**
|
|
* Remove profile - delegates to remove-command.ts
|
|
*/
|
|
async handleRemove(args: string[]): Promise<void> {
|
|
return handleRemove(this.getContext(), args);
|
|
}
|
|
|
|
/**
|
|
* Set default profile - delegates to default-command.ts
|
|
*/
|
|
async handleDefault(args: string[]): Promise<void> {
|
|
return handleDefault(this.getContext(), args);
|
|
}
|
|
|
|
/**
|
|
* Reset default profile - delegates to default-command.ts
|
|
*/
|
|
async handleResetDefault(args: string[] = []): Promise<void> {
|
|
return handleResetDefault(this.getContext(), args);
|
|
}
|
|
|
|
/**
|
|
* Route auth command to appropriate handler
|
|
*/
|
|
async route(args: string[]): Promise<void> {
|
|
if (args.length === 0 || args[0] === '--help' || args[0] === '-h' || args[0] === 'help') {
|
|
await this.showHelp();
|
|
return;
|
|
}
|
|
|
|
const command = args[0];
|
|
const commandArgs = args.slice(1);
|
|
|
|
switch (command) {
|
|
case 'create':
|
|
await this.handleCreate(commandArgs);
|
|
break;
|
|
|
|
case 'save':
|
|
// Deprecated - redirect to create
|
|
await initUI();
|
|
console.log(warn('Command "save" is deprecated'));
|
|
console.log(` Use: ${color('ccs auth create <profile>', 'command')} instead`);
|
|
console.log('');
|
|
await this.handleCreate(commandArgs);
|
|
break;
|
|
|
|
case 'list':
|
|
await this.handleList(commandArgs);
|
|
break;
|
|
|
|
case 'backup':
|
|
await this.handleBackup(commandArgs);
|
|
break;
|
|
|
|
case 'show':
|
|
await this.handleShow(commandArgs);
|
|
break;
|
|
|
|
case 'resources':
|
|
await this.handleResources(commandArgs);
|
|
break;
|
|
|
|
case 'remove':
|
|
await this.handleRemove(commandArgs);
|
|
break;
|
|
|
|
case 'default':
|
|
await this.handleDefault(commandArgs);
|
|
break;
|
|
|
|
case 'reset-default':
|
|
await this.handleResetDefault(commandArgs);
|
|
break;
|
|
|
|
case 'current':
|
|
await initUI();
|
|
console.log(warn('Command "current" has been removed'));
|
|
console.log('');
|
|
console.log('Each profile has its own login in an isolated instance.');
|
|
console.log(`Use ${color('ccs auth list', 'command')} to see all profiles.`);
|
|
console.log('');
|
|
break;
|
|
|
|
case 'cleanup':
|
|
await initUI();
|
|
console.log(warn('Command "cleanup" has been removed'));
|
|
console.log('');
|
|
console.log('No cleanup needed - no separate vault files.');
|
|
console.log(`Use ${color('ccs auth list', 'command')} to see all profiles.`);
|
|
console.log('');
|
|
break;
|
|
|
|
default:
|
|
await initUI();
|
|
console.log(fail(`Unknown command: ${command}`));
|
|
console.log('');
|
|
console.log('Run for help:');
|
|
console.log(` ${color('ccs auth --help', 'command')}`);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
export default AuthCommands;
|