Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,16 @@ To use Claude Code's full functionality, you'll need to manually enable tools:

### Core Features

#### Claude CLI alias

If you use an alternative launcher like claude-code-router, you can set a custom alias for the Claude CLI that this server will spawn.

- Env var: `CLAUDE_CODE_UI_CLAUDE_SPAWN_ALIAS`
- Default: `claude`
- Example: `CLAUDE_CODE_UI_CLAUDE_SPAWN_ALIAS=ccr code`

This is honored across all Claude CLI spawns, including MCP routes.

#### Project Management
The UI automatically discovers Claude Code projects from `~/.claude/projects/` and provides:
- **Visual Project Browser** - All available projects with metadata and session counts
Expand Down
45 changes: 34 additions & 11 deletions server/claude-cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,17 +225,40 @@ async function spawnClaude(command, options = {}, ws) {
console.log('📝 Skip permissions disabled due to plan mode');
}
}

console.log('Spawning Claude CLI:', 'claude', args.map(arg => {
const cleanArg = arg.replace(/\n/g, '\\n').replace(/\r/g, '\\r');
return cleanArg.includes(' ') ? `"${cleanArg}"` : cleanArg;
}).join(' '));
console.log('Working directory:', workingDir);
console.log('Session info - Input sessionId:', sessionId, 'Resume:', resume);
console.log('🔍 Full command args:', JSON.stringify(args, null, 2));
console.log('🔍 Final Claude command will be: claude ' + args.join(' '));

const claudeProcess = spawnFunction('claude', args, {

// Resolve alias at runtime so .env changes are picked up
const CLAUDE_SPAWN_ALIAS = (
process.env.CLAUDE_CODE_UI_CLAUDE_SPAWN_ALIAS || "claude"
).trim();
const [CLAUDE_CMD, ...CLAUDE_PREFIX_ARGS] =
CLAUDE_SPAWN_ALIAS.split(/\s+/).filter(Boolean);

console.log(
"Spawning Claude CLI:",
CLAUDE_SPAWN_ALIAS,
args
.map((arg) => {
const cleanArg = arg.replace(/\n/g, "\\n").replace(/\r/g, "\\r");
return cleanArg.includes(" ") ? `"${cleanArg}"` : cleanArg;
})
.join(" "),
);
console.log("Working directory:", workingDir);
console.log(
"Session info - Input sessionId:",
sessionId,
"Resume:",
resume,
);
console.log("🔍 Full command args:", JSON.stringify(args, null, 2));
console.log(
"🔍 Final Claude command will be:",
CLAUDE_SPAWN_ALIAS + " " + args.join(" "),
);

// Prepend any alias prefix args (e.g., when alias is "ccr code")
const finalArgs = [...CLAUDE_PREFIX_ARGS, ...args];
const claudeProcess = spawnFunction(CLAUDE_CMD, finalArgs, {
cwd: workingDir,
stdio: ['pipe', 'pipe', 'pipe'],
env: { ...process.env } // Inherit all environment variables
Expand Down