claude_swarm 0.3.2 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7b271585c56ae3f85e921a7558bd46d82430ee60383fc999b6e89f27ffcdd0b0
4
- data.tar.gz: 6b84e34b59412155d1a43cc00e8c41fe989287da7b98e2b12f8e1576f2002f87
3
+ metadata.gz: be01b40a18b703189532df1e653c15e406c0b798b220c20fe1f014a35331e213
4
+ data.tar.gz: a4eddd8c10cb1974e9693c27cb9d6660117bd781a4ed16ef52dc1408b4c414d2
5
5
  SHA512:
6
- metadata.gz: 98c7d8d77ea9fb5256556fe7e73f83194cca4893084cab5b9b1826c6426052afd12b86f4fabad28e8e35d36a0114f6f7d6e1cd25fd4f02fb40f4450a5f048940
7
- data.tar.gz: 33c134e8f553510dfee481b935c67eae21e196c4bc8bc494657042e69e32b91238169feaf0b138a632abda219fef791ad224294da958732c135b04a9fc7a1cf0
6
+ metadata.gz: c8207b22b7d3514e910d9f4c72ba7c99e5f5b2f5034e532fa8708ae5d9e9219047153d54ac148c688114cc3f9bd167a4e7a16ceed9439512fe9f1c60c77f8d63
7
+ data.tar.gz: 53cfc85b8898b8906372e5518913de7c373e98ca2a7de1202f343f1d93f9efc566ed21acee1529f8bc9945e3e60f0cde335040dd49a9d582f723ea739c790c4e
@@ -0,0 +1,27 @@
1
+ ---
2
+ description: Bump version, update changelog, and prepare for release
3
+ allowed-tools: [Read, Edit, Bash]
4
+ ---
5
+
6
+ Prepare a new release for Claude Swarm by:
7
+
8
+ 1. Read the current version from @lib/claude_swarm/version.rb
9
+ 2. Determine the new version number: $ARGUMENTS (should be in format like 0.3.11 or use patch/minor/major)
10
+ 3. Update the version in @lib/claude_swarm/version.rb
11
+ 4. Update @CHANGELOG.md:
12
+ - Change "## [Unreleased]" to "## [new_version]"
13
+ - Add a new "## [Unreleased]" section at the top for future changes
14
+ 5. Run these commands:
15
+ - `git add .`
16
+ - `bundle install`
17
+ - `git add .`
18
+ - `git commit -m "Release version X.X.X"`
19
+ - `git push`
20
+
21
+ Make sure all tests pass before releasing. The version argument should be either:
22
+ - A specific version number (e.g., 0.3.11)
23
+ - "patch" for incrementing the patch version (0.3.10 -> 0.3.11)
24
+ - "minor" for incrementing the minor version (0.3.10 -> 0.4.0)
25
+ - "major" for incrementing the major version (0.3.10 -> 1.0.0)
26
+
27
+ If no argument is provided, default to "patch".
data/CHANGELOG.md CHANGED
@@ -1,3 +1,177 @@
1
+ ## [Unreleased]
2
+
3
+ ## [1.0.0]
4
+
5
+ ### Added
6
+ - **HTTP MCP server configuration support**: Added support for HTTP-type MCP servers alongside existing stdio and SSE types
7
+ - HTTP servers can be configured with a `url` field
8
+ - Properly preserves server type (http/sse) in generated configurations
9
+ - Full compatibility with Claude Code's HTTP MCP server implementation
10
+
11
+ ### Changed
12
+ - **Updated dependency from fast-mcp-annotations to fast-mcp gem**: Migrated to the consolidated fast-mcp gem (~> 1.6)
13
+ - Consolidates MCP functionality into a single, more maintainable gem
14
+ - Maintains all existing functionality with improved performance
15
+ - **Updated claude-code-sdk-ruby dependency**: Minimum version requirement increased to 0.1.6
16
+ - Includes latest SDK improvements and bug fixes
17
+ - Better error handling and stability
18
+ - **Swarm generation improvements**: Generator now avoids creating swarms with circular dependencies
19
+ - Prevents generation of invalid configurations
20
+ - Improves reliability of generated swarm templates
21
+
22
+ ### Fixed
23
+ - **Empty response validation**: Added validation to prevent empty or nil responses from being passed to MCP callers
24
+ - ClaudeCodeExecutor now validates that Claude SDK returns non-empty result content
25
+ - TaskTool validates response structure and content before returning to MCP caller
26
+ - Clear error messages indicate when agent completes execution but provides no response
27
+ - Prevents silent failures when Claude SDK returns empty results
28
+ - **Before commands directory handling**: Fixed error when before commands need to create the main instance directory
29
+ - Smart directory detection: if the main instance directory exists, commands run inside it (for `npm install`, etc.)
30
+ - If the directory doesn't exist, commands run in the parent directory (allowing `mkdir` commands to create it)
31
+ - Works correctly with both regular directories and Git worktrees
32
+ - After commands follow the same logic for consistency
33
+ - Fixes "No such file or directory @ dir_chdir" errors when before commands create directories
34
+
35
+ ### Internal
36
+ - **Centralized JSON handling**: Added JsonHandler class for consistent JSON parsing and generation
37
+ - Improved error handling for malformed JSON files
38
+ - Standardized JSON output formatting across all modules
39
+ - **Centralized CLAUDE_SWARM_HOME handling**: Refactored environment variable management for cleaner code
40
+ - **Enhanced test coverage**: Added comprehensive configuration tests and enabled branch coverage in SimpleCov
41
+ - Extensive validation of edge cases including circular dependencies
42
+ - Better coverage metrics with branch coverage enabled
43
+
44
+ ## [0.3.11]
45
+
46
+ ### Added
47
+ - **Deferred directory validation for before commands**: Directories are now validated after `before` commands run, allowing them to create required directories
48
+ - Automatically skips initial directory validation when `before` commands are present in configuration
49
+ - Validates all directories after `before` commands complete successfully
50
+ - Enables dynamic directory creation workflows without pre-creating directory structures
51
+
52
+ ### Fixed
53
+ - **--root-dir parameter path resolution**: Fixed relative config file paths to be resolved relative to the --root-dir value instead of current directory
54
+ - Config paths are now expanded using the root directory as the base path
55
+ - Allows running claude-swarm from any location with consistent path resolution
56
+ - Absolute paths continue to work as expected regardless of --root-dir setting
57
+
58
+ ### Improved
59
+ - **Enhanced worktree cleanup on errors**: Improved error handling to ensure worktrees are always cleaned up properly
60
+ - Added comprehensive error handling with cleanup at all failure points
61
+ - Worktrees are now cleaned up when worktree setup fails, before commands fail, or directory validation fails
62
+ - Prevents orphaned worktrees that could clutter the system or cause issues with future runs
63
+
64
+ ## [0.3.10]
65
+
66
+ ### Added
67
+ - **Token-based cost calculation for main instance**: Main instance costs in interactive mode are now calculated from token usage using Claude model pricing
68
+ - Opus: $15/MTok input, $75/MTok output, $18.75/MTok cache write, $1.50/MTok cache read
69
+ - Sonnet: $3/MTok input, $15/MTok output, $3.75/MTok cache write, $0.30/MTok cache read
70
+ - Haiku: $0.80/MTok input, $4/MTok output, $1/MTok cache write, $0.08/MTok cache read
71
+ - Automatically extracts usage data from assistant messages in session logs
72
+
73
+ ### Changed
74
+ - **Simplified cost calculation**: Switched from cumulative `total_cost_usd` to per-request `cost_usd` for non-main instances
75
+ - Removed complex session reset detection logic
76
+ - Now uses simple summation of individual request costs
77
+ - More accurate and maintainable cost tracking
78
+ - **Improved ps command cost display**:
79
+ - Only shows cost warning when sessions are missing main instance data
80
+ - Adds asterisk (*) indicator to costs that exclude main instance
81
+ - Displays accurate total costs including main instance when available
82
+
83
+ ### Fixed
84
+ - **Main instance log format consistency**: Fixed transcript logs in interactive mode to match standard instance log format
85
+ - Converted transcript wrapper to request/assistant event structure
86
+ - Properly extracts text content from nested message arrays
87
+ - Ensures uniform log parsing across all instances
88
+
89
+ ## [0.3.9]
90
+
91
+ ### Added
92
+ - **Main instance transcript integration**: Main Claude instance activity is now captured in session.log.json during interactive mode
93
+ - Automatically configures SessionStart hook for main instance to capture transcript path
94
+ - Background thread continuously tails transcript file and integrates entries into session.log.json
95
+ - Filters out summary entries to avoid duplicate conversation titles
96
+ - Uses file locking for thread-safe writes to maintain consistency
97
+ - Provides complete session history including main instance interactions
98
+
99
+ ## [0.3.8]
100
+
101
+ ### Added
102
+ - **Hooks support**: Claude Swarm now supports configuring Claude Code hooks for each instance
103
+ - Configure hooks directly in the YAML configuration file using Claude Code's format
104
+ - Each instance can have its own hooks configuration (PreToolUse, PostToolUse, UserPromptSubmit, etc.)
105
+ - Automatically generates `settings.json` files in the session directory when hooks are configured
106
+ - Main instance receives hooks via `--settings` CLI flag
107
+ - Connected instances receive hooks via SDK's `settings` attribute
108
+ - Full environment variable interpolation support in hook configurations
109
+ - See README.md "Hooks Configuration" section for usage examples
110
+ - **Persistent HTTP connections for OpenAI**: Added `faraday-net_http_persistent` dependency and configured OpenAI client to use persistent connections
111
+ - Improves performance when making multiple API requests by reusing HTTP connections
112
+ - Automatically configured for all OpenAI instances
113
+
114
+ ### Changed
115
+ - **Improved OpenAI executor code organization**: Refactored internal methods for better maintainability
116
+ - Extracted configuration building and response handling into focused private methods
117
+ - Improved code readability with functional patterns
118
+
119
+ ### Fixed
120
+ - **Settings integration**: Fixed passing settings to Claude instances
121
+ - Corrected SDK attribute name from `settings_path` to `settings`
122
+ - Added missing `--settings` flag for main instance CLI command
123
+
124
+ ## [0.3.7]
125
+
126
+ ### Added
127
+ - **Main instance logging**: Captures main Claude instance output in `session.log` with prettified JSON format
128
+
129
+ ### Changed
130
+ - **Updated claude-code-sdk-ruby dependency**: Bumped from 0.1.4 to 0.1.6
131
+ - Includes latest SDK improvements and bug fixes
132
+
133
+ ## [0.3.6]
134
+
135
+ ### Added
136
+ - **SSE MCP server headers support**: SSE-type MCP servers can now include custom headers for authentication
137
+ - Supports headers like `Authorization: "Bearer ${TOKEN}"` in MCP configurations
138
+ - Environment variables in header values are automatically interpolated
139
+ - **Comprehensive retry middleware for OpenAI API calls**: Added robust retry logic for OpenAI provider to handle API errors gracefully
140
+ - Automatically retries on rate limit errors (429) with exponential backoff
141
+ - Retries on server errors (500, 502, 503, 504) and timeout errors
142
+ - Configurable retry attempts, delay, and backoff settings
143
+ - Detailed logging of retry attempts and errors
144
+
145
+ ## [0.3.5]
146
+
147
+ ### Changed
148
+ - Relaxed dependency version constraints for better flexibility
149
+ - `claude-code-sdk-ruby`: from `~> 0.1.0` to `~> 0.1`
150
+ - `fast-mcp-annotations`: from `~> 1.5.3` to `~> 1.5`
151
+
152
+ ## [0.3.4]
153
+
154
+ ### Changed
155
+ - Add tests for thinking_budget feature by @parruda in https://github.com/parruda/claude-swarm/pull/85
156
+ - Improve process group handling and signal management by @ericproulx in https://github.com/parruda/claude-swarm/pull/87
157
+ - Migrated from CLI to SDK-based execution**: Claude Swarm now uses the `claude-code-sdk-ruby` gem instead of executing Claude Code via CLI
158
+ - Removed CLI-based `ClaudeCodeExecutor` implementation that used `Open3.popen3`
159
+ - All Claude Code execution now uses the SDK for improved reliability and performance
160
+ - Session management and logging functionality remains unchanged
161
+ - MCP configuration parsing updated to convert JSON format to SDK hash format
162
+ - Supports all MCP server types: stdio, sse, and http
163
+ - This change is transparent to users but may affect custom integrations that relied on CLI-specific behavior
164
+
165
+ ### Added
166
+ - **SDK dependency**: Added `claude-code-sdk-ruby` (~> 0.1.0)
167
+
168
+ ## [0.3.3]
169
+
170
+ ### Fixed
171
+ - **Bundler constant error**: Fixed `uninitialized constant ClaudeSwarm::Orchestrator::Bundler` error by adding missing `require "bundler"` statement
172
+ - Issue occurred when using `Bundler.with_unbundled_env` without properly requiring the bundler gem
173
+ - Resolves issue #83 reported by users upgrading to version 0.3.2
174
+
1
175
  ## [0.3.2]
2
176
 
3
177
  ### Added
data/CLAUDE.md CHANGED
@@ -6,6 +6,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
6
6
 
7
7
  Claude Swarm is a Ruby gem that orchestrates multiple Claude Code instances as a collaborative AI development team. It enables running AI agents with specialized roles, tools, and directory contexts, communicating via MCP (Model Context Protocol).
8
8
 
9
+ SwarmCore is a complete reimagining of Claude Swarm that decouples from Claude Code and runs everything in a single process using RubyLLM for all LLM interactions. It is being developed in `lib/swarm_core`, and using the gemspec swarm-core.gemspec.
10
+
9
11
  ## Development Commands
10
12
 
11
13
  ### Testing
@@ -93,6 +95,16 @@ instances:
93
95
  - Existing worktrees with the same name are reused
94
96
  - The `claude-swarm clean` command removes orphaned worktrees
95
97
 
98
+ ## Claude Code SDK Integration
99
+
100
+ Claude Swarm uses the Claude Code SDK (`claude-code-sdk-ruby`) for all Claude instances. This provides:
101
+ - Better performance and reliability
102
+ - Structured message handling
103
+ - Improved error recovery
104
+ - Direct MCP server configuration support (stdio, sse, http)
105
+
106
+ The SDK executor handles all three MCP server types and properly converts MCP JSON configurations to SDK format.
107
+
96
108
  ## Architecture
97
109
 
98
110
  The gem is fully implemented with the following components:
@@ -120,9 +132,10 @@ The gem is fully implemented with the following components:
120
132
  1. User creates a `claude-swarm.yml` file defining the swarm topology
121
133
  2. Running `claude-swarm` parses the configuration and validates it
122
134
  3. MCP configuration files are generated for each instance in a session directory
123
- 4. The main instance is launched with `exec`, replacing the current process
124
- 5. Connected instances are available as MCP servers to the main instance
125
- 6. When an instance has connections, those connections are automatically added to its allowed tools as `mcp__<connection_name>`
135
+ 4. Settings files (with hooks) are generated for each instance if hooks are configured
136
+ 5. The main instance is launched with `exec`, replacing the current process
137
+ 6. Connected instances are available as MCP servers to the main instance
138
+ 7. When an instance has connections, those connections are automatically added to its allowed tools as `mcp__<connection_name>`
126
139
 
127
140
  ### Configuration Example
128
141
 
@@ -149,6 +162,52 @@ swarm:
149
162
  worktree: false # Optional: disable worktree for this instance
150
163
  ```
151
164
 
165
+ ### Hooks Support
166
+
167
+ Claude Swarm supports configuring [Claude Code hooks](https://docs.anthropic.com/en/docs/claude-code/hooks) for each instance. This allows you to run custom scripts before/after tools, on prompt submission, and more.
168
+
169
+ #### Configuration Example with Hooks
170
+
171
+ ```yaml
172
+ version: 1
173
+ swarm:
174
+ name: "Dev Team"
175
+ main: lead
176
+ instances:
177
+ lead:
178
+ description: "Lead developer"
179
+ directory: .
180
+ model: opus
181
+ # Hooks configuration follows Claude Code's format exactly
182
+ hooks:
183
+ PreToolUse:
184
+ - matcher: "Write|Edit"
185
+ hooks:
186
+ - type: "command"
187
+ command: "$CLAUDE_PROJECT_DIR/.claude/hooks/validate-code.py"
188
+ timeout: 10
189
+ PostToolUse:
190
+ - matcher: "Bash"
191
+ hooks:
192
+ - type: "command"
193
+ command: "echo 'Command executed by lead' >> /tmp/lead.log"
194
+ UserPromptSubmit:
195
+ - hooks:
196
+ - type: "command"
197
+ command: "$CLAUDE_PROJECT_DIR/.claude/hooks/add-context.py"
198
+ frontend:
199
+ description: "Frontend developer"
200
+ directory: ./frontend
201
+ hooks:
202
+ PreToolUse:
203
+ - matcher: "Write"
204
+ hooks:
205
+ - type: "command"
206
+ command: "npm run lint"
207
+ ```
208
+
209
+ The hooks configuration is passed directly to Claude Code via a generated settings.json file in the session directory. Each instance gets its own settings file with its specific hooks.
210
+
152
211
  ## Testing
153
212
 
154
213
  The gem includes comprehensive tests covering:
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Claude Swarm
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/claude_swarm.svg?cache_bust=0.3.0)](https://badge.fury.io/rb/claude_swarm)
3
+ [![Gem Version](https://badge.fury.io/rb/claude_swarm.svg?cache_bust1=0.3.2)](https://badge.fury.io/rb/claude_swarm)
4
4
  [![CI](https://github.com/parruda/claude-swarm/actions/workflows/ci.yml/badge.svg)](https://github.com/parruda/claude-swarm/actions/workflows/ci.yml)
5
5
 
6
6
  Claude Swarm orchestrates multiple Claude Code instances as a collaborative AI development team. It enables running AI agents with specialized roles, tools, and directory contexts, communicating via MCP (Model Context Protocol) in a tree-like hierarchy. Define your swarm topology in simple YAML and let Claude instances delegate tasks through connected instances. Perfect for complex projects requiring specialized AI agents for frontend, backend, testing, DevOps, or research tasks.
@@ -42,7 +42,7 @@ gem install claude_swarm
42
42
  Or add it to your Gemfile:
43
43
 
44
44
  ```ruby
45
- gem 'claude_swarm'
45
+ gem 'claude_swarm', "~> 0.3.2"
46
46
  ```
47
47
 
48
48
  Then run:
@@ -228,6 +228,53 @@ swarm:
228
228
  # Instance definitions...
229
229
  ```
230
230
 
231
+ #### YAML Aliases
232
+
233
+ Claude Swarm supports [YAML aliases](https://yaml.org/spec/1.2.2/#71-alias-nodes) to reduce duplication in your configuration. This is particularly useful for sharing common values like prompts, tool lists, or MCP configurations across multiple instances:
234
+
235
+ ```yaml
236
+ version: 1
237
+ swarm:
238
+ name: "Development Team"
239
+ main: lead
240
+ instances:
241
+ lead:
242
+ description: "Lead developer"
243
+ prompt: &shared_prompt "You are an expert developer following best practices"
244
+ allowed_tools: &standard_tools
245
+ - Read
246
+ - Edit
247
+ - Bash
248
+ - WebSearch
249
+ mcps: &common_mcps
250
+ - name: github
251
+ type: stdio
252
+ command: gh
253
+ args: ["mcp"]
254
+
255
+ frontend:
256
+ description: "Frontend developer"
257
+ prompt: *shared_prompt # Reuses the same prompt
258
+ allowed_tools: *standard_tools # Reuses the same tool list
259
+ mcps: *common_mcps # Reuses the same MCP servers
260
+ directory: ./frontend
261
+
262
+ backend:
263
+ description: "Backend developer"
264
+ prompt: *shared_prompt # Reuses the same prompt
265
+ allowed_tools: *standard_tools # Reuses the same tool list
266
+ mcps: *common_mcps # Reuses the same MCP servers
267
+ directory: ./backend
268
+ ```
269
+
270
+ In this example:
271
+ - `&shared_prompt` defines an anchor for the prompt string
272
+ - `&standard_tools` defines an anchor for the tool array
273
+ - `&common_mcps` defines an anchor for the MCP configuration
274
+ - `*shared_prompt`, `*standard_tools`, and `*common_mcps` reference those anchors
275
+
276
+ This helps maintain consistency across instances and makes configuration updates easier.
277
+
231
278
  #### Environment Variable Interpolation
232
279
 
233
280
  Claude Swarm supports environment variable interpolation in all configuration values using the `${ENV_VAR_NAME}` syntax:
@@ -303,6 +350,7 @@ Each instance can have:
303
350
  - **vibe**: Enable vibe mode (--dangerously-skip-permissions) for this instance (default: false)
304
351
  - **worktree**: Configure Git worktree usage for this instance (true/false/string)
305
352
  - **provider**: AI provider to use - "claude" (default) or "openai"
353
+ - **hooks**: Configure Claude Code hooks for this instance (see Hooks Configuration section below)
306
354
 
307
355
  #### OpenAI Provider Configuration
308
356
 
@@ -389,8 +437,85 @@ mcps:
389
437
  - name: remote_api
390
438
  type: sse
391
439
  url: "https://api.example.com/mcp"
440
+ headers: # Optional: custom headers for authentication
441
+ Authorization: "Bearer ${API_TOKEN}"
442
+ X-Custom-Header: "value"
392
443
  ```
393
444
 
445
+ #### http (HTTP-based MCP)
446
+ ```yaml
447
+ mcps:
448
+ - name: http_service
449
+ type: http
450
+ url: "https://api.example.com/mcp-endpoint"
451
+ headers: # Optional: custom headers for authentication
452
+ Authorization: "Bearer ${API_TOKEN}"
453
+ X-API-Key: "${API_KEY}"
454
+ ```
455
+
456
+ ### Hooks Configuration
457
+
458
+ Claude Swarm supports configuring [Claude Code hooks](https://docs.anthropic.com/en/docs/claude-code/hooks) for each instance. Hooks allow you to run custom scripts before/after tools, on prompt submission, and more. Each instance can have its own hooks configuration.
459
+
460
+ #### Supported Hook Events
461
+
462
+ - **PreToolUse**: Run before a tool is executed
463
+ - **PostToolUse**: Run after a tool completes
464
+ - **UserPromptSubmit**: Run when a user prompt is submitted
465
+ - **Stop**: Run when the Claude instance stops
466
+ - **SessionStart**: Run when a session starts
467
+ - **And more...** (see Claude Code hooks documentation)
468
+
469
+ #### Configuration Example
470
+
471
+ ```yaml
472
+ instances:
473
+ lead:
474
+ description: "Lead developer"
475
+ directory: .
476
+ # Hooks configuration follows Claude Code's format exactly
477
+ hooks:
478
+ PreToolUse:
479
+ - matcher: "Write|Edit"
480
+ hooks:
481
+ - type: "command"
482
+ command: "$CLAUDE_PROJECT_DIR/.claude/hooks/validate-code.py"
483
+ timeout: 10
484
+ PostToolUse:
485
+ - matcher: "Bash"
486
+ hooks:
487
+ - type: "command"
488
+ command: "echo 'Bash executed by ${INSTANCE_NAME}' >> ${LOG_DIR}/commands.log"
489
+ UserPromptSubmit:
490
+ - hooks:
491
+ - type: "command"
492
+ command: "${HOOKS_DIR:=$CLAUDE_PROJECT_DIR/.claude/hooks}/add-context.py"
493
+ frontend:
494
+ description: "Frontend developer"
495
+ directory: ./frontend
496
+ hooks:
497
+ PreToolUse:
498
+ - matcher: "Write"
499
+ hooks:
500
+ - type: "command"
501
+ command: "npm run lint"
502
+ timeout: 5
503
+ ```
504
+
505
+ #### How It Works
506
+
507
+ 1. Define hooks in your instance configuration using the exact format expected by Claude Code
508
+ 2. Claude Swarm generates a `settings.json` file for each instance with hooks
509
+ 3. The settings file is passed to Claude Code SDK via the `--settings` parameter
510
+ 4. Each instance runs with its own hooks configuration
511
+
512
+ #### Environment Variables in Hooks
513
+
514
+ Hooks have access to standard Claude Code environment variables plus:
515
+ - `$CLAUDE_PROJECT_DIR` - The project directory
516
+ - `$CLAUDE_SWARM_SESSION_DIR` - The swarm session directory
517
+ - `$CLAUDE_SWARM_INSTANCE_NAME` - The name of the current instance
518
+
394
519
  ### Tools
395
520
 
396
521
  Specify which tools each instance can use:
@@ -757,8 +882,8 @@ swarm:
757
882
  claude-swarm
758
883
 
759
884
  # Specify a different configuration file
760
- claude-swarm my-swarm.yml
761
- claude-swarm team-config.yml
885
+ claude-swarm start my-swarm.yml
886
+ claude-swarm start team-config.yml
762
887
 
763
888
  # Run with --dangerously-skip-permissions for all instances
764
889
  claude-swarm --vibe
@@ -978,6 +1103,7 @@ Check the session directory `~/.claude-swarm/sessions/{project}/{session-id}/` f
978
1103
  - `{instance}.mcp.json`: MCP configuration for each instance
979
1104
  - All files for a session are kept together for easy review
980
1105
 
1106
+
981
1107
  ## Architecture
982
1108
 
983
1109
  Claude Swarm consists of these core components:
@@ -986,7 +1112,7 @@ Claude Swarm consists of these core components:
986
1112
  - **ClaudeSwarm::Configuration** (`configuration.rb`): YAML parser and validator with path expansion
987
1113
  - **ClaudeSwarm::McpGenerator** (`mcp_generator.rb`): Generates MCP JSON configs for each instance
988
1114
  - **ClaudeSwarm::Orchestrator** (`orchestrator.rb`): Launches the main Claude instance with shared session management
989
- - **ClaudeSwarm::ClaudeCodeExecutor** (`claude_code_executor.rb`): Wrapper for executing Claude commands with session persistence
1115
+ - **ClaudeSwarm::ClaudeCodeExecutor** (`claude_code_executor.rb`): Executor for Claude Code with session persistence
990
1116
  - **ClaudeSwarm::ClaudeMcpServer** (`claude_mcp_server.rb`): FastMCP-based server providing task execution, session info, and reset capabilities
991
1117
 
992
1118
  ## Development
@@ -0,0 +1,37 @@
1
+ version: 1
2
+ swarm:
3
+ name: "Simple Session Hook Swarm"
4
+ main: developer
5
+ instances:
6
+ developer:
7
+ description: "Main developer instance"
8
+ directory: .
9
+ model: sonnet
10
+ allowed_tools:
11
+ - Read
12
+ - Edit
13
+ - Write
14
+ - Bash
15
+ connections: [session_tracker]
16
+ prompt: |
17
+ You are the main developer. You can delegate session tracking tasks to the session_tracker instance.
18
+
19
+ For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
20
+
21
+ session_tracker:
22
+ description: "Session tracking specialist that monitors and logs session information"
23
+ directory: .
24
+ model: sonnet
25
+ allowed_tools:
26
+ - Write
27
+ - Bash
28
+ hooks:
29
+ SessionStart:
30
+ - hooks:
31
+ - type: "command"
32
+ command: "cat > session_id.txt"
33
+ timeout: 5
34
+ prompt: |
35
+ You specialize in session tracking and monitoring. You automatically create session tracking files when you start.
36
+
37
+ For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ClaudeSwarm
4
+ class BaseExecutor
5
+ attr_reader :session_id, :last_response, :working_directory, :logger, :session_path, :session_json_path, :instance_info
6
+
7
+ def initialize(working_directory: Dir.pwd, model: nil, mcp_config: nil, vibe: false,
8
+ instance_name: nil, instance_id: nil, calling_instance: nil, calling_instance_id: nil,
9
+ claude_session_id: nil, additional_directories: [], debug: false)
10
+ @working_directory = working_directory
11
+ @additional_directories = additional_directories
12
+ @model = model
13
+ @mcp_config = mcp_config
14
+ @vibe = vibe
15
+ @session_id = claude_session_id
16
+ @last_response = nil
17
+ @instance_name = instance_name
18
+ @instance_id = instance_id
19
+ @calling_instance = calling_instance
20
+ @calling_instance_id = calling_instance_id
21
+ @debug = debug
22
+
23
+ # Setup static info strings for logging
24
+ @instance_info = build_info(@instance_name, @instance_id)
25
+ @caller_info = build_info(@calling_instance, @calling_instance_id)
26
+ @caller_to_instance = "#{@caller_info} -> #{instance_info}:"
27
+ @instance_to_caller = "#{instance_info} -> #{@caller_info}:"
28
+
29
+ # Setup logging
30
+ setup_logging
31
+
32
+ # Setup static event templates
33
+ setup_event_templates
34
+ end
35
+
36
+ def execute(_prompt, _options = {})
37
+ raise NotImplementedError, "Subclasses must implement the execute method"
38
+ end
39
+
40
+ def reset_session
41
+ @session_id = nil
42
+ @last_response = nil
43
+ end
44
+
45
+ def has_session?
46
+ !@session_id.nil?
47
+ end
48
+
49
+ protected
50
+
51
+ def build_info(name, id)
52
+ return name unless id
53
+
54
+ "#{name} (#{id})"
55
+ end
56
+
57
+ def setup_logging
58
+ # Use session path from environment (required)
59
+ @session_path = SessionPath.from_env
60
+ SessionPath.ensure_directory(@session_path)
61
+
62
+ # Initialize session JSON path
63
+ @session_json_path = File.join(@session_path, "session.log.json")
64
+
65
+ # Create logger with session.log filename
66
+ log_filename = "session.log"
67
+ log_path = File.join(@session_path, log_filename)
68
+ log_level = @debug ? :debug : :info
69
+ @logger = Logger.new(log_path, level: log_level, progname: @instance_name)
70
+
71
+ logger.info { "Started #{self.class.name} for instance: #{instance_info}" }
72
+ end
73
+
74
+ def setup_event_templates
75
+ @log_request_event_template = {
76
+ type: "request",
77
+ from_instance: @calling_instance,
78
+ from_instance_id: @calling_instance_id,
79
+ to_instance: @instance_name,
80
+ to_instance_id: @instance_id,
81
+ }.freeze
82
+
83
+ @session_json_entry_template = {
84
+ instance: @instance_name,
85
+ instance_id: @instance_id,
86
+ calling_instance: @calling_instance,
87
+ calling_instance_id: @calling_instance_id,
88
+ }.freeze
89
+ end
90
+
91
+ def log_request(prompt)
92
+ logger.info { "#{@caller_to_instance} \n---\n#{prompt}\n---" }
93
+
94
+ # Merge dynamic data with static template
95
+ event = @log_request_event_template.merge(
96
+ prompt: prompt,
97
+ timestamp: Time.now.iso8601,
98
+ )
99
+
100
+ append_to_session_json(event)
101
+ end
102
+
103
+ def log_response(response)
104
+ logger.info do
105
+ "($#{response["total_cost"]} - #{response["duration_ms"]}ms) #{@instance_to_caller} \n---\n#{response["result"]}\n---"
106
+ end
107
+ end
108
+
109
+ def append_to_session_json(event)
110
+ # Use file locking to ensure thread-safe writes
111
+ File.open(@session_json_path, File::WRONLY | File::APPEND | File::CREAT) do |file|
112
+ file.flock(File::LOCK_EX)
113
+
114
+ # Merge dynamic data with static template
115
+ entry = @session_json_entry_template.merge(
116
+ timestamp: Time.now.iso8601,
117
+ event: event,
118
+ )
119
+
120
+ # Write as single line JSON (JSONL format)
121
+ file.puts(entry.to_json)
122
+
123
+ file.flock(File::LOCK_UN)
124
+ end
125
+ rescue StandardError => e
126
+ logger.error { "Failed to append to session JSON: #{e.message}" }
127
+ raise
128
+ end
129
+
130
+ class ExecutionError < StandardError; end
131
+ class ParseError < StandardError; end
132
+ end
133
+ end