claude_swarm 0.1.6 → 0.1.7
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 +20 -0
- data/README.md +49 -4
- data/claude-swarm.yml +7 -2
- data/lib/claude_swarm/claude_code_executor.rb +4 -1
- data/lib/claude_swarm/cli.rb +15 -0
- data/lib/claude_swarm/configuration.rb +2 -1
- data/lib/claude_swarm/mcp_generator.rb +22 -1
- data/lib/claude_swarm/orchestrator.rb +5 -1
- data/lib/claude_swarm/permission_mcp_server.rb +77 -0
- data/lib/claude_swarm/permission_tool.rb +63 -0
- data/lib/claude_swarm/version.rb +1 -1
- data/lib/claude_swarm.rb +2 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0b5aa9e698fe0c055fc16aa5263df48a2c6e473179d5472e06f83c8845a3447c
|
4
|
+
data.tar.gz: ce36d61d30177b38e2f9dbb6f9b00fc1222f0d5ee4cb4539e75f912ad9777904
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ffbac2fb59e4f76ab39efe172a89d1a11b0893efd763770ba3f4c6e52785df44d19cc0db9a8dd87e2df52c05c7d8cceadc47deb2a8304e34ccb2c921b781842c
|
7
|
+
data.tar.gz: dd4eeb38f8d56c3cd41570fe0be0ccda029240893780d95c82c134ad02d91c840ba8fd3fb344dc205c7a3345e37fbce33b8f633abd076390783b31babaf6014d
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
## [0.1.7]
|
2
|
+
|
3
|
+
### Added
|
4
|
+
- **Vibe mode support**: Per-instance `vibe: true` configuration to skip all permission checks for specific instances
|
5
|
+
- **Automatic permission management**: Built-in permission MCP server that handles tool authorization without manual approval
|
6
|
+
- **Permission logging**: All permission checks are logged to `.claude-swarm/sessions/{timestamp}/permissions.log`
|
7
|
+
- **Mixed permission modes**: Support for running some instances with full permissions while others remain restricted
|
8
|
+
- **New CLI command**: `claude-swarm tools-mcp` for starting a standalone permission management MCP server
|
9
|
+
- **Permission tool patterns**: Support for wildcard patterns in tool permissions (e.g., `mcp__frontend__*`)
|
10
|
+
|
11
|
+
### Changed
|
12
|
+
- Fixed `--system-prompt` to use `--append-system-prompt` for proper Claude Code integration
|
13
|
+
- Added `--permission-prompt-tool` flag pointing to `mcp__permissions__check_permission` when not in vibe mode
|
14
|
+
- Enhanced MCP generation to include a permission server for each instance (unless in vibe mode)
|
15
|
+
|
16
|
+
### Technical Details
|
17
|
+
- Permission checks use Fast MCP server with pattern matching for tool names
|
18
|
+
- Each instance can have its own permission configuration independent of global settings
|
19
|
+
- Permission decisions are made based on configured tool patterns with wildcard support
|
20
|
+
|
1
21
|
## [0.1.6]
|
2
22
|
- Refactor: move tools out of the ClaudeMcpServer class
|
3
23
|
- Move logging into code executor and save instance interaction streams to session.log
|
data/README.md
CHANGED
@@ -208,6 +208,7 @@ Each instance can have:
|
|
208
208
|
- **tools**: Array of tools this instance can use
|
209
209
|
- **mcps**: Array of additional MCP servers to connect
|
210
210
|
- **prompt**: Custom system prompt to append to the instance
|
211
|
+
- **vibe**: Enable vibe mode (--dangerously-skip-permissions) for this instance (default: false)
|
211
212
|
|
212
213
|
```yaml
|
213
214
|
instance_name:
|
@@ -216,6 +217,7 @@ instance_name:
|
|
216
217
|
model: opus
|
217
218
|
connections: [other_instance1, other_instance2]
|
218
219
|
prompt: "You are a specialized agent focused on..."
|
220
|
+
vibe: false # Set to true to skip all permission checks for this instance
|
219
221
|
tools:
|
220
222
|
- Read
|
221
223
|
- Edit
|
@@ -388,6 +390,37 @@ swarm:
|
|
388
390
|
- Read
|
389
391
|
```
|
390
392
|
|
393
|
+
#### Mixed Permission Modes
|
394
|
+
|
395
|
+
You can have different permission modes for different instances:
|
396
|
+
|
397
|
+
```yaml
|
398
|
+
version: 1
|
399
|
+
swarm:
|
400
|
+
name: "Mixed Mode Team"
|
401
|
+
main: lead
|
402
|
+
instances:
|
403
|
+
lead:
|
404
|
+
description: "Lead with full permissions"
|
405
|
+
directory: .
|
406
|
+
model: opus
|
407
|
+
vibe: true # This instance runs with --dangerously-skip-permissions
|
408
|
+
connections: [restricted_worker, trusted_worker]
|
409
|
+
|
410
|
+
restricted_worker:
|
411
|
+
description: "Worker with restricted permissions"
|
412
|
+
directory: ./sensitive
|
413
|
+
model: sonnet
|
414
|
+
tools: [Read, "Bash(ls:*)"] # Only allow read and ls commands
|
415
|
+
|
416
|
+
trusted_worker:
|
417
|
+
description: "Trusted worker with more permissions"
|
418
|
+
directory: ./workspace
|
419
|
+
model: sonnet
|
420
|
+
vibe: true # This instance also skips permissions
|
421
|
+
tools: [] # Tools list ignored when vibe: true
|
422
|
+
```
|
423
|
+
|
391
424
|
### Command Line Options
|
392
425
|
|
393
426
|
```bash
|
@@ -408,6 +441,9 @@ claude-swarm --prompt "Fix the bug in the payment module"
|
|
408
441
|
# Show version
|
409
442
|
claude-swarm version
|
410
443
|
|
444
|
+
# Start permission MCP server (for testing/debugging)
|
445
|
+
claude-swarm tools-mcp --allowed-tools 'mcp__frontend__*,mcp__backend__*'
|
446
|
+
|
411
447
|
# Internal command for MCP server (used by connected instances)
|
412
448
|
claude-swarm mcp-serve INSTANCE_NAME --config CONFIG_FILE --session-timestamp TIMESTAMP
|
413
449
|
```
|
@@ -418,18 +454,27 @@ claude-swarm mcp-serve INSTANCE_NAME --config CONFIG_FILE --session-timestamp TI
|
|
418
454
|
2. **MCP Generation**: For each instance, it generates an MCP configuration file that includes:
|
419
455
|
- Any explicitly defined MCP servers
|
420
456
|
- MCP servers for each connected instance (using `claude-swarm mcp-serve`)
|
421
|
-
|
457
|
+
- A permission MCP server (unless using `--vibe` mode)
|
458
|
+
3. **Tool Permissions**: Claude Swarm automatically manages tool permissions:
|
459
|
+
- Each instance's configured tools are allowed via the permission MCP
|
460
|
+
- Supports wildcard patterns (e.g., `mcp__frontend__*` allows all frontend MCP tools)
|
461
|
+
- Eliminates the need to manually accept each tool or use global `--vibe` mode
|
462
|
+
- Per-instance `vibe: true` skips all permission checks for that specific instance
|
463
|
+
- The permission MCP uses `--permission-prompt-tool` to check tool access
|
464
|
+
- Permission decisions are logged to `.claude-swarm/sessions/{timestamp}/permissions.log`
|
465
|
+
4. **Session Management**: Claude Swarm maintains session continuity:
|
422
466
|
- Generates a shared session timestamp for all instances
|
423
467
|
- Each instance can maintain its own Claude session ID
|
424
468
|
- Sessions can be reset via the MCP server interface
|
425
|
-
|
426
|
-
|
469
|
+
5. **Main Instance Launch**: The main instance is launched with its MCP configuration, giving it access to all connected instances
|
470
|
+
6. **Inter-Instance Communication**: Connected instances expose themselves as MCP servers with these tools:
|
427
471
|
- **task**: Execute tasks using Claude Code with configurable tools and return results. The tool description includes the instance name and description (e.g., "Execute a task using Agent frontend_dev. Frontend developer specializing in React and TypeScript")
|
428
472
|
- **session_info**: Get current Claude session information including ID and working directory
|
429
473
|
- **reset_session**: Reset the Claude session for a fresh start
|
430
|
-
|
474
|
+
7. **Session Management**: All session files are organized in `.claude-swarm/sessions/{timestamp}/`:
|
431
475
|
- MCP configuration files: `{instance_name}.mcp.json`
|
432
476
|
- Session log: `session.log` with detailed request/response tracking
|
477
|
+
- Permission log: `permissions.log` with all permission checks and decisions
|
433
478
|
|
434
479
|
## Troubleshooting
|
435
480
|
|
data/claude-swarm.yml
CHANGED
@@ -8,7 +8,7 @@ swarm:
|
|
8
8
|
directory: .
|
9
9
|
model: opus
|
10
10
|
prompt: "You are the lead developer coordinating the team"
|
11
|
-
|
11
|
+
vibe: true
|
12
12
|
connections: [frontend_dev]
|
13
13
|
|
14
14
|
# Example instances (uncomment and modify as needed):
|
@@ -18,4 +18,9 @@ swarm:
|
|
18
18
|
directory: .
|
19
19
|
model: opus
|
20
20
|
prompt: "You specialize in frontend development with React, TypeScript, and modern web technologies"
|
21
|
-
tools: [
|
21
|
+
tools: [mcp__headless_browser__*]
|
22
|
+
mcps:
|
23
|
+
- name: headless_browser
|
24
|
+
type: stdio
|
25
|
+
command: bundle
|
26
|
+
args: ["exec", "hbt", "stdio"]
|
@@ -191,7 +191,7 @@ module ClaudeSwarm
|
|
191
191
|
cmd_array += ["--print", "-p", prompt]
|
192
192
|
|
193
193
|
# Add any custom system prompt
|
194
|
-
cmd_array += ["--system-prompt", options[:system_prompt]] if options[:system_prompt]
|
194
|
+
cmd_array += ["--append-system-prompt", options[:system_prompt]] if options[:system_prompt]
|
195
195
|
|
196
196
|
# Add any allowed tools or vibe flag
|
197
197
|
if @vibe
|
@@ -201,6 +201,9 @@ module ClaudeSwarm
|
|
201
201
|
cmd_array += ["--allowedTools", tools]
|
202
202
|
end
|
203
203
|
|
204
|
+
# Add permission prompt tool if not in vibe mode
|
205
|
+
cmd_array += ["--permission-prompt-tool", "mcp__permissions__check_permission"] unless @vibe
|
206
|
+
|
204
207
|
cmd_array
|
205
208
|
end
|
206
209
|
|
data/lib/claude_swarm/cli.rb
CHANGED
@@ -5,6 +5,7 @@ require_relative "configuration"
|
|
5
5
|
require_relative "mcp_generator"
|
6
6
|
require_relative "orchestrator"
|
7
7
|
require_relative "claude_mcp_server"
|
8
|
+
require_relative "permission_mcp_server"
|
8
9
|
|
9
10
|
module ClaudeSwarm
|
10
11
|
class CLI < Thor
|
@@ -156,6 +157,20 @@ module ClaudeSwarm
|
|
156
157
|
say "Claude Swarm #{VERSION}"
|
157
158
|
end
|
158
159
|
|
160
|
+
desc "tools-mcp", "Start a permission management MCP server for tool access control"
|
161
|
+
method_option :allowed_tools, aliases: "-t", type: :array,
|
162
|
+
desc: "Comma-separated list of allowed tool patterns (supports wildcards)"
|
163
|
+
method_option :debug, type: :boolean, default: false,
|
164
|
+
desc: "Enable debug output"
|
165
|
+
def tools_mcp
|
166
|
+
server = PermissionMcpServer.new(allowed_tools: options[:allowed_tools])
|
167
|
+
server.start
|
168
|
+
rescue StandardError => e
|
169
|
+
error "Error starting permission MCP server: #{e.message}"
|
170
|
+
error e.backtrace.join("\n") if options[:debug]
|
171
|
+
exit 1
|
172
|
+
end
|
173
|
+
|
159
174
|
default_task :start
|
160
175
|
|
161
176
|
private
|
@@ -58,6 +58,9 @@ module ClaudeSwarm
|
|
58
58
|
mcp_servers[connection_name] = build_instance_mcp_config(connection_name, connected_instance, calling_instance: name)
|
59
59
|
end
|
60
60
|
|
61
|
+
# Add permission MCP server if not in vibe mode (global or instance-specific)
|
62
|
+
mcp_servers["permissions"] = build_permission_mcp_config(instance[:tools]) unless @vibe || instance[:vibe]
|
63
|
+
|
61
64
|
config = {
|
62
65
|
"mcpServers" => mcp_servers
|
63
66
|
}
|
@@ -106,7 +109,7 @@ module ClaudeSwarm
|
|
106
109
|
|
107
110
|
args.push("--calling-instance", calling_instance) if calling_instance
|
108
111
|
|
109
|
-
args.push("--vibe") if @vibe
|
112
|
+
args.push("--vibe") if @vibe || instance[:vibe]
|
110
113
|
|
111
114
|
{
|
112
115
|
"type" => "stdio",
|
@@ -114,5 +117,23 @@ module ClaudeSwarm
|
|
114
117
|
"args" => args
|
115
118
|
}
|
116
119
|
end
|
120
|
+
|
121
|
+
def build_permission_mcp_config(allowed_tools)
|
122
|
+
exe_path = "claude-swarm"
|
123
|
+
|
124
|
+
args = ["tools-mcp"]
|
125
|
+
|
126
|
+
# Add allowed tools if specified
|
127
|
+
args.push("--allowed-tools", allowed_tools.join(",")) if allowed_tools && !allowed_tools.empty?
|
128
|
+
|
129
|
+
{
|
130
|
+
"type" => "stdio",
|
131
|
+
"command" => exe_path,
|
132
|
+
"args" => args,
|
133
|
+
"env" => {
|
134
|
+
"CLAUDE_SWARM_SESSION_TIMESTAMP" => @timestamp
|
135
|
+
}
|
136
|
+
}
|
137
|
+
end
|
117
138
|
end
|
118
139
|
end
|
@@ -41,6 +41,7 @@ module ClaudeSwarm
|
|
41
41
|
puts " Directory: #{main_instance[:directory]}"
|
42
42
|
puts " Tools: #{main_instance[:tools].join(", ")}" if main_instance[:tools].any?
|
43
43
|
puts " Connections: #{main_instance[:connections].join(", ")}" if main_instance[:connections].any?
|
44
|
+
puts " 😎 Vibe mode ON for this instance" if main_instance[:vibe]
|
44
45
|
puts
|
45
46
|
end
|
46
47
|
|
@@ -65,12 +66,15 @@ module ClaudeSwarm
|
|
65
66
|
instance[:model]
|
66
67
|
]
|
67
68
|
|
68
|
-
if @vibe
|
69
|
+
if @vibe || instance[:vibe]
|
69
70
|
parts << "--dangerously-skip-permissions"
|
70
71
|
elsif instance[:tools].any?
|
71
72
|
tools_str = instance[:tools].join(",")
|
72
73
|
parts << "--allowedTools"
|
73
74
|
parts << tools_str
|
75
|
+
# Add permission prompt tool
|
76
|
+
parts << "--permission-prompt-tool"
|
77
|
+
parts << "mcp__permissions__check_permission"
|
74
78
|
end
|
75
79
|
|
76
80
|
if instance[:prompt]
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
require "fast_mcp"
|
5
|
+
require "logger"
|
6
|
+
require "fileutils"
|
7
|
+
require_relative "permission_tool"
|
8
|
+
|
9
|
+
module ClaudeSwarm
|
10
|
+
class PermissionMcpServer
|
11
|
+
SWARM_DIR = ".claude-swarm"
|
12
|
+
SESSIONS_DIR = "sessions"
|
13
|
+
|
14
|
+
def initialize(allowed_tools: nil)
|
15
|
+
@allowed_tools = allowed_tools
|
16
|
+
setup_logging
|
17
|
+
end
|
18
|
+
|
19
|
+
def start
|
20
|
+
# Parse allowed tools
|
21
|
+
allowed_patterns = parse_allowed_tools(@allowed_tools)
|
22
|
+
|
23
|
+
@logger.info("Starting permission MCP server with allowed patterns: #{allowed_patterns.inspect}")
|
24
|
+
|
25
|
+
# Set the patterns on the tool class
|
26
|
+
PermissionTool.allowed_patterns = allowed_patterns
|
27
|
+
PermissionTool.logger = @logger
|
28
|
+
|
29
|
+
server = FastMcp::Server.new(
|
30
|
+
name: "claude-swarm-permissions",
|
31
|
+
version: "1.0.0"
|
32
|
+
)
|
33
|
+
|
34
|
+
# Register the tool class
|
35
|
+
server.register_tool(PermissionTool)
|
36
|
+
|
37
|
+
@logger.info("Permission MCP server started successfully")
|
38
|
+
|
39
|
+
# Start the stdio server
|
40
|
+
server.start
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def setup_logging
|
46
|
+
# Use environment variable for session timestamp if available
|
47
|
+
# Otherwise create a new timestamp
|
48
|
+
session_timestamp = ENV["CLAUDE_SWARM_SESSION_TIMESTAMP"] || Time.now.strftime("%Y%m%d_%H%M%S")
|
49
|
+
|
50
|
+
# Ensure the session directory exists
|
51
|
+
session_dir = File.join(Dir.pwd, SWARM_DIR, SESSIONS_DIR, session_timestamp)
|
52
|
+
FileUtils.mkdir_p(session_dir)
|
53
|
+
|
54
|
+
# Create logger with permissions.log filename
|
55
|
+
log_path = File.join(session_dir, "permissions.log")
|
56
|
+
@logger = Logger.new(log_path)
|
57
|
+
@logger.level = Logger::DEBUG
|
58
|
+
|
59
|
+
# Custom formatter for better readability
|
60
|
+
@logger.formatter = proc do |severity, datetime, _progname, msg|
|
61
|
+
"[#{datetime.strftime("%Y-%m-%d %H:%M:%S.%L")}] [#{severity}] #{msg}\n"
|
62
|
+
end
|
63
|
+
|
64
|
+
@logger.info("Permission MCP server logging initialized")
|
65
|
+
end
|
66
|
+
|
67
|
+
def parse_allowed_tools(tools)
|
68
|
+
return [] if tools.nil? || tools.empty?
|
69
|
+
|
70
|
+
# Handle both string and array inputs
|
71
|
+
tool_list = tools.is_a?(Array) ? tools : tools.split(/[,\s]+/)
|
72
|
+
|
73
|
+
# Clean up and return
|
74
|
+
tool_list.map(&:strip).reject(&:empty?)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
require "fast_mcp"
|
5
|
+
|
6
|
+
module ClaudeSwarm
|
7
|
+
class PermissionTool < FastMcp::Tool
|
8
|
+
# Class variables to store allowed patterns and logger
|
9
|
+
class << self
|
10
|
+
attr_accessor :allowed_patterns, :logger
|
11
|
+
end
|
12
|
+
|
13
|
+
tool_name "check_permission"
|
14
|
+
description "Check if a tool is allowed to be used based on configured patterns"
|
15
|
+
|
16
|
+
arguments do
|
17
|
+
required(:tool_name).filled(:string).description("The tool requesting permission")
|
18
|
+
required(:input).value(:hash).description("The input for the tool")
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(tool_name:, input:)
|
22
|
+
logger = self.class.logger
|
23
|
+
logger.info("Permission check requested for tool: #{tool_name}")
|
24
|
+
logger.info("Tool input: #{input.inspect}")
|
25
|
+
|
26
|
+
# Check if the tool matches any allowed pattern
|
27
|
+
patterns = self.class.allowed_patterns || []
|
28
|
+
logger.info("Checking against patterns: #{patterns.inspect}")
|
29
|
+
|
30
|
+
allowed = patterns.any? do |pattern|
|
31
|
+
match = if pattern.include?("*")
|
32
|
+
# Convert wildcard pattern to regex
|
33
|
+
regex_pattern = pattern.gsub("*", ".*")
|
34
|
+
tool_name.match?(/^#{regex_pattern}$/)
|
35
|
+
else
|
36
|
+
# Exact match
|
37
|
+
tool_name == pattern
|
38
|
+
end
|
39
|
+
logger.info("Pattern '#{pattern}' vs '#{tool_name}': #{match}")
|
40
|
+
match
|
41
|
+
end
|
42
|
+
|
43
|
+
result = if allowed
|
44
|
+
logger.info("ALLOWED: Tool '#{tool_name}' matches configured patterns")
|
45
|
+
{
|
46
|
+
"behavior" => "allow",
|
47
|
+
"updatedInput" => input
|
48
|
+
}
|
49
|
+
else
|
50
|
+
logger.info("DENIED: Tool '#{tool_name}' does not match any configured patterns")
|
51
|
+
{
|
52
|
+
"behavior" => "deny",
|
53
|
+
"message" => "Tool '#{tool_name}' is not allowed by configured patterns"
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
# Return JSON-stringified result as per SDK docs
|
58
|
+
response = JSON.generate(result)
|
59
|
+
logger.info("Returning response: #{response}")
|
60
|
+
response
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/claude_swarm/version.rb
CHANGED
data/lib/claude_swarm.rb
CHANGED
@@ -4,6 +4,8 @@ require_relative "claude_swarm/version"
|
|
4
4
|
require_relative "claude_swarm/cli"
|
5
5
|
require_relative "claude_swarm/claude_code_executor"
|
6
6
|
require_relative "claude_swarm/claude_mcp_server"
|
7
|
+
require_relative "claude_swarm/permission_tool"
|
8
|
+
require_relative "claude_swarm/permission_mcp_server"
|
7
9
|
|
8
10
|
module ClaudeSwarm
|
9
11
|
class Error < StandardError; end
|
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.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paulo Arruda
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-06-
|
10
|
+
date: 2025-06-03 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: thor
|
@@ -67,6 +67,8 @@ files:
|
|
67
67
|
- lib/claude_swarm/configuration.rb
|
68
68
|
- lib/claude_swarm/mcp_generator.rb
|
69
69
|
- lib/claude_swarm/orchestrator.rb
|
70
|
+
- lib/claude_swarm/permission_mcp_server.rb
|
71
|
+
- lib/claude_swarm/permission_tool.rb
|
70
72
|
- lib/claude_swarm/reset_session_tool.rb
|
71
73
|
- lib/claude_swarm/session_info_tool.rb
|
72
74
|
- lib/claude_swarm/task_tool.rb
|