@akiojin/claude-worktree
Version:
Interactive Git worktree manager for Claude Code with graphical branch selection
104 lines âĸ 4.74 kB
JavaScript
import { execa } from 'execa';
import chalk from 'chalk';
import { platform } from 'os';
import { existsSync } from 'fs';
export class ClaudeError extends Error {
cause;
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = 'ClaudeError';
}
}
export async function launchClaudeCode(worktreePath, options = {}) {
try {
// Check if the worktree path exists
if (!existsSync(worktreePath)) {
throw new Error(`Worktree path does not exist: ${worktreePath}`);
}
console.log(chalk.blue('đ Launching Claude Code...'));
console.log(chalk.gray(` Working directory: ${worktreePath}`));
const args = [];
// Handle execution mode
switch (options.mode) {
case 'continue':
args.push('-c');
console.log(chalk.cyan(' đą Continuing most recent conversation'));
break;
case 'resume':
// Use our custom conversation selection instead of claude -r
console.log(chalk.cyan(' đ Selecting conversation to resume'));
try {
const { selectClaudeConversation } = await import('./ui/prompts.js');
const selectedConversation = await selectClaudeConversation(worktreePath);
if (selectedConversation) {
console.log(chalk.green(` ⨠Resuming: ${selectedConversation.title}`));
// Use specific session ID if available
if (selectedConversation.sessionId) {
args.push('--resume', selectedConversation.sessionId);
console.log(chalk.cyan(` đ Using session ID: ${selectedConversation.sessionId}`));
}
else {
// Fallback: try to use filename as session identifier
const fileName = selectedConversation.id;
console.log(chalk.yellow(` â ī¸ No session ID found, trying filename: ${fileName}`));
args.push('--resume', fileName);
}
}
else {
// User cancelled - return without launching Claude
console.log(chalk.gray(' âŠī¸ Selection cancelled, returning to menu'));
return;
}
}
catch (error) {
console.warn(chalk.yellow(' â ī¸ Failed to load conversation history, using standard resume'));
args.push('-r');
}
break;
case 'normal':
default:
console.log(chalk.green(' ⨠Starting new session'));
break;
}
// Handle skip permissions
if (options.skipPermissions) {
args.push('--dangerously-skip-permissions');
console.log(chalk.yellow(' â ī¸ Skipping permissions check'));
}
const isWindows = platform() === 'win32';
await execa('claude', args, {
cwd: worktreePath,
stdio: 'inherit',
shell: true
});
}
catch (error) {
const errorMessage = error.code === 'ENOENT'
? 'Claude Code command not found. Please ensure Claude Code is installed and available in your PATH.'
: `Failed to launch Claude Code: ${error.message || 'Unknown error'}`;
if (platform() === 'win32') {
console.error(chalk.red('\nđĄ Windows troubleshooting tips:'));
console.error(chalk.yellow(' 1. Ensure Claude Code is installed: pnpm add -g @anthropic-ai/claude-code'));
console.error(chalk.yellow(' 2. Try restarting your terminal or IDE'));
console.error(chalk.yellow(' 3. Check if "claude" is available in your PATH'));
console.error(chalk.yellow(' 4. Try running "where claude" or "npx claude" to test the command'));
}
throw new ClaudeError(errorMessage, error);
}
}
export async function isClaudeCodeAvailable() {
try {
const isWindows = platform() === 'win32';
await execa('claude', ['--version'], { shell: true });
return true;
}
catch (error) {
if (error.code === 'ENOENT') {
console.error(chalk.yellow('\nâ ī¸ Claude Code not found in PATH'));
console.error(chalk.gray(' Please install Claude Code: pnpm add -g @anthropic-ai/claude-code'));
}
return false;
}
}
//# sourceMappingURL=claude.js.map