Files
claude-code-router/packages/cli/src/utils/codeCommand.ts
2025-12-25 23:00:24 +08:00

100 lines
2.8 KiB
TypeScript

import { spawn, type StdioOptions } from "child_process";
import { readConfigFile } from ".";
import {
decrementReferenceCount,
incrementReferenceCount,
closeService,
} from "./processCheck";
import { quote } from 'shell-quote';
import minimist from "minimist";
import { createEnvVariables } from "./createEnvVariables";
export async function executeCodeCommand(args: string[] = []) {
// Set environment variables using shared function
const config = await readConfigFile();
const env = await createEnvVariables();
const settingsFlag: ClaudeSettingsFlag = {
env: env as ClaudeSettingsFlag['env']
};
if (config?.StatusLine?.enabled) {
settingsFlag.statusLine = {
type: "command",
command: "ccr statusline",
padding: 0,
}
}
// args.push('--settings', `${JSON.stringify(settingsFlag)}`);
// Non-interactive mode for automation environments
if (config.NON_INTERACTIVE_MODE) {
env.CI = "true";
env.FORCE_COLOR = "0";
env.NODE_NO_READLINE = "1";
env.TERM = "dumb";
}
// Set ANTHROPIC_SMALL_FAST_MODEL if it exists in config
if (config?.ANTHROPIC_SMALL_FAST_MODEL) {
env.ANTHROPIC_SMALL_FAST_MODEL = config.ANTHROPIC_SMALL_FAST_MODEL;
}
// Increment reference count when command starts
incrementReferenceCount();
// Execute claude command
const claudePath = config?.CLAUDE_PATH || process.env.CLAUDE_PATH || "claude";
const joinedArgs = args.length > 0 ? quote(args) : "";
const stdioConfig: StdioOptions = config.NON_INTERACTIVE_MODE
? ["pipe", "inherit", "inherit"] // Pipe stdin for non-interactive
: "inherit"; // Default inherited behavior
const argsObj = minimist(args)
const argsArr = []
for (const [argsObjKey, argsObjValue] of Object.entries(argsObj)) {
if (argsObjKey !== '_' && argsObj[argsObjKey]) {
const prefix = argsObjKey.length === 1 ? '-' : '--';
// For boolean flags, don't append the value
if (argsObjValue === true) {
argsArr.push(`${prefix}${argsObjKey}`);
} else {
argsArr.push(`${prefix}${argsObjKey} ${JSON.stringify(argsObjValue)}`);
}
}
}
const claudeProcess = spawn(
claudePath,
argsArr,
{
env: {
...process.env,
...env
},
stdio: stdioConfig,
shell: true,
}
);
// Close stdin for non-interactive mode
if (config.NON_INTERACTIVE_MODE) {
claudeProcess.stdin?.end();
}
claudeProcess.on("error", (error) => {
console.error("Failed to start claude command:", error.message);
console.log(
"Make sure Claude Code is installed: npm install -g @anthropic-ai/claude-code"
);
decrementReferenceCount();
process.exit(1);
});
claudeProcess.on("close", (code) => {
decrementReferenceCount();
closeService();
process.exit(code || 0);
});
}