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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32206b2e4ec4228e8d9c2450447f0508a2c58378d37c80ce24d327a54653ee05
4
- data.tar.gz: c11bf2d8042b73de10ee2f40c01e977d8bae0a8bd74e23b74fc29216735396c3
3
+ metadata.gz: 0b5aa9e698fe0c055fc16aa5263df48a2c6e473179d5472e06f83c8845a3447c
4
+ data.tar.gz: ce36d61d30177b38e2f9dbb6f9b00fc1222f0d5ee4cb4539e75f912ad9777904
5
5
  SHA512:
6
- metadata.gz: 5e639606be661128f4c23411f6e9c4164cf9b212ce37e6f99178ba33e4d67a5eb0995b25c1dbe885fff0c20230ea12e347c7b04c7b3bef8b4313353bce6cb948
7
- data.tar.gz: 8d51962bb83f7268510b44a1aff1b13c5f5260c008b8bb26b41d971d0fbdd816c76a9221c275c028851c7ccc825c2aeee7b0d7d0e311f50485119693b3b5791a
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
- 3. **Session Management**: Claude Swarm maintains session continuity:
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
- 4. **Main Instance Launch**: The main instance is launched with its MCP configuration, giving it access to all connected instances
426
- 5. **Inter-Instance Communication**: Connected instances expose themselves as MCP servers with these tools:
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
- 6. **Session Management**: All session files are organized in `.claude-swarm/sessions/{timestamp}/`:
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
- tools: [Read, Edit, Bash, Write]
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: [Read, Edit, Write, "Bash(npm:*)", "Bash(yarn:*)", "Bash(pnpm:*)"]
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
 
@@ -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
@@ -84,7 +84,8 @@ module ClaudeSwarm
84
84
  tools: Array(config["tools"]),
85
85
  mcps: parse_mcps(config["mcps"] || []),
86
86
  prompt: config["prompt"],
87
- description: config["description"]
87
+ description: config["description"],
88
+ vibe: config["vibe"] || false
88
89
  }
89
90
  end
90
91
 
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ClaudeSwarm
4
- VERSION = "0.1.6"
4
+ VERSION = "0.1.7"
5
5
  end
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.6
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-02 00:00:00.000000000 Z
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