fix: allow claude CLI provider to run inside Claude Code sessions

Remove CLAUDECODE env var from subprocess environment to allow nesting.
Also parse stdout before checking exit code to handle stderr diagnostic
noise without losing valid JSON output (same pattern as codex provider).
This commit is contained in:
Leandro Barbosa 2026-02-13 14:32:31 -03:00
parent 1aea912fcd
commit 4a701b3065

View file

@ -5,6 +5,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"os"
"os/exec" "os/exec"
"strings" "strings"
) )
@ -41,13 +42,40 @@ func (p *ClaudeCliProvider) Chat(ctx context.Context, messages []Message, tools
if p.workspace != "" { if p.workspace != "" {
cmd.Dir = p.workspace cmd.Dir = p.workspace
} }
// Remove CLAUDECODE env var to allow nesting (Claude Code blocks
// subprocess launches when this variable is set).
env := os.Environ()
filtered := env[:0]
for _, e := range env {
if !strings.HasPrefix(e, "CLAUDECODE=") {
filtered = append(filtered, e)
}
}
cmd.Env = filtered
cmd.Stdin = bytes.NewReader([]byte(prompt)) cmd.Stdin = bytes.NewReader([]byte(prompt))
var stdout, stderr bytes.Buffer var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout cmd.Stdout = &stdout
cmd.Stderr = &stderr cmd.Stderr = &stderr
if err := cmd.Run(); err != nil { err := cmd.Run()
// Parse JSON from stdout even if exit code is non-zero,
// because claude writes diagnostic noise to stderr but still
// produces valid JSON output.
if stdoutStr := stdout.String(); stdoutStr != "" {
resp, parseErr := p.parseClaudeCliResponse(stdoutStr)
if parseErr == nil && resp != nil && resp.Content != "" {
return resp, nil
}
}
if err != nil {
if ctx.Err() == context.Canceled {
return nil, ctx.Err()
}
if stderrStr := stderr.String(); stderrStr != "" { if stderrStr := stderr.String(); stderrStr != "" {
return nil, fmt.Errorf("claude cli error: %s", stderrStr) return nil, fmt.Errorf("claude cli error: %s", stderrStr)
} }