schwarm-cli 0.1.1 → 0.1.2
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/lib/schwarm_cli/commands/main.rb +6 -0
- data/lib/schwarm_cli/commands/tasks.rb +27 -0
- data/lib/schwarm_cli/git.rb +18 -0
- data/lib/schwarm_cli/hands_off_task.rb +147 -0
- data/lib/schwarm_cli/version.rb +1 -1
- data/lib/schwarm_cli.rb +2 -0
- data/schwarm-skill.md +226 -0
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 066e7d9d88f9e9d06311933b23308735d9856580de1f2d2dfc320d90f45f6deb
|
|
4
|
+
data.tar.gz: f46de7b54809c3283f14669c0727d308d6e5b8d24066c0e99618c7945b0b044f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 28ae5f67cdd2bbca5a04d1571171252adb36fd7eaccc489f8306038887c52e55c65fea6e348fc5af1ac849f5fd6725be49741d3f68cadfd863897d370fc9ac44
|
|
7
|
+
data.tar.gz: ace4db1afda31bcdc3b4555c7167c3259ec2723ec9a86f6750b9c6eb85ef4dcf26cc71f7e1e636b2882d510cb1e006daf277988851758467412811f445a9765c
|
|
@@ -59,6 +59,12 @@ module SchwarmCli
|
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
map %w[-v --version] => :version
|
|
62
|
+
|
|
63
|
+
desc "skill", "Print the agent skill documenting how AI agents use the Schwarm CLI"
|
|
64
|
+
def skill
|
|
65
|
+
path = File.expand_path("../../../schwarm-skill.md", __dir__)
|
|
66
|
+
puts File.read(path)
|
|
67
|
+
end
|
|
62
68
|
end
|
|
63
69
|
end
|
|
64
70
|
end
|
|
@@ -114,6 +114,23 @@ module SchwarmCli
|
|
|
114
114
|
end
|
|
115
115
|
end
|
|
116
116
|
|
|
117
|
+
desc "handoff", "Hand off the current local branch to schwarm as a ready task"
|
|
118
|
+
option :prompt, type: :string, desc: "Task prompt"
|
|
119
|
+
option :prompt_file, type: :string, desc: "Read prompt from file"
|
|
120
|
+
option :repo, type: :string, desc: "Repository ID (skips origin auto-detect)"
|
|
121
|
+
option :name, type: :string, desc: "Task name (defaults to the branch name)"
|
|
122
|
+
def handoff
|
|
123
|
+
prompt = read_prompt
|
|
124
|
+
abort "Error: --prompt or --prompt-file is required." if prompt.nil? || prompt.strip.empty?
|
|
125
|
+
|
|
126
|
+
handle_errors do
|
|
127
|
+
result = SchwarmCli::HandsOffTask.new(client: client).call(
|
|
128
|
+
prompt: prompt, repo_override: options[:repo], name_override: options[:name]
|
|
129
|
+
)
|
|
130
|
+
print_handoff_result(result)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
117
134
|
private
|
|
118
135
|
|
|
119
136
|
def list_attrs
|
|
@@ -124,6 +141,16 @@ module SchwarmCli
|
|
|
124
141
|
}
|
|
125
142
|
end
|
|
126
143
|
|
|
144
|
+
def print_handoff_result(result)
|
|
145
|
+
if result.success?
|
|
146
|
+
puts "Pushed #{result.branch_name} to origin."
|
|
147
|
+
puts "Task #{result.task_id} created (status: #{result.status})."
|
|
148
|
+
puts " #{result.task_url}"
|
|
149
|
+
else
|
|
150
|
+
abort "Error: #{result.error_message}"
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
127
154
|
def create_attrs
|
|
128
155
|
{
|
|
129
156
|
name: options[:name], prompt: read_prompt,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "open3"
|
|
4
|
+
|
|
5
|
+
module SchwarmCli
|
|
6
|
+
# Minimal git shell-out wrapper.
|
|
7
|
+
#
|
|
8
|
+
# Returns a Result struct for every invocation so callers can pattern-match on
|
|
9
|
+
# +success?+ and surface +stderr+ verbatim when a command fails.
|
|
10
|
+
module Git
|
|
11
|
+
Result = Struct.new(:stdout, :stderr, :success?, keyword_init: true)
|
|
12
|
+
|
|
13
|
+
def self.run(*, chdir: Dir.pwd)
|
|
14
|
+
stdout, stderr, status = Open3.capture3("git", *, chdir: chdir)
|
|
15
|
+
Result.new(stdout: stdout, stderr: stderr, success?: status.success?)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SchwarmCli
|
|
4
|
+
# Runs preflight checks, pushes the current branch, and creates a schwarm
|
|
5
|
+
# task pointing at it. Returns a Result the CLI command prints.
|
|
6
|
+
class HandsOffTask
|
|
7
|
+
Result = Struct.new(:success?, :task_id, :task_url, :branch_name, :status, :error_message,
|
|
8
|
+
keyword_init: true)
|
|
9
|
+
|
|
10
|
+
def initialize(git: SchwarmCli::Git, client: SchwarmCli::Client.new)
|
|
11
|
+
@git = git
|
|
12
|
+
@client = client
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def call(prompt:, repo_override:, name_override:)
|
|
16
|
+
repo, branch, error = run_preflight(repo_override)
|
|
17
|
+
return error if error
|
|
18
|
+
|
|
19
|
+
push_result = @git.run("push", "-u", "origin", "HEAD")
|
|
20
|
+
return failure(push_result.stderr.strip) unless push_result.success?
|
|
21
|
+
|
|
22
|
+
create_task(repo: repo, branch: branch, prompt: prompt, name_override: name_override)
|
|
23
|
+
rescue Faraday::Error => e
|
|
24
|
+
failure(parse_api_error(e))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def run_preflight(repo_override) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
30
|
+
return [nil, nil, failure("not in a git repository")] unless inside_work_tree?
|
|
31
|
+
|
|
32
|
+
origin = origin_url
|
|
33
|
+
unless github_url?(origin)
|
|
34
|
+
return [nil, nil, failure("handoff requires a GitHub `origin` remote (got `#{origin}`)")]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
repo = resolve_repository(origin: origin, override: repo_override)
|
|
38
|
+
return [nil, nil, failure(missing_repo_message(origin, repo_override))] if repo.nil?
|
|
39
|
+
|
|
40
|
+
branch = current_branch
|
|
41
|
+
if branch.empty?
|
|
42
|
+
return [nil, nil, failure("not on a branch (detached HEAD). Check out a branch before handing off.")]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
base_branch = repo["base_branch"]
|
|
46
|
+
if branch == base_branch
|
|
47
|
+
return [nil, nil,
|
|
48
|
+
failure("refusing to hand off the base branch `#{base_branch}`; create a feature branch first.")]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
dirty = status_porcelain
|
|
52
|
+
return [nil, nil, failure("commit or stash your changes before handing off:\n#{dirty}")] unless dirty.empty?
|
|
53
|
+
|
|
54
|
+
[repo, branch, nil]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def missing_repo_message(origin, repo_override)
|
|
58
|
+
if repo_override
|
|
59
|
+
"no schwarm repository with id `#{repo_override}`."
|
|
60
|
+
else
|
|
61
|
+
"no schwarm repository matches origin `#{origin}`. Pass --repo <id> to override."
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def inside_work_tree?
|
|
66
|
+
@git.run("rev-parse", "--is-inside-work-tree").success?
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def origin_url
|
|
70
|
+
result = @git.run("remote", "get-url", "origin")
|
|
71
|
+
result.success? ? result.stdout.strip : ""
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def github_url?(url)
|
|
75
|
+
url.include?("github.com")
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def current_branch
|
|
79
|
+
@git.run("symbolic-ref", "--short", "HEAD").stdout.strip
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def status_porcelain
|
|
83
|
+
@git.run("status", "--porcelain").stdout
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def resolve_repository(origin:, override:)
|
|
87
|
+
if override
|
|
88
|
+
begin
|
|
89
|
+
return @client.repositories.find(override)["data"]
|
|
90
|
+
rescue Faraday::ResourceNotFound
|
|
91
|
+
return nil
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
slug = origin_slug(origin)
|
|
96
|
+
response = @client.repositories.list(query: slug)
|
|
97
|
+
Array(response["data"]).find { |r| normalize_url(r["github_url"]) == normalize_url(origin) }
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def origin_slug(url)
|
|
101
|
+
# Accept both https://github.com/org/repo[.git] and git@github.com:org/repo.git
|
|
102
|
+
url.sub(%r{\Ahttps?://github\.com/}, "").sub(/\Agit@github\.com:/, "").sub(/\.git\z/, "")
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def normalize_url(url)
|
|
106
|
+
return nil if url.nil?
|
|
107
|
+
|
|
108
|
+
url.sub(/\.git\z/, "").sub(/\Agit@github\.com:/, "https://github.com/")
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def create_task(repo:, branch:, prompt:, name_override:)
|
|
112
|
+
response = @client.tasks.create(
|
|
113
|
+
name: name_override || branch,
|
|
114
|
+
branch_name: branch,
|
|
115
|
+
prompt: prompt,
|
|
116
|
+
status: "ready",
|
|
117
|
+
github_repository_id: repo["id"]
|
|
118
|
+
)
|
|
119
|
+
data = response["data"]
|
|
120
|
+
Result.new(
|
|
121
|
+
success?: true,
|
|
122
|
+
task_id: data["id"],
|
|
123
|
+
task_url: task_url_for(data["id"]),
|
|
124
|
+
branch_name: data["branch_name"],
|
|
125
|
+
status: data["status"]
|
|
126
|
+
)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def task_url_for(task_id)
|
|
130
|
+
base = ENV["SCHWARM_URL"] || SchwarmCli::Config.new.url
|
|
131
|
+
"#{base.chomp('/')}/tasks/#{task_id}"
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def parse_api_error(error)
|
|
135
|
+
body = error.response&.dig(:body)
|
|
136
|
+
return error.message unless body.is_a?(String)
|
|
137
|
+
|
|
138
|
+
JSON.parse(body).dig("error", "message") || error.message
|
|
139
|
+
rescue JSON::ParserError
|
|
140
|
+
error.message
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def failure(message)
|
|
144
|
+
Result.new(success?: false, error_message: message)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
data/lib/schwarm_cli/version.rb
CHANGED
data/lib/schwarm_cli.rb
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
require_relative "schwarm_cli/version"
|
|
4
4
|
require_relative "schwarm_cli/config"
|
|
5
5
|
require_relative "schwarm_cli/client"
|
|
6
|
+
require_relative "schwarm_cli/git"
|
|
7
|
+
require_relative "schwarm_cli/hands_off_task"
|
|
6
8
|
require_relative "schwarm_cli/formatters/json"
|
|
7
9
|
require_relative "schwarm_cli/formatters/table"
|
|
8
10
|
require_relative "schwarm_cli/commands/main"
|
data/schwarm-skill.md
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Schwarm
|
|
2
|
+
|
|
3
|
+
Schwarm is a distributed system that orchestrates Claude Code agents working on
|
|
4
|
+
tasks in parallel. Use the `schwarm` CLI to dispatch work to Schwarm from your
|
|
5
|
+
local machine.
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
The `schwarm` CLI is installed and configured (`schwarm configure`).
|
|
10
|
+
|
|
11
|
+
## Key Concepts
|
|
12
|
+
|
|
13
|
+
- **Repository** — a GitHub repo linked to Schwarm. Tasks run against a repo.
|
|
14
|
+
- **Task** — a unit of work. Schwarm creates an isolated git worktree and runs
|
|
15
|
+
Claude Code on it. Tasks have a lifecycle: draft -> ready -> claimed -> archived.
|
|
16
|
+
- **Dependencies** — tasks can depend on other tasks, forming a DAG. A task with
|
|
17
|
+
unresolved dependencies stays in `waiting` until they're all archived.
|
|
18
|
+
- **Node** — a worker machine that picks up `ready` tasks and runs Claude Code.
|
|
19
|
+
|
|
20
|
+
## Workflows
|
|
21
|
+
|
|
22
|
+
### 1. Dispatch a single task
|
|
23
|
+
|
|
24
|
+
**When:** You have a self-contained piece of work to send to Schwarm.
|
|
25
|
+
|
|
26
|
+
**Steps:**
|
|
27
|
+
1. Find the repository ID:
|
|
28
|
+
```bash
|
|
29
|
+
schwarm repos list
|
|
30
|
+
```
|
|
31
|
+
2. Create the task and start it immediately:
|
|
32
|
+
```bash
|
|
33
|
+
schwarm tasks create --repo <REPO_ID> --name "Fix login bug" --prompt "The login form crashes when email is empty. Fix the validation in app/models/user.rb" --status ready
|
|
34
|
+
```
|
|
35
|
+
Use `--prompt-file ./prompt.md` for long prompts.
|
|
36
|
+
3. Check the created task:
|
|
37
|
+
```bash
|
|
38
|
+
schwarm tasks show <TASK_ID>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Watch for:** If you set `--status ready`, the task starts immediately. Omit
|
|
42
|
+
`--status` (defaults to draft) if you want to review before starting.
|
|
43
|
+
|
|
44
|
+
### 1b. Hand off a WIP branch to schwarm
|
|
45
|
+
|
|
46
|
+
**When:** You have work in progress on a local branch and want schwarm to
|
|
47
|
+
continue from where you left off. Schwarm picks up the same branch and
|
|
48
|
+
continues committing to it.
|
|
49
|
+
|
|
50
|
+
**Steps:**
|
|
51
|
+
1. Make sure your working tree is clean (commit or stash local changes).
|
|
52
|
+
2. Hand off from the current branch:
|
|
53
|
+
```bash
|
|
54
|
+
schwarm tasks handoff --prompt "continue the validation logic, add tests"
|
|
55
|
+
```
|
|
56
|
+
Use `--prompt-file ./handoff.md` for long prompts.
|
|
57
|
+
3. Take note of the task ID printed on success; you can monitor it like any
|
|
58
|
+
other task.
|
|
59
|
+
|
|
60
|
+
**Watch for:**
|
|
61
|
+
- The command refuses to hand off the base branch (`main`). Create a feature
|
|
62
|
+
branch first.
|
|
63
|
+
- It refuses if the working tree is dirty — commit or stash first.
|
|
64
|
+
- If another non-archived task already owns this branch name, the command
|
|
65
|
+
will print the conflicting task ID. Archive or reset it first.
|
|
66
|
+
- The repository is auto-detected from `git remote get-url origin`. Use
|
|
67
|
+
`--repo <id>` if you need to override it (e.g. in a fork).
|
|
68
|
+
|
|
69
|
+
### 2. Dispatch a DAG of tasks
|
|
70
|
+
|
|
71
|
+
**When:** You need to break work into multiple steps with ordering constraints.
|
|
72
|
+
|
|
73
|
+
**Steps:**
|
|
74
|
+
1. Create all tasks as drafts first:
|
|
75
|
+
```bash
|
|
76
|
+
schwarm tasks create --repo <REPO_ID> --name "Step 1: Refactor models" --prompt "..."
|
|
77
|
+
schwarm tasks create --repo <REPO_ID> --name "Step 2: Add tests" --prompt "..." --depends-on <STEP1_ID>
|
|
78
|
+
schwarm tasks create --repo <REPO_ID> --name "Step 3: Update docs" --prompt "..." --depends-on <STEP1_ID>
|
|
79
|
+
schwarm tasks create --repo <REPO_ID> --name "Step 4: Integration tests" --prompt "..." --depends-on <STEP2_ID> <STEP3_ID>
|
|
80
|
+
```
|
|
81
|
+
2. Start all tasks — Schwarm cascades automatically:
|
|
82
|
+
```bash
|
|
83
|
+
schwarm tasks start <STEP1_ID>
|
|
84
|
+
schwarm tasks start <STEP2_ID>
|
|
85
|
+
schwarm tasks start <STEP3_ID>
|
|
86
|
+
schwarm tasks start <STEP4_ID>
|
|
87
|
+
```
|
|
88
|
+
Tasks with unresolved dependencies move to `waiting` and become `ready`
|
|
89
|
+
automatically when their dependencies are archived.
|
|
90
|
+
|
|
91
|
+
**Watch for:** You must start all tasks, not just the root. Starting moves
|
|
92
|
+
drafts to `ready` or `waiting` (depending on whether dependencies are resolved).
|
|
93
|
+
Tasks left as `draft` will never run.
|
|
94
|
+
|
|
95
|
+
### 3. Monitor task progress
|
|
96
|
+
|
|
97
|
+
**When:** You've dispatched tasks and want to check on them.
|
|
98
|
+
|
|
99
|
+
**Steps:**
|
|
100
|
+
1. List active tasks:
|
|
101
|
+
```bash
|
|
102
|
+
schwarm tasks list --status claimed
|
|
103
|
+
schwarm tasks list --status ready
|
|
104
|
+
schwarm tasks list --status error
|
|
105
|
+
```
|
|
106
|
+
2. Check a specific task:
|
|
107
|
+
```bash
|
|
108
|
+
schwarm tasks show <TASK_ID>
|
|
109
|
+
```
|
|
110
|
+
Look at Status, Branch, and Error fields.
|
|
111
|
+
3. View agent session logs for debugging:
|
|
112
|
+
```bash
|
|
113
|
+
schwarm sessions list --json
|
|
114
|
+
schwarm sessions show <SESSION_ID>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Watch for:** A task in `claimed` status means a node is actively working on
|
|
118
|
+
it. `ready` means it's waiting for a node to pick it up.
|
|
119
|
+
|
|
120
|
+
### 4. Send a message to a running task
|
|
121
|
+
|
|
122
|
+
**When:** A task is in `claimed` status and you want to give it additional
|
|
123
|
+
instructions or course corrections.
|
|
124
|
+
|
|
125
|
+
**Steps:**
|
|
126
|
+
1. Send the message:
|
|
127
|
+
```bash
|
|
128
|
+
schwarm tasks message <TASK_ID> --content "Also fix the validation for the password field"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Watch for:** Messages are delivered asynchronously via the node's polling loop.
|
|
132
|
+
The agent will see the message on its next check. Only works for `claimed` tasks.
|
|
133
|
+
|
|
134
|
+
### 5. Handle failures
|
|
135
|
+
|
|
136
|
+
**When:** A task has moved to `error` status.
|
|
137
|
+
|
|
138
|
+
**Steps:**
|
|
139
|
+
1. Check what went wrong:
|
|
140
|
+
```bash
|
|
141
|
+
schwarm tasks show <TASK_ID>
|
|
142
|
+
```
|
|
143
|
+
The Error field shows the failure reason.
|
|
144
|
+
2. Decide: retry or reset.
|
|
145
|
+
- **Retry** — re-runs the task from where it left off (same worktree):
|
|
146
|
+
```bash
|
|
147
|
+
schwarm tasks retry <TASK_ID>
|
|
148
|
+
```
|
|
149
|
+
- **Reset** — moves the task back to `draft` for a fresh start:
|
|
150
|
+
```bash
|
|
151
|
+
schwarm tasks reset <TASK_ID>
|
|
152
|
+
schwarm tasks start <TASK_ID>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Watch for:** Use `retry` for transient failures (node crash, timeout). Use
|
|
156
|
+
`reset` when you need to change the prompt or start clean. After reset, you
|
|
157
|
+
must `start` again.
|
|
158
|
+
|
|
159
|
+
### 6. Discover repos and templates
|
|
160
|
+
|
|
161
|
+
**When:** Before creating tasks, you need to know what's available.
|
|
162
|
+
|
|
163
|
+
**Steps:**
|
|
164
|
+
1. List repositories:
|
|
165
|
+
```bash
|
|
166
|
+
schwarm repos list
|
|
167
|
+
```
|
|
168
|
+
2. List task templates (pre-made prompts):
|
|
169
|
+
```bash
|
|
170
|
+
schwarm templates list
|
|
171
|
+
schwarm templates show <TEMPLATE_ID>
|
|
172
|
+
```
|
|
173
|
+
3. Create a task from a template:
|
|
174
|
+
```bash
|
|
175
|
+
schwarm tasks create --repo <REPO_ID> --name "Apply template" --template <TEMPLATE_ID> --status ready
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### 7. Manage recurring tasks
|
|
179
|
+
|
|
180
|
+
**When:** You want a task to run on a schedule (e.g., nightly tests).
|
|
181
|
+
|
|
182
|
+
**Steps:**
|
|
183
|
+
1. Create a recurring task:
|
|
184
|
+
```bash
|
|
185
|
+
schwarm recurring create --repo <REPO_ID> --name "Nightly tests" --schedule "0 0 * * *" --prompt "Run the full test suite and fix any failures"
|
|
186
|
+
```
|
|
187
|
+
2. Toggle on/off:
|
|
188
|
+
```bash
|
|
189
|
+
schwarm recurring toggle <ID>
|
|
190
|
+
```
|
|
191
|
+
3. List existing recurring tasks:
|
|
192
|
+
```bash
|
|
193
|
+
schwarm recurring list --repo <REPO_ID>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### 8. Configure skills and agents
|
|
197
|
+
|
|
198
|
+
**When:** You want to customize what skills or agent instructions are available
|
|
199
|
+
for tasks in a repository.
|
|
200
|
+
|
|
201
|
+
**Steps:**
|
|
202
|
+
1. List available skills:
|
|
203
|
+
```bash
|
|
204
|
+
schwarm skills list
|
|
205
|
+
```
|
|
206
|
+
2. Attach a skill to a repository:
|
|
207
|
+
```bash
|
|
208
|
+
schwarm repo-skills create --repo <REPO_ID> --skill <SKILL_ID>
|
|
209
|
+
```
|
|
210
|
+
3. Create a repository agent (custom instructions for all tasks in a repo):
|
|
211
|
+
```bash
|
|
212
|
+
schwarm agents create --repo <REPO_ID> --name "Code style" --prompt "Always follow the project's eslint config"
|
|
213
|
+
```
|
|
214
|
+
4. List agents for a repo:
|
|
215
|
+
```bash
|
|
216
|
+
schwarm agents list --repo <REPO_ID>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Tips
|
|
220
|
+
|
|
221
|
+
- Use `--json` when parsing output programmatically.
|
|
222
|
+
- Check task status before taking actions (e.g., only `retry` works on `error`
|
|
223
|
+
tasks, only `start` works on `draft` tasks).
|
|
224
|
+
- When building a DAG, create all tasks as drafts first, then start them all.
|
|
225
|
+
- For long prompts, write them to a file and use `--prompt-file`.
|
|
226
|
+
- Run `schwarm <command> help` for full flag documentation on any command.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: schwarm-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vincent Garrigues
|
|
@@ -119,7 +119,10 @@ files:
|
|
|
119
119
|
- lib/schwarm_cli/config.rb
|
|
120
120
|
- lib/schwarm_cli/formatters/json.rb
|
|
121
121
|
- lib/schwarm_cli/formatters/table.rb
|
|
122
|
+
- lib/schwarm_cli/git.rb
|
|
123
|
+
- lib/schwarm_cli/hands_off_task.rb
|
|
122
124
|
- lib/schwarm_cli/version.rb
|
|
125
|
+
- schwarm-skill.md
|
|
123
126
|
homepage: https://github.com/getdexter/schwarm
|
|
124
127
|
licenses:
|
|
125
128
|
- MIT
|