cyberlegion 1.2.0 → 1.4.0
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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.plugin/pins.json +1 -1
- package/bin/cyberlegion +5 -0
- package/dist/cli.mjs +560 -97
- package/dist/index.d.mts +36 -3
- package/dist/index.mjs +177 -37
- package/hooks/hooks.json +1 -1
- package/package.json +2 -2
- package/plugin.json +1 -1
- package/readme.md +5 -0
- package/skills/dispatch-governance/SKILL.md +1 -1
- package/skills/dispatch-governance/scripts/cyberlegion.mjs +1 -1
- package/skills/init-cyberlegion/README.md +6 -4
- package/skills/init-cyberlegion/SKILL.md +141 -15
- package/skills/init-cyberlegion/scripts/cyberlegion.mjs +1 -1
- package/skills/legate/SKILL.md +1 -1
- package/skills/legate/scripts/cyberlegion.mjs +1 -1
- package/skills/manage-inbox/SKILL.md +1 -1
- package/skills/manage-inbox/scripts/cyberlegion.mjs +1 -1
- package/skills/relay-governance/SKILL.md +1 -1
- package/skills/relay-governance/scripts/cyberlegion.mjs +1 -1
- package/skills/subagent-backend-governance/SKILL.md +1 -1
- package/skills/subagent-backend-governance/scripts/cyberlegion.mjs +1 -1
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: init-cyberlegion
|
|
3
|
-
description: "Use this skill to set up or onboard cyberlegion in this session or repo — probe the environment, register the mail-surfacing hook,
|
|
3
|
+
description: "Use this skill to set up or onboard cyberlegion in this session or repo — probe the environment, register the mail-surfacing hook, (in a root session, on your yes) allow the cyberlegion CLI in Claude Code's permissions, and bind this pane as the durable legate owner inbox. Triggers: 'set up cyberlegion', 'onboard the legion', 'register the cyberlegion surfacing hook', 'make this pane my main legion inbox', 'get cyberlegion working in this repo'. Not for spawning/messaging/dispatching a peer (that is legate), reading or acking owner mail (that is manage-inbox), or unrelated init like a git repo, npm package, or commit discipline."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# init-cyberlegion
|
|
7
7
|
|
|
8
8
|
The onboarding front door to the Legion — a thin, user-invocable wrapper that walks a session through
|
|
9
9
|
getting `cyberlegion` working in this repo: probe the environment, register the surfacing hook, and
|
|
10
|
-
(only in a root session, only on an explicit yes)
|
|
10
|
+
(only in a root session, only on an explicit yes) allow the `cyberlegion` CLI in Claude Code's
|
|
11
|
+
permissions and bind this pane as the durable `legate` owner inbox, offering that owner a **home** to
|
|
12
|
+
wake in when nobody is standing in for it.
|
|
11
13
|
It is a **thin wrapper**: every mechanic is a `cyberlegion` CLI call. The skill holds the *conversation
|
|
12
14
|
and the judgment* — is this a root session? should we ask to bind? what does the environment look
|
|
13
15
|
like? — the CLI holds all the *mechanism*.
|
|
@@ -37,21 +39,54 @@ node scripts/cyberlegion.mjs mux doctor
|
|
|
37
39
|
```
|
|
38
40
|
|
|
39
41
|
Run this **before** touching the hook or any identity. It reports `harness`, `mux`, `pane`,
|
|
40
|
-
`hubRoot`, and `
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
`hubRoot`, `selfId`, and `permissionRule` — read it to learn the environment (is there a
|
|
43
|
+
multiplexer? a pane? does Claude Code allow the CLI?) and to detect root vs spawned (see step 3).
|
|
44
|
+
Narrate a short, grounded summary of what it found, including the permission rule (e.g. "permission
|
|
45
|
+
rule: missing") — do not invent facts the probe did not report.
|
|
43
46
|
|
|
44
|
-
|
|
47
|
+
`permissionRule` is whether Claude Code's user settings carry a `permissions.allow` rule covering
|
|
48
|
+
`cyberlegion`: `present`, `missing`, `unreadable`, or `n/a` (not Claude Code). Without it, Claude
|
|
49
|
+
Code's auto-mode classifier can deny a unit's `cyberlegion mail send` as *External System Writes*,
|
|
50
|
+
so a unit that finished its work cannot report back. Step 2 handles it.
|
|
51
|
+
|
|
52
|
+
### 2. Register the surfacing hook (and, on a yes, allow the CLI)
|
|
45
53
|
|
|
46
54
|
```bash
|
|
47
55
|
node scripts/cyberlegion.mjs init --pin <version>
|
|
48
56
|
```
|
|
49
57
|
|
|
58
|
+
**The permission rule — ask first, never silent.** When the probe reported `permissionRule: missing`
|
|
59
|
+
in a **root** session with a broader onboarding intent (see step 3 for how root is derived), ask
|
|
60
|
+
before running `init`, e.g.:
|
|
61
|
+
|
|
62
|
+
> "Claude Code has no permission rule for `cyberlegion`, so its auto-mode classifier can block a
|
|
63
|
+
> unit's `cyberlegion mail send` and the unit's report never reaches you. Add
|
|
64
|
+
> `Bash(cyberlegion *)` to `permissions.allow` in your Claude Code user settings
|
|
65
|
+
> (`~/.claude/settings.json`)? It is merged into your existing list."
|
|
66
|
+
|
|
67
|
+
On an explicit yes, add `--allow-cli` to the `init` call — the CLI merges the rule into the existing
|
|
68
|
+
array, never replaces it, and refuses to rewrite a settings file it cannot parse:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
node scripts/cyberlegion.mjs init --pin <version> --allow-cli
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
On a decline, run `init` without `--allow-cli` and say the rule stays missing. Never edit the
|
|
75
|
+
settings file by hand. Do not ask, and do not pass `--allow-cli`, when:
|
|
76
|
+
|
|
77
|
+
- the rule is `present` or `n/a` — nothing to do;
|
|
78
|
+
- the rule is `unreadable` — tell the user the settings file could not be parsed and must be fixed
|
|
79
|
+
by hand; `--allow-cli` would refuse it;
|
|
80
|
+
- this is a **spawned** unit — it never changes the user's global settings; report the rule as
|
|
81
|
+
missing in its result so the human can run this skill from a root session;
|
|
82
|
+
- the request is hook-only — report the rule's state and stop (see step 3).
|
|
83
|
+
|
|
50
84
|
Pass `--pin <version>` with the version resolved above so a project hook's npx fallback fetches the
|
|
51
85
|
shipped version; **omit `--pin`** when the map yielded no version.
|
|
52
86
|
|
|
53
87
|
Auto-detect is the default — no `--agent` flag. Pass `--agent <name>` **only** when `mux doctor` could
|
|
54
|
-
not auto-detect the harness, or the user named one explicitly (it composes with `--pin`
|
|
88
|
+
not auto-detect the harness, or the user named one explicitly (it composes with `--pin` and
|
|
89
|
+
`--allow-cli`):
|
|
55
90
|
|
|
56
91
|
```bash
|
|
57
92
|
node scripts/cyberlegion.mjs init --pin <version> --agent <name>
|
|
@@ -60,7 +95,9 @@ node scripts/cyberlegion.mjs init --pin <version> --agent <name>
|
|
|
60
95
|
This step is **idempotent**: if the hook is already registered, `init` reports `already present` —
|
|
61
96
|
that is a clean no-op, never a duplicate registration and never an error. On Claude Code and Codex the
|
|
62
97
|
plugin ships the hook itself, so `init` reports `provided by plugin` (or `removed project hook` when it
|
|
63
|
-
cleared one an earlier `init` wrote); both mean the hook is set up.
|
|
98
|
+
cleared one an earlier `init` wrote); both mean the hook is set up. On Claude Code its summary also
|
|
99
|
+
reports `permission rule <state>` — `added` after `--allow-cli`, `present` when a covering rule was
|
|
100
|
+
already there.
|
|
64
101
|
|
|
65
102
|
### 3. Detect root vs spawned — derived, never asked
|
|
66
103
|
|
|
@@ -72,7 +109,18 @@ has it set. Derive this from the probe — never ask the user to declare it.
|
|
|
72
109
|
- **A hook-only request in a root session** ("just register the surfacing hook") — also stop here.
|
|
73
110
|
Registering the hook satisfies the ask; do not proceed to the bind offer unasked.
|
|
74
111
|
- **Root session, broader onboarding intent, no `legate` owner bound yet** — continue to step 4.
|
|
75
|
-
- **Root session where a `legate` owner is already bound** —
|
|
112
|
+
- **Root session where a `legate` owner is already bound** — do not re-ask the bind and do not mint a
|
|
113
|
+
second owner; go to step 6 to offer a home. A bind request ("make this pane my main legion inbox")
|
|
114
|
+
made when the owner already exists lands here too.
|
|
115
|
+
|
|
116
|
+
To tell whether the owner exists, list the standing owners:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
node scripts/cyberlegion.mjs unit register --standing --format json
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
A record with `"handle": "legate"` is the owner. Its `home` field says where its presence is
|
|
123
|
+
spawned (`dir` plus `harness` or `agent`); no `home` field means it has none.
|
|
76
124
|
|
|
77
125
|
### 4. Ask before binding — never silent
|
|
78
126
|
|
|
@@ -85,27 +133,105 @@ Only a root session with no `legate` owner bound is offered the bind. Ask plainl
|
|
|
85
133
|
- **User agrees explicitly** — proceed to step 5.
|
|
86
134
|
- **Already bound** — never reach this ask (see step 3).
|
|
87
135
|
|
|
88
|
-
### 5. On an explicit yes — mint and bind
|
|
136
|
+
### 5. On an explicit yes — offer a home, then mint and bind
|
|
137
|
+
|
|
138
|
+
**No multiplexer or pane in the probe** → skip the home: mint bare and continue (see *Non-mux parity*
|
|
139
|
+
below). `unit claim` refuses a caller with no multiplexer, and a home is spawned the same way
|
|
140
|
+
`unit spawn` opens a session.
|
|
141
|
+
|
|
142
|
+
Otherwise, before minting, explain the presence and ask for a home. Mail to the `legate` owner
|
|
143
|
+
reaches whoever stands in for it, in this order:
|
|
144
|
+
|
|
145
|
+
1. **A live presence** — a session that ran `unit claim legate`. The claim holds until another
|
|
146
|
+
session claims the owner, until `unit claim legate --clear` unbinds it, or until that session
|
|
147
|
+
exits.
|
|
148
|
+
2. **The home** — when nobody holds the presence, a session is started in the home folder, bound as
|
|
149
|
+
the presence, and woken to read the owner's inbox. A home **outranks this pane**: with a home set,
|
|
150
|
+
a delivery with no live presence starts a session there instead of ringing the pane `attach` binds.
|
|
151
|
+
Say this in the question: setting a home means unclaimed mail no longer rings this pane.
|
|
152
|
+
3. **This pane** (`attach`) — rung only when focused, when there is neither a presence nor a home.
|
|
153
|
+
|
|
154
|
+
Ask plainly, e.g.:
|
|
155
|
+
|
|
156
|
+
> "Should the legate owner have a home — a folder where a session is started to act for it when
|
|
157
|
+
> mail arrives and nobody is live? While you're here, `cyberlegion unit claim legate` makes this
|
|
158
|
+
> session the one that gets the mail, until another session claims it, you run
|
|
159
|
+
> `unit claim legate --clear`, or this one exits; the home is only used when nobody holds it — and
|
|
160
|
+
> once it is set, mail nobody holds starts a session there instead of ringing this pane.
|
|
161
|
+
> A session started there has the folder's trust prompt accepted for it, since you named the
|
|
162
|
+
> folder. Name a folder, or say none."
|
|
163
|
+
|
|
164
|
+
**A folder** → mint with the home and **exactly one** launch:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
node scripts/cyberlegion.mjs unit register --standing --handle legate --home <dir> --harness <harness>
|
|
168
|
+
node scripts/cyberlegion.mjs attach
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
`<harness>` is the `harness` the probe reported, or the one the user names instead — one of
|
|
172
|
+
`claude`, `cursor`, or `codex`. When the user
|
|
173
|
+
names an agent definition to launch there, pass `--agent <definition>` and **no** `--harness`. This
|
|
174
|
+
`--agent` is `unit register`'s — an agent definition resolved from the home — not `init --agent`.
|
|
175
|
+
If the probe reported `harness: unknown` and the user named no agent definition, ask for one — never
|
|
176
|
+
run `--home` without a launch, and never pass `--harness unknown`. Pass `<dir>` as an absolute path.
|
|
177
|
+
|
|
178
|
+
**None** → mint bare, as before:
|
|
89
179
|
|
|
90
180
|
```bash
|
|
91
181
|
node scripts/cyberlegion.mjs unit register --standing --handle legate
|
|
92
182
|
node scripts/cyberlegion.mjs attach
|
|
93
183
|
```
|
|
94
184
|
|
|
95
|
-
Run
|
|
96
|
-
`legate` owner inbox first, then bind the current pane as
|
|
185
|
+
Run the mint and `attach` **in this order** and only after the explicit yes: mint the durable,
|
|
186
|
+
session-independent `legate` owner inbox first, then bind the current pane as the owner's main pane.
|
|
187
|
+
|
|
188
|
+
**The CLI refuses a home** (the folder does not exist, it is a repository's primary checkout, the
|
|
189
|
+
agent definition does not resolve from it) — it writes nothing. Tell the user its reason and ask for
|
|
190
|
+
another folder or none; do not pick a folder yourself and do not fall back to a bare mint unasked.
|
|
191
|
+
If it rejects `--home` as an unknown option, the CLI is older than homes: say so, and mint bare only
|
|
192
|
+
if the user agrees. On a decline, mint nothing and skip `attach`; the hook stays.
|
|
97
193
|
|
|
98
194
|
**Non-mux parity.** If the probe reported no multiplexer or pane, `attach` is a no-op —
|
|
99
195
|
that is expected, not a failure. Still run `unit register --standing --handle legate` on yes, and complete
|
|
100
196
|
**without erroring**. The root session surfaces owner mail via the `!spawnedBy` fallback instead of a
|
|
101
197
|
bound pane.
|
|
102
198
|
|
|
199
|
+
### 6. An owner already minted — add or drop a home
|
|
200
|
+
|
|
201
|
+
Reached only from step 3, in a root session with a broader onboarding intent, when `legate` is
|
|
202
|
+
already minted. Never re-ask the bind and never run `attach` here. Re-registering a standing owner
|
|
203
|
+
refreshes the same record — the same id, its bound presence kept — so it is not a second mint.
|
|
204
|
+
|
|
205
|
+
With no multiplexer or pane in the probe, offer nothing here — neither adding nor dropping a home.
|
|
206
|
+
|
|
207
|
+
- **No home** — explain the presence and the trust-prompt acceptance as in step 5 and offer to give the owner one. On a folder, run
|
|
208
|
+
`unit register --standing --handle legate --home <dir>` with exactly one of `--harness` /
|
|
209
|
+
`--agent`, exactly as in step 5; a refusal is handled the same way.
|
|
210
|
+
If the CLI rejects `--home` (or `--clear-home`) as an unknown option, say it predates homes and
|
|
211
|
+
change nothing.
|
|
212
|
+
- **A home** — name its folder and offer to drop it. On a yes:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
node scripts/cyberlegion.mjs unit register --standing --handle legate --clear-home
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
- **A decline** — run nothing.
|
|
219
|
+
|
|
220
|
+
## Troubleshooting
|
|
221
|
+
|
|
222
|
+
**A unit's `cyberlegion mail send` was denied by the auto-mode classifier** (*Permission for this
|
|
223
|
+
action was denied by the Claude Code auto mode classifier. Reason: [External System Writes]*) — the
|
|
224
|
+
`Bash(cyberlegion *)` permission rule is missing. Run this skill from a root session and say yes to
|
|
225
|
+
the permission ask, or run `cyberlegion init --allow-cli` there.
|
|
226
|
+
|
|
103
227
|
## Boundaries
|
|
104
228
|
|
|
105
|
-
- Every mechanic here is a `cyberlegion` CLI call — this skill writes no hub state
|
|
106
|
-
config format
|
|
229
|
+
- Every mechanic here is a `cyberlegion` CLI call — this skill writes no hub state, invents no
|
|
230
|
+
config format, and never edits Claude Code's settings by hand (the permission rule goes in only
|
|
231
|
+
through `init --allow-cli`, only on an explicit yes in a root session). Its only filesystem read is the plugin's own bundled `${CLAUDE_PLUGIN_ROOT}/.plugin/pins.json`
|
|
107
232
|
version map, to resolve the CLI pin.
|
|
108
|
-
- It never mints or binds an owner identity without an explicit user yes
|
|
233
|
+
- It never mints or binds an owner identity without an explicit user yes, and never sets or drops
|
|
234
|
+
an owner's home except on a folder or a drop the user named.
|
|
109
235
|
- It is distinct from `legate` — sending/spawning/dispatching to a peer is `legate`'s job, not this
|
|
110
236
|
skill's.
|
|
111
237
|
- It is distinct from `manage-inbox` — reading or acking owner mail once bound is `manage-inbox`'s
|
|
@@ -11,7 +11,7 @@ import { spawnSync } from 'node:child_process'
|
|
|
11
11
|
import { existsSync } from 'node:fs'
|
|
12
12
|
import { fileURLToPath } from 'node:url'
|
|
13
13
|
|
|
14
|
-
const FALLBACK = 'npx -y cyberlegion@1.
|
|
14
|
+
const FALLBACK = 'npx -y cyberlegion@1.4.0'
|
|
15
15
|
const bin = new URL('../../../bin/cyberlegion.mjs', import.meta.url)
|
|
16
16
|
|
|
17
17
|
if (existsSync(fileURLToPath(bin))) {
|
package/skills/legate/SKILL.md
CHANGED
|
@@ -13,7 +13,7 @@ logic, loads no other governance, and writes no state of its own.
|
|
|
13
13
|
> **Running the CLI.** Every `node scripts/cyberlegion.mjs …` command below runs the `cyberlegion` CLI
|
|
14
14
|
> this plugin ships. The path is relative to this skill's own directory, not the working directory.
|
|
15
15
|
> If you cannot resolve it, run the published CLI of the version that shipped this skill instead,
|
|
16
|
-
> with the same arguments: `npx -y cyberlegion@1.
|
|
16
|
+
> with the same arguments: `npx -y cyberlegion@1.4.0`.
|
|
17
17
|
|
|
18
18
|
## Doorbell vs mailbox
|
|
19
19
|
|
|
@@ -11,7 +11,7 @@ import { spawnSync } from 'node:child_process'
|
|
|
11
11
|
import { existsSync } from 'node:fs'
|
|
12
12
|
import { fileURLToPath } from 'node:url'
|
|
13
13
|
|
|
14
|
-
const FALLBACK = 'npx -y cyberlegion@1.
|
|
14
|
+
const FALLBACK = 'npx -y cyberlegion@1.4.0'
|
|
15
15
|
const bin = new URL('../../../bin/cyberlegion.mjs', import.meta.url)
|
|
16
16
|
|
|
17
17
|
if (existsSync(fileURLToPath(bin))) {
|
|
@@ -13,7 +13,7 @@ the one owner mailbox from wherever they are.
|
|
|
13
13
|
> **Running the CLI.** Every `node scripts/cyberlegion.mjs …` command below runs the `cyberlegion` CLI
|
|
14
14
|
> this plugin ships. The path is relative to this skill's own directory, not the working directory.
|
|
15
15
|
> If you cannot resolve it, run the published CLI of the version that shipped this skill instead,
|
|
16
|
-
> with the same arguments: `npx -y cyberlegion@1.
|
|
16
|
+
> with the same arguments: `npx -y cyberlegion@1.4.0`.
|
|
17
17
|
|
|
18
18
|
## Resolve the owner handle
|
|
19
19
|
|
|
@@ -11,7 +11,7 @@ import { spawnSync } from 'node:child_process'
|
|
|
11
11
|
import { existsSync } from 'node:fs'
|
|
12
12
|
import { fileURLToPath } from 'node:url'
|
|
13
13
|
|
|
14
|
-
const FALLBACK = 'npx -y cyberlegion@1.
|
|
14
|
+
const FALLBACK = 'npx -y cyberlegion@1.4.0'
|
|
15
15
|
const bin = new URL('../../../bin/cyberlegion.mjs', import.meta.url)
|
|
16
16
|
|
|
17
17
|
if (existsSync(fileURLToPath(bin))) {
|
|
@@ -15,7 +15,7 @@ agent (`headless-legate`, `sdd-automaton`, the cold judges) to know how *it* rep
|
|
|
15
15
|
> **Running the CLI.** Every `node scripts/cyberlegion.mjs …` command below runs the `cyberlegion` CLI
|
|
16
16
|
> this plugin ships. The path is relative to this skill's own directory, not the working directory.
|
|
17
17
|
> If you cannot resolve it, run the published CLI of the version that shipped this skill instead,
|
|
18
|
-
> with the same arguments: `npx -y cyberlegion@1.
|
|
18
|
+
> with the same arguments: `npx -y cyberlegion@1.4.0`.
|
|
19
19
|
|
|
20
20
|
## The one probe: who, if anyone, collects my return?
|
|
21
21
|
|
|
@@ -11,7 +11,7 @@ import { spawnSync } from 'node:child_process'
|
|
|
11
11
|
import { existsSync } from 'node:fs'
|
|
12
12
|
import { fileURLToPath } from 'node:url'
|
|
13
13
|
|
|
14
|
-
const FALLBACK = 'npx -y cyberlegion@1.
|
|
14
|
+
const FALLBACK = 'npx -y cyberlegion@1.4.0'
|
|
15
15
|
const bin = new URL('../../../bin/cyberlegion.mjs', import.meta.url)
|
|
16
16
|
|
|
17
17
|
if (existsSync(fileURLToPath(bin))) {
|
|
@@ -14,7 +14,7 @@ the unit's **role** — see *Mid-turn messaging is scoped by role*, below.
|
|
|
14
14
|
> **Running the CLI.** Every `node scripts/cyberlegion.mjs …` command below runs the `cyberlegion` CLI
|
|
15
15
|
> this plugin ships. The path is relative to this skill's own directory, not the working directory.
|
|
16
16
|
> If you cannot resolve it, run the published CLI of the version that shipped this skill instead,
|
|
17
|
-
> with the same arguments: `npx -y cyberlegion@1.
|
|
17
|
+
> with the same arguments: `npx -y cyberlegion@1.4.0`.
|
|
18
18
|
|
|
19
19
|
## 1. Resolve the agent def
|
|
20
20
|
|
|
@@ -11,7 +11,7 @@ import { spawnSync } from 'node:child_process'
|
|
|
11
11
|
import { existsSync } from 'node:fs'
|
|
12
12
|
import { fileURLToPath } from 'node:url'
|
|
13
13
|
|
|
14
|
-
const FALLBACK = 'npx -y cyberlegion@1.
|
|
14
|
+
const FALLBACK = 'npx -y cyberlegion@1.4.0'
|
|
15
15
|
const bin = new URL('../../../bin/cyberlegion.mjs', import.meta.url)
|
|
16
16
|
|
|
17
17
|
if (existsSync(fileURLToPath(bin))) {
|