Skip to content

Releases: guess/claude_code

v0.36.4 | CC 2.1.76

27 May 06:14

Choose a tag to compare

Fixed

  • Streams now halt on terminal AssistantMessage errors — When the CLI encounters an unrecoverable error (rate limit, auth failure, billing), it previously entered an infinite loop emitting synthetic message pairs because the stream only halted on ResultMessage. The stream now detects AssistantMessage with a non-nil error field and synthesizes a ResultMessage with is_error: true, so query/2, final_text/1, and collect/1 all handle the error correctly. (ce727de)
  • :can_use_tool callback returning bare :allow or unmessaged :deny no longer triggers CLI ZodErrorPermissionDecision.Allow.to_wire/1 now always emits "updatedInput" (defaulting to %{} when nil), and PermissionDecision.Deny.to_wire/1 now always emits "message" (defaulting to "" when nil). The Claude CLI's permission-response schema (Zod union) treats both fields as required on their respective arms, so omitting them caused every tool call routed through can_use_tool to fail validation. Verified against CLI 2.1.76. (c60799c)

v0.36.3 | CC 2.1.76

30 Mar 06:27

Choose a tag to compare

Fixed

  • ClaudeCode.History ~/.claude path evaluated at runtime — The default ~/.claude directory was a module attribute computed at compile time, which could resolve to the wrong home directory in release builds or containerized environments. Now evaluated at runtime via a private function. ([90eb073])

v0.36.2 | CC 2.1.76

30 Mar 04:35

Choose a tag to compare

Fixed

  • --control-timeout no longer sent to CLI — The :control_timeout option, which is internal to the Elixir SDK, was incorrectly passed to the CLI as a flag. ([5ac7a0a])
  • Silenced stray Plug messages in CallbackProxy — When MCP tools execute in-process API calls via Dispatch, Plug sends messages to the CallbackProxy process, which OTP logged as errors. These harmless messages are now silently discarded. ([27087c4])

Changed

  • :extra_args changed from list to map — The :extra_args option now accepts a map of %{flag => value} (or %{flag => true} for boolean flags) instead of a list, aligning with the Python SDK convention. ([5ac7a0a])

v0.36.1 | CC 2.1.76

30 Mar 00:10

Choose a tag to compare

Removed

  • Query-level option overrides for stream/3 — Removed the ability to pass options to stream/3 at call time. Since adopting the control protocol, the CLI subprocess ignores per-query option changes. All configuration should be set at session start via start_link/1. ([addd8b4])

v0.36.0 | CC 2.1.76

29 Mar 19:12

Choose a tag to compare

Added

  • :inherit_env option — Controls which system environment variables are inherited by the CLI subprocess. Defaults to :all (inherit everything except CLAUDECODE, matching Python SDK behavior). Set to a list of exact strings or {:prefix, "..."} tuples for selective inheritance, or [] to inherit nothing. See Secure Deployment.

  • :env now accepts false values — Setting a key to false in the :env option unsets that variable in the CLI subprocess, leveraging Erlang Port's native env unsetting. Useful for removing sensitive inherited vars: env: %{"RELEASE_COOKIE" => false}.

Fixed

  • Hardened timing-sensitive tests — Replaced Process.sleep calls across ClaudeCode.SessionTest, ClaudeCodeTest, and ClaudeCode.SupervisorTest with deterministic synchronization (MockCLI.poll_until/2, Process.monitor + assert_receive, synchronous :sys.get_state calls). Corrected two supervisor tests that assumed empty config would crash the child — api_key is now optional (defaults to ANTHROPIC_API_KEY env var), so the child starts successfully; tests now assert count == 1 to reflect current behavior.

Changed

  • MCP tool DSL — Tool descriptions moved from a positional argument into the block. This is a breaking change. ([44573a7])

    # Before
    tool :add, "Add two numbers" do
      ...
    end
    
    # After
    tool :add do
      description "Add two numbers"
      ...
    end
  • Port spawning refactored to direct spawn_executableClaudeCode.Adapter.Port now spawns the CLI binary directly via Erlang's native :spawn_executable with :args, :env, and :cd port options, replacing the previous /bin/sh -c approach that required hand-rolled shell escaping. This eliminates ClaudeCode.Adapter.Port.shell_escape/1, build_shell_command/4, and the @shell_safe_pattern module attribute entirely. Environment variables, arguments, and paths with special characters (e.g. !, #, <, >, [, ]) are now handled natively by the Erlang runtime without shell interpretation.

Fixed

  • CLI arg ordering for :plugins, :add_dir, and :file — Flag/value pairs were reversed (e.g., /path --plugin-dir instead of --plugin-dir /path), causing the CLI to misinterpret arguments.

  • Flaky health/1 provisioning testClaudeCode.Adapter.PortIntegrationTest now accepts both {:unhealthy, :provisioning} and {:unhealthy, :not_connected} during startup, fixing a race condition where fast CI runners could resolve the CLI before the assertion.

v0.35.0 | CC 2.1.76

26 Mar 18:38

Choose a tag to compare

Added

  • MCP test helpers — New ClaudeCode.Test.mcp_list_tools/1, ClaudeCode.Test.mcp_call_tool/3,4, and ClaudeCode.Test.mcp_request/2,3 for testing MCP tool servers without JSONRPC boilerplate. ([5d920e0])
  • ClaudeCode.Session.execute/4 — New optional execute/4 callback on the Adapter behaviour for running arbitrary MFA calls through the adapter layer, enabling transparent local/remote execution. ClaudeCode.Session.get_messages/2 and ClaudeCode.Session.list_sessions/2 now route through the Server for node-aware operation. ([aa3b54b])

Fixed

  • Shell escape safetyshell_escape now quotes all non-safe characters instead of allowlisting known dangerous ones, preventing shell interpretation of !, #, <, >, ?, [, ], {, }, *, ~, tab, etc. ([0882139])

Changed

  • MCP backend migrated from hermes to anubis — Internal MCP backend replaced hermes_mcp with anubis_mcp. No breaking changes to the public API. ([967216d])

v0.34.0 | CC 2.1.76

26 Mar 04:53

Choose a tag to compare

Changed

  • anubis_mcp upgraded to 1.0 and made a required dependencyanubis_mcp has been bumped from ~> 0.17 (optional) to ~> 1.0 (required). Users who depend on MCP functionality no longer need to explicitly add anubis_mcp to their deps. ([47a9afd])

v0.33.1 | CC 2.1.76

20 Mar 22:20

Choose a tag to compare

Changed

  • Enhanced can_use_tool callback context — The :can_use_tool hook callback now receives additional context fields: cwd, session_id, and permission_suggestions, enabling more informed permission decisions. (59ea547)

v0.33.0 | CC 2.1.76

15 Mar 06:08

Choose a tag to compare

Added

  • MCP backend abstraction — New ClaudeCode.MCP.Backend behaviour allows pluggable MCP library backends. Ships with Backend.Anubis (new default) and Backend.Hermes (legacy). Both backends are optional — only compile when their respective library is loaded. Centralized backend detection via ClaudeCode.MCP.backend_for/1. ([4c69cbb])
  • Enhanced session history (Python SDK parity) — New ClaudeCode.History.list_sessions/1 returns rich ClaudeCode.History.SessionInfo metadata (summary, custom title, first prompt, git branch, cwd) using fast head/tail reads without full JSONL parsing. Supports worktree-aware scanning, deduplication, and :limit. ([bf93d7c])
  • Chain-built message retrieval — New ClaudeCode.History.get_messages/2 and ClaudeCode.Session.get_messages/2 reconstruct conversations via parentUuid chain walking, correctly handling branched and compacted conversations. Returns ClaudeCode.History.SessionMessage structs with parsed content blocks (TextBlock, ToolUseBlock, etc.). Supports :limit and :offset pagination. ([bf93d7c])
  • ClaudeCode.History.SessionMessage struct — Typed struct for history messages with :user/:assistant atom types, chain metadata (uuid, session_id), and parsed message content. ([bf93d7c])
  • ClaudeCode.History.SessionInfo struct — Rich session metadata including session_id, summary, last_modified, file_size, custom_title, first_prompt, git_branch, and cwd. ([bf93d7c])
  • ClaudeCode.History.sanitize_path/1 — Python SDK-compatible path sanitization (replaces all non-alphanumeric chars with hyphens, handles long paths with hash suffix). ([bf93d7c])
  • Configurable control_timeout session option — Max time in ms to wait for CLI control responses (e.g. initialize handshake, MCP server startup). Defaults to 60,000ms to match the Python SDK. Useful when MCP servers are slow to start. ([fb28a46], [6758caa])

Changed

  • MCP tool macro rewriteClaudeCode.MCP.Server.tool/3 now generates standalone modules without Hermes dependency. Tools use execute/2 with (params, assigns) instead of Hermes frames. ([4c69cbb])
  • MCP Router decoupled from Hermes — Router delegates all tool operations to the configured backend instead of importing Hermes modules directly. ([4c69cbb])
  • Breaking: Removed ClaudeCode.History.conversation/2, ClaudeCode.History.conversation_from_file/1, and ClaudeCode.Session.conversation/2 — replaced by get_messages/2 which properly handles branched/compacted conversations via parentUuid chain building. ([bf93d7c])
  • Breaking: Removed :callback_timeout from ClaudeCode.Adapter.Node — proxy delegation for hooks and MCP now uses the unified :control_timeout option instead. If you were passing :callback_timeout in adapter config, change it to :control_timeout as a session option. ([6758caa])

v0.32.2 | CC 2.1.76

14 Mar 23:06

Choose a tag to compare

Fixed

  • mix claude_code.install version checkClaudeCode.Adapter.Port.Installer.version_of/1 now retries once after 500ms on exit code 137 (SIGKILL). On macOS, Gatekeeper can kill a freshly-copied binary during initial code signature verification, causing claude --version to fail with empty output. This led to "Could not determine installed version" on every install and unnecessary reinstalls.