claude_swarm 0.3.10 → 0.3.11

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: a44d1b33e538b1efaeca7eb223f09bd617fcb4ba2288d7844773ae5908a10248
4
- data.tar.gz: 28312f81eada550b05bbf568807be51c5077366c08d168b928a35a4d356148da
3
+ metadata.gz: 8e0bade0292291825648214e0a1a420241ec1d6ffff018831d131d5c0f532e45
4
+ data.tar.gz: 74d62b916f1dbde6b725e8990924839c6ace2b6de75cb812f43305d044def7b7
5
5
  SHA512:
6
- metadata.gz: 2d8ba31f8a64f91060b980ee90bea57c736e4541410eeb36c4c78bdc602f7c3335ea82a388c0b61847a04c90210fb432c2d525df4f4bfa85cbe3725a0034b260
7
- data.tar.gz: 15180a4a4df3f9ccc55da9dd40769435c1ba650a575b476c10d7c0b16d650bb1f65524b8d44a10d731e9aed3dcda886b0bb63fd2b64e5665c5ba1cc22633182b
6
+ metadata.gz: 0f7f0b3dad9bb034a5b1cf07417df7b3cef6dc7fa88d02d4c9617db354ff0f52d7a368f678f0d2502343fdb03112cf8672f68f2dce3a77a46d769f4cc8f0afa6
7
+ data.tar.gz: d2c81f31e2534e4f92f519ea1b218236d68ed2e08adbd3bfdb2d0569de1a5f80a2f5b2452e3c47b75e6e4441fb70575ca1fbf381d169c0b9ee2aca4b2072c7d6
data/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.3.11]
4
+
5
+ ### Added
6
+ - **Deferred directory validation for before commands**: Directories are now validated after `before` commands run, allowing them to create required directories
7
+ - Automatically skips initial directory validation when `before` commands are present in configuration
8
+ - Validates all directories after `before` commands complete successfully
9
+ - Enables dynamic directory creation workflows without pre-creating directory structures
10
+
11
+ ### Fixed
12
+ - **--root-dir parameter path resolution**: Fixed relative config file paths to be resolved relative to the --root-dir value instead of current directory
13
+ - Config paths are now expanded using the root directory as the base path
14
+ - Allows running claude-swarm from any location with consistent path resolution
15
+ - Absolute paths continue to work as expected regardless of --root-dir setting
16
+
17
+ ### Improved
18
+ - **Enhanced worktree cleanup on errors**: Improved error handling to ensure worktrees are always cleaned up properly
19
+ - Added comprehensive error handling with cleanup at all failure points
20
+ - Worktrees are now cleaned up when worktree setup fails, before commands fail, or directory validation fails
21
+ - Prevents orphaned worktrees that could clutter the system or cause issues with future runs
22
+
1
23
  ## [0.3.10]
2
24
 
3
25
  ### Added
@@ -42,16 +42,19 @@ module ClaudeSwarm
42
42
  type: :string,
43
43
  desc: "Root directory for resolving relative paths (defaults to current directory)"
44
44
  def start(config_file = nil)
45
+ # Set root directory early so it's available to all components
46
+ root_dir = options[:root_dir] || Dir.pwd
47
+ ENV["CLAUDE_SWARM_ROOT_DIR"] = File.expand_path(root_dir)
48
+
49
+ # Resolve config path relative to root directory
45
50
  config_path = config_file || "claude-swarm.yml"
51
+ config_path = File.expand_path(config_path, root_dir)
52
+
46
53
  unless File.exist?(config_path)
47
54
  error("Configuration file not found: #{config_path}")
48
55
  exit(1)
49
56
  end
50
57
 
51
- # Set root directory early so it's available to all components
52
- root_dir = options[:root_dir] || Dir.pwd
53
- ENV["CLAUDE_SWARM_ROOT_DIR"] = File.expand_path(root_dir)
54
-
55
58
  say("Starting Claude Swarm from #{config_path}...") unless options[:prompt]
56
59
 
57
60
  # Validate stream_logs option
@@ -331,7 +334,7 @@ module ClaudeSwarm
331
334
  system!("command -v claude > /dev/null 2>&1")
332
335
  rescue Error
333
336
  error("Claude CLI is not installed or not in PATH")
334
- say("To install Claude CLI, visit: https://docs.anthropic.com/en/docs/claude-code")
337
+ error("To install Claude CLI, visit: https://docs.anthropic.com/en/docs/claude-code")
335
338
  exit(1)
336
339
  end
337
340
 
@@ -508,7 +511,7 @@ module ClaudeSwarm
508
511
  private
509
512
 
510
513
  def error(message)
511
- say(message, :red)
514
+ $stderr.puts(Thor::Shell::Color.new.set_color(message, :red))
512
515
  end
513
516
 
514
517
  def restore_session(session_id)
@@ -43,15 +43,30 @@ module ClaudeSwarm
43
43
  @swarm["after"] || []
44
44
  end
45
45
 
46
+ def validate_directories
47
+ @instances.each do |name, instance|
48
+ # Validate all directories in the directories array
49
+ instance[:directories].each do |directory|
50
+ raise Error, "Directory '#{directory}' for instance '#{name}' does not exist" unless File.directory?(directory)
51
+ end
52
+ end
53
+ end
54
+
46
55
  private
47
56
 
57
+ def has_before_commands?
58
+ @swarm && @swarm["before"] && !@swarm["before"].empty?
59
+ end
60
+
48
61
  def load_and_validate
49
62
  @config = YAML.load_file(@config_path)
50
63
  interpolate_env_vars!(@config)
51
64
  validate_version
52
65
  validate_swarm
53
66
  parse_swarm
54
- validate_directories
67
+ # Skip directory validation if before commands are present
68
+ # They might create the directories
69
+ validate_directories unless has_before_commands?
55
70
  rescue Errno::ENOENT
56
71
  raise Error, "Configuration file not found: #{@config_path}"
57
72
  rescue Psych::SyntaxError => e
@@ -273,15 +288,6 @@ module ClaudeSwarm
273
288
  visited.add(instance_name)
274
289
  end
275
290
 
276
- def validate_directories
277
- @instances.each do |name, instance|
278
- # Validate all directories in the directories array
279
- instance[:directories].each do |directory|
280
- raise Error, "Directory '#{directory}' for instance '#{name}' does not exist" unless File.directory?(directory)
281
- end
282
- end
283
- end
284
-
285
291
  def validate_tool_field(instance_name, config, field_name)
286
292
  return unless config.key?(field_name)
287
293
 
@@ -73,6 +73,20 @@ module ClaudeSwarm
73
73
  # Track start time
74
74
  @start_time = Time.now
75
75
 
76
+ begin
77
+ start_internal
78
+ rescue StandardError => e
79
+ # Ensure cleanup happens even on unexpected errors
80
+ cleanup_processes
81
+ cleanup_run_symlink
82
+ cleanup_worktrees
83
+ raise e
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ def start_internal
76
90
  if @restore_session_path
77
91
  non_interactive_output do
78
92
  puts "🔄 Restoring Claude Swarm: #{@config.swarm_name}"
@@ -115,16 +129,24 @@ module ClaudeSwarm
115
129
 
116
130
  # Setup worktrees if needed
117
131
  if @worktree_manager
118
- non_interactive_output { print("🌳 Setting up Git worktrees...") }
132
+ begin
133
+ non_interactive_output { print("🌳 Setting up Git worktrees...") }
119
134
 
120
- # Get all instances for worktree setup
121
- # Note: instances.values already includes the main instance
122
- all_instances = @config.instances.values
135
+ # Get all instances for worktree setup
136
+ # Note: instances.values already includes the main instance
137
+ all_instances = @config.instances.values
123
138
 
124
- @worktree_manager.setup_worktrees(all_instances)
139
+ @worktree_manager.setup_worktrees(all_instances)
125
140
 
126
- non_interactive_output do
127
- puts "✓ Worktrees created with branch: #{@worktree_manager.worktree_name}"
141
+ non_interactive_output do
142
+ puts "✓ Worktrees created with branch: #{@worktree_manager.worktree_name}"
143
+ end
144
+ rescue StandardError => e
145
+ non_interactive_output { print("❌ Failed to setup worktrees: #{e.message}") }
146
+ cleanup_processes
147
+ cleanup_run_symlink
148
+ cleanup_worktrees
149
+ raise
128
150
  end
129
151
  end
130
152
 
@@ -200,6 +222,20 @@ module ClaudeSwarm
200
222
  non_interactive_output do
201
223
  puts "✓ Before commands completed successfully"
202
224
  end
225
+
226
+ # Validate directories after before commands have run
227
+ begin
228
+ @config.validate_directories
229
+ non_interactive_output do
230
+ puts "✓ All directories validated successfully"
231
+ end
232
+ rescue ClaudeSwarm::Error => e
233
+ non_interactive_output { print("❌ Directory validation failed: #{e.message}") }
234
+ cleanup_processes
235
+ cleanup_run_symlink
236
+ cleanup_worktrees
237
+ exit(1)
238
+ end
203
239
  end
204
240
 
205
241
  # Execute main Claude instance with unbundled environment to avoid bundler conflicts
@@ -249,8 +285,6 @@ module ClaudeSwarm
249
285
  cleanup_worktrees
250
286
  end
251
287
 
252
- private
253
-
254
288
  def non_interactive_output
255
289
  return if @non_interactive_prompt
256
290
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ClaudeSwarm
4
- VERSION = "0.3.10"
4
+ VERSION = "0.3.11"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: claude_swarm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.10
4
+ version: 0.3.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paulo Arruda