claude-agent-sdk 0.31.0 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -0
- data/README.md +110 -225
- data/docs/cli-installer.md +57 -0
- data/docs/client.md +4 -0
- data/docs/configuration.md +55 -0
- data/docs/hooks-and-permissions.md +66 -2
- data/docs/sessions.md +28 -0
- data/docs/subagents.md +198 -0
- data/docs/types.md +37 -5
- data/lib/claude_agent_sdk/cancellation_signal.rb +28 -0
- data/lib/claude_agent_sdk/command_builder.rb +18 -0
- data/lib/claude_agent_sdk/message_parser.rb +3 -1
- data/lib/claude_agent_sdk/query.rb +111 -21
- data/lib/claude_agent_sdk/sessions.rb +37 -0
- data/lib/claude_agent_sdk/types.rb +259 -14
- data/lib/claude_agent_sdk/version.rb +1 -1
- data/lib/claude_agent_sdk.rb +68 -2
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c5c70ede77de755091c7587cb3bed3ea95075ed6db34b7a2cc4e3214db9adcb5
|
|
4
|
+
data.tar.gz: b4d77a1e0888dc0ef3e436e933ee2334d6912b087e440fb88af0765e34703e10
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '0658614c047b36d2cd7c8724c01e31b1bdcb4aac81246caf6e56c7afb9e8203bf2e7cedfd112c59c317fb0cd5359785737e8a4e33efa67f448ee47792a81fc17'
|
|
7
|
+
data.tar.gz: 2938e8804ee6396fdadb60be8345da7317628f853ec35947aba5f8542c732346d4a360aa0222f57977d18578e3689e0307d55337802f908ce4eed85543518122
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.33.0] - 2026-09-21
|
|
11
|
+
|
|
12
|
+
Subagent capabilities for UI builders: metadata reads, background snapshots, cooperative callback cancellation, and the task/background/permission signals the CLI already emits — all raw data and controls, no status model. Ruby-ahead of the Python SDK (0.2.153).
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- `get_subagent_metadata` / `get_subagent_metadata_from_store`: read optional subagent metadata with original string keys, including type, spawning tool ID, parent agent, depth, and future CLI fields. Disk reads reuse transcript scoping without parsing the transcript; store reads select the latest metadata entry even before messages arrive. These are historical reads, not live-status queries.
|
|
16
|
+
- `background_tasks` and `session_crons` on `StopHookInput` / `SubagentStopHookInput`. Raw snapshots preserve unavailable (`nil`) versus explicitly empty (`[]`) and describe the parent session, not all foreground/background agents.
|
|
17
|
+
- Cooperative permission cancellation through `ToolPermissionContext#signal` (`CancellationSignal#cancelled?` / `#wait`) and the associated `request_id`. CLI cancellation, disconnect, EOF, and failed dispatch invalidate pending requests, including callbacks running on worker threads; normal decisions do not. User threads are not forcibly stopped, and late decisions after observed cancellation cannot become allow responses.
|
|
18
|
+
- `HookContext#signal` / `#request_id` use the same per-invocation cancellation contract, including hook timeouts. Thread callbacks can cooperate with cancellation; late hook output is discarded.
|
|
19
|
+
- A minimal subagent event subscription example and capability reference covering lifecycle events, metadata, background snapshots, and permission cancellation. UI and application status aggregation remain outside the SDK.
|
|
20
|
+
- Opt-in real-CLI subagent contract tests for ID/metadata/text correlation, permission cancellation on interrupt, and background completion/stop after a parent result. They self-skip without CLI credentials.
|
|
21
|
+
- Subagent UI signals the CLI already emits, read from the schema embedded in Claude Code CLI 2.1.278 (the Python SDK has none of these as of Python SDK 0.2.153; only partly verified live — a smoke run against CLI 2.1.278 confirmed the `task_started` fields and the targeted-miss `background_tasks` response; the rest is schema-derived). The SDK exposes raw data and controls only — no status aggregation.
|
|
22
|
+
- `TaskStartedMessage#subagent_type` / `#is_backgrounded` / `#spawn_depth`, `TaskProgressMessage#subagent_type`, `TaskNotificationMessage#reason` / `#resource_links` (raw Array, symbol keys with the wire spelling), the `#skip_transcript` / `#ambient` display flags on both `TaskStartedMessage` and `TaskNotificationMessage` (hints for the host — the SDK never filters frames or computes activity), and `TaskUpdatedMessage#is_backgrounded` / `#error` / `#end_time` / `#total_paused_ms` / `#description` derived from `patch` like `status`. `is_backgrounded` keeps `nil` (not reported) distinct from an explicit `false` (foreground, spawning tool call blocking). `TaskUpdatedMessage` now also reads a string-keyed `patch` on hand-built messages.
|
|
23
|
+
- `BackgroundTasksChangedMessage` (`background_tasks_changed`): the full set of live background tasks, a level signal with REPLACE semantics. The SDK's own stdin-close bookkeeping still deliberately ignores this frame.
|
|
24
|
+
- `PermissionDeniedMessage` (`permission_denied`): a tool call auto-denied without an interactive prompt, with `agent_id` for subagent routing (not a permission `request_id`). A best-effort advisory, not a complete denial feed — `ResultMessage#permission_denials` stays authoritative.
|
|
25
|
+
- `Client#background_tasks(tool_use_id: nil)` / `Query#background_tasks`: send in-flight foreground tasks to the background (Ctrl+B). Keyed by the spawning `tool_use_id`, not `task_id` / `agent_id`. The targeted form returns `{ backgrounded: true }` or `{ backgrounded: false }` — a definitive miss, after which no event is coming; `nil` is the explicit all-tasks form and returns `{}`. Because the CLI treats `''` as "all tasks", anything other than `nil` or a non-empty String raises `ArgumentError` before a request is written. `TaskUpdatedMessage#is_backgrounded` / `BackgroundTasksChangedMessage` report the lifecycle state that follows.
|
|
26
|
+
- `ClaudeAgentOptions#agent_progress_summaries`: request model-generated progress summaries for subagents; `TaskProgressMessage#summary` may then be present, and stays optional. Tri-state; `nil` omits `agentProgressSummaries` from the `initialize` request and `true` / `false` are forwarded verbatim. An enable switch, not a live toggle: CLI 2.1.278 only acts on a truthy value, so `false` is equivalent to unset.
|
|
27
|
+
- **Compatibility:** `background_tasks_changed` and `permission_denied` frames previously parsed as a generic `SystemMessage`. Both new classes subclass it, so `when SystemMessage` and `#data` consumers are unaffected; code matching on `message.class == SystemMessage` will no longer see them.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
- Best-effort control error/cancellation replies no longer leak a secondary connection error when the CLI has already exited. Original transport read errors still propagate to the consumer.
|
|
31
|
+
- Control-request tracking is identity-guarded: if the CLI ever reused an in-flight request ID, the first handler finishing no longer untracks the later request's cancellation signal or task, so EOF, disconnect, and `control_cancel_request` still invalidate it and its late decision cannot be sent as a success.
|
|
32
|
+
- `ClaudeAgentSDK.configure` defaults now merge by option, not by literal key spelling. `ClaudeAgentOptions` accepts symbol/string and snake_case/camelCase names, but the defaults merge compared raw keys, so a differently spelled per-call key rode along as a second entry: `'permissionMode' => nil` wiped a configured `permission_mode:` instead of inheriting it, and a Hash option such as `'env' => {...}` replaced the configured `env:` instead of merging into it. Unknown option names are still reported with the caller's own spelling.
|
|
33
|
+
|
|
34
|
+
## [0.32.0] - 2026-09-17
|
|
35
|
+
|
|
36
|
+
Syncs the gem with Python SDK **0.2.153** (previously 0.2.147). The intervening Python releases 0.2.148–0.2.152 only bump the CLI binary Python bundles; this gem does not vendor a CLI, so they carry no Ruby-side change.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
- **`snapshot` on `SystemPromptPreset`, and a new `SystemPromptCustom` type** (port of Python [#1268](https://github.com/anthropics/claude-agent-sdk-python/pull/1268), v0.2.153). By default the CLI records the system prompt on a session's first request and reuses it on every later request, including after resume, so a changed `append` or custom prompt has no effect until the session is compacted or a new one starts. `snapshot: false` makes the CLI rebuild the prompt on every request instead — useful while iterating on prompt text across calls that resume the same session. `SystemPromptCustom` (`prompt:`, `snapshot:`) is the object form of a String prompt, so `snapshot` can travel with it; the `{ type: 'custom', prompt: '...', snapshot: false }` and `{ type: 'preset', ..., snapshot: false }` Hash forms are accepted too. The value rides on the control-protocol `initialize` request as `systemPromptSnapshot` (never as a CLI flag), so it applies to both `query()` and `Client`; `false` is sent explicitly and only an unset value is omitted. `SystemPromptFile` has no `snapshot`, and one given on a file Hash is ignored, as in Python. Requires Claude Code CLI 2.1.257 or later; before 2.1.265 a session with an `append` or custom prompt recorded it only when `snapshot` was `true`. Older CLIs silently ignore the field.
|
|
40
|
+
- **Compatibility:** a `{ type: 'custom', ... }` Hash previously fell through the command builder unrecognised — pushing no flag at all — and so silently activated the *default* Claude Code system prompt. It now forwards `--system-prompt <prompt>` exactly like a String, and a custom prompt without a String `prompt` raises `ArgumentError` at command-build time rather than falling through (Python raises `KeyError` on the same input).
|
|
41
|
+
|
|
10
42
|
## [0.31.0] - 2026-08-28
|
|
11
43
|
|
|
12
44
|
Syncs the gem with Python SDK **0.2.147** (previously 0.2.134). The intervening Python releases 0.2.135/136/138/139/141–147 only bump the CLI binary Python bundles; this gem does not vendor a CLI, so they carry no Ruby-side change.
|
data/README.md
CHANGED
|
@@ -1,143 +1,48 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-

|
|
4
|
-
|
|
5
|
-
[](https://badge.fury.io/rb/claude-agent-sdk)
|
|
6
|
-
|
|
7
|
-
An **unofficial, community-maintained** Ruby SDK for the [Claude Code](https://docs.claude.com/en/docs/claude-code-overview) agent runtime. Not affiliated with or supported by Anthropic.
|
|
8
|
-
|
|
9
|
-
Official SDKs: [TypeScript](https://github.com/anthropics/claude-agent-sdk-typescript) · [Python](https://github.com/anthropics/claude-agent-sdk-python).
|
|
10
|
-
|
|
11
|
-
## Why a Ruby SDK?
|
|
12
|
-
|
|
13
|
-
Ruby powers a massive ecosystem — Rails, Sidekiq, Kamal, countless production web apps — but has no official Claude Agent SDK. This gem fills that gap so Ruby and Rails developers can build AI agents, automate coding workflows, and integrate Claude into existing applications without switching languages or shelling out to Python/Node.
|
|
1
|
+

|
|
14
2
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
### Comparison with Official SDKs
|
|
3
|
+
# Claude Agent SDK for Ruby
|
|
18
4
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
| Custom tools (SDK MCP servers) | `tool()` | `@tool` decorator | `create_tool` block |
|
|
25
|
-
| Hooks (all 27 events) | ✅ | ✅ | ✅ |
|
|
26
|
-
| Permission callbacks | ✅ | ✅ | ✅ |
|
|
27
|
-
| Structured output | ✅ | ✅ | ✅ |
|
|
28
|
-
| All 25 message types | ✅ | partial | ✅ |
|
|
29
|
-
| [Sandbox](https://github.com/anthropic-experimental/sandbox-runtime) settings | ✅ | partial | ✅ |
|
|
30
|
-
| Bare mode (`--bare`) | ✅ | ✅ | ✅ |
|
|
31
|
-
| File checkpointing & rewind | ✅ | ✅ | ✅ |
|
|
32
|
-
| Session browsing & mutations | ✅ | ✅ | ✅ |
|
|
33
|
-
| Programmatic subagents | ✅ | ✅ | ✅ |
|
|
34
|
-
| Bundled CLI binary | ✅ | ✅ | — (install `claude` separately) |
|
|
35
|
-
| Observability (OTel / Langfuse) | via [Arize](https://github.com/Arize-ai/openinference) | — | ✅ (built-in) |
|
|
36
|
-
| Custom transport (pluggable I/O) | — | — | ✅ |
|
|
37
|
-
| Rails integration | — | — | ✅ |
|
|
5
|
+
[](https://rubygems.org/gems/claude-agent-sdk)
|
|
6
|
+
[](https://github.com/ya-luotao/claude-agent-sdk-ruby/actions/workflows/ci.yml)
|
|
7
|
+
[](https://www.ruby-lang.org/)
|
|
8
|
+
[](https://rubydoc.info/gems/claude-agent-sdk)
|
|
9
|
+
[](LICENSE)
|
|
38
10
|
|
|
39
|
-
|
|
11
|
+
A Ruby SDK for the [Claude Code](https://docs.claude.com/en/docs/claude-code-overview) agent runtime. Build AI agents, automate coding workflows, and integrate Claude into Rails and other Ruby applications with the same capabilities as the official [TypeScript](https://github.com/anthropics/claude-agent-sdk-typescript) and [Python](https://github.com/anthropics/claude-agent-sdk-python) SDKs.
|
|
40
12
|
|
|
41
|
-
**
|
|
13
|
+
> **Unofficial and community-maintained.** This project is not affiliated with or supported by Anthropic. It tracks the official SDKs release by release; see the [CHANGELOG](CHANGELOG.md) for the currently synced version.
|
|
42
14
|
|
|
43
|
-
|
|
44
|
-
<summary><strong>Implementation differences from the official SDKs</strong></summary>
|
|
15
|
+
## Highlights
|
|
45
16
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
client.disconnect
|
|
55
|
-
end.wait
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Types use plain Ruby classes with `attr_accessor` and keyword args — no runtime type checking, but the same structure and field names as the TS Zod schemas / Python dataclasses. Subprocess transport uses `Open3.popen3`; wire protocol is identical.
|
|
59
|
-
|
|
60
|
-
</details>
|
|
17
|
+
- **Same wire protocol as the official SDKs.** Spawns the `claude` CLI as a subprocess and speaks stream-JSON over stdin/stdout, so every feature of the runtime is available: sessions, subagents, sandboxing, structured output, file checkpointing and rewind.
|
|
18
|
+
- **`query()` for one-shot calls, `Client` for bidirectional sessions** with interrupts, mid-session model switching, and streaming input from any `Enumerator`.
|
|
19
|
+
- **In-process custom tools.** Define tools as Ruby blocks; they run inside your process with direct access to your app state (SDK MCP servers), with JSON-Schema-validated arguments.
|
|
20
|
+
- **All 27 hook events and permission callbacks** with typed inputs, so you can gate, audit, or rewrite every tool call.
|
|
21
|
+
- **Rails-ready.** Fiber-safe callback dispatch, an initializer-style `configure` block, ActionCable streaming, background-job session resumption, and a `callback_scheduling: :inline` mode for fiber workers.
|
|
22
|
+
- **Built-in OpenTelemetry observer** with Langfuse support; no third-party instrumentation library required.
|
|
23
|
+
- **Pluggable transport** to run the CLI somewhere else (an E2B microVM, a container, over SSH).
|
|
24
|
+
- **Hermetic deploys.** `CLIInstaller` vendors a checksum-verified, pinned CLI binary into your project so production never depends on a global `npm install`.
|
|
61
25
|
|
|
62
26
|
## Installation
|
|
63
27
|
|
|
64
|
-
Add this line to your application's Gemfile:
|
|
65
|
-
|
|
66
28
|
```ruby
|
|
67
|
-
#
|
|
68
|
-
gem 'claude-agent-sdk',
|
|
69
|
-
|
|
70
|
-
# Or use a stable version from RubyGems
|
|
71
|
-
gem 'claude-agent-sdk', '~> 0.31.0'
|
|
29
|
+
# Gemfile
|
|
30
|
+
gem 'claude-agent-sdk', '~> 0.33.0'
|
|
72
31
|
```
|
|
73
32
|
|
|
74
|
-
Then `bundle install`, or install directly
|
|
75
|
-
|
|
76
|
-
**Prerequisites:**
|
|
77
|
-
- Ruby 3.2+
|
|
78
|
-
- Node.js
|
|
79
|
-
- Claude Code 2.0.0+: `npm install -g @anthropic-ai/claude-code`
|
|
33
|
+
Then `bundle install`, or install directly with `gem install claude-agent-sdk`. To track unreleased changes, point the Gemfile at GitHub: `gem 'claude-agent-sdk', github: 'ya-luotao/claude-agent-sdk-ruby'`.
|
|
80
34
|
|
|
81
|
-
|
|
35
|
+
**Prerequisites**
|
|
82
36
|
|
|
83
|
-
|
|
37
|
+
- Ruby 3.2 or newer
|
|
38
|
+
- Claude Code CLI 2.0.0 or newer, either installed globally (`npm install -g @anthropic-ai/claude-code`) or vendored with `CLIInstaller`:
|
|
84
39
|
|
|
85
40
|
```ruby
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
# 'stable' (default), 'latest', or a concrete version — pin it in production.
|
|
89
|
-
ClaudeAgentSDK::CLIInstaller.install(version: '2.1.220')
|
|
90
|
-
# => "/app/vendor/claude/claude"
|
|
91
|
-
|
|
92
|
-
ClaudeAgentSDK::CLIInstaller.install(version: '2.1.220', dir: '/opt/claude')
|
|
93
|
-
|
|
94
|
-
# nil unless a binary is already installed there
|
|
95
|
-
ClaudeAgentSDK::CLIInstaller.installed_path
|
|
41
|
+
# bin/setup or a cached Docker layer — pin a concrete version in production
|
|
42
|
+
ClaudeAgentSDK::CLIInstaller.install(version: '2.1.220') # => "/app/vendor/claude/claude"
|
|
96
43
|
```
|
|
97
44
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
- The install directory's `VERSION` file records the installed version **and** the SHA-256 that was verified at download time. The shortcut re-hashes the vendored binary (~0.1s for the real 245MB binary) and only skips the download when both match — a truncated, swapped or half-written binary is reinstalled instead of trusted. It makes **no network request**, so repeat boots work offline — with a pinned concrete version; `'stable'`/`'latest'` must always re-resolve through the endpoint, which is one more reason to pin in production.
|
|
101
|
-
- An exclusive `flock` on `<dir>/.install.lock` covers the whole check → download → place → record sequence, so parallel installs into one directory don't race; the loser simply observes the finished install.
|
|
102
|
-
|
|
103
|
-
Failures (unsupported platform, invalid version, HTTP error, response-size cap, oversized download, checksum mismatch, filesystem errors) raise `ClaudeAgentSDK::CLIInstallError`.
|
|
104
|
-
|
|
105
|
-
**A failed install never breaks a working one.** The new binary is downloaded to a temp file, checksum-verified and recorded, and only then renamed into place — the rename is the last step, and nothing can fail after it. So a failed upgrade leaves the previously installed binary intact and runnable (the SDK keeps working), and the next `install` redoes it cleanly. A first install that fails leaves nothing behind at all.
|
|
106
|
-
|
|
107
|
-
> The vendored directory is trusted input: anything that can write to it can replace the binary the SDK executes. Keep it inside your deploy artifact, owned by the deploy user and not world-writable, exactly as you would treat `bin/`.
|
|
108
|
-
|
|
109
|
-
```dockerfile
|
|
110
|
-
# Dockerfile — pin the CLI in its own cached layer
|
|
111
|
-
RUN bundle exec ruby -e "require 'claude_agent_sdk'; \
|
|
112
|
-
ClaudeAgentSDK::CLIInstaller.install(version: '2.1.220')"
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
```ruby
|
|
116
|
-
#!/usr/bin/env ruby
|
|
117
|
-
# bin/setup
|
|
118
|
-
require 'claude_agent_sdk'
|
|
119
|
-
puts ClaudeAgentSDK::CLIInstaller.install(version: ENV.fetch('CLAUDE_CLI_VERSION', 'stable'))
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
Supported platforms: `darwin-arm64`, `darwin-x64` (Rosetta 2 gets the arm64 build), `linux-x64`, `linux-arm64`, and the `-musl` variants. Windows is not supported.
|
|
123
|
-
|
|
124
|
-
**CLI discovery order.** With no explicit `cli_path:` in `ClaudeAgentOptions`, the transport probes in this order:
|
|
125
|
-
|
|
126
|
-
1. `CLAUDE_CLI_PATH` — an explicit path to an executable, no discovery at all (a relative value is resolved against the process's working directory, not `cwd:`)
|
|
127
|
-
2. The vendored binary (`CLIInstaller.installed_path`) — deliberately ahead of `PATH`, so a pinned install beats whatever is installed globally
|
|
128
|
-
3. `which claude`
|
|
129
|
-
4. Common install locations (`~/.claude/local/claude`, `/usr/local/bin/claude`, …)
|
|
130
|
-
|
|
131
|
-
### Agentic Coding Skill
|
|
132
|
-
|
|
133
|
-
If you're using [Claude Code](https://claude.ai/claude-code), this repo is a Claude Code plugin marketplace. Add it once, then install the skill:
|
|
134
|
-
|
|
135
|
-
```bash
|
|
136
|
-
/plugin marketplace add ya-luotao/claude-agent-sdk-ruby
|
|
137
|
-
/plugin install claude-agent-ruby@claude-agent-sdk-ruby
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
This skill teaches your AI coding assistant about the SDK's APIs, patterns, and best practices.
|
|
45
|
+
The vendored binary is found ahead of `PATH`, installs are idempotent and concurrency-safe, and a failed upgrade never breaks a working install. See [docs/cli-installer.md](docs/cli-installer.md) for the full behaviour, supported platforms, and the CLI discovery order.
|
|
141
46
|
|
|
142
47
|
## Quick Start
|
|
143
48
|
|
|
@@ -145,46 +50,29 @@ This skill teaches your AI coding assistant about the SDK's APIs, patterns, and
|
|
|
145
50
|
require 'claude_agent_sdk'
|
|
146
51
|
|
|
147
52
|
ClaudeAgentSDK.query(prompt: "What is 2 + 2?") do |message|
|
|
148
|
-
puts message
|
|
53
|
+
puts message.text if message.is_a?(ClaudeAgentSDK::AssistantMessage)
|
|
149
54
|
end
|
|
150
55
|
```
|
|
151
56
|
|
|
152
|
-
|
|
57
|
+
### `query()` — one-shot and streaming
|
|
153
58
|
|
|
154
|
-
`query()`
|
|
59
|
+
`query()` runs a single conversation and yields each response message to the block.
|
|
155
60
|
|
|
156
61
|
```ruby
|
|
157
|
-
require 'claude_agent_sdk'
|
|
158
|
-
|
|
159
|
-
# Simple query
|
|
160
|
-
ClaudeAgentSDK.query(prompt: "Hello Claude") do |message|
|
|
161
|
-
puts message.text if message.is_a?(ClaudeAgentSDK::AssistantMessage)
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
# With options
|
|
165
62
|
options = ClaudeAgentSDK::ClaudeAgentOptions.new(
|
|
166
63
|
system_prompt: "You are a helpful assistant",
|
|
167
|
-
max_turns: 1
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
ClaudeAgentSDK.query(prompt: "Tell me a joke", options: options) do |message|
|
|
171
|
-
puts message
|
|
172
|
-
end
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
**Using tools:**
|
|
176
|
-
|
|
177
|
-
```ruby
|
|
178
|
-
options = ClaudeAgentSDK::ClaudeAgentOptions.new(
|
|
179
64
|
allowed_tools: ['Read', 'Write', 'Bash'],
|
|
180
65
|
permission_mode: 'acceptEdits',
|
|
181
|
-
cwd: "/path/to/project"
|
|
66
|
+
cwd: "/path/to/project",
|
|
67
|
+
max_turns: 5
|
|
182
68
|
)
|
|
183
69
|
|
|
184
|
-
ClaudeAgentSDK.query(prompt: "Create a hello.rb file", options: options)
|
|
70
|
+
ClaudeAgentSDK.query(prompt: "Create a hello.rb file", options: options) do |message|
|
|
71
|
+
puts message
|
|
72
|
+
end
|
|
185
73
|
```
|
|
186
74
|
|
|
187
|
-
|
|
75
|
+
Pass an `Enumerator` instead of a string to stream several user messages into one session:
|
|
188
76
|
|
|
189
77
|
```ruby
|
|
190
78
|
stream = ClaudeAgentSDK::Streaming.from_array(['Hello!', 'What is 2+2?', 'Thanks!'])
|
|
@@ -194,11 +82,9 @@ ClaudeAgentSDK.query(prompt: stream) do |message|
|
|
|
194
82
|
end
|
|
195
83
|
```
|
|
196
84
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
## `Client` — Bidirectional Sessions
|
|
85
|
+
### `Client` — bidirectional sessions
|
|
200
86
|
|
|
201
|
-
`Client`
|
|
87
|
+
`Client` keeps a session open so you can send follow-up queries, interrupt, switch models, and use hooks, permission callbacks, and custom tools. It runs inside an [`async`](https://github.com/socketry/async) block; blocking calls yield automatically, no `await` needed.
|
|
202
88
|
|
|
203
89
|
```ruby
|
|
204
90
|
require 'claude_agent_sdk'
|
|
@@ -217,11 +103,11 @@ Async do
|
|
|
217
103
|
end.wait
|
|
218
104
|
```
|
|
219
105
|
|
|
220
|
-
|
|
106
|
+
See [docs/client.md](docs/client.md) for `interrupt`, mid-session model and permission switching, MCP status, and custom transports.
|
|
221
107
|
|
|
222
|
-
|
|
108
|
+
### Custom tools (SDK MCP servers)
|
|
223
109
|
|
|
224
|
-
|
|
110
|
+
Tools are Ruby blocks that run in-process, with no subprocess or IPC between Claude's tool call and your code.
|
|
225
111
|
|
|
226
112
|
```ruby
|
|
227
113
|
greet = ClaudeAgentSDK.create_tool('greet', 'Greet a user', { name: :string }) do |args|
|
|
@@ -236,13 +122,11 @@ options = ClaudeAgentSDK::ClaudeAgentOptions.new(
|
|
|
236
122
|
)
|
|
237
123
|
```
|
|
238
124
|
|
|
239
|
-
|
|
125
|
+
Arguments are validated against the tool's JSON Schema before your handler runs, and handler exceptions are reported back to the model in-band so it can self-correct. See [docs/mcp-servers.md](docs/mcp-servers.md) for resources, prompts, mixed SDK + external servers, and schema details.
|
|
240
126
|
|
|
241
|
-
|
|
127
|
+
### Hooks and permission callbacks
|
|
242
128
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
**Hooks** let the Claude Code application invoke your Ruby code at all 27 lifecycle points (`PreToolUse`, `PostToolUse`, `UserPromptSubmit`, `Stop`, `PreCompact`, etc.) with typed input objects. **Permission callbacks** give you programmatic control over tool execution.
|
|
129
|
+
Hooks run your Ruby code at any of the 27 lifecycle events (`PreToolUse`, `PostToolUse`, `UserPromptSubmit`, `Stop`, `PreCompact`, …) with typed inputs. Permission callbacks decide programmatically whether a tool call may proceed.
|
|
246
130
|
|
|
247
131
|
```ruby
|
|
248
132
|
options = ClaudeAgentSDK::ClaudeAgentOptions.new(
|
|
@@ -251,88 +135,89 @@ options = ClaudeAgentSDK::ClaudeAgentOptions.new(
|
|
|
251
135
|
)
|
|
252
136
|
```
|
|
253
137
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
##
|
|
257
|
-
|
|
258
|
-
| Topic |
|
|
259
|
-
|
|
260
|
-
|
|
|
261
|
-
|
|
|
262
|
-
|
|
|
263
|
-
|
|
|
138
|
+
See [docs/hooks-and-permissions.md](docs/hooks-and-permissions.md) for the full event list and worked examples.
|
|
139
|
+
|
|
140
|
+
## Documentation
|
|
141
|
+
|
|
142
|
+
| Topic | Guide |
|
|
143
|
+
|-------|-------|
|
|
144
|
+
| `Client` advanced features and custom transports | [docs/client.md](docs/client.md) |
|
|
145
|
+
| SDK MCP servers: tools, resources, prompts, schema compatibility | [docs/mcp-servers.md](docs/mcp-servers.md) |
|
|
146
|
+
| All hook events, typed inputs, permission callbacks | [docs/hooks-and-permissions.md](docs/hooks-and-permissions.md) |
|
|
147
|
+
| Structured output, thinking, budget, fallback and advisor models, sandbox, bare mode, checkpointing | [docs/configuration.md](docs/configuration.md) |
|
|
148
|
+
| Session listing, reading, renaming, tagging, forking, resume-at-message | [docs/sessions.md](docs/sessions.md) |
|
|
149
|
+
| Subagent capabilities, event contracts, and minimal example | [docs/subagents.md](docs/subagents.md) |
|
|
150
|
+
| OpenTelemetry tracing, Langfuse, custom observers | [docs/observability.md](docs/observability.md) |
|
|
151
|
+
| Rails: fiber safety, solid_queue fiber workers, ActionCable, jobs, initializer | [docs/rails.md](docs/rails.md) |
|
|
152
|
+
| Vendoring a pinned CLI binary and CLI discovery order | [docs/cli-installer.md](docs/cli-installer.md) |
|
|
264
153
|
| Message, content block, and configuration type reference | [docs/types.md](docs/types.md) |
|
|
265
|
-
| Error handling, exception hierarchy,
|
|
154
|
+
| Error handling, exception hierarchy, timeouts | [docs/errors.md](docs/errors.md) |
|
|
155
|
+
|
|
156
|
+
API reference: [rubydoc.info/gems/claude-agent-sdk](https://rubydoc.info/gems/claude-agent-sdk). Available built-in tools: [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code/settings#tools-available-to-claude).
|
|
266
157
|
|
|
267
158
|
## Examples
|
|
268
159
|
|
|
269
|
-
|
|
160
|
+
Runnable scripts live in [`examples/`](https://github.com/ya-luotao/claude-agent-sdk-ruby/tree/main/examples).
|
|
270
161
|
|
|
271
|
-
|
|
|
272
|
-
|
|
273
|
-
| [quick_start.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/
|
|
274
|
-
| [
|
|
275
|
-
| [
|
|
276
|
-
| [
|
|
277
|
-
| [
|
|
278
|
-
| [
|
|
279
|
-
| [error_handling_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/error_handling_example.rb) | Error handling with `AssistantMessage.error` |
|
|
280
|
-
| [bare_mode_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/bare_mode_example.rb) | Minimal startup with `bare: true` |
|
|
281
|
-
| [sandbox_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/sandbox_example.rb) | Full sandbox settings (network, filesystem, violations) |
|
|
162
|
+
| Area | Examples |
|
|
163
|
+
|------|----------|
|
|
164
|
+
| Getting started | [quick_start](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/quick_start.rb) · [client](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/client_example.rb) · [streaming_input](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/streaming_input_example.rb) · [message_types](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/message_types_example.rb) · [error_handling](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/error_handling_example.rb) |
|
|
165
|
+
| Sessions and output | [session_resumption](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/session_resumption_example.rb) · [structured_output](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/structured_output_example.rb) · [extended_thinking](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/extended_thinking_example.rb) · [session_stores/](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/session_stores/README.md) |
|
|
166
|
+
| Tools and MCP | [mcp_calculator](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/mcp_calculator.rb) · [mcp_resources_prompts](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/mcp_resources_prompts_example.rb) · [http_mcp_server](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/http_mcp_server_example.rb) |
|
|
167
|
+
| Hooks and permissions | [hooks](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/hooks_example.rb) · [advanced_hooks](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/advanced_hooks_example.rb) · [lifecycle_hooks](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/lifecycle_hooks_example.rb) · [permission_callback](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/permission_callback_example.rb) |
|
|
168
|
+
| Models and limits | [budget_control](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/budget_control_example.rb) · [fallback_model](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/fallback_model_example.rb) · [advisor](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/advisor_example.rb) · [bare_mode](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/bare_mode_example.rb) · [sandbox](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/sandbox_example.rb) |
|
|
169
|
+
| Rails, observability, transports | [rails_actioncable](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/rails_actioncable_example.rb) · [rails_background_job](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/rails_background_job_example.rb) · [otel_langfuse](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/otel_langfuse_example.rb) · [e2b_transport](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/e2b_transport_example.rb) |
|
|
282
170
|
|
|
283
|
-
|
|
171
|
+
## Comparison with the official SDKs
|
|
284
172
|
|
|
285
|
-
|
|
286
|
-
|---------|-------------|
|
|
287
|
-
| [mcp_calculator.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/mcp_calculator.rb) | Custom tools with SDK MCP servers |
|
|
288
|
-
| [mcp_resources_prompts_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/mcp_resources_prompts_example.rb) | MCP resources and prompts |
|
|
289
|
-
| [http_mcp_server_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/http_mcp_server_example.rb) | HTTP/SSE MCP server configuration |
|
|
173
|
+
All three SDKs drive the same CLI over the same protocol, so capabilities line up feature for feature. Ruby differs mainly in idiom: `Enumerator` for streaming input, blocks for tools, and the `async` gem with fibers instead of `async`/`await`.
|
|
290
174
|
|
|
291
|
-
|
|
175
|
+
| Capability | TypeScript | Python | Ruby (this gem) |
|
|
176
|
+
|---|:---:|:---:|:---:|
|
|
177
|
+
| One-shot `query()` | ✅ | ✅ | ✅ |
|
|
178
|
+
| Bidirectional `Client` | ✅ | ✅ | ✅ |
|
|
179
|
+
| Streaming input | `AsyncIterable` | `AsyncIterable` | `Enumerator` |
|
|
180
|
+
| Custom tools (SDK MCP servers) | `tool()` | `@tool` decorator | `create_tool` block |
|
|
181
|
+
| Hooks (all 27 events) | ✅ | ✅ | ✅ |
|
|
182
|
+
| Permission callbacks | ✅ | ✅ | ✅ |
|
|
183
|
+
| Structured output | ✅ | ✅ | ✅ |
|
|
184
|
+
| All 28 message types | ✅ | partial | ✅ |
|
|
185
|
+
| [Sandbox](https://github.com/anthropic-experimental/sandbox-runtime) settings | ✅ | partial | ✅ |
|
|
186
|
+
| Bare mode (`--bare`) | ✅ | ✅ | ✅ |
|
|
187
|
+
| File checkpointing & rewind | ✅ | ✅ | ✅ |
|
|
188
|
+
| Session browsing & mutations | ✅ | ✅ | ✅ |
|
|
189
|
+
| Programmatic subagents | ✅ | ✅ | ✅ |
|
|
190
|
+
| CLI binary | bundled | bundled | vendored on demand (`CLIInstaller`) |
|
|
191
|
+
| Observability (OTel / Langfuse) | via [Arize](https://github.com/Arize-ai/openinference) | — | ✅ built-in |
|
|
192
|
+
| Custom transport (pluggable I/O) | — | — | ✅ |
|
|
193
|
+
| Rails integration | — | — | ✅ |
|
|
292
194
|
|
|
293
|
-
|
|
294
|
-
|---------|-------------|
|
|
295
|
-
| [hooks_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/hooks_example.rb) | Using hooks to control tool execution |
|
|
296
|
-
| [advanced_hooks_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/advanced_hooks_example.rb) | Typed hook inputs/outputs |
|
|
297
|
-
| [lifecycle_hooks_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/lifecycle_hooks_example.rb) | All 27 hook events |
|
|
298
|
-
| [permission_callback_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/permission_callback_example.rb) | Dynamic tool permission control |
|
|
195
|
+
Types are plain Ruby classes with `attr_accessor` and keyword arguments, mirroring the field names of the TypeScript Zod schemas and Python dataclasses; there is no runtime type checking.
|
|
299
196
|
|
|
300
|
-
|
|
197
|
+
## Claude Code plugin
|
|
301
198
|
|
|
302
|
-
|
|
303
|
-
|---------|-------------|
|
|
304
|
-
| [budget_control_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/budget_control_example.rb) | Budget control with `max_budget_usd` |
|
|
305
|
-
| [fallback_model_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/fallback_model_example.rb) | Fallback model configuration |
|
|
306
|
-
| [advisor_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/advisor_example.rb) | Server-side advisor tool (`advisor_model`) |
|
|
307
|
-
| [extended_thinking_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/extended_thinking_example.rb) | Extended thinking |
|
|
308
|
-
| [e2b_transport_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/e2b_transport_example.rb) | Custom transport running CLI in an E2B microVM |
|
|
199
|
+
This repository is also a Claude Code plugin marketplace. The bundled skill teaches Claude Code the gem's APIs and patterns:
|
|
309
200
|
|
|
310
|
-
|
|
201
|
+
```bash
|
|
202
|
+
/plugin marketplace add ya-luotao/claude-agent-sdk-ruby
|
|
203
|
+
/plugin install claude-agent-ruby@claude-agent-sdk-ruby
|
|
204
|
+
```
|
|
311
205
|
|
|
312
|
-
|
|
313
|
-
|---------|-------------|
|
|
314
|
-
| [otel_langfuse_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/otel_langfuse_example.rb) | OpenTelemetry tracing with Langfuse backend |
|
|
315
|
-
| [rails_actioncable_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/rails_actioncable_example.rb) | ActionCable streaming to frontend |
|
|
316
|
-
| [rails_background_job_example.rb](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/examples/rails_background_job_example.rb) | Background jobs with session resumption |
|
|
206
|
+
## Development
|
|
317
207
|
|
|
318
|
-
|
|
208
|
+
```bash
|
|
209
|
+
bundle install
|
|
210
|
+
bundle exec rspec # unit suite
|
|
211
|
+
bundle exec rubocop # lint
|
|
212
|
+
RUN_INTEGRATION=1 bundle exec rspec # also run the real-CLI integration suite (needs `claude` and ANTHROPIC_API_KEY)
|
|
213
|
+
```
|
|
319
214
|
|
|
320
|
-
|
|
215
|
+
CI runs the suite and RuboCop on Ruby 3.2, 3.3, and 3.4. See [spec/README.md](https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/spec/README.md) for the test layout.
|
|
321
216
|
|
|
322
|
-
##
|
|
217
|
+
## Contributing
|
|
323
218
|
|
|
324
|
-
|
|
219
|
+
Bug reports and pull requests are welcome on [GitHub](https://github.com/ya-luotao/claude-agent-sdk-ruby/issues). Please include a failing spec with bug reports where possible, and keep pull requests focused on one change. Releases follow [Semantic Versioning](https://semver.org/) and are recorded in the [CHANGELOG](CHANGELOG.md).
|
|
325
220
|
|
|
326
221
|
## License
|
|
327
222
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
## Star History
|
|
331
|
-
|
|
332
|
-
<a href="https://www.star-history.com/?repos=ya-luotao%2Fclaude-agent-sdk-ruby&type=date&legend=top-left">
|
|
333
|
-
<picture>
|
|
334
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=ya-luotao/claude-agent-sdk-ruby&type=date&theme=dark&legend=top-left" />
|
|
335
|
-
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=ya-luotao/claude-agent-sdk-ruby&type=date&legend=top-left" />
|
|
336
|
-
<img alt="Star History Chart" src="https://api.star-history.com/chart?repos=ya-luotao/claude-agent-sdk-ruby&type=date&legend=top-left" />
|
|
337
|
-
</picture>
|
|
338
|
-
</a>
|
|
223
|
+
Released under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Vendoring the CLI (`CLIInstaller`)
|
|
2
|
+
|
|
3
|
+
The SDK runs the `claude` CLI as a subprocess, so a deploy is only reproducible if the CLI version is pinned with it. `ClaudeAgentSDK::CLIInstaller` downloads a pinned binary from the official release endpoint into a project-local directory (`vendor/claude` by default) — checksum-verified, no npm/Node at runtime, and nothing extra shipped inside the gem.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
require 'claude_agent_sdk'
|
|
9
|
+
|
|
10
|
+
# 'stable' (default), 'latest', or a concrete version — pin it in production.
|
|
11
|
+
ClaudeAgentSDK::CLIInstaller.install(version: '2.1.220')
|
|
12
|
+
# => "/app/vendor/claude/claude"
|
|
13
|
+
|
|
14
|
+
ClaudeAgentSDK::CLIInstaller.install(version: '2.1.220', dir: '/opt/claude')
|
|
15
|
+
|
|
16
|
+
# nil unless a binary is already installed there
|
|
17
|
+
ClaudeAgentSDK::CLIInstaller.installed_path
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`install` is idempotent and safe to run concurrently, so it fits `bin/setup`, a cached Docker layer, and every process of a multi-process boot:
|
|
21
|
+
|
|
22
|
+
- The install directory's `VERSION` file records the installed version **and** the SHA-256 that was verified at download time. The shortcut re-hashes the vendored binary (~0.1s for the real 245MB binary) and only skips the download when both match — a truncated, swapped or half-written binary is reinstalled instead of trusted. It makes **no network request**, so repeat boots work offline — with a pinned concrete version; `'stable'`/`'latest'` must always re-resolve through the endpoint, which is one more reason to pin in production.
|
|
23
|
+
- An exclusive `flock` on `<dir>/.install.lock` covers the whole check → download → place → record sequence, so parallel installs into one directory don't race; the loser simply observes the finished install.
|
|
24
|
+
|
|
25
|
+
Failures (unsupported platform, invalid version, HTTP error, response-size cap, oversized download, checksum mismatch, filesystem errors) raise `ClaudeAgentSDK::CLIInstallError`.
|
|
26
|
+
|
|
27
|
+
**A failed install never breaks a working one.** The new binary is downloaded to a temp file, checksum-verified and recorded, and only then renamed into place — the rename is the last step, and nothing can fail after it. So a failed upgrade leaves the previously installed binary intact and runnable (the SDK keeps working), and the next `install` redoes it cleanly. A first install that fails leaves nothing behind at all.
|
|
28
|
+
|
|
29
|
+
> The vendored directory is trusted input: anything that can write to it can replace the binary the SDK executes. Keep it inside your deploy artifact, owned by the deploy user and not world-writable, exactly as you would treat `bin/`.
|
|
30
|
+
|
|
31
|
+
## Docker and `bin/setup`
|
|
32
|
+
|
|
33
|
+
```dockerfile
|
|
34
|
+
# Dockerfile — pin the CLI in its own cached layer
|
|
35
|
+
RUN bundle exec ruby -e "require 'claude_agent_sdk'; \
|
|
36
|
+
ClaudeAgentSDK::CLIInstaller.install(version: '2.1.220')"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
#!/usr/bin/env ruby
|
|
41
|
+
# bin/setup
|
|
42
|
+
require 'claude_agent_sdk'
|
|
43
|
+
puts ClaudeAgentSDK::CLIInstaller.install(version: ENV.fetch('CLAUDE_CLI_VERSION', 'stable'))
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Supported platforms
|
|
47
|
+
|
|
48
|
+
`darwin-arm64`, `darwin-x64` (Rosetta 2 gets the arm64 build), `linux-x64`, `linux-arm64`, and the `-musl` variants. Windows is not supported.
|
|
49
|
+
|
|
50
|
+
## CLI discovery order
|
|
51
|
+
|
|
52
|
+
With no explicit `cli_path:` in `ClaudeAgentOptions`, the transport probes in this order:
|
|
53
|
+
|
|
54
|
+
1. `CLAUDE_CLI_PATH` — an explicit path to an executable, no discovery at all (a relative value is resolved against the process's working directory, not `cwd:`)
|
|
55
|
+
2. The vendored binary (`CLIInstaller.installed_path`) — deliberately ahead of `PATH`, so a pinned install beats whatever is installed globally
|
|
56
|
+
3. `which claude`
|
|
57
|
+
4. Common install locations (`~/.claude/local/claude`, `/usr/local/bin/claude`, …)
|
data/docs/client.md
CHANGED
|
@@ -44,6 +44,10 @@ Async do
|
|
|
44
44
|
client.reconnect_mcp_server('my-server') # Reconnect a failed MCP server
|
|
45
45
|
client.toggle_mcp_server('my-server', false) # Enable/disable an MCP server
|
|
46
46
|
client.stop_task('task_abc123') # Stop a running background task
|
|
47
|
+
client.background_tasks # Background every foreground task (Ctrl+B) => {}
|
|
48
|
+
client.background_tasks(tool_use_id: 'toolu_01') # Only the task spawned by that tool_use block
|
|
49
|
+
# => { backgrounded: true } | { backgrounded: false } (definitive miss)
|
|
50
|
+
# '' or a non-String raises ArgumentError; nil is the all-tasks form
|
|
47
51
|
|
|
48
52
|
client.disconnect
|
|
49
53
|
end.wait
|