← Back to PRs

#21701: fix(agents): handle JSON array output from Claude Code CLI

by kenantan32 open 2026-02-20 07:58 View on GitHub →
agents size: XS
## Summary - `parseCliJson()` in `src/agents/cli-runner/helpers.ts` fails when Claude Code v2.1.49+ outputs a JSON array instead of a single JSON object - `isRecord(parsed)` rejects arrays, returns `null`, and the raw JSON gets dumped as the message text to Discord/Telegram - Added array handling: iterates entries for session ID and usage, prefers the `"result"` entry, falls back to `"assistant"` ## Problem Claude Code `--output-format json` now outputs: ```json [ {"type": "system", "subtype": "init", ...}, {"type": "assistant", "message": {...}, ...}, {"type": "result", "result": "response text", "session_id": "...", ...} ] ``` But `parseCliJson()` only handled single JSON objects. The `isRecord()` check rejected arrays, causing `null` return and raw JSON fallback. ## Test plan - [x] Tested with Claude Code v2.1.49 via OpenClaw CLI runner (`claude-cli/opus`) on Discord - [x] Before fix: raw JSON array dumped as Discord message - [x] After fix: clean text response with proper session ID and usage stats - [ ] Verify backward compatibility with single-object JSON output (older Claude Code versions) - [ ] Verify no regression for Codex CLI backend <!-- greptile_comment --> <h3>Greptile Summary</h3> Adds support for Claude Code CLI v2.1.49+ JSON array output format to prevent raw JSON from being dumped to Discord/Telegram. The parser now handles both array and single-object formats, iterating through array entries to extract session ID, usage stats, and response text from the appropriate entry type (`"result"` preferred, `"assistant"` as fallback). Backward compatibility with older single-object output is preserved. <h3>Confidence Score: 5/5</h3> - Safe to merge - well-structured fix with preserved backward compatibility - The fix correctly handles the new array format while maintaining backward compatibility with single-object JSON. Logic properly iterates entries, prefers `result` over `assistant` type, and collects session/usage metadata. Only minor style issue found (redundant type check). - No files require special attention <sub>Last reviewed commit: 9ffb1f7</sub> <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs