claude_swarm 0.1.19 → 0.2.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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +9 -63
  3. data/.rubocop_todo.yml +11 -0
  4. data/CHANGELOG.md +110 -0
  5. data/CLAUDE.md +64 -2
  6. data/README.md +190 -28
  7. data/Rakefile +1 -1
  8. data/examples/mixed-provider-swarm.yml +23 -0
  9. data/examples/monitoring-demo.yml +4 -4
  10. data/lib/claude_swarm/claude_code_executor.rb +7 -13
  11. data/lib/claude_swarm/claude_mcp_server.rb +26 -17
  12. data/lib/claude_swarm/cli.rb +384 -265
  13. data/lib/claude_swarm/commands/ps.rb +22 -24
  14. data/lib/claude_swarm/commands/show.rb +45 -63
  15. data/lib/claude_swarm/configuration.rb +137 -8
  16. data/lib/claude_swarm/mcp_generator.rb +39 -15
  17. data/lib/claude_swarm/openai/chat_completion.rb +264 -0
  18. data/lib/claude_swarm/openai/executor.rb +301 -0
  19. data/lib/claude_swarm/openai/responses.rb +338 -0
  20. data/lib/claude_swarm/orchestrator.rb +221 -45
  21. data/lib/claude_swarm/process_tracker.rb +7 -7
  22. data/lib/claude_swarm/session_cost_calculator.rb +93 -0
  23. data/lib/claude_swarm/session_path.rb +3 -5
  24. data/lib/claude_swarm/system_utils.rb +16 -0
  25. data/lib/claude_swarm/templates/generation_prompt.md.erb +230 -0
  26. data/lib/claude_swarm/tools/reset_session_tool.rb +24 -0
  27. data/lib/claude_swarm/tools/session_info_tool.rb +24 -0
  28. data/lib/claude_swarm/tools/task_tool.rb +43 -0
  29. data/lib/claude_swarm/version.rb +1 -1
  30. data/lib/claude_swarm/worktree_manager.rb +145 -48
  31. data/lib/claude_swarm.rb +34 -12
  32. data/llms.txt +2 -2
  33. data/single.yml +482 -6
  34. data/team.yml +344 -0
  35. metadata +65 -14
  36. data/claude-swarm.yml +0 -64
  37. data/lib/claude_swarm/reset_session_tool.rb +0 -22
  38. data/lib/claude_swarm/session_info_tool.rb +0 -22
  39. data/lib/claude_swarm/task_tool.rb +0 -39
  40. /data/{example → examples}/claude-swarm.yml +0 -0
  41. /data/{example → examples}/microservices-team.yml +0 -0
  42. /data/{example → examples}/session-restoration-demo.yml +0 -0
  43. /data/{example → examples}/test-generation.yml +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ecbec0c31b9252f826e28978e871cdc0003644d691a541906a8c36ae60c717f6
4
- data.tar.gz: 9d88ab7118d614108adcd2995b270f3c223e08a0a7ccd8768136f362f9f002d6
3
+ metadata.gz: 4085d9345464dcd7fc7be4c78155aa03f2467f7f089b056f2be0589f5de260f2
4
+ data.tar.gz: fda22e57619c30b1d9e1efcabb5a8a0b2b74f9f6df2d969944e07d27753adbd9
5
5
  SHA512:
6
- metadata.gz: 66783c2bc619846d7ce78b33e290d34b414946a5e66714f0528ef312a1e641cc9c6950e30d492e1f428374da391f39e11556bffaa68ced4b4cda726987ea4a8c
7
- data.tar.gz: f04e7f694fb8f151c5ccfa4bd145a2184cb7674b78a1c3af414704664b6efadd5887d9f78e3ad8da4d7f41a25bdfb8e23d355eb79c4bb7675aebb79424995a59
6
+ metadata.gz: 216ff3a7bfda3f2763195eec1e32821596d7047c155d0757d33da0718ad1dbb3c51f04fe50591c2a99d98da37d53255a9bda11c9bf9b6bf79dff788ac27fc0c9
7
+ data.tar.gz: 39784e3be63360c32ec3388983a10068f9d8193bde6cebef190aae856a2da9caa47cb63c772e268203a85eb8a8fad2e0717a901401fffbd0ce8e716979cd3f20
data/.rubocop.yml CHANGED
@@ -1,68 +1,14 @@
1
- AllCops:
2
- TargetRubyVersion: 3.4
3
- NewCops: enable
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ inherit_gem:
4
+ rubocop-shopify: rubocop.yml
4
5
 
5
6
  plugins:
6
7
  - rubocop-minitest
7
8
  - rubocop-rake
8
9
 
9
-
10
- Style/StringLiterals:
11
- EnforcedStyle: double_quotes
12
-
13
- Style/StringLiteralsInInterpolation:
14
- EnforcedStyle: double_quotes
15
-
16
- # Disable documentation for internal classes
17
- Style/Documentation:
18
- Enabled: false
19
-
20
- # Allow slightly longer methods
21
- Metrics/MethodLength:
22
- Enabled: false
23
-
24
- # Disable gemspec specific cops
25
- Gemspec/RequireMFA:
26
- Enabled: false
27
-
28
- Gemspec/RequiredRubyVersion:
29
- Enabled: false
30
-
31
- Gemspec/DevelopmentDependencies:
32
- Enabled: false
33
-
34
- Naming/AccessorMethodName:
35
- Enabled: false
36
-
37
- Metrics/BlockLength:
38
- Enabled: false
39
-
40
- Metrics/ClassLength:
41
- Enabled: false
42
-
43
- Metrics/PerceivedComplexity:
44
- Enabled: false
45
-
46
- Metrics/CyclomaticComplexity:
47
- Enabled: false
48
-
49
- Metrics/AbcSize:
50
- Enabled: false
51
-
52
- Naming/PredicateName:
53
- Enabled: false
54
-
55
- Layout/LineLength:
56
- Max: 150
57
-
58
- Metrics/ModuleLength:
59
- Enabled: false
60
-
61
- Minitest/MultipleAssertions:
62
- Enabled: false
63
-
64
- Metrics/ParameterLists:
65
- Enabled: false
66
-
67
- Style/PerlBackrefs:
68
- Enabled: false
10
+ AllCops:
11
+ TargetRubyVersion: 3.4
12
+ NewCops: enable
13
+ Exclude:
14
+ - '.ruby-lsp/**/*'
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,11 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2025-07-02 11:28:10 UTC using RuboCop version 1.77.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 34
10
+ Minitest/MultipleAssertions:
11
+ Max: 23
data/CHANGELOG.md CHANGED
@@ -1,3 +1,113 @@
1
+ ## [0.2.0]
2
+
3
+ ### Added
4
+ - **After commands support**: Added `after` field to swarm configuration for executing cleanup commands
5
+ - Commands run after Claude exits but before cleanup processes
6
+ - Execute in the main instance's directory (including worktree if enabled)
7
+ - Run even when interrupted by signals (Ctrl+C)
8
+ - Failures in after commands do not prevent cleanup from proceeding
9
+ - Not executed during session restoration
10
+ - Example: `after: ["docker-compose down", "rm -rf temp/*"]`
11
+
12
+ ### Changed
13
+ - **Session restoration command**: Session restoration now uses a dedicated `restore` command instead of the `--session-id` flag
14
+ - Previous: `claude-swarm start --session-id SESSION_ID`
15
+ - New: `claude-swarm restore SESSION_ID`
16
+ - More intuitive command structure following standard CLI patterns
17
+ - **Removed redundant -c flag**: The `-c/--config` option has been removed from the `start` command
18
+ - Config file can still be specified as a positional argument: `claude-swarm start my-config.yml`
19
+ - Default remains `claude-swarm.yml` when no file is specified
20
+ - **Session ID format**: Session IDs now use UUIDs instead of timestamp format
21
+ - Previous format: `YYYYMMDD_HHMMSS` (e.g., `20250707_181341`)
22
+ - New format: UUID v4 (e.g., `550e8400-e29b-41d4-a716-446655440000`)
23
+ - Provides globally unique identifiers suitable for external application integration
24
+ - Sessions remain sorted by file creation time, not by ID
25
+ - **BREAKING CHANGE: Before commands now execute in main instance directory**: The `before` commands specified in swarm configuration now run after changing to the main instance's directory (including worktrees when enabled), rather than in the original working directory
26
+ - This ensures commands like `npm install` or `bundle install` affect only the isolated worktree
27
+ - Makes behavior more intuitive and consistent with user expectations
28
+ - Existing swarms relying on before commands running in the original directory will need to be updated
29
+ - **Custom session ID support**: Added `--session-id` option to the `start` command to allow users to specify their own session ID
30
+ - Use `claude-swarm start --session-id my-custom-id` to use a custom session ID
31
+ - If not provided, a UUID is generated automatically
32
+ - Useful for integrating with external systems that need predictable session identifiers
33
+ - **Environment variable interpolation in configuration**: Claude Swarm now supports environment variable interpolation in all YAML configuration values
34
+ - Use `${ENV_VAR_NAME}` syntax to reference environment variables
35
+ - Variables are interpolated recursively in strings, arrays, and nested structures
36
+ - Fails with clear error message if referenced environment variable is not set
37
+ - Supports multiple variables in the same string and partial string interpolation
38
+ - **Environment variable defaults**: Environment variables in configuration now support default values
39
+ - Use `${ENV_VAR_NAME:=default_value}` syntax to provide defaults
40
+ - Default values are used when the environment variable is not set
41
+ - Supports any string as default value, including spaces and special characters
42
+ - Examples: `${DB_PORT:=5432}`, `${API_URL:=https://api.example.com}`
43
+ - **Session path display in show command**: The `claude-swarm show SESSION_ID` command now displays the session path for easier access to session files
44
+ - **Main process PID tracking**: The orchestrator now writes its process ID to `SESSION_PATH/main_pid` for external monitoring and management
45
+ - **Swarm execution summary**: Display runtime duration and total cost at the end of each swarm run [@claudenm]
46
+ - Shows total execution time in hours, minutes, and seconds format
47
+ - Calculates and displays aggregate cost across all instances
48
+ - Indicates when main instance cost is excluded (e.g., for interactive sessions)
49
+ - Session metadata now includes end time and duration in seconds
50
+
51
+ - **Session cost calculator**: New `SessionCostCalculator` class for aggregating costs from session logs [@claudenm]
52
+ - Processes session.log.json files to calculate total usage costs
53
+ - Tracks which instances have cost data available
54
+
55
+ - **Session cost calculator**: New `SessionCostCalculator` class for aggregating costs from session logs
56
+ - Processes session.log.json files to calculate total usage costs
57
+ - Tracks which instances have cost data available
58
+
59
+ - **OpenAI provider support**: Claude Swarm now supports OpenAI models as an alternative provider
60
+ - Instances can specify `provider: openai` in configuration (default remains "claude")
61
+ - Full MCP tool support for OpenAI instances via automatic conversion
62
+ - Mixed provider swarms allow Claude and OpenAI instances to collaborate
63
+ - OpenAI instances only work with `vibe: true` at the moment. There's no way to set allowed/disallowed tools.
64
+
65
+ - **Dual OpenAI API support**: Two API versions available for different use cases
66
+ - Chat Completion API (`api_version: "chat_completion"`) - Traditional format with tool calling
67
+ - Responses API (`api_version: "responses"`) - New structured format with function calls
68
+ - Both APIs support recursive tool execution with proper conversation tracking
69
+
70
+ - **OpenAI-specific configuration options**:
71
+ - `temperature`: Control response randomness (default: 0.3)
72
+ - `api_version`: Choose between "chat_completion" or "responses"
73
+ - `openai_token_env`: Custom environment variable for API key (default: "OPENAI_API_KEY")
74
+ - `base_url`: Support for OpenAI-compatible endpoints and proxies
75
+
76
+ - **Enhanced debugging and logging**:
77
+ - Detailed error response logging for OpenAI API calls
78
+ - Conversation flow tracking with IDs for debugging
79
+ - Full request/response logging in session JSONL files
80
+
81
+ ### Changed
82
+ - Configuration validation now enforces provider-specific fields
83
+ - Example configurations moved from `example/` to `examples/` directory
84
+ - Added `mixed-provider-swarm.yml` example demonstrating Claude-OpenAI collaboration
85
+ - Session metadata now includes `start_time`, `end_time`, and `duration_seconds` fields [@claudenm]
86
+ - Updated `ps` and `show` commands to use the new cost calculation functionality [@claudenm]
87
+
88
+
89
+ ### Internal
90
+ - New classes: `OpenAIExecutor`, `OpenAIChatCompletion`, `OpenAIResponses`
91
+ - Comprehensive test coverage for OpenAI provider functionality
92
+ - MCP generator enhanced to support provider-specific configurations
93
+
94
+ ## [0.1.20]
95
+
96
+ ### Added
97
+ - **External worktree directory**: Git worktrees are now created in `~/.claude-swarm/worktrees/` for better isolation from the main repository
98
+ - Prevents conflicts with bundler and other tools
99
+ - Each unique Git repository gets its own worktree with the same name
100
+ - Session metadata tracks worktree information for restoration
101
+ - **Zeitwerk autoloading**: Implemented Zeitwerk for better code organization and loading
102
+
103
+ ### Changed
104
+ - **Improved team coordination**: Removed circular dependencies in team configurations
105
+ - **Better code organization**: Refactored code structure to work with Zeitwerk autoloading
106
+
107
+ ### Internal
108
+ - Updated Gemfile.lock to include zeitwerk dependency
109
+ - Added prompt best practices documentation
110
+
1
111
  ## [0.1.19]
2
112
 
3
113
  ### Added
data/CLAUDE.md CHANGED
@@ -18,6 +18,23 @@ bin/setup # Install dependencies
18
18
  rake test # Run the Minitest test suite
19
19
  ```
20
20
 
21
+ **Important**: Tests should not generate any output to stdout or stderr. When writing tests:
22
+ - Capture or suppress all stdout/stderr output from tested methods
23
+ - Use `capture_io` or `capture_subprocess_io` for Minitest
24
+ - Redirect output streams to `StringIO` or `/dev/null` when necessary
25
+ - Mock or stub methods that produce console output
26
+ - Ensure clean test output for better CI/CD integration
27
+
28
+ Example:
29
+ ```ruby
30
+ def test_command_with_output
31
+ output, err = capture_io do
32
+ # Code that produces output
33
+ end
34
+ # Test assertions here
35
+ end
36
+ ```
37
+
21
38
  ### Linting
22
39
  ```bash
23
40
  rake rubocop -A # Run RuboCop linter to auto fix problems
@@ -71,14 +88,15 @@ instances:
71
88
  ```
72
89
 
73
90
  ### Worktree Behavior
74
- - Worktrees are created inside each repository in a `.worktrees/` directory
75
- - A `.gitignore` file is automatically created inside `.worktrees/` to ignore all contents
91
+ - Worktrees are created in external directory: `~/.claude-swarm/worktrees/[session_id]/[repo_name-hash]/[worktree_name]`
92
+ - This ensures proper isolation from the main repository and avoids conflicts with bundler and other tools
76
93
  - Each unique Git repository gets its own worktree with the same name
77
94
  - All instance directories are mapped to their worktree equivalents
78
95
  - Worktrees are automatically cleaned up when the swarm exits
79
96
  - Session metadata tracks worktree information for restoration
80
97
  - Non-Git directories are used as-is without creating worktrees
81
98
  - Existing worktrees with the same name are reused
99
+ - The `claude-swarm clean` command removes orphaned worktrees
82
100
 
83
101
  ## Architecture
84
102
 
@@ -151,3 +169,47 @@ The gem includes comprehensive tests covering:
151
169
 
152
170
  - **thor** (~> 1.3): Command-line interface framework
153
171
  - **yaml**: Built-in Ruby YAML parser (no explicit dependency needed)
172
+
173
+ ## Zeitwerk Autoloading
174
+
175
+ This project uses Zeitwerk for automatic class loading. Important guidelines:
176
+
177
+ ### Require Statement Rules
178
+
179
+ 1. **DO NOT include any require statements for lib files**: Zeitwerk automatically loads all classes under `lib/claude_swarm/`. Never use `require`, `require_relative`, or `require "claude_swarm/..."` for internal project files.
180
+
181
+ 2. **All dependencies must be consolidated in lib/claude_swarm.rb**: Both standard library and external gem dependencies are required at the top of `lib/claude_swarm.rb`. This includes:
182
+ - Standard library dependencies (json, yaml, fileutils, etc.)
183
+ - External gem dependencies (thor, openai, mcp_client, fast_mcp_annotations)
184
+
185
+ 3. **No requires in other lib files**: Individual files in `lib/claude_swarm/` should not have any require statements. They rely on:
186
+ - Dependencies loaded in `lib/claude_swarm.rb`
187
+ - Other classes autoloaded by Zeitwerk
188
+
189
+ ### Example
190
+
191
+ ```ruby
192
+ # ✅ CORRECT - lib/claude_swarm.rb
193
+ # Standard library dependencies
194
+ require "json"
195
+ require "yaml"
196
+ require "fileutils"
197
+ # ... other standard libraries
198
+
199
+ # External dependencies
200
+ require "thor"
201
+ require "openai"
202
+ # ... other gems
203
+
204
+ # Zeitwerk setup
205
+ require "zeitwerk"
206
+ loader = Zeitwerk::Loader.for_gem
207
+ loader.setup
208
+
209
+ # ❌ INCORRECT - lib/claude_swarm/some_class.rb
210
+ require "json" # Don't do this!
211
+ require_relative "other_class" # Don't do this!
212
+ require "claude_swarm/configuration" # Don't do this!
213
+ ```
214
+
215
+ This approach ensures clean dependency management and leverages Ruby's modern autoloading capabilities.
data/README.md CHANGED
@@ -27,7 +27,13 @@ Claude Swarm orchestrates multiple Claude Code instances as a collaborative AI d
27
27
 
28
28
  ## Installation
29
29
 
30
- Install the gem by executing:
30
+ Install [Claude CLI](https://docs.anthropic.com/en/docs/claude-code/overview) if you haven't already:
31
+
32
+ ```bash
33
+ npm install -g @anthropic-ai/claude-code
34
+ ```
35
+
36
+ Install this gem by executing:
31
37
 
32
38
  ```bash
33
39
  gem install claude_swarm
@@ -215,10 +221,70 @@ swarm:
215
221
  - "echo 'Setting up environment...'"
216
222
  - "npm install"
217
223
  - "docker-compose up -d"
224
+ after: # Optional: commands to run after exiting the swarm
225
+ - "echo 'Cleaning up environment...'"
226
+ - "docker-compose down"
218
227
  instances:
219
228
  # Instance definitions...
220
229
  ```
221
230
 
231
+ #### Environment Variable Interpolation
232
+
233
+ Claude Swarm supports environment variable interpolation in all configuration values using the `${ENV_VAR_NAME}` syntax:
234
+
235
+ ```yaml
236
+ version: 1
237
+ swarm:
238
+ name: "${APP_NAME} Development Team"
239
+ main: lead
240
+ instances:
241
+ lead:
242
+ description: "Lead developer for ${APP_NAME}"
243
+ directory: "${PROJECT_ROOT}"
244
+ model: "${CLAUDE_MODEL}"
245
+ prompt: "You are developing ${APP_NAME} version ${APP_VERSION}"
246
+ allowed_tools: ["${TOOL_1}", "${TOOL_2}", "Bash"]
247
+ mcps:
248
+ - name: github
249
+ type: stdio
250
+ command: "${MCP_GITHUB_PATH}"
251
+ env:
252
+ GITHUB_TOKEN: "${GITHUB_TOKEN}"
253
+ ```
254
+
255
+ Features:
256
+ - Variables are interpolated recursively in strings, arrays, and nested structures
257
+ - Multiple variables can be used in the same string
258
+ - Partial string interpolation is supported (e.g., `"prefix-${VAR}-suffix"`)
259
+ - If a referenced environment variable is not set, Claude Swarm will exit with a clear error message
260
+ - Non-matching patterns like `$VAR` or `{VAR}` are preserved as-is
261
+
262
+ ##### Default Values
263
+
264
+ Environment variables can have default values using the `${VAR_NAME:=default_value}` syntax:
265
+
266
+ ```yaml
267
+ version: 1
268
+ swarm:
269
+ name: "Dev Team"
270
+ main: lead
271
+ instances:
272
+ lead:
273
+ description: "Lead developer"
274
+ directory: "${PROJECT_DIR:=.}"
275
+ model: "${CLAUDE_MODEL:=sonnet}"
276
+ mcps:
277
+ - name: api-server
278
+ type: sse
279
+ url: "${API_URL:=http://localhost:8080}"
280
+ worktree: "${BRANCH_NAME:=feature-branch}"
281
+ ```
282
+
283
+ - Default values are used when the environment variable is not set
284
+ - Any string can be used as a default value, including spaces and special characters
285
+ - Empty defaults are supported: `${VAR:=}` results in an empty string if VAR is not set
286
+ - Works in all configuration values: strings, arrays, and nested structures
287
+
222
288
  #### Instance Configuration
223
289
 
224
290
  Each instance must have:
@@ -236,6 +302,24 @@ Each instance can have:
236
302
  - **prompt**: Custom system prompt to append to the instance
237
303
  - **vibe**: Enable vibe mode (--dangerously-skip-permissions) for this instance (default: false)
238
304
  - **worktree**: Configure Git worktree usage for this instance (true/false/string)
305
+ - **provider**: AI provider to use - "claude" (default) or "openai"
306
+
307
+ #### OpenAI Provider Configuration
308
+
309
+ When using `provider: openai`, the following additional fields are available:
310
+
311
+ - **temperature**: Temperature for GPT models only (0.0-2.0). Not supported for O-series reasoning models (o1, o1-preview, o1-mini, o3, etc.)
312
+ - **api_version**: API version to use - "chat_completion" (default) or "responses"
313
+ - **openai_token_env**: Environment variable name for OpenAI API key (default: "OPENAI_API_KEY")
314
+ - **base_url**: Custom base URL for OpenAI API (optional)
315
+ - **reasoning_effort**: Reasoning effort for O-series models only - "low", "medium", or "high"
316
+
317
+ **Important Notes:**
318
+ - O-series models (o1, o1-preview, o1-mini, o3, etc.) use deterministic reasoning and do not support the `temperature` parameter
319
+ - The `reasoning_effort` parameter is only supported by O-series models
320
+ - GPT models support `temperature` but not `reasoning_effort`
321
+ - OpenAI instances default to and ONLY operate as `vibe: true` and use MCP for tool access
322
+ - By default it comes with Claude Code tools, connected with MCP to `claude mcp serve`
239
323
 
240
324
  ```yaml
241
325
  instance_name:
@@ -262,6 +346,27 @@ instance_name:
262
346
  args: ["arg1", "arg2"]
263
347
  env:
264
348
  VAR1: value1
349
+
350
+ # OpenAI instance examples
351
+
352
+ # GPT model with temperature
353
+ gpt_instance:
354
+ description: "OpenAI GPT-powered creative assistant"
355
+ provider: openai
356
+ model: gpt-4o
357
+ temperature: 0.7 # Supported for GPT models
358
+ api_version: chat_completion
359
+ openai_token_env: OPENAI_API_KEY
360
+ prompt: "You are a creative assistant specializing in content generation"
361
+
362
+ # O-series reasoning model with reasoning_effort
363
+ reasoning_instance:
364
+ description: "OpenAI O-series reasoning assistant"
365
+ provider: openai
366
+ model: o1-mini
367
+ reasoning_effort: medium # Only for O-series models
368
+ api_version: responses # Can use either API version
369
+ prompt: "You are a reasoning assistant for complex problem solving"
265
370
  ```
266
371
 
267
372
  ### MCP Server Types
@@ -453,9 +558,54 @@ When using multiple directories:
453
558
  - Additional directories are accessible via the `--add-dir` flag in Claude
454
559
  - All directories must exist or the configuration will fail validation
455
560
 
456
- #### Before Commands
561
+ #### Mixed AI Provider Team
562
+
563
+ Combine Claude and OpenAI instances in a single swarm:
564
+
565
+ ```yaml
566
+ version: 1
567
+ swarm:
568
+ name: "Mixed AI Development Team"
569
+ main: lead_developer
570
+ instances:
571
+ lead_developer:
572
+ description: "Claude lead developer coordinating the team"
573
+ directory: .
574
+ model: opus
575
+ connections: [creative_assistant, reasoning_expert, backend_dev]
576
+ prompt: "You are the lead developer coordinating a mixed AI team"
577
+ allowed_tools: [Read, Edit, Bash, Write]
578
+
579
+ creative_assistant:
580
+ description: "OpenAI-powered assistant for creative and UI/UX tasks"
581
+ provider: openai
582
+ model: gpt-4o
583
+ temperature: 0.7 # Supported for GPT models
584
+ directory: ./frontend
585
+ prompt: "You are a creative frontend developer specializing in UI/UX design"
586
+ # OpenAI instances default to vibe: true
587
+
588
+ reasoning_expert:
589
+ description: "OpenAI O-series model for complex problem solving"
590
+ provider: openai
591
+ model: o1-mini
592
+ reasoning_effort: high # For O-series models only
593
+ directory: ./architecture
594
+ prompt: "You solve complex architectural and algorithmic problems"
595
+
596
+ backend_dev:
597
+ description: "Claude backend developer for system architecture"
598
+ directory: ./backend
599
+ model: sonnet
600
+ prompt: "You specialize in backend development and system architecture"
601
+ allowed_tools: [Read, Edit, Write, Bash]
602
+ ```
603
+
604
+ Note: OpenAI instances require the API key to be set in the environment variable (default: `OPENAI_API_KEY`).
457
605
 
458
- You can specify commands to run before launching the swarm using the `before` field:
606
+ #### Before and After Commands
607
+
608
+ You can specify commands to run before launching and after exiting the swarm using the `before` and `after` fields:
459
609
 
460
610
  ```yaml
461
611
  version: 1
@@ -467,6 +617,10 @@ swarm:
467
617
  - "npm install"
468
618
  - "docker-compose up -d"
469
619
  - "bundle install"
620
+ after:
621
+ - "echo '🛑 Cleaning up development environment...'"
622
+ - "docker-compose down"
623
+ - "rm -rf temp/*"
470
624
  instances:
471
625
  lead_developer:
472
626
  description: "Lead developer coordinating the team"
@@ -477,16 +631,26 @@ swarm:
477
631
 
478
632
  The `before` commands:
479
633
  - Are executed in sequence before launching any Claude instances
634
+ - Execute in the main instance's directory (including worktree if enabled)
480
635
  - Must all succeed for the swarm to launch (exit code 0)
481
636
  - Are only executed on initial swarm launch, not when restoring sessions
482
637
  - Have their output logged to the session log file
483
638
  - Will abort the swarm launch if any command fails
484
639
 
640
+ The `after` commands:
641
+ - Are executed after Claude exits but before cleanup processes
642
+ - Execute in the main instance's directory (including worktree if enabled)
643
+ - Run even when the swarm is interrupted by signals (Ctrl+C)
644
+ - Failures do not prevent cleanup from proceeding
645
+ - Are only executed on initial swarm runs, not when restoring sessions
646
+ - Have their output logged to the session log file
647
+
485
648
  This is useful for:
486
- - Installing dependencies
649
+ - Installing dependencies in the isolated worktree environment
487
650
  - Starting required services (databases, Docker containers, etc.)
488
651
  - Setting up the development environment
489
652
  - Running any prerequisite setup scripts
653
+ - Ensuring setup commands affect only the working directory, not the original repository
490
654
 
491
655
 
492
656
  #### Mixed Permission Modes
@@ -522,17 +686,16 @@ swarm:
522
686
 
523
687
  #### Git Worktrees
524
688
 
525
- Claude Swarm supports running instances in Git worktrees, allowing isolated work without affecting your main repository state. Worktrees are created inside each repository in a `.worktrees/` directory following Git best practices.
689
+ Claude Swarm supports running instances in Git worktrees, allowing isolated work without affecting your main repository state. Worktrees are created in an external directory (`~/.claude-swarm/worktrees/`) to ensure proper isolation from the main repository and avoid conflicts with bundler and other tools.
526
690
 
527
691
  **Example Structure:**
528
692
  ```
529
- my-repo/
530
- ├── .git/
531
- ├── .worktrees/ (created by Claude Swarm)
532
- ├── .gitignore (auto-created, contains "*")
533
- └── feature-x/ (worktree for feature-x branch)
534
- ├── src/
535
- └── tests/
693
+ ~/.claude-swarm/worktrees/
694
+ └── [session_id]/
695
+ ├── my-repo-[hash]/
696
+ └── feature-x/ (worktree for feature-x branch)
697
+ └── other-repo-[hash]/
698
+ └── feature-x/ (worktree for feature-x branch)
536
699
  ```
537
700
 
538
701
  **CLI Option:**
@@ -577,14 +740,14 @@ swarm:
577
740
  - Omitted - Follows CLI behavior (use worktree if `--worktree` is specified)
578
741
 
579
742
  **Notes:**
580
- - Worktrees are created inside each repository in a `.worktrees/` directory
581
743
  - Auto-generated worktree names use the session ID (e.g., `worktree-20241206_143022`)
582
744
  - This makes it easy to correlate worktrees with their Claude Swarm sessions
583
- - A `.gitignore` file is automatically created inside `.worktrees/` to ignore all worktree contents
745
+ - Worktrees are stored externally in `~/.claude-swarm/worktrees/[session_id]/`
584
746
  - All worktrees are automatically cleaned up when the swarm exits
585
747
  - Worktrees with the same name across different repositories share that name
586
748
  - Non-Git directories are unaffected by worktree settings
587
749
  - Existing worktrees with the same name are reused
750
+ - The `claude-swarm clean` command also removes orphaned worktrees
588
751
 
589
752
  ### Command Line Options
590
753
 
@@ -593,8 +756,8 @@ swarm:
593
756
  claude-swarm
594
757
 
595
758
  # Specify a different configuration file
596
- claude-swarm --config my-swarm.yml
597
- claude-swarm -c team-config.yml
759
+ claude-swarm my-swarm.yml
760
+ claude-swarm team-config.yml
598
761
 
599
762
  # Run with --dangerously-skip-permissions for all instances
600
763
  claude-swarm --vibe
@@ -603,9 +766,11 @@ claude-swarm --vibe
603
766
  claude-swarm -p "Implement the new user authentication feature"
604
767
  claude-swarm --prompt "Fix the bug in the payment module"
605
768
 
606
- # Resume a previous session by ID
607
- claude-swarm --session-id 20241206_143022
608
- claude-swarm --session-id ~/path/to/session
769
+ # Use a custom session ID instead of auto-generated UUID
770
+ claude-swarm --session-id my-custom-session-123
771
+
772
+ # Stream logs to stdout in prompt mode
773
+ claude-swarm -p "Fix the tests" --stream-logs
609
774
 
610
775
  # Run all instances in Git worktrees
611
776
  claude-swarm --worktree # Auto-generated name (worktree-SESSION_ID)
@@ -652,10 +817,10 @@ claude-swarm watch 20250617_235233 -n 50
652
817
  claude-swarm list-sessions
653
818
  claude-swarm list-sessions --limit 20
654
819
 
655
- # Clean up stale session symlinks
820
+ # Clean up stale session symlinks and orphaned worktrees
656
821
  claude-swarm clean
657
822
 
658
- # Remove sessions older than 30 days
823
+ # Remove sessions and worktrees older than 30 days
659
824
  claude-swarm clean --days 30
660
825
  ```
661
826
 
@@ -666,7 +831,7 @@ Example output from `claude-swarm ps`:
666
831
  SESSION_ID SWARM_NAME TOTAL_COST UPTIME DIRECTORY
667
832
  -------------------------------------------------------------------------------
668
833
  20250617_235233 Feature Development $0.3847 15m .
669
- 20250617_143022 Bug Investigation $1.2156 1h ./shopify
834
+ 20250617_143022 Bug Investigation $1.2156 1h .
670
835
  20250617_091547 Multi-Module Dev $0.8932 30m ./frontend, ./backend, ./shared
671
836
  ```
672
837
 
@@ -729,11 +894,8 @@ Output shows:
729
894
  Resume a previous session with all instances restored to their Claude session states:
730
895
 
731
896
  ```bash
732
- # Resume by session ID
733
- claude-swarm --session-id 20250617_143022
734
-
735
- # Resume by full path
736
- claude-swarm --session-id ~/.claude-swarm/sessions/my-project/20250617_143022
897
+ # Restore using the session's UUID
898
+ claude-swarm restore 550e8400-e29b-41d4-a716-446655440000
737
899
  ```
738
900
 
739
901
  This will:
@@ -805,7 +967,7 @@ The swarm will display:
805
967
 
806
968
  ### Session Files
807
969
 
808
- Check the session directory `~/.claude-swarm/sessions/{project}/{timestamp}/` for:
970
+ Check the session directory `~/.claude-swarm/sessions/{project}/{session-id}/` for:
809
971
  - `session.log`: Human-readable logs with request/response tracking
810
972
  - `session.log.json`: All events in JSONL format (one JSON object per line)
811
973
  - `{instance}.mcp.json`: MCP configuration for each instance
data/Rakefile CHANGED
@@ -9,4 +9,4 @@ require "rubocop/rake_task"
9
9
 
10
10
  RuboCop::RakeTask.new
11
11
 
12
- task default: %i[test rubocop]
12
+ task default: [:test, :rubocop]
@@ -0,0 +1,23 @@
1
+ version: 1
2
+ swarm:
3
+ name: "Mixed AI Team"
4
+ main: lead_developer
5
+ instances:
6
+ lead_developer:
7
+ description: "Claude lead developer coordinating the team"
8
+ directory: .
9
+ model: opus
10
+ prompt: "You are the lead developer coordinating a mixed AI team"
11
+ allowed_tools: [Read, Edit, Bash, Write]
12
+ connections: [openai_assistant]
13
+
14
+ openai_assistant:
15
+ description: "OpenAI-powered assistant for creative tasks"
16
+ directory: .
17
+ provider: openai
18
+ model: o3
19
+ api_version: responses
20
+ reasoning_effort: high # Optional: low, medium, or high
21
+ prompt: "You are a creative frontend developer using React and modern web technologies"
22
+ # OpenAI instances default to vibe: true
23
+