bullswarm 0.10.2 → 0.10.3
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.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +9 -0
- package/README.md +9 -0
- package/package.json +1 -1
- package/skill/SKILL.md +4 -0
- package/src/cli.js +6 -0
- package/src/help.js +150 -0
package/AGENTS.md
CHANGED
|
@@ -37,7 +37,7 @@ content. Published as `bullswarm` on npm.
|
|
|
37
37
|
## Development
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
|
-
npm test #
|
|
40
|
+
npm test # 235 tests, no network needed (meters read from cache)
|
|
41
41
|
node bin/bullswarm.js doctor --json # readiness report
|
|
42
42
|
node bin/bullswarm.js workflow list # discover workflows
|
|
43
43
|
node bin/bullswarm.js workflow runs # ongoing workflow instances
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# bullswarm changelog
|
|
2
2
|
|
|
3
|
+
## 0.10.3 — contextual help everywhere
|
|
4
|
+
|
|
5
|
+
- Added side-effect-free `-h` / `--help` handling for the top-level CLI and
|
|
6
|
+
every command and nested subcommand, including workflow drafts, run history,
|
|
7
|
+
approvals, actions, integrations, and strategy policy controls.
|
|
8
|
+
- Added a centralized command help tree so contextual help is consistent and
|
|
9
|
+
intercepted before setup, provider discovery, state writes, or destructive
|
|
10
|
+
command execution.
|
|
11
|
+
|
|
3
12
|
## 0.10.2 — cross-agent skill integration
|
|
4
13
|
|
|
5
14
|
- Added explicit `bullswarm integrate status|install|remove` support for Codex,
|
package/README.md
CHANGED
|
@@ -5,6 +5,15 @@ orchestrator, build and expand the plan, route bounded worker actions by quota,
|
|
|
5
5
|
verify the result, and finish without an initiating agent authoring a graph.
|
|
6
6
|
Every delegate output is judged by content before it counts.
|
|
7
7
|
|
|
8
|
+
Every command and nested subcommand supports contextual `-h` / `--help`
|
|
9
|
+
without initializing state or executing the command:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
bullswarm --help
|
|
13
|
+
bullswarm workflow run --help
|
|
14
|
+
bullswarm workflow draft step add --help
|
|
15
|
+
```
|
|
16
|
+
|
|
8
17
|
## The doctrine (non-negotiable)
|
|
9
18
|
|
|
10
19
|
1. **Judge by CONTENT, not exit code.** Every delegate CLI can exit 0 while
|
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -10,6 +10,10 @@ CLI subscription has the most quota headroom. Every delegate output is
|
|
|
10
10
|
judged by **content**, not exit code. A non-zero exit is never a success; a
|
|
11
11
|
`verified` output is.
|
|
12
12
|
|
|
13
|
+
Every command and nested subcommand supports side-effect-free `-h` / `--help`.
|
|
14
|
+
When a flag or argument is uncertain, inspect the exact surface before acting,
|
|
15
|
+
for example `bullswarm workflow draft step add --help`.
|
|
16
|
+
|
|
13
17
|
This skill is registered globally by:
|
|
14
18
|
|
|
15
19
|
```bash
|
package/src/cli.js
CHANGED
|
@@ -17,6 +17,7 @@ import { release } from './lib/release.js';
|
|
|
17
17
|
import { cmdWorkflow } from './workflow/cli.js';
|
|
18
18
|
import { cmdStrategy, maybeRefreshStrategy } from './strategy-cli.js';
|
|
19
19
|
import { cmdIntegrate, installIntegration } from './integrate.js';
|
|
20
|
+
import { helpForArgs } from './help.js';
|
|
20
21
|
|
|
21
22
|
export function getBullswarmDir() {
|
|
22
23
|
const h = process.env.BULLSWARM_HOME?.trim();
|
|
@@ -394,6 +395,11 @@ async function cmdDoctor(opts) {
|
|
|
394
395
|
// --- main ---------------------------------------------------------------------
|
|
395
396
|
|
|
396
397
|
export async function main(argv) {
|
|
398
|
+
const help = helpForArgs(argv);
|
|
399
|
+
if (help) {
|
|
400
|
+
console.log(help);
|
|
401
|
+
return 0;
|
|
402
|
+
}
|
|
397
403
|
const [verb, ...rest] = argv;
|
|
398
404
|
const opts = parseArgs(rest);
|
|
399
405
|
const { ensureSetup } = await import('./setup.js');
|
package/src/help.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// Central CLI help tree. Help is resolved before setup or command dispatch so
|
|
2
|
+
// `--help` is side-effect free even for commands that normally touch state.
|
|
3
|
+
|
|
4
|
+
const top = `Usage: bullswarm <command> [options]
|
|
5
|
+
|
|
6
|
+
Route bounded work across coding-agent subscriptions and verify the result.
|
|
7
|
+
|
|
8
|
+
Commands:
|
|
9
|
+
setup discover and configure installed coding agents
|
|
10
|
+
integrate register Bullswarm guidance with Codex, Claude, and Grok
|
|
11
|
+
run dispatch one bounded task
|
|
12
|
+
health re-judge saved delegate outputs
|
|
13
|
+
pools show routing pools, meters, and quarantine state
|
|
14
|
+
strategy discover models and manage tier assignments
|
|
15
|
+
doctor report installation readiness
|
|
16
|
+
workflow create, execute, observe, and audit workflows
|
|
17
|
+
runs alias for workflow runs
|
|
18
|
+
version print the installed version
|
|
19
|
+
release create a version commit and tag
|
|
20
|
+
|
|
21
|
+
Run bullswarm <command> --help for command-specific help.`;
|
|
22
|
+
|
|
23
|
+
const leaf = (usage, body = '') => `Usage: ${usage}${body ? `\n\n${body}` : ''}`;
|
|
24
|
+
|
|
25
|
+
const HELP = {
|
|
26
|
+
_text: top,
|
|
27
|
+
setup: { _text: leaf('bullswarm setup [--yes] [--integrate] [--agents <list>] [--json]',
|
|
28
|
+
'Discover installed agent CLIs and initialize routing. Without --yes on a TTY, opens the interactive wizard.') },
|
|
29
|
+
integrate: {
|
|
30
|
+
_text: leaf('bullswarm integrate <status|install|remove|retire-legacy> [options]',
|
|
31
|
+
'Manage the canonical Bullswarm skill and recursion-safe global awareness rules.'),
|
|
32
|
+
status: { _text: leaf('bullswarm integrate status [--agents codex,claude,grok] [--json]') },
|
|
33
|
+
install: { _text: leaf('bullswarm integrate install [--agents codex,claude,grok] --yes [--json]') },
|
|
34
|
+
remove: { _text: leaf('bullswarm integrate remove [--agents codex,claude,grok] --yes [--json]') },
|
|
35
|
+
'retire-legacy': { _text: leaf('bullswarm integrate retire-legacy --yes [--json]',
|
|
36
|
+
'Recoverably archive the retired Claude offload skill.') },
|
|
37
|
+
},
|
|
38
|
+
run: { _text: leaf('bullswarm run --lane <analyze|build|chore> --add-dir <dir> (--task-file <file> | --prompt <text>) [options]',
|
|
39
|
+
'Options: --effort <high|medium|low>, --timeout <seconds>, --json. Routes one task and verifies its content.') },
|
|
40
|
+
health: { _text: leaf('bullswarm health [--json]', 'Re-judge saved outputs and report failed gates or quarantine clusters.') },
|
|
41
|
+
pools: { _text: leaf('bullswarm pools [--force] [--json]', 'Show live meter, quota-surplus, burst-gate, and quarantine state.') },
|
|
42
|
+
doctor: { _text: leaf('bullswarm doctor [--json]', 'Self-initialize if needed and report readiness without dispatching work.') },
|
|
43
|
+
version: { _text: leaf('bullswarm version') },
|
|
44
|
+
release: { _text: leaf('bullswarm release <patch|minor|major> [--dry-run]') },
|
|
45
|
+
strategy: {
|
|
46
|
+
_text: leaf('bullswarm strategy <command> [options]',
|
|
47
|
+
'Commands: refresh, apply, show, assign, clear-assignment, set-subscription, auto.'),
|
|
48
|
+
refresh: { _text: leaf('bullswarm strategy refresh [--json] [--apply --yes] [--refresh-hours <n>]') },
|
|
49
|
+
recommend: { _text: leaf('bullswarm strategy recommend [--json] [--apply --yes]', 'Alias for strategy refresh.') },
|
|
50
|
+
apply: { _text: leaf('bullswarm strategy apply --yes [--refresh-hours <n>]') },
|
|
51
|
+
show: { _text: leaf('bullswarm strategy show [--json]') },
|
|
52
|
+
assign: { _text: leaf('bullswarm strategy assign <high|medium|low> --pool <pool> --model <model>') },
|
|
53
|
+
'clear-assignment': { _text: leaf('bullswarm strategy clear-assignment <high|medium|low>') },
|
|
54
|
+
'set-subscription': { _text: leaf('bullswarm strategy set-subscription <pool> [--plan <name>] [--monthly-usd <n|unknown>] [--included-usd <n|unknown>] [--quota-window <name>]') },
|
|
55
|
+
auto: {
|
|
56
|
+
_text: leaf('bullswarm strategy auto <status|off> [--yes]'),
|
|
57
|
+
status: { _text: leaf('bullswarm strategy auto status') },
|
|
58
|
+
off: { _text: leaf('bullswarm strategy auto off --yes') },
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
workflow: {
|
|
62
|
+
_text: leaf('bullswarm workflow <command> [options]',
|
|
63
|
+
'Commands: goal, run, validate, list, draft, runs, capabilities, inspect, tui, watch, events, steer, action, approval.'),
|
|
64
|
+
goal: { _text: leaf('bullswarm workflow goal "<goal>" [--cwd <dir>] [--detach] [--json] [planning options]',
|
|
65
|
+
'Use --resume <shortId|runId> to resume. Planning options include --orchestrator, --max-agents, --max-expansion-rounds, --max-actions, --max-items-per-expansion, --max-workflow-seconds, --concurrency, and --retry-attempts.') },
|
|
66
|
+
run: { _text: leaf('bullswarm workflow run <file-or-name> [--input k=v]... [--resume <shortId|runId>] [--json] [--quiet]') },
|
|
67
|
+
validate: { _text: leaf('bullswarm workflow validate <file-or-name>') },
|
|
68
|
+
list: { _text: leaf('bullswarm workflow list [--json]') },
|
|
69
|
+
capabilities: { _text: leaf('bullswarm workflow capabilities [--json]') },
|
|
70
|
+
inspect: { _text: leaf('bullswarm workflow inspect <file-or-name>') },
|
|
71
|
+
tui: { _text: leaf('bullswarm workflow tui [<runId>] [--json] [--all] [--show <runId>] [--cancel <runId>]') },
|
|
72
|
+
watch: { _text: leaf('bullswarm workflow watch <runId> [--interval <seconds>] [--heartbeat <seconds>] [--jsonl] [--once]') },
|
|
73
|
+
events: { _text: leaf('bullswarm workflow events <runId> [--after <sequence>] [--json]') },
|
|
74
|
+
steer: { _text: leaf('bullswarm workflow steer <runId> --message <guidance> [--json]') },
|
|
75
|
+
action: {
|
|
76
|
+
_text: leaf('bullswarm workflow action <command> ...', 'Commands: show.'),
|
|
77
|
+
show: { _text: leaf('bullswarm workflow action show <runId> <actionId> [--json]') },
|
|
78
|
+
},
|
|
79
|
+
approval: {
|
|
80
|
+
_text: leaf('bullswarm workflow approval <approve|reject> <runId> [--json]'),
|
|
81
|
+
approve: { _text: leaf('bullswarm workflow approval approve <runId> [--json]') },
|
|
82
|
+
reject: { _text: leaf('bullswarm workflow approval reject <runId> [--json]') },
|
|
83
|
+
},
|
|
84
|
+
runs: runsHelp(),
|
|
85
|
+
draft: draftHelp(),
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Top-level `runs` is a documented alias and gets the same nested help.
|
|
90
|
+
HELP.runs = HELP.workflow.runs;
|
|
91
|
+
|
|
92
|
+
export const HELP_PATHS = Object.freeze(collectPaths(HELP));
|
|
93
|
+
|
|
94
|
+
export function helpForArgs(argv) {
|
|
95
|
+
const wantsHelp = argv.includes('--help') || argv.includes('-h') || argv[0] === 'help';
|
|
96
|
+
if (!wantsHelp) return null;
|
|
97
|
+
const tokens = argv[0] === 'help' ? argv.slice(1) : argv;
|
|
98
|
+
let node = HELP;
|
|
99
|
+
for (const token of tokens) {
|
|
100
|
+
if (token === '--help' || token === '-h' || token.startsWith('-')) continue;
|
|
101
|
+
if (!node[token]) break;
|
|
102
|
+
node = node[token];
|
|
103
|
+
}
|
|
104
|
+
return node._text ?? HELP._text;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function runsHelp() {
|
|
108
|
+
return {
|
|
109
|
+
_text: leaf('bullswarm workflow runs [list] [--all|--historical] [--name <workflow>] [--since <time>] [--until <time>] [--limit <n>] [--json]',
|
|
110
|
+
'Commands: show <id>, delete <id> --yes. Time filters use the workflow initiation timestamp.'),
|
|
111
|
+
list: { _text: leaf('bullswarm workflow runs list [--all|--historical] [--name <workflow>] [--since <time>] [--until <time>] [--limit <n>] [--json]') },
|
|
112
|
+
show: { _text: leaf('bullswarm workflow runs show <shortId|runId> [--json]') },
|
|
113
|
+
delete: { _text: leaf('bullswarm workflow runs delete <shortId|runId> --yes [--force] [--json]') },
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function draftHelp() {
|
|
118
|
+
return {
|
|
119
|
+
_text: leaf('bullswarm workflow draft <command> [options]',
|
|
120
|
+
'Commands: create, show, list, phase, step, set, validate, export, delete, run.'),
|
|
121
|
+
create: { _text: leaf('bullswarm workflow draft create <name> [--description <text>] [--input k=v]... [--required <keys>] [--json]') },
|
|
122
|
+
show: { _text: leaf('bullswarm workflow draft show <name> [--json]') },
|
|
123
|
+
list: { _text: leaf('bullswarm workflow draft list [--json]') },
|
|
124
|
+
phase: {
|
|
125
|
+
_text: leaf('bullswarm workflow draft phase <add|remove> <draft> <phase> [--json]'),
|
|
126
|
+
add: { _text: leaf('bullswarm workflow draft phase add <draft> <phase> [--json]') },
|
|
127
|
+
remove: { _text: leaf('bullswarm workflow draft phase remove <draft> <phase> [--json]') },
|
|
128
|
+
},
|
|
129
|
+
step: {
|
|
130
|
+
_text: leaf('bullswarm workflow draft step <add|remove|set> <draft> <phase> <step-id> [options]'),
|
|
131
|
+
add: { _text: leaf('bullswarm workflow draft step add <draft> <phase> <step-id> [--type <run|fanout|verify|decide>] [--lane <lane>] [--prompt <text>] [step options]') },
|
|
132
|
+
remove: { _text: leaf('bullswarm workflow draft step remove <draft> <phase> <step-id> [--json]') },
|
|
133
|
+
set: { _text: leaf('bullswarm workflow draft step set <draft> <phase> <step-id> <field> --value <text> [--json]') },
|
|
134
|
+
},
|
|
135
|
+
set: { _text: leaf('bullswarm workflow draft set <draft> <field> --value <text> [--json]') },
|
|
136
|
+
validate: { _text: leaf('bullswarm workflow draft validate <name> [--json]') },
|
|
137
|
+
export: { _text: leaf('bullswarm workflow draft export <name> <out-file> [--json]') },
|
|
138
|
+
delete: { _text: leaf('bullswarm workflow draft delete <name> --yes [--json]') },
|
|
139
|
+
run: { _text: leaf('bullswarm workflow draft run <name> [--input k=v]... [--resume <shortId|runId>] [--json] [--quiet]') },
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function collectPaths(node, prefix = []) {
|
|
144
|
+
const paths = prefix.length ? [prefix] : [[]];
|
|
145
|
+
for (const [name, child] of Object.entries(node)) {
|
|
146
|
+
if (name === '_text') continue;
|
|
147
|
+
paths.push(...collectPaths(child, [...prefix, name]));
|
|
148
|
+
}
|
|
149
|
+
return paths;
|
|
150
|
+
}
|