schwarm-cli 0.1.2 → 0.1.4
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/README.md +68 -0
- data/lib/schwarm_cli/client/user_messages.rb +1 -1
- data/lib/schwarm_cli/commands/agents.rb +13 -7
- data/lib/schwarm_cli/commands/base.rb +7 -0
- data/lib/schwarm_cli/commands/recurring.rb +4 -4
- data/lib/schwarm_cli/commands/repo_skills.rb +6 -4
- data/lib/schwarm_cli/commands/secrets.rb +7 -4
- data/lib/schwarm_cli/commands/tasks.rb +8 -8
- data/lib/schwarm_cli/hands_off_task.rb +8 -19
- data/lib/schwarm_cli/repository_resolver.rb +65 -0
- data/lib/schwarm_cli/version.rb +1 -1
- data/lib/schwarm_cli.rb +1 -0
- data/schwarm-skill.md +10 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fda5a7c0a0a68a6e07573a5509cadb8ea7ff600f94a3feabf065317c332a9b40
|
|
4
|
+
data.tar.gz: bfd4c31bca63d5862c9df68514c8ab3bdeefb0a1ebbd944c316aeed4522a626d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cf2aac68753184cd3ef7fcd28ff24eb75010b84237f2b661e76a00e1582ead6ad07b0789941f9d3c518bd40eadc34bea14d463bc83e7d69dfb62f68f165920a3
|
|
7
|
+
data.tar.gz: 9bdf3cbb26adecc1f40e90d681e9cb722bd2ae477cd7faa1ac258f3bf690cc77aa1374cb2744a8fe9bb6583b7b328b242f81e80f19ab79afa2dedad23c5d6b55
|
data/README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# schwarm-cli
|
|
2
|
+
|
|
3
|
+
Command-line interface for [Schwarm](https://github.com/getdexter/schwarm) — a
|
|
4
|
+
distributed system that orchestrates Claude Code agents working on tasks in
|
|
5
|
+
parallel. Wraps the Schwarm Public API v2 to manage tasks, repositories,
|
|
6
|
+
skills, agents, and more.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
Requires Ruby >= 4.0.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
gem install schwarm-cli
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
This installs the `schwarm` executable.
|
|
17
|
+
|
|
18
|
+
## Configuration
|
|
19
|
+
|
|
20
|
+
Run the interactive configuration once to point the CLI at your Schwarm
|
|
21
|
+
server and save an API key:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
schwarm configure
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
You'll be prompted for:
|
|
28
|
+
|
|
29
|
+
- **Server URL** (defaults to `https://schwarm.getdexter.net`)
|
|
30
|
+
- **API Key** — create one from your Schwarm server's API Keys page
|
|
31
|
+
|
|
32
|
+
The credentials are saved to `~/.schwarm/config/<env>.json` and the connection
|
|
33
|
+
is tested before saving.
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
List top-level commands:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
schwarm help
|
|
41
|
+
schwarm tree # full command tree
|
|
42
|
+
schwarm version
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Common workflows:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
schwarm repos list
|
|
49
|
+
schwarm tasks list
|
|
50
|
+
schwarm tasks create --repo <REPO_ID> --name "Fix bug" --prompt "..." --status ready
|
|
51
|
+
schwarm tasks show <TASK_ID>
|
|
52
|
+
schwarm tasks handoff --repo <REPO_ID> --name "Continue WIP"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
For the full set of agent-oriented workflows (dispatching tasks, DAGs,
|
|
56
|
+
handoffs, monitoring, messaging), print the bundled skill:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
schwarm skill
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
This is the same document AI agents read to learn how to drive the CLI, and
|
|
63
|
+
it's kept in sync with the gem at [`cli/schwarm-skill.md`](schwarm-skill.md).
|
|
64
|
+
|
|
65
|
+
## Links
|
|
66
|
+
|
|
67
|
+
- [Schwarm repository](https://github.com/getdexter/schwarm)
|
|
68
|
+
- [Source](https://github.com/getdexter/schwarm/tree/main/cli)
|
|
@@ -4,7 +4,7 @@ module SchwarmCli
|
|
|
4
4
|
class Client
|
|
5
5
|
class UserMessages < Resource
|
|
6
6
|
def create(task_id:, content:)
|
|
7
|
-
post("/api/v2/tasks/#{task_id}/messages", {
|
|
7
|
+
post("/api/v2/tasks/#{task_id}/messages", { message: { content: } }).body
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
end
|
|
@@ -4,13 +4,13 @@ module SchwarmCli
|
|
|
4
4
|
module Commands
|
|
5
5
|
class Agents < Base
|
|
6
6
|
desc "list", "List repository agents"
|
|
7
|
-
option :repo, type: :string, desc: "Filter by repository ID"
|
|
7
|
+
option :repo, type: :string, desc: "Filter by repository ID, owner/repo, or GitHub URL"
|
|
8
8
|
option :query, type: :string, desc: "Search by name"
|
|
9
9
|
pagination_options
|
|
10
10
|
def list
|
|
11
11
|
handle_errors do
|
|
12
12
|
data = fetch_paged do |page_params|
|
|
13
|
-
client.agents.list(repository_id: options[:repo], query: options[:query], **page_params)
|
|
13
|
+
client.agents.list(repository_id: resolve_repo(options[:repo]), query: options[:query], **page_params)
|
|
14
14
|
end
|
|
15
15
|
output_list(data, columns: [%w[ID id], %w[NAME name], %w[REPO github_repository_name],
|
|
16
16
|
%w[ENABLED enabled], %w[SCHEDULE schedule]])
|
|
@@ -31,15 +31,12 @@ module SchwarmCli
|
|
|
31
31
|
|
|
32
32
|
desc "create", "Create a repository agent"
|
|
33
33
|
option :name, type: :string, required: true, desc: "Agent name"
|
|
34
|
-
option :repo, type: :string, required: true, desc: "Repository ID"
|
|
34
|
+
option :repo, type: :string, required: true, desc: "Repository ID, owner/repo, or GitHub URL"
|
|
35
35
|
option :prompt, type: :string, required: true, desc: "Agent prompt"
|
|
36
36
|
option :schedule, type: :string, desc: "Cron schedule"
|
|
37
37
|
def create
|
|
38
38
|
handle_errors do
|
|
39
|
-
|
|
40
|
-
attrs[:schedule] = options[:schedule] if options[:schedule]
|
|
41
|
-
|
|
42
|
-
data = client.agents.create(**attrs)
|
|
39
|
+
data = client.agents.create(**create_attrs)
|
|
43
40
|
output_record(data, fields: { "ID" => "id", "Name" => "name", "Enabled" => "enabled" })
|
|
44
41
|
end
|
|
45
42
|
end
|
|
@@ -83,6 +80,15 @@ module SchwarmCli
|
|
|
83
80
|
|
|
84
81
|
private
|
|
85
82
|
|
|
83
|
+
def create_attrs
|
|
84
|
+
attrs = {
|
|
85
|
+
name: options[:name], github_repository_id: resolve_repo(options[:repo]),
|
|
86
|
+
prompt: options[:prompt]
|
|
87
|
+
}
|
|
88
|
+
attrs[:schedule] = options[:schedule] if options[:schedule]
|
|
89
|
+
attrs
|
|
90
|
+
end
|
|
91
|
+
|
|
86
92
|
def update_attrs
|
|
87
93
|
{}.tap do |attrs|
|
|
88
94
|
attrs[:name] = options[:name] if options[:name]
|
|
@@ -25,6 +25,13 @@ module SchwarmCli
|
|
|
25
25
|
@client ||= SchwarmCli::Client.new(url: options[:url], api_key: options[:token])
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
# Resolves --repo input (ID, owner/repo, or GitHub URL) to a schwarm repo ID.
|
|
29
|
+
def resolve_repo(ref)
|
|
30
|
+
SchwarmCli::RepositoryResolver.new(client: client).resolve(ref)
|
|
31
|
+
rescue SchwarmCli::RepositoryResolver::ResolutionError => e
|
|
32
|
+
abort "Error: #{e.message}"
|
|
33
|
+
end
|
|
34
|
+
|
|
28
35
|
def output_list(data, columns:)
|
|
29
36
|
if options[:json]
|
|
30
37
|
Formatters::Json.format(data)
|
|
@@ -4,13 +4,13 @@ module SchwarmCli
|
|
|
4
4
|
module Commands
|
|
5
5
|
class Recurring < Base
|
|
6
6
|
desc "list", "List recurring tasks"
|
|
7
|
-
option :repo, type: :string, desc: "Filter by repository ID"
|
|
7
|
+
option :repo, type: :string, desc: "Filter by repository ID, owner/repo, or GitHub URL"
|
|
8
8
|
option :query, type: :string, desc: "Search by name"
|
|
9
9
|
pagination_options
|
|
10
10
|
def list
|
|
11
11
|
handle_errors do
|
|
12
12
|
data = fetch_paged do |page_params|
|
|
13
|
-
client.recurring.list(repository_id: options[:repo], query: options[:query], **page_params)
|
|
13
|
+
client.recurring.list(repository_id: resolve_repo(options[:repo]), query: options[:query], **page_params)
|
|
14
14
|
end
|
|
15
15
|
output_list(data, columns: [%w[ID id], %w[NAME name], %w[REPO github_repository_name],
|
|
16
16
|
%w[ENABLED enabled], %w[SCHEDULE schedule]])
|
|
@@ -31,13 +31,13 @@ module SchwarmCli
|
|
|
31
31
|
|
|
32
32
|
desc "create", "Create a recurring task"
|
|
33
33
|
option :name, type: :string, required: true, desc: "Task name"
|
|
34
|
-
option :repo, type: :string, required: true, desc: "Repository ID"
|
|
34
|
+
option :repo, type: :string, required: true, desc: "Repository ID, owner/repo, or GitHub URL"
|
|
35
35
|
option :prompt, type: :string, required: true, desc: "Task prompt"
|
|
36
36
|
option :schedule, type: :string, required: true, desc: "Cron schedule"
|
|
37
37
|
def create
|
|
38
38
|
handle_errors do
|
|
39
39
|
attrs = {
|
|
40
|
-
name: options[:name], github_repository_id: options[:repo],
|
|
40
|
+
name: options[:name], github_repository_id: resolve_repo(options[:repo]),
|
|
41
41
|
prompt: options[:prompt], schedule: options[:schedule]
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -4,13 +4,15 @@ module SchwarmCli
|
|
|
4
4
|
module Commands
|
|
5
5
|
class RepoSkills < Base
|
|
6
6
|
desc "list", "List repository-skill associations"
|
|
7
|
-
option :repo, type: :string, desc: "Filter by repository ID"
|
|
7
|
+
option :repo, type: :string, desc: "Filter by repository ID, owner/repo, or GitHub URL"
|
|
8
8
|
option :skill, type: :string, desc: "Filter by skill ID"
|
|
9
9
|
pagination_options
|
|
10
10
|
def list
|
|
11
11
|
handle_errors do
|
|
12
12
|
data = fetch_paged do |page_params|
|
|
13
|
-
client.repo_skills.list(
|
|
13
|
+
client.repo_skills.list(
|
|
14
|
+
repository_id: resolve_repo(options[:repo]), skill_id: options[:skill], **page_params
|
|
15
|
+
)
|
|
14
16
|
end
|
|
15
17
|
output_list(data, columns: [%w[ID id], %w[REPO github_repository_name],
|
|
16
18
|
%w[SKILL skill_name]])
|
|
@@ -29,12 +31,12 @@ module SchwarmCli
|
|
|
29
31
|
end
|
|
30
32
|
|
|
31
33
|
desc "create", "Associate a skill with a repository"
|
|
32
|
-
option :repo, type: :string, required: true, desc: "Repository ID"
|
|
34
|
+
option :repo, type: :string, required: true, desc: "Repository ID, owner/repo, or GitHub URL"
|
|
33
35
|
option :skill, type: :string, required: true, desc: "Skill ID"
|
|
34
36
|
def create
|
|
35
37
|
handle_errors do
|
|
36
38
|
data = client.repo_skills.create(
|
|
37
|
-
github_repository_id: options[:repo], skill_id: options[:skill]
|
|
39
|
+
github_repository_id: resolve_repo(options[:repo]), skill_id: options[:skill]
|
|
38
40
|
)
|
|
39
41
|
output_record(data, fields: { "ID" => "id", "Repository" => "github_repository_id",
|
|
40
42
|
"Skill" => "skill_id" })
|
|
@@ -4,12 +4,12 @@ module SchwarmCli
|
|
|
4
4
|
module Commands
|
|
5
5
|
class Secrets < Base
|
|
6
6
|
desc "list", "List secret files"
|
|
7
|
-
option :repo, type: :string, desc: "Filter by repository ID"
|
|
7
|
+
option :repo, type: :string, desc: "Filter by repository ID, owner/repo, or GitHub URL"
|
|
8
8
|
pagination_options
|
|
9
9
|
def list
|
|
10
10
|
handle_errors do
|
|
11
11
|
data = fetch_paged do |page_params|
|
|
12
|
-
client.secrets.list(repository_id: options[:repo], **page_params)
|
|
12
|
+
client.secrets.list(repository_id: resolve_repo(options[:repo]), **page_params)
|
|
13
13
|
end
|
|
14
14
|
output_list(data, columns: [%w[ID id], %w[NAME name], %w[REPO github_repository_name],
|
|
15
15
|
%w[PATH path]])
|
|
@@ -29,14 +29,17 @@ module SchwarmCli
|
|
|
29
29
|
|
|
30
30
|
desc "create", "Create a secret file"
|
|
31
31
|
option :name, type: :string, required: true, desc: "Secret name"
|
|
32
|
-
option :repo, type: :string, required: true, desc: "Repository ID"
|
|
32
|
+
option :repo, type: :string, required: true, desc: "Repository ID, owner/repo, or GitHub URL"
|
|
33
33
|
option :path, type: :string, required: true, desc: "File path in workspace"
|
|
34
34
|
option :content, type: :string, desc: "Secret content"
|
|
35
35
|
option :file, type: :string, desc: "Read content from file"
|
|
36
36
|
def create
|
|
37
37
|
handle_errors do
|
|
38
38
|
content = read_content
|
|
39
|
-
attrs = {
|
|
39
|
+
attrs = {
|
|
40
|
+
name: options[:name], github_repository_id: resolve_repo(options[:repo]),
|
|
41
|
+
path: options[:path], content:
|
|
42
|
+
}
|
|
40
43
|
|
|
41
44
|
data = client.secrets.create(**attrs)
|
|
42
45
|
output_record(data, fields: { "ID" => "id", "Name" => "name", "Path" => "path" })
|
|
@@ -5,7 +5,7 @@ module SchwarmCli
|
|
|
5
5
|
class Tasks < Base
|
|
6
6
|
desc "list", "List tasks (excludes archived by default)"
|
|
7
7
|
option :status, type: :string, desc: "Filter by status"
|
|
8
|
-
option :repo, type: :string, desc: "Filter by repository ID"
|
|
8
|
+
option :repo, type: :string, desc: "Filter by repository ID, owner/repo, or GitHub URL"
|
|
9
9
|
option :query, type: :string, desc: "Search by name"
|
|
10
10
|
pagination_options
|
|
11
11
|
def list
|
|
@@ -33,7 +33,7 @@ module SchwarmCli
|
|
|
33
33
|
option :name, type: :string, required: true, desc: "Task name"
|
|
34
34
|
option :prompt, type: :string, desc: "Task prompt"
|
|
35
35
|
option :prompt_file, type: :string, desc: "Read prompt from file"
|
|
36
|
-
option :repo, type: :string, desc: "Repository ID"
|
|
36
|
+
option :repo, type: :string, desc: "Repository ID, owner/repo, or GitHub URL"
|
|
37
37
|
option :status, type: :string, desc: "Initial status (draft/waiting)"
|
|
38
38
|
option :template, type: :string, desc: "Template ID"
|
|
39
39
|
option :depends_on, type: :array, desc: "Dependency task IDs"
|
|
@@ -48,7 +48,7 @@ module SchwarmCli
|
|
|
48
48
|
option :name, type: :string, desc: "Task name"
|
|
49
49
|
option :prompt, type: :string, desc: "Task prompt"
|
|
50
50
|
option :prompt_file, type: :string, desc: "Read prompt from file"
|
|
51
|
-
option :repo, type: :string, desc: "Repository ID"
|
|
51
|
+
option :repo, type: :string, desc: "Repository ID, owner/repo, or GitHub URL"
|
|
52
52
|
option :depends_on, type: :array, desc: "Dependency task IDs"
|
|
53
53
|
def update(id)
|
|
54
54
|
handle_errors do
|
|
@@ -117,7 +117,7 @@ module SchwarmCli
|
|
|
117
117
|
desc "handoff", "Hand off the current local branch to schwarm as a ready task"
|
|
118
118
|
option :prompt, type: :string, desc: "Task prompt"
|
|
119
119
|
option :prompt_file, type: :string, desc: "Read prompt from file"
|
|
120
|
-
option :repo, type: :string, desc: "Repository ID (skips origin auto-detect)"
|
|
120
|
+
option :repo, type: :string, desc: "Repository ID, owner/repo, or GitHub URL (skips origin auto-detect)"
|
|
121
121
|
option :name, type: :string, desc: "Task name (defaults to the branch name)"
|
|
122
122
|
def handoff
|
|
123
123
|
prompt = read_prompt
|
|
@@ -125,7 +125,7 @@ module SchwarmCli
|
|
|
125
125
|
|
|
126
126
|
handle_errors do
|
|
127
127
|
result = SchwarmCli::HandsOffTask.new(client: client).call(
|
|
128
|
-
prompt: prompt, repo_override: options[:repo], name_override: options[:name]
|
|
128
|
+
prompt: prompt, repo_override: resolve_repo(options[:repo]), name_override: options[:name]
|
|
129
129
|
)
|
|
130
130
|
print_handoff_result(result)
|
|
131
131
|
end
|
|
@@ -136,7 +136,7 @@ module SchwarmCli
|
|
|
136
136
|
def list_attrs
|
|
137
137
|
exclude_archived = options[:status].nil? && !options[:all]
|
|
138
138
|
{
|
|
139
|
-
status: options[:status], repository_id: options[:repo], query: options[:query],
|
|
139
|
+
status: options[:status], repository_id: resolve_repo(options[:repo]), query: options[:query],
|
|
140
140
|
archived: exclude_archived ? false : nil
|
|
141
141
|
}
|
|
142
142
|
end
|
|
@@ -154,14 +154,14 @@ module SchwarmCli
|
|
|
154
154
|
def create_attrs
|
|
155
155
|
{
|
|
156
156
|
name: options[:name], prompt: read_prompt,
|
|
157
|
-
github_repository_id: options[:repo], status: options[:status],
|
|
157
|
+
github_repository_id: resolve_repo(options[:repo]), status: options[:status],
|
|
158
158
|
task_template_id: options[:template], dependency_ids: options[:depends_on]
|
|
159
159
|
}.compact
|
|
160
160
|
end
|
|
161
161
|
|
|
162
162
|
def update_attrs
|
|
163
163
|
{
|
|
164
|
-
name: options[:name], github_repository_id: options[:repo],
|
|
164
|
+
name: options[:name], github_repository_id: resolve_repo(options[:repo]),
|
|
165
165
|
dependency_ids: options[:depends_on]
|
|
166
166
|
}.compact.tap do |attrs|
|
|
167
167
|
attrs[:prompt] = read_prompt if options[:prompt] || options[:prompt_file]
|
|
@@ -84,28 +84,17 @@ module SchwarmCli
|
|
|
84
84
|
end
|
|
85
85
|
|
|
86
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
|
|
87
|
+
return find_by_id(override) if override
|
|
99
88
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
89
|
+
RepositoryResolver.new(client: @client).resolve_record(origin)
|
|
90
|
+
rescue RepositoryResolver::ResolutionError
|
|
91
|
+
nil
|
|
103
92
|
end
|
|
104
93
|
|
|
105
|
-
def
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
94
|
+
def find_by_id(id)
|
|
95
|
+
@client.repositories.find(id)["data"]
|
|
96
|
+
rescue Faraday::ResourceNotFound
|
|
97
|
+
nil
|
|
109
98
|
end
|
|
110
99
|
|
|
111
100
|
def create_task(repo:, branch:, prompt:, name_override:)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SchwarmCli
|
|
4
|
+
# Turns a user-provided `--repo` reference into a schwarm repository ID.
|
|
5
|
+
#
|
|
6
|
+
# Accepted inputs:
|
|
7
|
+
# - a schwarm repository ID (returned as-is)
|
|
8
|
+
# - "owner/repo"
|
|
9
|
+
# - "https://github.com/owner/repo[.git]"
|
|
10
|
+
# - "git@github.com:owner/repo[.git]"
|
|
11
|
+
class RepositoryResolver
|
|
12
|
+
class ResolutionError < StandardError; end
|
|
13
|
+
|
|
14
|
+
SLUG_PATTERNS = [
|
|
15
|
+
%r{\Ahttps?://github\.com/([^/\s]+/[^/\s]+?)(?:\.git)?/?\z},
|
|
16
|
+
%r{\Agit@github\.com:([^/\s:]+/[^/\s:]+?)(?:\.git)?\z},
|
|
17
|
+
%r{\A([^/\s:]+/[^/\s:]+?)(?:\.git)?\z}
|
|
18
|
+
].freeze
|
|
19
|
+
|
|
20
|
+
def initialize(client:)
|
|
21
|
+
@client = client
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def resolve(ref)
|
|
25
|
+
return nil if blank?(ref)
|
|
26
|
+
|
|
27
|
+
record = resolve_record(ref)
|
|
28
|
+
record ? record["id"] : ref
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Like `resolve`, but returns the full repo record when the ref is looked up
|
|
32
|
+
# via slug/URL. Returns nil when `ref` is blank or already a bare ID (caller
|
|
33
|
+
# should `find` by id directly in that case).
|
|
34
|
+
def resolve_record(ref)
|
|
35
|
+
return nil if blank?(ref)
|
|
36
|
+
|
|
37
|
+
slug = extract_slug(ref.strip)
|
|
38
|
+
slug ? lookup_by_slug(slug, ref) : nil
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def blank?(ref)
|
|
44
|
+
ref.nil? || ref.to_s.strip.empty?
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def extract_slug(ref)
|
|
48
|
+
SLUG_PATTERNS.filter_map { |pat| ref.match(pat)&.[](1) }.first
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def lookup_by_slug(slug, original)
|
|
52
|
+
response = @client.repositories.list(query: slug)
|
|
53
|
+
match = Array(response["data"]).find { |r| slug_from_url(r["url"]) == slug }
|
|
54
|
+
raise ResolutionError, "no schwarm repository matches `#{original}`" if match.nil?
|
|
55
|
+
|
|
56
|
+
match
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def slug_from_url(url)
|
|
60
|
+
return nil if url.nil?
|
|
61
|
+
|
|
62
|
+
url.sub(%r{\Ahttps?://github\.com/}, "").sub(/\Agit@github\.com:/, "").sub(/\.git\z/, "")
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
data/lib/schwarm_cli/version.rb
CHANGED
data/lib/schwarm_cli.rb
CHANGED
|
@@ -4,6 +4,7 @@ require_relative "schwarm_cli/version"
|
|
|
4
4
|
require_relative "schwarm_cli/config"
|
|
5
5
|
require_relative "schwarm_cli/client"
|
|
6
6
|
require_relative "schwarm_cli/git"
|
|
7
|
+
require_relative "schwarm_cli/repository_resolver"
|
|
7
8
|
require_relative "schwarm_cli/hands_off_task"
|
|
8
9
|
require_relative "schwarm_cli/formatters/json"
|
|
9
10
|
require_relative "schwarm_cli/formatters/table"
|
data/schwarm-skill.md
CHANGED
|
@@ -97,8 +97,9 @@ Tasks left as `draft` will never run.
|
|
|
97
97
|
**When:** You've dispatched tasks and want to check on them.
|
|
98
98
|
|
|
99
99
|
**Steps:**
|
|
100
|
-
1. List active tasks:
|
|
100
|
+
1. List active tasks (archived excluded by default):
|
|
101
101
|
```bash
|
|
102
|
+
schwarm tasks list
|
|
102
103
|
schwarm tasks list --status claimed
|
|
103
104
|
schwarm tasks list --status ready
|
|
104
105
|
schwarm tasks list --status error
|
|
@@ -224,3 +225,11 @@ for tasks in a repository.
|
|
|
224
225
|
- When building a DAG, create all tasks as drafts first, then start them all.
|
|
225
226
|
- For long prompts, write them to a file and use `--prompt-file`.
|
|
226
227
|
- Run `schwarm <command> help` for full flag documentation on any command.
|
|
228
|
+
- `schwarm tasks list` excludes archived tasks by default. Use `--all` to
|
|
229
|
+
include them or `--status archived` to see only archived.
|
|
230
|
+
- `schwarm sessions list` shows only active sessions (pending/running) by
|
|
231
|
+
default. Use `--all` to include terminal states.
|
|
232
|
+
- All list commands support `--limit N` and `--page N` for pagination. The
|
|
233
|
+
footer shows "showing N of M · page X of Y".
|
|
234
|
+
- Run `schwarm skill` to print this document — useful for piping into context
|
|
235
|
+
or refreshing your knowledge of the available workflows.
|
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.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vincent Garrigues
|
|
@@ -86,6 +86,7 @@ executables:
|
|
|
86
86
|
extensions: []
|
|
87
87
|
extra_rdoc_files: []
|
|
88
88
|
files:
|
|
89
|
+
- README.md
|
|
89
90
|
- bin/schwarm
|
|
90
91
|
- lib/schwarm_cli.rb
|
|
91
92
|
- lib/schwarm_cli/client.rb
|
|
@@ -121,6 +122,7 @@ files:
|
|
|
121
122
|
- lib/schwarm_cli/formatters/table.rb
|
|
122
123
|
- lib/schwarm_cli/git.rb
|
|
123
124
|
- lib/schwarm_cli/hands_off_task.rb
|
|
125
|
+
- lib/schwarm_cli/repository_resolver.rb
|
|
124
126
|
- lib/schwarm_cli/version.rb
|
|
125
127
|
- schwarm-skill.md
|
|
126
128
|
homepage: https://github.com/getdexter/schwarm
|