claude_swarm 0.1.6 → 0.1.8

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: 4694bdf654adfb2784e4156d504ace610c9b48bd7aedafb4d5571ee0483325e6
4
+ data.tar.gz: 9f26361aac4c2815b11f95ab28a67fbb684377d691b7ee5a1b99c89a1a4fa3c1
5
5
  SHA512:
6
- metadata.gz: 5e639606be661128f4c23411f6e9c4164cf9b212ce37e6f99178ba33e4d67a5eb0995b25c1dbe885fff0c20230ea12e347c7b04c7b3bef8b4313353bce6cb948
7
- data.tar.gz: 8d51962bb83f7268510b44a1aff1b13c5f5260c008b8bb26b41d971d0fbdd816c76a9221c275c028851c7ccc825c2aeee7b0d7d0e311f50485119693b3b5791a
6
+ metadata.gz: 8c5d95adfea48bb560e8ed04d1149284fa199e72a9051e85f7e3e23222a1c117c96b6eb977a418bc573d41a6e6c846d7071dd552121d3810a33b0937ac3228c4
7
+ data.tar.gz: aaf42838c5caf597bde330171ebd0aca702089731794f2c45df395b177fe6871c96f27f5838da587a9454de7cc397ca8fae7f910c6f61b1f775f6c2911444823
data/CHANGELOG.md CHANGED
@@ -1,3 +1,34 @@
1
+ ## [0.1.8]
2
+
3
+ ### Added
4
+ - **Disallowed tools support**: New `disallowed_tools` YAML key for explicitly denying specific tools (takes precedence over allowed tools)
5
+
6
+ ### Changed
7
+ - **Renamed YAML key**: `tools` renamed to `allowed_tools` while maintaining backward compatibility
8
+ - Tool permissions now support both allow and deny patterns, with deny taking precedence
9
+ - Both `--allowedTools` and `--disallowedTools` are passed as comma-separated lists to Claude
10
+ - New CLI option `--stream-logs` - can only be used with `-p`
11
+
12
+ ## [0.1.7]
13
+
14
+ ### Added
15
+ - **Vibe mode support**: Per-instance `vibe: true` configuration to skip all permission checks for specific instances
16
+ - **Automatic permission management**: Built-in permission MCP server that handles tool authorization without manual approval
17
+ - **Permission logging**: All permission checks are logged to `.claude-swarm/sessions/{timestamp}/permissions.log`
18
+ - **Mixed permission modes**: Support for running some instances with full permissions while others remain restricted
19
+ - **New CLI command**: `claude-swarm tools-mcp` for starting a standalone permission management MCP server
20
+ - **Permission tool patterns**: Support for wildcard patterns in tool permissions (e.g., `mcp__frontend__*`)
21
+
22
+ ### Changed
23
+ - Fixed `--system-prompt` to use `--append-system-prompt` for proper Claude Code integration
24
+ - Added `--permission-prompt-tool` flag pointing to `mcp__permissions__check_permission` when not in vibe mode
25
+ - Enhanced MCP generation to include a permission server for each instance (unless in vibe mode)
26
+
27
+ ### Technical Details
28
+ - Permission checks use Fast MCP server with pattern matching for tool names
29
+ - Each instance can have its own permission configuration independent of global settings
30
+ - Permission decisions are made based on configured tool patterns with wildcard support
31
+
1
32
  ## [0.1.6]
2
33
  - Refactor: move tools out of the ClaudeMcpServer class
3
34
  - Move logging into code executor and save instance interaction streams to session.log
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Claude Swarm
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/claude_swarm.svg)](https://badge.fury.io/rb/claude_swarm)
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
+
3
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.
4
7
 
5
8
  ## Installation
@@ -24,7 +27,7 @@ bundle install
24
27
 
25
28
  ## Prerequisites
26
29
 
27
- - Ruby 3.1.0 or higher
30
+ - Ruby 3.2.0 or higher
28
31
  - Claude CLI installed and configured
29
32
  - Any MCP servers you plan to use (optional)
30
33
 
@@ -45,7 +48,7 @@ swarm:
45
48
  directory: .
46
49
  model: opus
47
50
  connections: [frontend, backend]
48
- tools: # Tools aren't required if you run it with `--vibe`
51
+ allowed_tools: # Tools aren't required if you run it with `--vibe`
49
52
  - Read
50
53
  - Edit
51
54
  - Bash
@@ -53,7 +56,7 @@ swarm:
53
56
  description: "Frontend specialist handling UI and user experience"
54
57
  directory: ./frontend
55
58
  model: opus
56
- tools:
59
+ allowed_tools:
57
60
  - Edit
58
61
  - Write
59
62
  - Bash
@@ -61,7 +64,7 @@ swarm:
61
64
  description: "Backend developer managing APIs and data layer"
62
65
  directory: ./backend
63
66
  model: opus
64
- tools:
67
+ allowed_tools:
65
68
  - Edit
66
69
  - Write
67
70
  - Bash
@@ -98,7 +101,7 @@ swarm:
98
101
  model: opus
99
102
  connections: [frontend_lead, backend_lead, mobile_lead, devops]
100
103
  prompt: "You are the system architect coordinating between different service teams"
101
- tools: [Read, Edit, WebSearch]
104
+ allowed_tools: [Read, Edit, WebSearch]
102
105
 
103
106
  frontend_lead:
104
107
  description: "Frontend team lead overseeing React development"
@@ -106,21 +109,21 @@ swarm:
106
109
  model: opus
107
110
  connections: [react_dev, css_expert]
108
111
  prompt: "You lead the web frontend team working with React"
109
- tools: [Read, Edit, Bash]
112
+ allowed_tools: [Read, Edit, Bash]
110
113
 
111
114
  react_dev:
112
115
  description: "React developer specializing in components and state management"
113
116
  directory: ./web-frontend/src
114
117
  model: opus
115
118
  prompt: "You specialize in React components and state management"
116
- tools: [Edit, Write, "Bash(npm:*)"]
119
+ allowed_tools: [Edit, Write, "Bash(npm:*)"]
117
120
 
118
121
  css_expert:
119
122
  description: "CSS specialist handling styling and responsive design"
120
123
  directory: ./web-frontend/styles
121
124
  model: opus
122
125
  prompt: "You handle all CSS and styling concerns"
123
- tools: [Edit, Write, Read]
126
+ allowed_tools: [Edit, Write, Read]
124
127
 
125
128
  backend_lead:
126
129
  description: "Backend team lead managing API development"
@@ -128,21 +131,21 @@ swarm:
128
131
  model: opus
129
132
  connections: [api_dev, database_expert]
130
133
  prompt: "You lead the API backend team"
131
- tools: [Read, Edit, Bash]
134
+ allowed_tools: [Read, Edit, Bash]
132
135
 
133
136
  api_dev:
134
137
  description: "API developer building REST endpoints"
135
138
  directory: ./api-server/src
136
139
  model: opus
137
140
  prompt: "You develop REST API endpoints"
138
- tools: [Edit, Write, Bash]
141
+ allowed_tools: [Edit, Write, Bash]
139
142
 
140
143
  database_expert:
141
144
  description: "Database specialist managing schemas and migrations"
142
145
  directory: ./api-server/db
143
146
  model: opus
144
147
  prompt: "You handle database schema and migrations"
145
- tools: [Edit, Write, "Bash(psql:*, migrate:*)"]
148
+ allowed_tools: [Edit, Write, "Bash(psql:*, migrate:*)"]
146
149
 
147
150
  mobile_lead:
148
151
  description: "Mobile team lead coordinating cross-platform development"
@@ -150,28 +153,28 @@ swarm:
150
153
  model: opus
151
154
  connections: [ios_dev, android_dev]
152
155
  prompt: "You coordinate mobile development across platforms"
153
- tools: [Read, Edit]
156
+ allowed_tools: [Read, Edit]
154
157
 
155
158
  ios_dev:
156
159
  description: "iOS developer building native Apple applications"
157
160
  directory: ./mobile-app/ios
158
161
  model: opus
159
162
  prompt: "You develop the iOS application"
160
- tools: [Edit, Write, "Bash(xcodebuild:*, pod:*)"]
163
+ allowed_tools: [Edit, Write, "Bash(xcodebuild:*, pod:*)"]
161
164
 
162
165
  android_dev:
163
166
  description: "Android developer creating native Android apps"
164
167
  directory: ./mobile-app/android
165
168
  model: opus
166
169
  prompt: "You develop the Android application"
167
- tools: [Edit, Write, "Bash(gradle:*, adb:*)"]
170
+ allowed_tools: [Edit, Write, "Bash(gradle:*, adb:*)"]
168
171
 
169
172
  devops:
170
173
  description: "DevOps engineer managing CI/CD and infrastructure"
171
174
  directory: ./infrastructure
172
175
  model: opus
173
176
  prompt: "You handle CI/CD and infrastructure"
174
- tools: [Read, Edit, "Bash(docker:*, kubectl:*)"]
177
+ allowed_tools: [Read, Edit, "Bash(docker:*, kubectl:*)"]
175
178
  ```
176
179
 
177
180
  In this setup:
@@ -205,9 +208,11 @@ Each instance can have:
205
208
  - **directory**: Working directory for this instance (can use ~ for home)
206
209
  - **model**: Claude model to use (opus, sonnet, haiku)
207
210
  - **connections**: Array of other instances this one can communicate with
208
- - **tools**: Array of tools this instance can use
211
+ - **allowed_tools**: Array of tools this instance can use (backward compatible with `tools`)
212
+ - **disallowed_tools**: Array of tools to explicitly deny (takes precedence over allowed_tools)
209
213
  - **mcps**: Array of additional MCP servers to connect
210
214
  - **prompt**: Custom system prompt to append to the instance
215
+ - **vibe**: Enable vibe mode (--dangerously-skip-permissions) for this instance (default: false)
211
216
 
212
217
  ```yaml
213
218
  instance_name:
@@ -216,13 +221,17 @@ instance_name:
216
221
  model: opus
217
222
  connections: [other_instance1, other_instance2]
218
223
  prompt: "You are a specialized agent focused on..."
219
- tools:
224
+ vibe: false # Set to true to skip all permission checks for this instance
225
+ allowed_tools:
220
226
  - Read
221
227
  - Edit
222
228
  - Write
223
229
  - Bash
224
230
  - WebFetch
225
231
  - WebSearch
232
+ disallowed_tools: # Optional: explicitly deny specific tools
233
+ - "Write(*.log)"
234
+ - "Bash(rm:*)"
226
235
  mcps:
227
236
  - name: server_name
228
237
  type: stdio
@@ -258,23 +267,27 @@ mcps:
258
267
  Specify which tools each instance can use:
259
268
 
260
269
  ```yaml
261
- tools:
270
+ allowed_tools:
262
271
  - Bash # Command execution
263
272
  - Edit # File editing
264
273
  - Write # File creation
265
274
  - Read # File reading
266
275
  - WebFetch # Fetch web content
267
276
  - WebSearch # Search the web
277
+
278
+ disallowed_tools: # Optional: explicitly deny specific tools
279
+ - "Write(*.md)" # Don't allow writing markdown files
280
+ - "Bash(rm:*)" # Don't allow rm commands
268
281
  ```
269
282
 
270
- Tools are passed to Claude using the `--allowedTools` flag with comma-separated values.
283
+ Tools are passed to Claude using the `--allowedTools` and `--disallowedTools` flags with comma-separated values. Disallowed tools take precedence over allowed tools.
271
284
 
272
285
  #### Tool Restrictions
273
286
 
274
287
  You can restrict tools with pattern-based filters:
275
288
 
276
289
  ```yaml
277
- tools:
290
+ allowed_tools:
278
291
  - Read # Unrestricted read access
279
292
  - Edit # Unrestricted edit access
280
293
  - "Bash(npm:*)" # Only allow npm commands
@@ -297,7 +310,7 @@ swarm:
297
310
  model: opus
298
311
  connections: [frontend, backend, devops]
299
312
  prompt: "You are the lead architect responsible for system design and code quality"
300
- tools:
313
+ allowed_tools:
301
314
  - Read
302
315
  - Edit
303
316
  - WebSearch
@@ -308,7 +321,7 @@ swarm:
308
321
  model: opus
309
322
  connections: [architect]
310
323
  prompt: "You specialize in React, TypeScript, and modern frontend development"
311
- tools:
324
+ allowed_tools:
312
325
  - Edit
313
326
  - Write
314
327
  - Bash
@@ -318,7 +331,7 @@ swarm:
318
331
  directory: ./backend
319
332
  model: opus
320
333
  connections: [architect, database]
321
- tools:
334
+ allowed_tools:
322
335
  - Edit
323
336
  - Write
324
337
  - Bash
@@ -327,7 +340,7 @@ swarm:
327
340
  description: "Database administrator managing data persistence"
328
341
  directory: ./db
329
342
  model: haiku
330
- tools:
343
+ allowed_tools:
331
344
  - Read
332
345
  - Bash
333
346
 
@@ -336,7 +349,7 @@ swarm:
336
349
  directory: .
337
350
  model: opus
338
351
  connections: [architect]
339
- tools:
352
+ allowed_tools:
340
353
  - Read
341
354
  - Edit
342
355
  - Bash
@@ -355,7 +368,7 @@ swarm:
355
368
  directory: ~/research
356
369
  model: opus
357
370
  connections: [data_analyst, writer]
358
- tools:
371
+ allowed_tools:
359
372
  - Read
360
373
  - WebSearch
361
374
  - WebFetch
@@ -368,7 +381,7 @@ swarm:
368
381
  description: "Data analyst processing research data and statistics"
369
382
  directory: ~/research/data
370
383
  model: opus
371
- tools:
384
+ allowed_tools:
372
385
  - Read
373
386
  - Write
374
387
  - Bash
@@ -382,12 +395,43 @@ swarm:
382
395
  description: "Technical writer preparing research documentation"
383
396
  directory: ~/research/papers
384
397
  model: opus
385
- tools:
398
+ allowed_tools:
386
399
  - Edit
387
400
  - Write
388
401
  - Read
389
402
  ```
390
403
 
404
+ #### Mixed Permission Modes
405
+
406
+ You can have different permission modes for different instances:
407
+
408
+ ```yaml
409
+ version: 1
410
+ swarm:
411
+ name: "Mixed Mode Team"
412
+ main: lead
413
+ instances:
414
+ lead:
415
+ description: "Lead with full permissions"
416
+ directory: .
417
+ model: opus
418
+ vibe: true # This instance runs with --dangerously-skip-permissions
419
+ connections: [restricted_worker, trusted_worker]
420
+
421
+ restricted_worker:
422
+ description: "Worker with restricted permissions"
423
+ directory: ./sensitive
424
+ model: sonnet
425
+ allowed_tools: [Read, "Bash(ls:*)"] # Only allow read and ls commands
426
+
427
+ trusted_worker:
428
+ description: "Trusted worker with more permissions"
429
+ directory: ./workspace
430
+ model: sonnet
431
+ vibe: true # This instance also skips permissions
432
+ allowed_tools: [] # Tools list ignored when vibe: true
433
+ ```
434
+
391
435
  ### Command Line Options
392
436
 
393
437
  ```bash
@@ -408,6 +452,10 @@ claude-swarm --prompt "Fix the bug in the payment module"
408
452
  # Show version
409
453
  claude-swarm version
410
454
 
455
+ # Start permission MCP server (for testing/debugging)
456
+ claude-swarm tools-mcp --allowed-tools 'mcp__frontend__*,mcp__backend__*'
457
+ claude-swarm tools-mcp --allowed-tools 'Read,Edit' --disallowed-tools 'Edit(*.log)'
458
+
411
459
  # Internal command for MCP server (used by connected instances)
412
460
  claude-swarm mcp-serve INSTANCE_NAME --config CONFIG_FILE --session-timestamp TIMESTAMP
413
461
  ```
@@ -418,18 +466,28 @@ claude-swarm mcp-serve INSTANCE_NAME --config CONFIG_FILE --session-timestamp TI
418
466
  2. **MCP Generation**: For each instance, it generates an MCP configuration file that includes:
419
467
  - Any explicitly defined MCP servers
420
468
  - MCP servers for each connected instance (using `claude-swarm mcp-serve`)
421
- 3. **Session Management**: Claude Swarm maintains session continuity:
469
+ - A permission MCP server (unless using `--vibe` mode)
470
+ 3. **Tool Permissions**: Claude Swarm automatically manages tool permissions:
471
+ - Each instance's configured tools are allowed via the permission MCP
472
+ - Supports wildcard patterns (e.g., `mcp__frontend__*` allows all frontend MCP tools)
473
+ - Disallowed tools take precedence over allowed tools for fine-grained control
474
+ - Eliminates the need to manually accept each tool or use global `--vibe` mode
475
+ - Per-instance `vibe: true` skips all permission checks for that specific instance
476
+ - The permission MCP uses `--permission-prompt-tool` to check tool access
477
+ - Permission decisions are logged to `.claude-swarm/sessions/{timestamp}/permissions.log`
478
+ 4. **Session Management**: Claude Swarm maintains session continuity:
422
479
  - Generates a shared session timestamp for all instances
423
480
  - Each instance can maintain its own Claude session ID
424
481
  - 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:
482
+ 5. **Main Instance Launch**: The main instance is launched with its MCP configuration, giving it access to all connected instances
483
+ 6. **Inter-Instance Communication**: Connected instances expose themselves as MCP servers with these tools:
427
484
  - **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
485
  - **session_info**: Get current Claude session information including ID and working directory
429
486
  - **reset_session**: Reset the Claude session for a fresh start
430
- 6. **Session Management**: All session files are organized in `.claude-swarm/sessions/{timestamp}/`:
487
+ 7. **Session Management**: All session files are organized in `.claude-swarm/sessions/{timestamp}/`:
431
488
  - MCP configuration files: `{instance_name}.mcp.json`
432
489
  - Session log: `session.log` with detailed request/response tracking
490
+ - Permission log: `permissions.log` with all permission checks and decisions
433
491
 
434
492
  ## Troubleshooting
435
493
 
@@ -492,6 +550,20 @@ bundle exec rake release # Release gem to RubyGems.org
492
550
  rake # Default: runs both tests and RuboCop
493
551
  ```
494
552
 
553
+ ### Release Process
554
+
555
+ The gem is automatically published to RubyGems when a new release is created on GitHub:
556
+
557
+ 1. Update the version number in `lib/claude_swarm/version.rb`
558
+ 2. Update `CHANGELOG.md` with the new version's changes
559
+ 3. Commit the changes: `git commit -am "Bump version to x.y.z"`
560
+ 4. Create a version tag: `git tag -a vx.y.z -m "Release version x.y.z"`
561
+ 5. Push the changes and tag: `git push && git push --tags`
562
+ 6. The GitHub workflow will create a draft release - review and publish it
563
+ 7. Once published, the gem will be automatically built and pushed to RubyGems
564
+
565
+ **Note**: You need to set up the `RUBYGEMS_AUTH_TOKEN` secret in your GitHub repository settings with your RubyGems API key.
566
+
495
567
  ## Contributing
496
568
 
497
569
  Bug reports and pull requests are welcome on GitHub at https://github.com/parruda/claude-swarm.
data/RELEASING.md ADDED
@@ -0,0 +1,110 @@
1
+ # Releasing Claude Swarm
2
+
3
+ This guide walks through the process of releasing a new version of Claude Swarm.
4
+
5
+ ## Prerequisites
6
+
7
+ - Ensure you have push access to the repository
8
+ - Ensure the `RUBYGEMS_AUTH_TOKEN` secret is configured in GitHub repository settings
9
+ - Ensure all tests are passing on the main branch
10
+
11
+ ## Release Steps
12
+
13
+ ### 1. Update Version
14
+
15
+ Edit `lib/claude_swarm/version.rb` and update the version number:
16
+
17
+ ```ruby
18
+ module ClaudeSwarm
19
+ VERSION = "0.1.8" # Update this
20
+ end
21
+ ```
22
+
23
+ ### 2. Update Changelog
24
+
25
+ Move items from the `[Unreleased]` section to a new version section in `CHANGELOG.md`:
26
+
27
+ ```markdown
28
+ ## [Unreleased]
29
+
30
+ ## [0.1.8] - 2025-06-02
31
+
32
+ ### Added
33
+ - Feature X
34
+
35
+ ### Changed
36
+ - Enhancement Y
37
+
38
+ ### Fixed
39
+ - Bug Z
40
+ ```
41
+
42
+ ### 3. Commit Changes
43
+
44
+ ```bash
45
+ git add lib/claude_swarm/version.rb CHANGELOG.md
46
+ git commit -m "Bump version to 0.1.8"
47
+ ```
48
+
49
+ ### 4. Create and Push Tag
50
+
51
+ ```bash
52
+ git tag -a v0.1.8 -m "Release version 0.1.8"
53
+ git push origin main
54
+ git push origin v0.1.8
55
+ ```
56
+
57
+ ### 5. Review Draft Release
58
+
59
+ The GitHub workflow will automatically create a draft release. Review it at:
60
+ https://github.com/parruda/claude-swarm/releases
61
+
62
+ ### 6. Publish Release
63
+
64
+ Once you're satisfied with the release notes, click "Publish release". This will trigger the workflow to:
65
+ - Run tests
66
+ - Build the gem
67
+ - Publish to RubyGems.org
68
+ - Publish to GitHub Packages
69
+
70
+ ### 7. Verify Publication
71
+
72
+ Check that the gem was published successfully:
73
+ - RubyGems: https://rubygems.org/gems/claude_swarm
74
+ - GitHub Packages: https://github.com/parruda/claude-swarm/packages
75
+
76
+ ## Troubleshooting
77
+
78
+ ### Failed Publication
79
+
80
+ If the release workflow fails:
81
+
82
+ 1. Check the workflow logs at: https://github.com/parruda/claude-swarm/actions
83
+ 2. Common issues:
84
+ - Invalid `RUBYGEMS_AUTH_TOKEN` secret
85
+ - Test failures
86
+ - RuboCop violations
87
+ - Network issues
88
+
89
+ ### Manual Release
90
+
91
+ If you need to release manually:
92
+
93
+ ```bash
94
+ # Ensure you're on the correct tag
95
+ git checkout v0.1.8
96
+
97
+ # Build the gem
98
+ gem build claude_swarm.gemspec
99
+
100
+ # Push to RubyGems (requires credentials)
101
+ gem push claude_swarm-0.1.8.gem
102
+ ```
103
+
104
+ ## Post-Release
105
+
106
+ After a successful release:
107
+
108
+ 1. Create a new `[Unreleased]` section in `CHANGELOG.md`
109
+ 2. Announce the release (optional)
110
+ 3. Update any dependent projects
@@ -191,14 +191,26 @@ 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
198
198
  cmd_array << "--dangerously-skip-permissions"
199
- elsif options[:allowed_tools]
200
- tools = Array(options[:allowed_tools]).join(",")
201
- cmd_array += ["--allowedTools", tools]
199
+ else
200
+ # Add allowed tools if any
201
+ if options[:allowed_tools]
202
+ tools = Array(options[:allowed_tools]).join(",")
203
+ cmd_array += ["--allowedTools", tools]
204
+ end
205
+
206
+ # Add disallowed tools if any
207
+ if options[:disallowed_tools]
208
+ disallowed_tools = Array(options[:disallowed_tools]).join(",")
209
+ cmd_array += ["--disallowedTools", disallowed_tools]
210
+ end
211
+
212
+ # Add permission prompt tool if not in vibe mode
213
+ cmd_array += ["--permission-prompt-tool", "mcp__permissions__check_permission"]
202
214
  end
203
215
 
204
216
  cmd_array
@@ -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
@@ -19,6 +20,8 @@ module ClaudeSwarm
19
20
  desc: "Run with --dangerously-skip-permissions for all instances"
20
21
  method_option :prompt, aliases: "-p", type: :string,
21
22
  desc: "Prompt to pass to the main Claude instance (non-interactive mode)"
23
+ method_option :stream_logs, type: :boolean, default: false,
24
+ desc: "Stream session logs to stdout (only works with -p)"
22
25
  def start(config_file = nil)
23
26
  config_path = config_file || options[:config]
24
27
  unless File.exist?(config_path)
@@ -27,6 +30,13 @@ module ClaudeSwarm
27
30
  end
28
31
 
29
32
  say "Starting Claude Swarm from #{config_path}..." unless options[:prompt]
33
+
34
+ # Validate stream_logs option
35
+ if options[:stream_logs] && !options[:prompt]
36
+ error "--stream-logs can only be used with -p/--prompt"
37
+ exit 1
38
+ end
39
+
30
40
  begin
31
41
  config = Configuration.new(config_path)
32
42
  session_timestamp = Time.now.strftime("%Y%m%d_%H%M%S")
@@ -34,7 +44,8 @@ module ClaudeSwarm
34
44
  orchestrator = Orchestrator.new(config, generator,
35
45
  vibe: options[:vibe],
36
46
  prompt: options[:prompt],
37
- session_timestamp: session_timestamp)
47
+ session_timestamp: session_timestamp,
48
+ stream_logs: options[:stream_logs])
38
49
  orchestrator.start
39
50
  rescue Error => e
40
51
  error e.message
@@ -59,6 +70,8 @@ module ClaudeSwarm
59
70
  desc: "Description of the instance's role"
60
71
  method_option :tools, aliases: "-t", type: :array,
61
72
  desc: "Allowed tools for the instance"
73
+ method_option :disallowed_tools, type: :array,
74
+ desc: "Disallowed tools for the instance"
62
75
  method_option :mcp_config_path, type: :string,
63
76
  desc: "Path to MCP configuration file"
64
77
  method_option :debug, type: :boolean, default: false,
@@ -75,6 +88,7 @@ module ClaudeSwarm
75
88
  prompt: options[:prompt],
76
89
  description: options[:description],
77
90
  tools: options[:tools] || [],
91
+ disallowed_tools: options[:disallowed_tools] || [],
78
92
  mcp_config_path: options[:mcp_config_path],
79
93
  vibe: options[:vibe]
80
94
  }
@@ -112,7 +126,7 @@ module ClaudeSwarm
112
126
  directory: .
113
127
  model: sonnet
114
128
  prompt: "You are the lead developer coordinating the team"
115
- tools: [Read, Edit, Bash, Write]
129
+ allowed_tools: [Read, Edit, Bash, Write]
116
130
  # connections: [frontend_dev, backend_dev]
117
131
 
118
132
  # Example instances (uncomment and modify as needed):
@@ -122,28 +136,28 @@ module ClaudeSwarm
122
136
  # directory: ./frontend
123
137
  # model: sonnet
124
138
  # prompt: "You specialize in frontend development with React, TypeScript, and modern web technologies"
125
- # tools: [Read, Edit, Write, "Bash(npm:*)", "Bash(yarn:*)", "Bash(pnpm:*)"]
139
+ # allowed_tools: [Read, Edit, Write, "Bash(npm:*)", "Bash(yarn:*)", "Bash(pnpm:*)"]
126
140
 
127
141
  # backend_dev:
128
142
  # description: "Backend developer focusing on APIs, databases, and server architecture"
129
143
  # directory: ../other-app/backend
130
144
  # model: sonnet
131
145
  # prompt: "You specialize in backend development, APIs, databases, and server architecture"
132
- # tools: [Read, Edit, Write, Bash]
146
+ # allowed_tools: [Read, Edit, Write, Bash]
133
147
 
134
148
  # devops_engineer:
135
149
  # description: "DevOps engineer managing infrastructure, CI/CD, and deployments"
136
150
  # directory: .
137
151
  # model: sonnet
138
152
  # prompt: "You specialize in infrastructure, CI/CD, containerization, and deployment"
139
- # tools: [Read, Edit, Write, "Bash(docker:*)", "Bash(kubectl:*)", "Bash(terraform:*)"]
153
+ # allowed_tools: [Read, Edit, Write, "Bash(docker:*)", "Bash(kubectl:*)", "Bash(terraform:*)"]
140
154
 
141
155
  # qa_engineer:
142
156
  # description: "QA engineer ensuring quality through comprehensive testing"
143
157
  # directory: ./tests
144
158
  # model: sonnet
145
159
  # prompt: "You specialize in testing, quality assurance, and test automation"
146
- # tools: [Read, Edit, Write, Bash]
160
+ # allowed_tools: [Read, Edit, Write, Bash]
147
161
  YAML
148
162
 
149
163
  File.write(config_path, template)
@@ -156,6 +170,22 @@ module ClaudeSwarm
156
170
  say "Claude Swarm #{VERSION}"
157
171
  end
158
172
 
173
+ desc "tools-mcp", "Start a permission management MCP server for tool access control"
174
+ method_option :allowed_tools, aliases: "-t", type: :array,
175
+ desc: "Comma-separated list of allowed tool patterns (supports wildcards)"
176
+ method_option :disallowed_tools, type: :array,
177
+ desc: "Comma-separated list of disallowed tool patterns (supports wildcards)"
178
+ method_option :debug, type: :boolean, default: false,
179
+ desc: "Enable debug output"
180
+ def tools_mcp
181
+ server = PermissionMcpServer.new(allowed_tools: options[:allowed_tools], disallowed_tools: options[:disallowed_tools])
182
+ server.start
183
+ rescue StandardError => e
184
+ error "Error starting permission MCP server: #{e.message}"
185
+ error e.backtrace.join("\n") if options[:debug]
186
+ exit 1
187
+ end
188
+
159
189
  default_task :start
160
190
 
161
191
  private
@@ -76,15 +76,21 @@ module ClaudeSwarm
76
76
  # Validate required fields
77
77
  raise Error, "Instance '#{name}' missing required 'description' field" unless config["description"]
78
78
 
79
+ # Support both 'tools' (deprecated) and 'allowed_tools' for backward compatibility
80
+ allowed_tools = config["allowed_tools"] || config["tools"] || []
81
+
79
82
  {
80
83
  name: name,
81
84
  directory: expand_path(config["directory"] || "."),
82
85
  model: config["model"] || "sonnet",
83
86
  connections: Array(config["connections"]),
84
- tools: Array(config["tools"]),
87
+ tools: Array(allowed_tools), # Keep as 'tools' internally for compatibility
88
+ allowed_tools: Array(allowed_tools),
89
+ disallowed_tools: Array(config["disallowed_tools"]),
85
90
  mcps: parse_mcps(config["mcps"] || []),
86
91
  prompt: config["prompt"],
87
- description: config["description"]
92
+ description: config["description"],
93
+ vibe: config["vibe"] || false
88
94
  }
89
95
  end
90
96
 
@@ -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], instance[:disallowed_tools]) unless @vibe || instance[:vibe]
63
+
61
64
  config = {
62
65
  "mcpServers" => mcp_servers
63
66
  }
@@ -102,11 +105,13 @@ module ClaudeSwarm
102
105
 
103
106
  args.push("--tools", instance[:tools].join(",")) if instance[:tools] && !instance[:tools].empty?
104
107
 
108
+ args.push("--disallowed-tools", instance[:disallowed_tools].join(",")) if instance[:disallowed_tools] && !instance[:disallowed_tools].empty?
109
+
105
110
  args.push("--mcp-config-path", mcp_config_path(name))
106
111
 
107
112
  args.push("--calling-instance", calling_instance) if calling_instance
108
113
 
109
- args.push("--vibe") if @vibe
114
+ args.push("--vibe") if @vibe || instance[:vibe]
110
115
 
111
116
  {
112
117
  "type" => "stdio",
@@ -114,5 +119,26 @@ module ClaudeSwarm
114
119
  "args" => args
115
120
  }
116
121
  end
122
+
123
+ def build_permission_mcp_config(allowed_tools, disallowed_tools)
124
+ exe_path = "claude-swarm"
125
+
126
+ args = ["tools-mcp"]
127
+
128
+ # Add allowed tools if specified
129
+ args.push("--allowed-tools", allowed_tools.join(",")) if allowed_tools && !allowed_tools.empty?
130
+
131
+ # Add disallowed tools if specified
132
+ args.push("--disallowed-tools", disallowed_tools.join(",")) if disallowed_tools && !disallowed_tools.empty?
133
+
134
+ {
135
+ "type" => "stdio",
136
+ "command" => exe_path,
137
+ "args" => args,
138
+ "env" => {
139
+ "CLAUDE_SWARM_SESSION_TIMESTAMP" => @timestamp
140
+ }
141
+ }
142
+ end
117
143
  end
118
144
  end
@@ -4,12 +4,13 @@ require "shellwords"
4
4
 
5
5
  module ClaudeSwarm
6
6
  class Orchestrator
7
- def initialize(configuration, mcp_generator, vibe: false, prompt: nil, session_timestamp: nil)
7
+ def initialize(configuration, mcp_generator, vibe: false, prompt: nil, session_timestamp: nil, stream_logs: false)
8
8
  @config = configuration
9
9
  @generator = mcp_generator
10
10
  @vibe = vibe
11
11
  @prompt = prompt
12
12
  @session_timestamp = session_timestamp || Time.now.strftime("%Y%m%d_%H%M%S")
13
+ @stream_logs = stream_logs
13
14
  end
14
15
 
15
16
  def start
@@ -39,8 +40,10 @@ module ClaudeSwarm
39
40
  puts "🚀 Launching main instance: #{@config.main_instance}"
40
41
  puts " Model: #{main_instance[:model]}"
41
42
  puts " Directory: #{main_instance[:directory]}"
42
- puts " Tools: #{main_instance[:tools].join(", ")}" if main_instance[:tools].any?
43
+ puts " Allowed tools: #{main_instance[:tools].join(", ")}" if main_instance[:tools].any?
44
+ puts " Disallowed tools: #{main_instance[:disallowed_tools].join(", ")}" if main_instance[:disallowed_tools]&.any?
43
45
  puts " Connections: #{main_instance[:connections].join(", ")}" if main_instance[:connections].any?
46
+ puts " 😎 Vibe mode ON for this instance" if main_instance[:vibe]
44
47
  puts
45
48
  end
46
49
 
@@ -50,14 +53,52 @@ module ClaudeSwarm
50
53
  puts
51
54
  end
52
55
 
56
+ # Start log streaming thread if in non-interactive mode with --stream-logs
57
+ log_thread = nil
58
+ log_thread = start_log_streaming if @prompt && @stream_logs
59
+
53
60
  # Execute the main instance - this will cascade to other instances via MCP
54
61
  Dir.chdir(main_instance[:directory]) do
55
62
  system(*command)
56
63
  end
64
+
65
+ # Clean up log streaming thread
66
+ return unless log_thread
67
+
68
+ log_thread.terminate
69
+ log_thread.join
57
70
  end
58
71
 
59
72
  private
60
73
 
74
+ def start_log_streaming
75
+ Thread.new do
76
+ session_log_path = File.join(Dir.pwd, ClaudeSwarm::ClaudeCodeExecutor::SWARM_DIR,
77
+ ClaudeSwarm::ClaudeCodeExecutor::SESSIONS_DIR,
78
+ @session_timestamp, "session.log")
79
+
80
+ # Wait for log file to be created
81
+ sleep 0.1 until File.exist?(session_log_path)
82
+
83
+ # Open file and seek to end
84
+ File.open(session_log_path, "r") do |file|
85
+ file.seek(0, IO::SEEK_END)
86
+
87
+ loop do
88
+ changes = file.read
89
+ if changes
90
+ print changes
91
+ $stdout.flush
92
+ else
93
+ sleep 0.1
94
+ end
95
+ end
96
+ end
97
+ rescue StandardError
98
+ # Silently handle errors (file might be deleted, process might end, etc.)
99
+ end
100
+ end
101
+
61
102
  def build_main_command(instance)
62
103
  parts = [
63
104
  "claude",
@@ -65,12 +106,26 @@ module ClaudeSwarm
65
106
  instance[:model]
66
107
  ]
67
108
 
68
- if @vibe
109
+ if @vibe || instance[:vibe]
69
110
  parts << "--dangerously-skip-permissions"
70
- elsif instance[:tools].any?
71
- tools_str = instance[:tools].join(",")
72
- parts << "--allowedTools"
73
- parts << tools_str
111
+ else
112
+ # Add allowed tools if any
113
+ if instance[:tools].any?
114
+ tools_str = instance[:tools].join(",")
115
+ parts << "--allowedTools"
116
+ parts << tools_str
117
+ end
118
+
119
+ # Add disallowed tools if any
120
+ if instance[:disallowed_tools]&.any?
121
+ disallowed_tools_str = instance[:disallowed_tools].join(",")
122
+ parts << "--disallowedTools"
123
+ parts << disallowed_tools_str
124
+ end
125
+
126
+ # Add permission prompt tool unless in vibe mode
127
+ parts << "--permission-prompt-tool"
128
+ parts << "mcp__permissions__check_permission"
74
129
  end
75
130
 
76
131
  if instance[:prompt]
@@ -0,0 +1,81 @@
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, disallowed_tools: nil)
15
+ @allowed_tools = allowed_tools
16
+ @disallowed_tools = disallowed_tools
17
+ setup_logging
18
+ end
19
+
20
+ def start
21
+ # Parse allowed and disallowed tools
22
+ allowed_patterns = parse_tool_patterns(@allowed_tools)
23
+ disallowed_patterns = parse_tool_patterns(@disallowed_tools)
24
+
25
+ @logger.info("Starting permission MCP server with allowed patterns: #{allowed_patterns.inspect}, " \
26
+ "disallowed patterns: #{disallowed_patterns.inspect}")
27
+
28
+ # Set the patterns on the tool class
29
+ PermissionTool.allowed_patterns = allowed_patterns
30
+ PermissionTool.disallowed_patterns = disallowed_patterns
31
+ PermissionTool.logger = @logger
32
+
33
+ server = FastMcp::Server.new(
34
+ name: "claude-swarm-permissions",
35
+ version: "1.0.0"
36
+ )
37
+
38
+ # Register the tool class
39
+ server.register_tool(PermissionTool)
40
+
41
+ @logger.info("Permission MCP server started successfully")
42
+
43
+ # Start the stdio server
44
+ server.start
45
+ end
46
+
47
+ private
48
+
49
+ def setup_logging
50
+ # Use environment variable for session timestamp if available
51
+ # Otherwise create a new timestamp
52
+ session_timestamp = ENV["CLAUDE_SWARM_SESSION_TIMESTAMP"] || Time.now.strftime("%Y%m%d_%H%M%S")
53
+
54
+ # Ensure the session directory exists
55
+ session_dir = File.join(Dir.pwd, SWARM_DIR, SESSIONS_DIR, session_timestamp)
56
+ FileUtils.mkdir_p(session_dir)
57
+
58
+ # Create logger with permissions.log filename
59
+ log_path = File.join(session_dir, "permissions.log")
60
+ @logger = Logger.new(log_path)
61
+ @logger.level = Logger::DEBUG
62
+
63
+ # Custom formatter for better readability
64
+ @logger.formatter = proc do |severity, datetime, _progname, msg|
65
+ "[#{datetime.strftime("%Y-%m-%d %H:%M:%S.%L")}] [#{severity}] #{msg}\n"
66
+ end
67
+
68
+ @logger.info("Permission MCP server logging initialized")
69
+ end
70
+
71
+ def parse_tool_patterns(tools)
72
+ return [] if tools.nil? || tools.empty?
73
+
74
+ # Handle both string and array inputs
75
+ tool_list = tools.is_a?(Array) ? tools : tools.split(/[,\s]+/)
76
+
77
+ # Clean up and return
78
+ tool_list.map(&:strip).reject(&:empty?)
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,87 @@
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/disallowed patterns and logger
9
+ class << self
10
+ attr_accessor :allowed_patterns, :disallowed_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
+ allowed_patterns = self.class.allowed_patterns || []
27
+ disallowed_patterns = self.class.disallowed_patterns || []
28
+
29
+ logger.info("Checking against allowed patterns: #{allowed_patterns.inspect}")
30
+ logger.info("Checking against disallowed patterns: #{disallowed_patterns.inspect}")
31
+
32
+ # Check if tool matches any disallowed pattern first (takes precedence)
33
+ disallowed = disallowed_patterns.any? do |pattern|
34
+ match = matches_pattern?(tool_name, pattern)
35
+ logger.info("Disallowed pattern '#{pattern}' vs '#{tool_name}': #{match}")
36
+ match
37
+ end
38
+
39
+ if disallowed
40
+ logger.info("DENIED: Tool '#{tool_name}' matches disallowed pattern")
41
+ result = {
42
+ "behavior" => "deny",
43
+ "message" => "Tool '#{tool_name}' is explicitly disallowed"
44
+ }
45
+ else
46
+ # Check if the tool matches any allowed pattern
47
+ allowed = allowed_patterns.empty? || allowed_patterns.any? do |pattern|
48
+ match = matches_pattern?(tool_name, pattern)
49
+ logger.info("Allowed pattern '#{pattern}' vs '#{tool_name}': #{match}")
50
+ match
51
+ end
52
+
53
+ result = if allowed
54
+ logger.info("ALLOWED: Tool '#{tool_name}' matches configured patterns")
55
+ {
56
+ "behavior" => "allow",
57
+ "updatedInput" => input
58
+ }
59
+ else
60
+ logger.info("DENIED: Tool '#{tool_name}' does not match any allowed patterns")
61
+ {
62
+ "behavior" => "deny",
63
+ "message" => "Tool '#{tool_name}' is not allowed by configured patterns"
64
+ }
65
+ end
66
+ end
67
+
68
+ # Return JSON-stringified result as per SDK docs
69
+ response = JSON.generate(result)
70
+ logger.info("Returning response: #{response}")
71
+ response
72
+ end
73
+
74
+ private
75
+
76
+ def matches_pattern?(tool_name, pattern)
77
+ if pattern.include?("*")
78
+ # Convert wildcard pattern to regex
79
+ regex_pattern = pattern.gsub("*", ".*")
80
+ tool_name.match?(/^#{regex_pattern}$/)
81
+ else
82
+ # Exact match
83
+ tool_name == pattern
84
+ end
85
+ end
86
+ end
87
+ end
@@ -23,6 +23,9 @@ module ClaudeSwarm
23
23
  # Add allowed tools from instance config
24
24
  options[:allowed_tools] = instance_config[:tools] if instance_config[:tools]&.any?
25
25
 
26
+ # Add disallowed tools from instance config
27
+ options[:disallowed_tools] = instance_config[:disallowed_tools] if instance_config[:disallowed_tools]&.any?
28
+
26
29
  response = executor.execute(prompt, options)
27
30
 
28
31
  # Return just the result text as expected by MCP
@@ -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.8"
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.8
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: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: thor
@@ -56,8 +56,8 @@ files:
56
56
  - CLAUDE.md
57
57
  - LICENSE
58
58
  - README.md
59
+ - RELEASING.md
59
60
  - Rakefile
60
- - claude-swarm.yml
61
61
  - example/claude-swarm.yml
62
62
  - exe/claude-swarm
63
63
  - lib/claude_swarm.rb
@@ -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
@@ -85,14 +87,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
85
87
  requirements:
86
88
  - - ">="
87
89
  - !ruby/object:Gem::Version
88
- version: 3.1.0
90
+ version: 3.2.0
89
91
  required_rubygems_version: !ruby/object:Gem::Requirement
90
92
  requirements:
91
93
  - - ">="
92
94
  - !ruby/object:Gem::Version
93
95
  version: '0'
94
96
  requirements: []
95
- rubygems_version: 3.6.2
97
+ rubygems_version: 3.6.7
96
98
  specification_version: 4
97
99
  summary: Orchestrate multiple Claude Code instances as a collaborative AI development
98
100
  team
data/claude-swarm.yml DELETED
@@ -1,21 +0,0 @@
1
- version: 1
2
- swarm:
3
- name: "Swarm Name"
4
- main: lead_developer
5
- instances:
6
- lead_developer:
7
- description: "Lead developer coordinating the team and making architectural decisions"
8
- directory: .
9
- model: opus
10
- prompt: "You are the lead developer coordinating the team"
11
- tools: [Read, Edit, Bash, Write]
12
- connections: [frontend_dev]
13
-
14
- # Example instances (uncomment and modify as needed):
15
-
16
- frontend_dev:
17
- description: "Frontend developer specializing in React and modern web technologies"
18
- directory: .
19
- model: opus
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:*)"]