Skip to content

v0.24.0

Choose a tag to compare

@ya-luotao ya-luotao released this 27 Jul 07:37
· 578 commits to main since this release

Parity batch with the Python SDK v0.2.111–v0.2.128 — everything substantive in that span; the rest is bundled-CLI version bumps, which don't apply to this gem.

Fixed

  • argv flag injection via resume / session_id / resume_session_at (Python #1123): these values are now passed as single =-joined argv tokens (--resume=<value>). The CLI declares --resume [value] with an optional value, so in the old two-token form a dash-leading untrusted value (e.g. a session id taken from a request) parsed as an independent CLI flag — letting it inject e.g. --dangerously-skip-permissions. extra_args values starting with - are likewise emitted in --flag=value form (Python #1127).
  • Premature stdin close while background tasks are in flight (Python #1103): a result frame ends one turn, not the run. The SDK no longer closes stdin on a result while run_in_background subagents are still running — previously their SDK-MCP tool calls failed with "Stream closed" and their PreToolUse hooks were silently bypassed. In-flight tasks are tracked from task_started / task_notification / terminal task_updated lifecycle frames.
  • Leaked CLI child when a cancellation interrupts close (Python #1082): SubprocessCLITransport#close now guarantees termination from an ensure with no suspension points — synchronous SIGTERM plus a background-thread SIGKILL after a 2s grace — and closes the pipe descriptors instead of leaking them, when Async::Stop interrupts the graceful escalation.

Added

  • ResultMessage#terminal_reason (Python #1142): why the query loop ended ("completed", "max_turns", "aborted_streaming", …). "aborted_streaming" / "aborted_tools" mean the turn was cancelled via Client#interrupt.
  • Advisory warning when can_use_tool is shadowed (Python #1081): permission_mode: 'bypassPermissions' or an allowed_tools entry that allows a whole tool ('Read', 'Read()', 'Read(*)', incl. the bare Skill implied by skills: 'all') silently turns a security callback into dead code — query() / Client#connect now warn to stderr, once per distinct message per process. Never raises.
  • Documented the ResultMessage#model_usage per-model value shape (verbatim CLI camelCase keys), including the new optional canonicalModel and provider keys (Python #1143).

Usage

result = nil
ClaudeAgentSDK.query(prompt: 'hi') { |msg| result = msg if msg.is_a?(ClaudeAgentSDK::ResultMessage) }
result.terminal_reason # => "completed" | "max_turns" | "aborted_streaming" | ...

What's changed

  • #46 Port Python SDK v0.2.111–v0.2.128 parity batch — @ya-luotao

Full Changelog: v0.23.0...v0.24.0


gem install claude-agent-sdk -v 0.24.0