Repository navigation
v0.15.0
Fixed
Protocol & CLI
--setting-sourcesis now only emitted when the option is explicitly configured. Previously every invocation sent--setting-sources "", which the CLI can interpret as "no setting sources" rather than "use defaults", overriding the CLI's own source resolution.extra_argsflag names are validated against a lowercase kebab-case pattern and raiseArgumentErrorotherwise. Prevents option injection from multi-tenant configs (e.g. an attacker-controlled hash injecting--permission-mode bypassPermissionsand relying on CLI last-wins to defeat SDK-chosen safety).
Concurrency
SubprocessCLITransport#closereplacedTimeout.timeoutwith Async-safe polling on@process.alive?. StdlibTimeout.timeoutraises viaThread#raise, which can corrupt fiber-scheduler state whencloseruns inside the Async reactor. Still raisesTimeout::Errorso existing rescue clauses keep working.- Inbound
control_requesthandlers are now spawned as children of the current read task viaAsync::Task.current.async. BareAsync dohad ambiguous parent linkage;@task.stopcould leave handler tasks writing to a closed transport.
Sessions
list_sessionsandget_session_messagescoerceoffset: nilto 0. Previously callers splatting from an options hash crashed onnil.positive?/messages[nil..].fork_sessionstreams the source JSONL viaFile.foreachinstead ofFile.read, and scrubs non-UTF-8 bytes on each line. FixesEncoding::InvalidByteSequenceErroron stray bytes in tool output and avoids slurping sessions that can reach hundreds of MB.simple_hash(used for project-dir hashing) now iterates UTF-16 code units to match JavaScript'scharCodeAt. Previouslyeach_char+orddiverged from the official tools for supplementary characters (emoji, CJK extensions), so paths containing them hashed to different project directories and silently returned no sessions.
Security
- Replaced shell backticks with
Open3.capture3(array args) in worktree detection. The path argument was alreadyShellwords.escaped, but running via/bin/shleaves a latent shell-injection surface — any future interpolation without escaping would be exploitable.
Changed
derive_fork_titlehelper onSessionMutationsis nowprivate_class_method, matching its siblings. It is not intended for external use.
What's changed
- #19 Fix 8 bugs found in multi-angle code review — @ya-luotao
- #21 test(effort): pin Integer effort pass-through contract — @ya-luotao
Full Changelog: v0.14.2...v0.15.0
gem install claude-agent-sdk -v 0.15.0