claude_swarm 0.1.2 → 0.1.3
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 +12 -1
- data/README.md +10 -8
- data/claude-swarm.yml +7 -0
- data/lib/claude_swarm/claude_code_executor.rb +2 -5
- data/lib/claude_swarm/claude_mcp_server.rb +18 -12
- data/lib/claude_swarm/cli.rb +9 -3
- data/lib/claude_swarm/mcp_generator.rb +11 -7
- data/lib/claude_swarm/orchestrator.rb +6 -6
- data/lib/claude_swarm/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8d82adc5c9d855904f9809e4e2c8d9e34b7dbd5b2dd6ebec98e4072d6c81f3cf
|
4
|
+
data.tar.gz: 1faa01211ebe1b05fcc0dbf8b654b77e3512b4a4653b9169ef8c1b1e40226680
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 539f27f040ff91900bd8d88f925564f07ee4ad673eaaadcfdda228e44ca21adfd46a8be3dd40ae3a9b267b15ac5df4a5bd154d855f75ef85f1888522b71a716b
|
7
|
+
data.tar.gz: 81c0d46bf825684597d80271e7b0e7480b8c92e80c2465af1513b6d80f4dea2100b173261311243f5514e4aeb07bbdedebc0467b293415647bd8397161f98e8d
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,15 @@
|
|
1
|
-
## [
|
1
|
+
## [0.1.3]
|
2
|
+
|
3
|
+
### Fixed
|
4
|
+
- Fixed duplicate prompt arguments being passed to Claude Code executor, which could cause command execution failures
|
5
|
+
|
6
|
+
### Changed
|
7
|
+
- Improved logging to track request flow between instances using `from_instance` and `to_instance` fields instead of generic `instance_name`
|
8
|
+
- Added required `calling_instance` parameter to MCP server command to properly identify the source of requests in tree configurations
|
9
|
+
- Consolidated session files into a single directory structure (`.claude-swarm/sessions/<timestamp>/`)
|
10
|
+
- MCP configuration files are now stored alongside session logs in the same timestamped directory
|
11
|
+
- Session logs are now named `session.log` instead of `session_<timestamp>.log`
|
12
|
+
- Improved organization by keeping all session-related files together
|
2
13
|
|
3
14
|
## [0.1.2] - 2025-05-29
|
4
15
|
|
data/README.md
CHANGED
@@ -77,7 +77,7 @@ claude-swarm --vibe # That will allow ALL tools for all instances! Be Careful!
|
|
77
77
|
This will:
|
78
78
|
- Launch the main instance (lead) with connections to other instances
|
79
79
|
- The lead instance can communicate with the other instances via MCP
|
80
|
-
- All
|
80
|
+
- All session files are stored in `.claude-swarm/sessions/{timestamp}/`
|
81
81
|
|
82
82
|
#### Multi-Level Swarm Example
|
83
83
|
|
@@ -400,7 +400,9 @@ claude-swarm mcp-serve INSTANCE_NAME --config CONFIG_FILE --session-timestamp TI
|
|
400
400
|
- **task**: Execute tasks using Claude Code with configurable tools and return results
|
401
401
|
- **session_info**: Get current Claude session information including ID and working directory
|
402
402
|
- **reset_session**: Reset the Claude session for a fresh start
|
403
|
-
6. **
|
403
|
+
6. **Session Management**: All session files are organized in `.claude-swarm/sessions/{timestamp}/`:
|
404
|
+
- MCP configuration files: `{instance_name}.mcp.json`
|
405
|
+
- Session log: `session.log` with detailed request/response tracking
|
404
406
|
|
405
407
|
## Troubleshooting
|
406
408
|
|
@@ -423,16 +425,16 @@ claude-swarm mcp-serve INSTANCE_NAME --config CONFIG_FILE --session-timestamp TI
|
|
423
425
|
### Debug Output
|
424
426
|
|
425
427
|
The swarm will display:
|
426
|
-
-
|
428
|
+
- Session directory location (`.claude-swarm/sessions/{timestamp}/`)
|
427
429
|
- Main instance details (model, directory, tools, connections)
|
428
430
|
- The exact command being run
|
429
431
|
|
430
|
-
###
|
432
|
+
### Session Files
|
431
433
|
|
432
|
-
Check the
|
433
|
-
-
|
434
|
-
- MCP
|
435
|
-
-
|
434
|
+
Check the session directory `.claude-swarm/sessions/{timestamp}/` for:
|
435
|
+
- `session.log`: Detailed logs with request/response tracking
|
436
|
+
- `{instance}.mcp.json`: MCP configuration for each instance
|
437
|
+
- All files for a session are kept together for easy review
|
436
438
|
|
437
439
|
## Architecture
|
438
440
|
|
data/claude-swarm.yml
CHANGED
@@ -17,3 +17,10 @@ swarm:
|
|
17
17
|
model: sonnet
|
18
18
|
prompt: "You specialize in frontend development with React, TypeScript, and modern web technologies"
|
19
19
|
tools: [Read, Edit, Write, "Bash(npm:*)", "Bash(yarn:*)", "Bash(pnpm:*)"]
|
20
|
+
connections: [css_dev]
|
21
|
+
|
22
|
+
css_dev:
|
23
|
+
directory: .
|
24
|
+
model: sonnet
|
25
|
+
prompt: "You specialize in CSS development with Tailwind CSS, CSS Modules, and modern web technologies"
|
26
|
+
tools: [Read, Edit, Write, "Bash(npm:*)", "Bash(yarn:*)", "Bash(pnpm:*)"]
|
@@ -67,8 +67,8 @@ module ClaudeSwarm
|
|
67
67
|
# Always use JSON output format for structured responses
|
68
68
|
cmd_array += ["--output-format", "json"]
|
69
69
|
|
70
|
-
# Add non-interactive mode
|
71
|
-
cmd_array
|
70
|
+
# Add non-interactive mode with prompt
|
71
|
+
cmd_array += ["--print", "-p", prompt]
|
72
72
|
|
73
73
|
# Add any custom system prompt
|
74
74
|
cmd_array += ["--system-prompt", options[:system_prompt]] if options[:system_prompt]
|
@@ -81,9 +81,6 @@ module ClaudeSwarm
|
|
81
81
|
cmd_array += ["--allowedTools", tools]
|
82
82
|
end
|
83
83
|
|
84
|
-
# Add the prompt as the last argument (no escaping needed with array syntax)
|
85
|
-
cmd_array << prompt
|
86
|
-
|
87
84
|
cmd_array
|
88
85
|
end
|
89
86
|
|
@@ -9,15 +9,16 @@ require_relative "claude_code_executor"
|
|
9
9
|
module ClaudeSwarm
|
10
10
|
class ClaudeMcpServer
|
11
11
|
SWARM_DIR = ".claude-swarm"
|
12
|
-
|
12
|
+
SESSIONS_DIR = "sessions"
|
13
13
|
|
14
14
|
# Class variables to share state with tool classes
|
15
15
|
class << self
|
16
|
-
attr_accessor :executor, :instance_config, :logger, :session_timestamp
|
16
|
+
attr_accessor :executor, :instance_config, :logger, :session_timestamp, :calling_instance
|
17
17
|
end
|
18
18
|
|
19
|
-
def initialize(instance_config)
|
19
|
+
def initialize(instance_config, calling_instance:)
|
20
20
|
@instance_config = instance_config
|
21
|
+
@calling_instance = calling_instance
|
21
22
|
@executor = ClaudeCodeExecutor.new(
|
22
23
|
working_directory: instance_config[:directory],
|
23
24
|
model: instance_config[:model],
|
@@ -32,6 +33,7 @@ module ClaudeSwarm
|
|
32
33
|
self.class.executor = @executor
|
33
34
|
self.class.instance_config = @instance_config
|
34
35
|
self.class.logger = @logger
|
36
|
+
self.class.calling_instance = @calling_instance
|
35
37
|
end
|
36
38
|
|
37
39
|
private
|
@@ -41,13 +43,13 @@ module ClaudeSwarm
|
|
41
43
|
# Otherwise create a new timestamp
|
42
44
|
self.class.session_timestamp ||= ENV["CLAUDE_SWARM_SESSION_TIMESTAMP"] || Time.now.strftime("%Y%m%d_%H%M%S")
|
43
45
|
|
44
|
-
# Ensure the
|
45
|
-
|
46
|
-
FileUtils.mkdir_p(
|
46
|
+
# Ensure the session directory exists
|
47
|
+
session_dir = File.join(Dir.pwd, SWARM_DIR, SESSIONS_DIR, self.class.session_timestamp)
|
48
|
+
FileUtils.mkdir_p(session_dir)
|
47
49
|
|
48
|
-
# Create logger with
|
49
|
-
log_filename = "
|
50
|
-
log_path = File.join(
|
50
|
+
# Create logger with session.log filename
|
51
|
+
log_filename = "session.log"
|
52
|
+
log_path = File.join(session_dir, log_filename)
|
51
53
|
@logger = Logger.new(log_path)
|
52
54
|
@logger.level = Logger::INFO
|
53
55
|
|
@@ -103,7 +105,8 @@ module ClaudeSwarm
|
|
103
105
|
# Log the request
|
104
106
|
log_entry = {
|
105
107
|
timestamp: Time.now.utc.iso8601,
|
106
|
-
|
108
|
+
from_instance: ClaudeMcpServer.calling_instance, # The instance making the request
|
109
|
+
to_instance: instance_config[:name], # This instance is receiving the request
|
107
110
|
model: instance_config[:model],
|
108
111
|
working_directory: instance_config[:directory],
|
109
112
|
session_id: executor.session_id,
|
@@ -120,7 +123,10 @@ module ClaudeSwarm
|
|
120
123
|
response = executor.execute(prompt, options)
|
121
124
|
|
122
125
|
# Log the response
|
123
|
-
response_entry =
|
126
|
+
response_entry = {
|
127
|
+
timestamp: Time.now.utc.iso8601,
|
128
|
+
from_instance: instance_config[:name], # This instance is sending the response
|
129
|
+
to_instance: ClaudeMcpServer.calling_instance, # The instance that made the request receives the response
|
124
130
|
session_id: executor.session_id, # Update with new session ID if changed
|
125
131
|
response: {
|
126
132
|
result: response["result"],
|
@@ -129,7 +135,7 @@ module ClaudeSwarm
|
|
129
135
|
is_error: response["is_error"],
|
130
136
|
total_cost: response["total_cost"]
|
131
137
|
}
|
132
|
-
|
138
|
+
}
|
133
139
|
|
134
140
|
logger.info("RESPONSE: #{JSON.pretty_generate(response_entry)}")
|
135
141
|
|
data/lib/claude_swarm/cli.rb
CHANGED
@@ -29,8 +29,12 @@ module ClaudeSwarm
|
|
29
29
|
say "Starting Claude Swarm from #{config_path}..." unless options[:prompt]
|
30
30
|
begin
|
31
31
|
config = Configuration.new(config_path)
|
32
|
-
|
33
|
-
|
32
|
+
session_timestamp = Time.now.strftime("%Y%m%d_%H%M%S")
|
33
|
+
generator = McpGenerator.new(config, vibe: options[:vibe], timestamp: session_timestamp)
|
34
|
+
orchestrator = Orchestrator.new(config, generator,
|
35
|
+
vibe: options[:vibe],
|
36
|
+
prompt: options[:prompt],
|
37
|
+
session_timestamp: session_timestamp)
|
34
38
|
orchestrator.start
|
35
39
|
rescue Error => e
|
36
40
|
error e.message
|
@@ -59,6 +63,8 @@ module ClaudeSwarm
|
|
59
63
|
desc: "Enable debug output"
|
60
64
|
method_option :vibe, type: :boolean, default: false,
|
61
65
|
desc: "Run with --dangerously-skip-permissions"
|
66
|
+
method_option :calling_instance, type: :string, required: true,
|
67
|
+
desc: "Name of the instance that launched this MCP server"
|
62
68
|
def mcp_serve
|
63
69
|
instance_config = {
|
64
70
|
name: options[:name],
|
@@ -71,7 +77,7 @@ module ClaudeSwarm
|
|
71
77
|
}
|
72
78
|
|
73
79
|
begin
|
74
|
-
server = ClaudeMcpServer.new(instance_config)
|
80
|
+
server = ClaudeMcpServer.new(instance_config, calling_instance: options[:calling_instance])
|
75
81
|
server.start
|
76
82
|
rescue StandardError => e
|
77
83
|
error "Error starting MCP server: #{e.message}"
|
@@ -7,10 +7,12 @@ require "shellwords"
|
|
7
7
|
module ClaudeSwarm
|
8
8
|
class McpGenerator
|
9
9
|
SWARM_DIR = ".claude-swarm"
|
10
|
+
SESSIONS_SUBDIR = "sessions"
|
10
11
|
|
11
|
-
def initialize(configuration, vibe: false)
|
12
|
+
def initialize(configuration, vibe: false, timestamp: nil)
|
12
13
|
@config = configuration
|
13
14
|
@vibe = vibe
|
15
|
+
@timestamp = timestamp || Time.now.strftime("%Y%m%d_%H%M%S")
|
14
16
|
end
|
15
17
|
|
16
18
|
def generate_all
|
@@ -22,7 +24,7 @@ module ClaudeSwarm
|
|
22
24
|
end
|
23
25
|
|
24
26
|
def mcp_config_path(instance_name)
|
25
|
-
File.join(Dir.pwd, SWARM_DIR, "#{instance_name}.mcp.json")
|
27
|
+
File.join(Dir.pwd, SWARM_DIR, SESSIONS_SUBDIR, @timestamp, "#{instance_name}.mcp.json")
|
26
28
|
end
|
27
29
|
|
28
30
|
private
|
@@ -34,9 +36,9 @@ module ClaudeSwarm
|
|
34
36
|
def ensure_swarm_directory
|
35
37
|
FileUtils.mkdir_p(swarm_dir)
|
36
38
|
|
37
|
-
# Create
|
38
|
-
|
39
|
-
FileUtils.mkdir_p(
|
39
|
+
# Create session directory with timestamp
|
40
|
+
session_dir = File.join(swarm_dir, SESSIONS_SUBDIR, @timestamp)
|
41
|
+
FileUtils.mkdir_p(session_dir)
|
40
42
|
|
41
43
|
gitignore_path = File.join(swarm_dir, ".gitignore")
|
42
44
|
File.write(gitignore_path, "*\n") unless File.exist?(gitignore_path)
|
@@ -53,7 +55,7 @@ module ClaudeSwarm
|
|
53
55
|
# Add connection MCPs for other instances
|
54
56
|
instance[:connections].each do |connection_name|
|
55
57
|
connected_instance = @config.instances[connection_name]
|
56
|
-
mcp_servers[connection_name] = build_instance_mcp_config(connection_name, connected_instance)
|
58
|
+
mcp_servers[connection_name] = build_instance_mcp_config(connection_name, connected_instance, calling_instance: name)
|
57
59
|
end
|
58
60
|
|
59
61
|
config = {
|
@@ -81,7 +83,7 @@ module ClaudeSwarm
|
|
81
83
|
end
|
82
84
|
end
|
83
85
|
|
84
|
-
def build_instance_mcp_config(name, instance)
|
86
|
+
def build_instance_mcp_config(name, instance, calling_instance:)
|
85
87
|
# Get the path to the claude-swarm executable
|
86
88
|
exe_path = "claude-swarm"
|
87
89
|
|
@@ -100,6 +102,8 @@ module ClaudeSwarm
|
|
100
102
|
|
101
103
|
args.push("--mcp-config-path", mcp_config_path(name))
|
102
104
|
|
105
|
+
args.push("--calling-instance", calling_instance) if calling_instance
|
106
|
+
|
103
107
|
args.push("--vibe") if @vibe
|
104
108
|
|
105
109
|
{
|
@@ -4,11 +4,12 @@ require "shellwords"
|
|
4
4
|
|
5
5
|
module ClaudeSwarm
|
6
6
|
class Orchestrator
|
7
|
-
def initialize(configuration, mcp_generator, vibe: false, prompt: nil)
|
7
|
+
def initialize(configuration, mcp_generator, vibe: false, prompt: nil, session_timestamp: nil)
|
8
8
|
@config = configuration
|
9
9
|
@generator = mcp_generator
|
10
10
|
@vibe = vibe
|
11
11
|
@prompt = prompt
|
12
|
+
@session_timestamp = session_timestamp || Time.now.strftime("%Y%m%d_%H%M%S")
|
12
13
|
end
|
13
14
|
|
14
15
|
def start
|
@@ -18,18 +19,17 @@ module ClaudeSwarm
|
|
18
19
|
puts
|
19
20
|
end
|
20
21
|
|
21
|
-
# Set session timestamp for all instances to share the same
|
22
|
-
|
23
|
-
ENV["CLAUDE_SWARM_SESSION_TIMESTAMP"] = session_timestamp
|
22
|
+
# Set session timestamp for all instances to share the same session directory
|
23
|
+
ENV["CLAUDE_SWARM_SESSION_TIMESTAMP"] = @session_timestamp
|
24
24
|
unless @prompt
|
25
|
-
puts "📝 Session
|
25
|
+
puts "📝 Session files will be saved to: .claude-swarm/sessions/#{@session_timestamp}/"
|
26
26
|
puts
|
27
27
|
end
|
28
28
|
|
29
29
|
# Generate all MCP configuration files
|
30
30
|
@generator.generate_all
|
31
31
|
unless @prompt
|
32
|
-
puts "✓ Generated MCP configurations in
|
32
|
+
puts "✓ Generated MCP configurations in session directory"
|
33
33
|
puts
|
34
34
|
end
|
35
35
|
|
data/lib/claude_swarm/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: claude_swarm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paulo Arruda
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-05-
|
10
|
+
date: 2025-05-30 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: thor
|