[BUG] --reply-on-resume is ignored on print / Agent SDK resume
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
--reply-on-resume is accepted on the CLI, and the interactive resume path honors it, but the print / Agent SDK resume path drops it. A resumed session whose last real message is a non-terminal tool_result still gets the synthetic pair:
- user text
Continue from where you left off.(merged onto the tool-result message in the API request) - assistant text
No response requested.
Then the prompt submitted on stdin is a second user turn. The flag was supposed to force interruption kind "none" and skip both lines so the caller's prompt is the only new user turn.
This is the path the Agent SDK uses (--output-format stream-json --input-format stream-json --resume). Setting extra_args={"reply-on-resume": None} correctly appends a bare --reply-on-resume. The process starts (the flag is not an unknown option). The synthetic pair is still inserted.
CLAUDE_CODE_RESUME_INTERRUPTED_TURN does not suppress the pair. In the same loader it only changes sibling-block handling, and only when replyOnResume is false.
What Should Happen?
Print mode should pass replyOnResume into the session loader the same way interactive resume already does. With the flag set, the loader should not append Continue from where you left off. and should not splice No response requested. The submitted stdin prompt should be the only user turn after the tool result.
Error Messages/Logs
No CLI error. --reply-on-resume=true is rejected (error: unknown option '--reply-on-resume=true'), which confirms the bare flag is the parsed form. The bare flag is accepted and then ignored on this path.
Observed API history after a tool-result resume with the flag set:
- user:
tool_resultblocks plus textContinue from where you left off. - assistant:
No response requested. - user: the prompt that was actually submitted (
Continue from where you left off.)
Steps to Reproduce
- Use Claude Code 2.1.294 (bundled in
claude-agent-sdk0.2.165) or 2.1.238 (SDK 0.2.143). Same omission in the 0.2.156 bundle. - Resume a session that ends on a user
tool_resultfor a non-terminal tool, via the print entrypoint:
claude --print --verbose \
--output-format stream-json \
--input-format stream-json \
--resume "$SESSION_ID" \
--reply-on-resume
Submit any user prompt on stdin.
- The model request still contains the synthetic user line and the assistant
No response requested.before that prompt.
The interactive entrypoint does honor the flag. In the 2.1.294 bundle, interactive session load passes it:
vEe(..., { forkSession: !!A.forkSession, replyOnResume: !!A.replyOnResume, ... })
The print entrypoint (--output-format stream-json) does not. nU is called without replyOnResume, and both of its session loads omit it:
await nU(e, s, At, {
continue: b.continue,
resume: b.resume,
resumeSessionAt: b.resumeSessionAt,
resumeDropsTurn: b.resumeDropsTurn,
forkSession: b.forkSession,
outputFormat: b.outputFormat,
// replyOnResume is not copied
})
await vEe(sessionId, jsonlFile, {
forkSession: !!s.forkSession,
// replyOnResume is not passed
})
Inside the deserializer, both synthetic lines are gated on that boolean (if (!r && last message is user) splice "No response requested.", and the continue line is pushed only when interruption kind is interrupted_turn, which is forced to none when r is true). Because print mode never sets r, the pair is always inserted.
Claude Model
Not sure / Multiple models
Is this a regression?
I don't know
Claude Code Version
2.1.294 (Claude Code), bundled with claude-agent-sdk 0.2.165. Also present in 2.1.238 (claude-agent-sdk 0.2.143) and the 0.2.156 bundle.
Platform
Other
The synthetic messages are inserted by the local CLI session loader, before the provider request. Reproduced by inspecting the macOS arm64 bundles above. The print-mode loader is the same code path the Python and TypeScript Agent SDKs spawn.
Operating System
macOS
Terminal/Shell
Non-interactive/CI environment
Additional Information
Public docs document CLAUDE_CODE_RESUME_INTERRUPTED_TURN and CLAUDE_CODE_RESUME_PROMPT, not --reply-on-resume. The flag exists in the binary and is wired for interactive resume and background-job respawn. The print-mode options bag (resume, resumeSessionAt, resumeDropsTurn, forkSession, outputFormat, …) never copies replyOnResume, so Agent SDK callers cannot turn the synthetic pair off.
Suggested fix: forward replyOnResume: !!b.replyOnResume into nU, and pass it through both vEe calls in that function, matching the interactive resume path.