From 7745a0befbe877a44d9e2fa39fb2870a51e72e5f Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Thu, 28 Aug 2025 13:42:04 -0700 Subject: [PATCH] Update Claude agent to use proper headless mode - Replace --dangerously-skip-permissions with official headless mode flags - Use -p (--print) for non-interactive mode - Add --output-format json for structured responses - Use --permission-mode acceptEdits for automation - Parse JSON response and extract metadata (cost, duration, session_id) - Handle both successful and error responses properly - Reference: https://docs.anthropic.com/en/docs/claude-code/sdk/sdk-headless --- agents/claude.ts | 27 ++++++++++++++++++++------- index.cjs | 25 ++++++++++++++++++------- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/agents/claude.ts b/agents/claude.ts index 3393640..3deec74 100644 --- a/agents/claude.ts +++ b/agents/claude.ts @@ -39,8 +39,8 @@ export class ClaudeAgent implements Agent { // Create a temporary file for the prompt const promptFile = createTempFile(prompt, "prompt.txt"); - // Execute Claude Code with the prompt - const command = `$HOME/.local/bin/claude --dangerously-skip-permissions "${promptFile}"`; + // Execute Claude Code with the prompt using proper headless mode + const command = `$HOME/.local/bin/claude -p "${promptFile}" --output-format json --permission-mode acceptEdits`; core.info(`Executing: ${command}`); const { stdout, stderr } = await executeCommand(command, { @@ -51,20 +51,33 @@ export class ClaudeAgent implements Agent { core.warning(`Claude Code stderr: ${stderr}`); } - if (stdout) { + // Parse JSON response from Claude Code + let claudeResponse: any; + try { + claudeResponse = JSON.parse(stdout); + } catch { + core.warning("Failed to parse Claude Code JSON response, using raw output"); + claudeResponse = { result: stdout }; + } + + if (claudeResponse.result) { core.info("Claude Code output:"); - console.log(stdout); + console.log(claudeResponse.result); } core.info("Claude Code executed successfully"); return { - success: true, - output: stdout, - error: stderr || undefined, + success: !claudeResponse.is_error, + output: claudeResponse.result || stdout, + error: claudeResponse.is_error ? claudeResponse.result : (stderr || undefined), metadata: { promptFile, command, + session_id: claudeResponse.session_id, + cost_usd: claudeResponse.total_cost_usd, + duration_ms: claudeResponse.duration_ms, + num_turns: claudeResponse.num_turns, }, }; } catch (error) { diff --git a/index.cjs b/index.cjs index 8de35e7..4ac379a 100644 --- a/index.cjs +++ b/index.cjs @@ -19861,7 +19861,7 @@ var ClaudeAgent = class { core.info("Executing Claude Code..."); try { const promptFile = createTempFile(prompt, "prompt.txt"); - const command = `$HOME/.local/bin/claude --dangerously-skip-permissions "${promptFile}"`; + const command = `$HOME/.local/bin/claude -p "${promptFile}" --output-format json --permission-mode acceptEdits`; core.info(`Executing: ${command}`); const { stdout, stderr } = await executeCommand(command, { ANTHROPIC_API_KEY: this.apiKey @@ -19869,18 +19869,29 @@ var ClaudeAgent = class { if (stderr) { core.warning(`Claude Code stderr: ${stderr}`); } - if (stdout) { + let claudeResponse; + try { + claudeResponse = JSON.parse(stdout); + } catch { + core.warning("Failed to parse Claude Code JSON response, using raw output"); + claudeResponse = { result: stdout }; + } + if (claudeResponse.result) { core.info("Claude Code output:"); - console.log(stdout); + console.log(claudeResponse.result); } core.info("Claude Code executed successfully"); return { - success: true, - output: stdout, - error: stderr || void 0, + success: !claudeResponse.is_error, + output: claudeResponse.result || stdout, + error: claudeResponse.is_error ? claudeResponse.result : stderr || void 0, metadata: { promptFile, - command + command, + session_id: claudeResponse.session_id, + cost_usd: claudeResponse.total_cost_usd, + duration_ms: claudeResponse.duration_ms, + num_turns: claudeResponse.num_turns } }; } catch (error) {