claude_swarm 0.1.11 → 0.1.13
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 +47 -0
- data/README.md +85 -15
- data/claude-swarm.yml +42 -0
- data/example/session-restoration-demo.yml +19 -0
- data/lib/claude_swarm/claude_code_executor.rb +101 -20
- data/lib/claude_swarm/claude_mcp_server.rb +16 -4
- data/lib/claude_swarm/cli.rb +169 -5
- data/lib/claude_swarm/configuration.rb +33 -7
- data/lib/claude_swarm/mcp_generator.rb +62 -22
- data/lib/claude_swarm/orchestrator.rb +122 -24
- data/lib/claude_swarm/permission_mcp_server.rb +14 -15
- data/lib/claude_swarm/process_tracker.rb +78 -0
- data/lib/claude_swarm/session_path.rb +50 -0
- data/lib/claude_swarm/version.rb +1 -1
- data/lib/claude_swarm.rb +8 -0
- metadata +5 -1
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
|
5
|
+
module ClaudeSwarm
|
6
|
+
class ProcessTracker
|
7
|
+
PIDS_DIR = "pids"
|
8
|
+
|
9
|
+
def initialize(session_path)
|
10
|
+
@session_path = session_path
|
11
|
+
@pids_dir = File.join(@session_path, PIDS_DIR)
|
12
|
+
ensure_pids_directory
|
13
|
+
end
|
14
|
+
|
15
|
+
def track_pid(pid, name)
|
16
|
+
pid_file = File.join(@pids_dir, pid.to_s)
|
17
|
+
File.write(pid_file, name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def cleanup_all
|
21
|
+
return unless Dir.exist?(@pids_dir)
|
22
|
+
|
23
|
+
# Get all PID files
|
24
|
+
pid_files = Dir.glob(File.join(@pids_dir, "*"))
|
25
|
+
|
26
|
+
pid_files.each do |pid_file|
|
27
|
+
pid = File.basename(pid_file).to_i
|
28
|
+
name = begin
|
29
|
+
File.read(pid_file).strip
|
30
|
+
rescue StandardError
|
31
|
+
"unknown"
|
32
|
+
end
|
33
|
+
|
34
|
+
begin
|
35
|
+
# Check if process is still running
|
36
|
+
Process.kill(0, pid)
|
37
|
+
# If we get here, process is running, so kill it
|
38
|
+
Process.kill("TERM", pid)
|
39
|
+
puts "✓ Terminated MCP server: #{name} (PID: #{pid})"
|
40
|
+
|
41
|
+
# Give it a moment to terminate gracefully
|
42
|
+
sleep 0.1
|
43
|
+
|
44
|
+
# Force kill if still running
|
45
|
+
begin
|
46
|
+
Process.kill(0, pid)
|
47
|
+
Process.kill("KILL", pid)
|
48
|
+
puts " → Force killed #{name} (PID: #{pid})"
|
49
|
+
rescue Errno::ESRCH
|
50
|
+
# Process is gone, which is what we want
|
51
|
+
end
|
52
|
+
rescue Errno::ESRCH
|
53
|
+
# Process not found, already terminated
|
54
|
+
puts " → MCP server #{name} (PID: #{pid}) already terminated"
|
55
|
+
rescue Errno::EPERM
|
56
|
+
# Permission denied
|
57
|
+
puts " ⚠️ No permission to terminate #{name} (PID: #{pid})"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Clean up the pids directory
|
62
|
+
FileUtils.rm_rf(@pids_dir)
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.cleanup_session(session_path)
|
66
|
+
return unless Dir.exist?(File.join(session_path, PIDS_DIR))
|
67
|
+
|
68
|
+
tracker = new(session_path)
|
69
|
+
tracker.cleanup_all
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def ensure_pids_directory
|
75
|
+
FileUtils.mkdir_p(@pids_dir)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
|
5
|
+
module ClaudeSwarm
|
6
|
+
module SessionPath
|
7
|
+
SESSIONS_DIR = "sessions"
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def swarm_home
|
11
|
+
ENV["CLAUDE_SWARM_HOME"] || File.expand_path("~/.claude-swarm")
|
12
|
+
end
|
13
|
+
|
14
|
+
# Convert a directory path to a safe folder name using + as separator
|
15
|
+
def project_folder_name(working_dir = Dir.pwd)
|
16
|
+
# Don't expand path if it's already expanded (avoids double expansion on Windows)
|
17
|
+
path = working_dir.start_with?("/") || working_dir.match?(/^[A-Za-z]:/) ? working_dir : File.expand_path(working_dir)
|
18
|
+
|
19
|
+
# Handle Windows drive letters (C:\ → C)
|
20
|
+
path = path.gsub(/^([A-Za-z]):/, '\1')
|
21
|
+
|
22
|
+
# Remove leading slash/backslash
|
23
|
+
path = path.sub(%r{^[/\\]}, "")
|
24
|
+
|
25
|
+
# Replace all path separators with +
|
26
|
+
path.gsub(%r{[/\\]}, "+")
|
27
|
+
end
|
28
|
+
|
29
|
+
# Generate a full session path for a given directory and timestamp
|
30
|
+
def generate(working_dir: Dir.pwd, timestamp: Time.now.strftime("%Y%m%d_%H%M%S"))
|
31
|
+
project_name = project_folder_name(working_dir)
|
32
|
+
File.join(swarm_home, SESSIONS_DIR, project_name, timestamp)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Ensure the session directory exists
|
36
|
+
def ensure_directory(session_path)
|
37
|
+
FileUtils.mkdir_p(session_path)
|
38
|
+
|
39
|
+
# Add .gitignore to swarm home if it doesn't exist
|
40
|
+
gitignore_path = File.join(swarm_home, ".gitignore")
|
41
|
+
File.write(gitignore_path, "*\n") unless File.exist?(gitignore_path)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Get the session path from environment (required)
|
45
|
+
def from_env
|
46
|
+
ENV["CLAUDE_SWARM_SESSION_PATH"] or raise "CLAUDE_SWARM_SESSION_PATH not set"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/claude_swarm/version.rb
CHANGED
data/lib/claude_swarm.rb
CHANGED
@@ -2,10 +2,18 @@
|
|
2
2
|
|
3
3
|
require_relative "claude_swarm/version"
|
4
4
|
require_relative "claude_swarm/cli"
|
5
|
+
require_relative "claude_swarm/configuration"
|
6
|
+
require_relative "claude_swarm/mcp_generator"
|
7
|
+
require_relative "claude_swarm/orchestrator"
|
5
8
|
require_relative "claude_swarm/claude_code_executor"
|
6
9
|
require_relative "claude_swarm/claude_mcp_server"
|
7
10
|
require_relative "claude_swarm/permission_tool"
|
8
11
|
require_relative "claude_swarm/permission_mcp_server"
|
12
|
+
require_relative "claude_swarm/session_path"
|
13
|
+
require_relative "claude_swarm/session_info_tool"
|
14
|
+
require_relative "claude_swarm/reset_session_tool"
|
15
|
+
require_relative "claude_swarm/task_tool"
|
16
|
+
require_relative "claude_swarm/process_tracker"
|
9
17
|
|
10
18
|
module ClaudeSwarm
|
11
19
|
class Error < StandardError; 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.1.
|
4
|
+
version: 0.1.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paulo Arruda
|
@@ -58,8 +58,10 @@ files:
|
|
58
58
|
- README.md
|
59
59
|
- RELEASING.md
|
60
60
|
- Rakefile
|
61
|
+
- claude-swarm.yml
|
61
62
|
- example/claude-swarm.yml
|
62
63
|
- example/microservices-team.yml
|
64
|
+
- example/session-restoration-demo.yml
|
63
65
|
- example/test-generation.yml
|
64
66
|
- exe/claude-swarm
|
65
67
|
- lib/claude_swarm.rb
|
@@ -71,8 +73,10 @@ files:
|
|
71
73
|
- lib/claude_swarm/orchestrator.rb
|
72
74
|
- lib/claude_swarm/permission_mcp_server.rb
|
73
75
|
- lib/claude_swarm/permission_tool.rb
|
76
|
+
- lib/claude_swarm/process_tracker.rb
|
74
77
|
- lib/claude_swarm/reset_session_tool.rb
|
75
78
|
- lib/claude_swarm/session_info_tool.rb
|
79
|
+
- lib/claude_swarm/session_path.rb
|
76
80
|
- lib/claude_swarm/task_tool.rb
|
77
81
|
- lib/claude_swarm/version.rb
|
78
82
|
- sdk-docs.md
|