leos-agent 10.7.2 → 12.2026090800.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/README.md +239 -670
- package/agents/leo-cheap.md +13 -0
- package/agents/leo-executor.md +13 -0
- package/agents/leo-parent.md +13 -0
- package/agents/leo-reviewer.md +12 -0
- package/agents/leo-runner.md +13 -0
- package/agents/leo-standard.md +13 -0
- package/hooks/README.md +43 -91
- package/hooks/hooks-codex.json +39 -0
- package/hooks/hooks-cursor.json +14 -2
- package/hooks/hooks.json +35 -1
- package/index.js +34 -108
- package/package.json +7 -4
- package/payload/codex-agents/leo-cheap.toml +4 -0
- package/payload/codex-agents/leo-executor.toml +3 -35
- package/payload/codex-agents/leo-parent.toml +4 -0
- package/payload/codex-agents/leo-reviewer.toml +5 -0
- package/payload/codex-agents/leo-runner.toml +3 -27
- package/payload/codex-agents/leo-standard.toml +4 -0
- package/payload/legacy-copy-hashes.json +21 -0
- package/payload/model-prices.json +2914 -0
- package/pi-extension.js +25 -0
- package/rules/preferences.md +29 -92
- package/scripts/bump.py +180 -0
- package/scripts/check.py +91 -18
- package/scripts/cursor_hook.py +58 -0
- package/scripts/dispatch_guard.py +87 -162
- package/scripts/dispatch_log.py +24 -25
- package/scripts/doctor.py +78 -0
- package/scripts/emit_payload.py +108 -0
- package/scripts/ghreview.py +176 -88
- package/scripts/handoff.py +25 -6
- package/scripts/harness_bridge.js +55 -0
- package/scripts/install_transaction.py +91 -0
- package/scripts/jsonc_edit.py +137 -0
- package/scripts/leo-install.py +323 -167
- package/scripts/measure_context.py +17 -19
- package/scripts/observe_agent.py +52 -0
- package/scripts/payload.py +99 -0
- package/scripts/pricing.py +321 -0
- package/scripts/publish-npm.py +12 -4
- package/scripts/routing.py +71 -82
- package/scripts/routing_engine.py +132 -0
- package/scripts/session_models.py +83 -0
- package/scripts/usage_scan.py +303 -278
- package/scripts/watch_review.py +153 -52
- package/skills/doctor/SKILL.md +45 -85
- package/skills/handoff/SKILL.md +3 -5
- package/skills/handon/SKILL.md +13 -21
- package/skills/install/SKILL.md +50 -74
- package/skills/review-pr/SKILL.md +27 -63
- package/skills/review-pr/reference/lenses.md +22 -56
- package/skills/review-pr/reference/procedure.md +128 -327
- package/skills/review-usage/SKILL.md +41 -91
- package/skills/review-usage/reference/sources.md +44 -80
- package/skills/tune-routing/SKILL.md +40 -109
- package/skills/tune-routing/reference/harnesses.md +25 -60
- package/skills-claude/attach-pr/SKILL.md +2 -2
- package/skills-claude/watch-review/SKILL.md +59 -108
- package/commands/handoff.md +0 -11
- package/commands/handon.md +0 -10
- package/commands/review-pr.md +0 -9
- package/commands-claude/watch-review.md +0 -9
package/README.md
CHANGED
|
@@ -1,718 +1,287 @@
|
|
|
1
1
|
# leos-agent
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
**Nothing reads it at run time.** `leo-install.py` renders the result into the
|
|
86
|
-
`<leos-agent>` block it already writes, so a session pays nothing to know its own
|
|
87
|
-
routing — no config read, no extra turn. It costs *less* than before: each
|
|
88
|
-
machine now carries only its own harness's dispatch line instead of all of them,
|
|
89
|
-
which took the installed payload from 4497 bytes to 4315–4344 depending on the
|
|
90
|
-
harness. `scripts/measure_context.py` prints the per-harness figure and fails if
|
|
91
|
-
an unconfigured harness ever grows past the old one.
|
|
92
|
-
|
|
93
|
-
Edit the file — by hand, or with `routing.py set --harness <h> --runner
|
|
94
|
-
<model>`, which [`/tune-routing`](#what-it-ships) drives end to end — then
|
|
95
|
-
re-run the installer to re-render; `leo-install.py <harness> --check` reports
|
|
96
|
-
"out of date" until you do, and `/doctor` surfaces it. Installing is
|
|
97
|
-
idempotent: same config, same version, same bytes, so a second run reports
|
|
98
|
-
`unchanged`.
|
|
99
|
-
|
|
100
|
-
**The config is yours, never the installer's.** `leo-install.py` only ever reads
|
|
101
|
-
it, and never creates, migrates, rewrites, or removes it, including under
|
|
102
|
-
`--uninstall`; it lives outside the plugin so an upgrade cannot take it. The one
|
|
103
|
-
thing that writes it is `routing.py set` / `unset`, run because you asked: it
|
|
104
|
-
creates the file if it is missing, replaces the one role you named, validates
|
|
105
|
-
the whole document before writing, and leaves every other harness's entry —
|
|
106
|
-
including the bare-string shorthand — exactly as you wrote it. `routing.py show`
|
|
107
|
-
prints what is configured; with no file at all, every harness uses its shipped
|
|
108
|
-
default and behaviour is exactly what it was before this existed.
|
|
109
|
-
|
|
110
|
-
Delivery differs by harness only in the last mile: Claude Code gets a `model:`
|
|
111
|
-
override alongside `subagent_type:` (the plugin-owned `agents/*.md` are never
|
|
112
|
-
rewritten), Codex gets the models substituted into its installed profile TOMLs,
|
|
113
|
-
Cursor gets its own `~/.cursor/rules/leos-agent-routing.mdc` because its rules
|
|
114
|
-
come straight out of the plugin directory, and the rest get the rendered line in
|
|
115
|
-
their global instruction file.
|
|
116
|
-
|
|
117
|
-
## The dispatch guard
|
|
118
|
-
|
|
119
|
-
The payload has always said that a subagent dispatch must name a model. Prose
|
|
120
|
-
alone did not hold: a forgotten dispatch inherits the parent's expensive model
|
|
121
|
-
and pays a cold cache write per child, which is the single most expensive shape
|
|
122
|
-
this policy has. From 10.7.2 that half of the rule is enforced by a hook instead,
|
|
123
|
-
and the prose it replaced came out of the always-loaded payload — enforcement in
|
|
124
|
-
code costs **zero** context per turn, so the guard paid for itself in bytes
|
|
125
|
-
before saving a cent.
|
|
126
|
-
|
|
127
|
-
`scripts/dispatch_guard.py` runs before a subagent dispatch and refuses exactly
|
|
128
|
-
one thing: an agent selected with a brief, **no model named**, on a harness that
|
|
129
|
-
can name one. Three ways to comply, all of them one word:
|
|
130
|
-
|
|
131
|
-
| Instead of | Use | For |
|
|
132
|
-
|---|---|---|
|
|
133
|
-
| a generic agent, no model | `subagent_type: "leo-runner"` | reading, search, tests, logs, codemods, fan-out |
|
|
134
|
-
| a generic agent, no model | `subagent_type: "leo-executor"` | an approved plan, a well-specified change |
|
|
135
|
-
| a generic agent, no model | `model: "<name>"` | investigation and debugging — naming it *is* the stated reason |
|
|
136
|
-
|
|
137
|
-
A plugin install namespaces the type — dispatch `leos-agent:leo-runner` rather
|
|
138
|
-
than `leo-runner`; the guard accepts either.
|
|
139
|
-
|
|
140
|
-
It never picks a model for you. It cannot force cheap work onto an expensive
|
|
141
|
-
problem, so it cannot cause a quality regression — only an explicit choice. It
|
|
142
|
-
is also deliberately narrow: a false block costs one re-dispatch, while a caught
|
|
143
|
-
inherited fan-out saves the cold prefix of every child, so the margin only holds
|
|
144
|
-
while the rule refuses to make judgment calls.
|
|
145
|
-
|
|
146
|
-
Detection is by **argument shape**, not tool name: a dispatch is a call that
|
|
147
|
-
selects an agent and carries a brief. A shape the guard does not recognise is
|
|
148
|
-
left alone, so a harness it has never met keeps working. MCP tools are never
|
|
149
|
-
guarded. Anything that goes wrong inside the guard allows the call and records
|
|
150
|
-
`decision: "error"`, kept distinct from a decision to allow, because a guard
|
|
151
|
-
that dies quietly is worse than no guard.
|
|
152
|
-
|
|
153
|
-
```
|
|
154
|
-
LEOS_AGENT_DISPATCH_GUARD=on block (default)
|
|
155
|
-
warn record, never block
|
|
156
|
-
off disabled entirely
|
|
157
|
-
verbose also put the over-delegation notice in front of the model
|
|
158
|
-
LEOS_AGENT_DISPATCH_LOG_PROMPTS=1 debug only: keep 200 chars of brief text in the log
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
**Per harness.** Claude Code dispatches `Agent` with `subagent_type`, and a
|
|
162
|
-
plugin install namespaces it — both forms are tiers. Codex dispatches
|
|
163
|
-
`spawn_agent`, which selects behaviour by `model` and `reasoning_effort` rather
|
|
164
|
-
than by naming an agent, so there the guard requires `model`; its `message` is
|
|
165
|
-
encrypted, so the over-delegation heuristic and block-conversion tracking do not
|
|
166
|
-
apply on Codex. Hermes and OpenCode run the same policy in-process, blocking by
|
|
167
|
-
directive and by throw respectively. Pi has no hook surface.
|
|
168
|
-
|
|
169
|
-
**Codex hash-pins hooks.** A new version of the guard enforces nothing there
|
|
170
|
-
until it is re-approved through `/hooks`, and the symptom is silence — zero
|
|
171
|
-
Codex rows in `dispatch_log.py report`.
|
|
172
|
-
|
|
173
|
-
### What it records
|
|
174
|
-
|
|
175
|
-
`~/.leos-agent-local/dispatch.jsonl`, one line per dispatch, mode `0600`,
|
|
176
|
-
rotated at 1 MiB with one generation kept — bounded at 2 MiB forever.
|
|
177
|
-
|
|
178
|
-
It stores **no prompt text and no paths.** Prompts, sessions and working
|
|
179
|
-
directories are truncated SHA-256. The prompt hash is what makes the report
|
|
180
|
-
meaningful: a blocked brief whose hash comes back naming a tier is a block that
|
|
181
|
-
worked, and one that never returns was abandoned work rather than a saving.
|
|
182
|
-
Delete it whenever you like — nothing depends on its history.
|
|
183
|
-
|
|
184
|
-
```bash
|
|
185
|
-
python3 scripts/dispatch_log.py report
|
|
186
|
-
python3 scripts/usage_scan.py --since 7d
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
## How it works
|
|
190
|
-
|
|
191
|
-
The payload lives in exactly one file: [`rules/preferences.md`](rules/preferences.md).
|
|
192
|
-
|
|
193
|
-
Cursor reads that file natively as an always-apply rule. Every other harness
|
|
194
|
-
gets it through its global instruction file, written by
|
|
195
|
-
[`scripts/leo-install.py`](scripts/leo-install.py) into a marker block:
|
|
196
|
-
|
|
197
|
-
```
|
|
198
|
-
<leos-agent version="10.7.2">
|
|
199
|
-
...the payload...
|
|
200
|
-
</leos-agent>
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
Updating replaces that block and nothing else, so anything you wrote in those
|
|
204
|
-
files by hand survives an upgrade untouched. The script writes only when the
|
|
205
|
-
bytes actually differ, so running it twice is a no-op, and it writes through a
|
|
206
|
-
temporary file and an atomic rename, so an interrupted run cannot leave a
|
|
207
|
-
half-written instruction file behind.
|
|
208
|
-
|
|
209
|
-
If it ever finds markers it cannot pair — an opener with no closer, a stray
|
|
210
|
-
closer, two blocks — it refuses to touch that file and tells you what to fix.
|
|
211
|
-
Guessing there would mean deleting whatever sits between the markers, which is
|
|
212
|
-
exactly the content it exists to protect.
|
|
213
|
-
|
|
214
|
-
| Harness | Global file the installer writes |
|
|
215
|
-
|---|---|
|
|
216
|
-
| Claude Code | `~/.claude/CLAUDE.md` (the `leo-runner` / `leo-executor` agents need no installer step — the plugin's `agents/` directory delivers them) |
|
|
217
|
-
| Codex | `~/.codex/AGENTS.md` (plus `~/.codex/agents/leo-runner.toml` and `leo-executor.toml`) |
|
|
218
|
-
| Cursor | none — the plugin's always-apply rule delivers it |
|
|
219
|
-
| Hermes | `~/.hermes/SOUL.md` (edited only if it already exists) |
|
|
220
|
-
| Pi | `~/.pi/agent/AGENTS.md` |
|
|
221
|
-
| OpenCode | `~/.config/opencode/AGENTS.md` (plus copied skills and commands) |
|
|
222
|
-
|
|
223
|
-
**The installer is per-harness and manual.** Running it inside Codex installs Codex and
|
|
224
|
-
nothing else; it never writes to another harness's files behind your back, and
|
|
225
|
-
it never runs on its own at session start. Install the plugin, then run the
|
|
226
|
-
installer once in that harness.
|
|
227
|
-
|
|
228
|
-
Requires Python 3.9+ and macOS, Linux, or WSL. No symlinks are used anywhere —
|
|
229
|
-
installs are real clones and copies.
|
|
230
|
-
|
|
231
|
-
---
|
|
232
|
-
|
|
233
|
-
## Claude Code
|
|
234
|
-
|
|
235
|
-
**Install**
|
|
236
|
-
|
|
237
|
-
```bash
|
|
3
|
+
Cost-aware delegation and portable workflows for Claude Code, Codex, Cursor,
|
|
4
|
+
OpenCode, Hermes, and Pi. Version **12.2026090800.0**.
|
|
5
|
+
|
|
6
|
+
The main agent handles small work directly and delegates substantial, bounded
|
|
7
|
+
work to the cheapest competent tier. The policy separates **whether to delegate**
|
|
8
|
+
from **which model to use**. Native adapters check model costs where the harness
|
|
9
|
+
exposes enough information, while skills load detailed procedures on demand.
|
|
10
|
+
|
|
11
|
+
This is a useful direction when expensive parents otherwise do large amounts of
|
|
12
|
+
routine work or spawn expensive children by inheritance. It can cost more when
|
|
13
|
+
briefing, duplicated context, verification, and retries exceed the work saved.
|
|
14
|
+
There is no claim of universal token reduction or measured savings without a
|
|
15
|
+
comparable task baseline. Optimizing dollars can mean spending more tokens on
|
|
16
|
+
a cheaper model while preserving quality.
|
|
17
|
+
|
|
18
|
+
## Routing and cost
|
|
19
|
+
|
|
20
|
+
| Tier | Appropriate work | Claude default | Codex default |
|
|
21
|
+
|---|---|---|---|
|
|
22
|
+
| Cheap | Bounded factual checks, mechanical work, known procedures | Haiku | GPT-5.6 Luna |
|
|
23
|
+
| Standard | Investigation, implementation, diagnosis, ordinary review | Sonnet | GPT-5.6 Terra |
|
|
24
|
+
| Parent-level | Work requiring the parent's capability | Current parent | Current parent |
|
|
25
|
+
|
|
26
|
+
Native profiles are `leo-cheap`, `leo-standard`, `leo-parent`, and
|
|
27
|
+
`leo-reviewer`. `leo-runner` and `leo-executor` remain legacy aliases. Review
|
|
28
|
+
may use nested read-only lenses; ordinary workers do not delegate. Small
|
|
29
|
+
reviews run locally, and larger reviews divide independent areas rather than
|
|
30
|
+
requiring every lens to reread everything.
|
|
31
|
+
|
|
32
|
+
The tier name is not a price ordering. For example, the bundled reference
|
|
33
|
+
catalog prices Terra output above Sol output; the ceiling therefore replaces
|
|
34
|
+
that selection with the current parent where supported. Input/output crossover
|
|
35
|
+
rates, unknown IDs, and ambiguous catalog matches are allowed with diagnostics,
|
|
36
|
+
as configured by this project's policy. Thus the ceiling prevents **known**
|
|
37
|
+
overselection, not every possible billing outcome.
|
|
38
|
+
|
|
39
|
+
Prices come from the public [OpenRouter model catalog](https://openrouter.ai/docs/guides/overview/models),
|
|
40
|
+
including Claude, GPT, DeepSeek, Kimi, GLM, and Qwen families. Exact IDs and
|
|
41
|
+
recognized aliases are preferred. Nearby versions of the same variant can use
|
|
42
|
+
an explicitly labeled estimate; sizes, cheap/pro variants, and free endpoints
|
|
43
|
+
are not conflated. A price alias never changes the identifier sent to a harness.
|
|
44
|
+
Public prices do not establish account access, model availability, negotiated
|
|
45
|
+
rates, or subscription-credit accounting.
|
|
46
|
+
|
|
47
|
+
Refresh runs in ordinary code at installation/update and, when used, at most
|
|
48
|
+
daily. It is bounded and runs separately from dispatch. Failed refreshes keep
|
|
49
|
+
the last catalog and record a diagnostic. No dispatch performs network I/O or
|
|
50
|
+
asks a model to look up prices. Set `LEOS_AGENT_PRICE_REFRESH=off` for offline
|
|
51
|
+
operation.
|
|
52
|
+
|
|
53
|
+
## Harness capabilities
|
|
54
|
+
|
|
55
|
+
| Harness | Policy delivery | Model control | Important limit |
|
|
56
|
+
|---|---|---|---|
|
|
57
|
+
| Claude Code | SessionStart, including forks | Agent/Task argument correction; native profiles | Forced settings and provider/org substitutions can affect execution; observe child transcripts. |
|
|
58
|
+
| Codex | Separate native SessionStart hook | Tier-enforcing explicit spawn selection; model-free native profiles | Hooks need native trust. Other/customized profiles can still override spawn settings. |
|
|
59
|
+
| Cursor | Native always-apply rule | Installed user agents; resolved subagentStart model ceiling | No invented Task model argument; hook diagnostics distinguish planned models from completion. |
|
|
60
|
+
| OpenCode | One registered rendered instruction | Native agent selection, confirmed through the SDK | Task has no model field; source/config paths must remain valid. |
|
|
61
|
+
| Hermes | Frozen system-prompt section | Global native delegation-model ceiling when parent/model are observable | Native delegation has one global model, not separate per-task tiers. |
|
|
62
|
+
| Pi | Extension caches rendered body per session | Advisory policy and extension-dependent dispatch checks | No native per-spawn model guarantee for third-party subagent tools. |
|
|
63
|
+
|
|
64
|
+
Portable skills are registered on all six. Native capability differences are
|
|
65
|
+
reported rather than presented as full enforcement parity. Policy, pricing,
|
|
66
|
+
routing decisions, and installation rendering share ordinary code; thin
|
|
67
|
+
adapters implement only supported controls. See [hook contracts](hooks/README.md).
|
|
68
|
+
|
|
69
|
+
## Install and upgrade
|
|
70
|
+
|
|
71
|
+
Requires macOS or Linux, Python 3.9+, and a current public harness. GitHub workflows need
|
|
72
|
+
authenticated `gh`. JavaScript harnesses supply their own Node/Bun runtime.
|
|
73
|
+
No OpenAI or Anthropic marketplace submission is needed: use this repository
|
|
74
|
+
as your own plugin source or a local checkout.
|
|
75
|
+
|
|
76
|
+
Install **only the harness you intend to configure**. Native plugin discovery
|
|
77
|
+
and the integration installer are separate steps. Run the installer again
|
|
78
|
+
after upgrades or model-mapping changes, because native profiles and copied
|
|
79
|
+
OpenCode resources may need refreshing.
|
|
80
|
+
|
|
81
|
+
### Claude Code
|
|
82
|
+
|
|
83
|
+
```sh
|
|
238
84
|
claude plugin marketplace add foxhatleo/leos-agent
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
```bash
|
|
242
85
|
claude plugin install leos-agent@leos-agent --scope user
|
|
243
86
|
```
|
|
244
87
|
|
|
245
|
-
Then
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
```bash
|
|
251
|
-
claude plugin marketplace update leos-agent
|
|
252
|
-
```
|
|
88
|
+
Then invoke the plugin's `install` skill in Claude. To upgrade, refresh the
|
|
89
|
+
marketplace and plugin through Claude's plugin manager, then run `install`
|
|
90
|
+
again and start a new session. Third-party marketplace auto-update settings may
|
|
91
|
+
be disabled; do not assume every client updates itself.
|
|
253
92
|
|
|
254
|
-
|
|
255
|
-
claude plugin install leos-agent@leos-agent --scope user
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
Re-run `/install` afterwards to refresh the block, then start a new session.
|
|
259
|
-
Both commands are safe to repeat; installing an already-current version reports
|
|
260
|
-
that it is already installed and changes nothing.
|
|
261
|
-
|
|
262
|
-
**Uninstall**
|
|
263
|
-
|
|
264
|
-
Run the installer's uninstall first, while the script is still on disk:
|
|
265
|
-
|
|
266
|
-
```bash
|
|
267
|
-
python3 ~/.claude/plugins/cache/leos-agent/leos-agent/10.7.2/scripts/leo-install.py claude --uninstall
|
|
268
|
-
```
|
|
93
|
+
### Codex
|
|
269
94
|
|
|
270
|
-
```
|
|
271
|
-
claude plugin uninstall leos-agent@leos-agent
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
Optionally drop the marketplace too:
|
|
275
|
-
|
|
276
|
-
```bash
|
|
277
|
-
claude plugin marketplace remove leos-agent
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
---
|
|
281
|
-
|
|
282
|
-
## Codex
|
|
283
|
-
|
|
284
|
-
**Install**
|
|
285
|
-
|
|
286
|
-
```bash
|
|
95
|
+
```sh
|
|
287
96
|
codex plugin marketplace add foxhatleo/leos-agent
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
```bash
|
|
291
|
-
codex plugin add leos-agent@leos-agent
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
Then run the `install` skill in a Codex session (`$leos-agent`, then `install`), or
|
|
295
|
-
run the script directly:
|
|
296
|
-
|
|
297
|
-
```bash
|
|
298
|
-
python3 ~/.codex/plugins/cache/leos-agent/leos-agent/10.7.2/scripts/leo-install.py codex
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
This writes `~/.codex/AGENTS.md` and installs two economical agents:
|
|
302
|
-
`leo-runner` (`gpt-5.6-luna`, low effort) for narrow repeatable work and
|
|
303
|
-
`leo-executor` (`gpt-5.6-terra`, medium effort) for well-specified
|
|
304
|
-
implementation. Codex plugins cannot ship agent definitions themselves, which
|
|
305
|
-
is why the installer writes them.
|
|
306
|
-
|
|
307
|
-
**Upgrade**
|
|
308
|
-
|
|
309
|
-
```bash
|
|
310
|
-
codex plugin marketplace upgrade leos-agent
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
```bash
|
|
314
97
|
codex plugin add leos-agent@leos-agent
|
|
315
98
|
```
|
|
316
99
|
|
|
317
|
-
|
|
318
|
-
|
|
100
|
+
Invoke the plugin's `install` skill to install native agent TOMLs. Review the
|
|
101
|
+
current hook definitions in `/hooks`; enabling a plugin does not trust its
|
|
102
|
+
hooks automatically. On upgrade, refresh the marketplace/plugin, rerun
|
|
103
|
+
`install`, and review any changed hook definition. The project does not bypass
|
|
104
|
+
that native trust boundary.
|
|
319
105
|
|
|
320
|
-
|
|
106
|
+
### Cursor
|
|
321
107
|
|
|
322
|
-
|
|
323
|
-
python3 ~/.codex/plugins/cache/leos-agent/leos-agent/10.7.2/scripts/leo-install.py codex --uninstall
|
|
324
|
-
```
|
|
108
|
+
Add this repository through Cursor's plugin UI, or use its local-plugin setup:
|
|
325
109
|
|
|
326
|
-
```
|
|
327
|
-
codex plugin remove leos-agent@leos-agent
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
```bash
|
|
331
|
-
codex plugin marketplace remove leos-agent
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
---
|
|
335
|
-
|
|
336
|
-
## Cursor
|
|
337
|
-
|
|
338
|
-
Cursor has no on-disk global rules file — its User Rules live in your synced
|
|
339
|
-
Cursor account — so there is nothing for the installer to write. The plugin ships the
|
|
340
|
-
payload as an always-apply rule instead, which takes effect as soon as the
|
|
341
|
-
plugin is installed.
|
|
342
|
-
|
|
343
|
-
**Install** — either through the UI, or as a local clone.
|
|
344
|
-
|
|
345
|
-
In the IDE: open the **Customize** sidebar, add the marketplace
|
|
346
|
-
`foxhatleo/leos-agent`, and install **Leo's Agent** at user scope.
|
|
347
|
-
|
|
348
|
-
Or clone it into Cursor's local plugin directory (a clone, not a symlink):
|
|
349
|
-
|
|
350
|
-
```bash
|
|
110
|
+
```sh
|
|
351
111
|
git clone https://github.com/foxhatleo/leos-agent ~/.cursor/plugins/local/leos-agent
|
|
112
|
+
python3 ~/.cursor/plugins/local/leos-agent/scripts/leo-install.py cursor
|
|
352
113
|
```
|
|
353
114
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
Refresh the marketplace from the Customize panel, or for a local clone:
|
|
360
|
-
|
|
361
|
-
```bash
|
|
362
|
-
git -C ~/.cursor/plugins/local/leos-agent pull
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
**Uninstall**
|
|
366
|
-
|
|
367
|
-
Remove the plugin from the Customize panel, or delete the clone:
|
|
368
|
-
|
|
369
|
-
```bash
|
|
370
|
-
rm -rf ~/.cursor/plugins/local/leos-agent
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
There is no block to remove — nothing was written outside the plugin directory.
|
|
374
|
-
|
|
375
|
-
---
|
|
376
|
-
|
|
377
|
-
## Hermes
|
|
378
|
-
|
|
379
|
-
**Install**
|
|
380
|
-
|
|
381
|
-
If the plugin resolves through the community index:
|
|
382
|
-
|
|
383
|
-
```bash
|
|
384
|
-
hermes plugins install leos-agent
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
Otherwise clone it into the Hermes plugin directory:
|
|
388
|
-
|
|
389
|
-
```bash
|
|
390
|
-
git clone https://github.com/foxhatleo/leos-agent ~/.hermes/plugins/leos-agent
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
Hermes plugins are opt-in, so enable it by adding `leos-agent` to
|
|
394
|
-
`plugins.enabled` in `~/.hermes/config.yaml`:
|
|
395
|
-
|
|
396
|
-
```yaml
|
|
397
|
-
plugins:
|
|
398
|
-
enabled:
|
|
399
|
-
- leos-agent
|
|
400
|
-
```
|
|
401
|
-
|
|
402
|
-
**Run Hermes once before installing.** The payload goes into `~/.hermes/SOUL.md`,
|
|
403
|
-
the agent's identity prompt, and Hermes writes its own starter version of that
|
|
404
|
-
file on first run. The installer deliberately never creates it — if `SOUL.md` is
|
|
405
|
-
missing it reports `skipped` and leaves Hermes' bootstrap alone. Once it exists:
|
|
406
|
-
|
|
407
|
-
```bash
|
|
408
|
-
/leo-install
|
|
409
|
-
```
|
|
410
|
-
|
|
411
|
-
**Upgrade**
|
|
115
|
+
Confirm the plugin in Customize and inspect Hooks diagnostics. Set explicit
|
|
116
|
+
models available to your Cursor account, then rerun the installer. Profiles
|
|
117
|
+
are written under `~/.cursor/agents`; `~/.cursor/rules` is not assumed to be a
|
|
118
|
+
supported global rule location. Upgrade a local clone with `git pull --ff-only`,
|
|
119
|
+
rerun the installer, and reload the plugin.
|
|
412
120
|
|
|
413
|
-
|
|
414
|
-
hermes plugins update leos-agent
|
|
415
|
-
```
|
|
121
|
+
### OpenCode
|
|
416
122
|
|
|
417
|
-
|
|
123
|
+
A stable checkout avoids versioned package-cache paths:
|
|
418
124
|
|
|
419
|
-
```
|
|
420
|
-
git -
|
|
125
|
+
```sh
|
|
126
|
+
git clone https://github.com/foxhatleo/leos-agent ~/.local/share/leos-agent
|
|
127
|
+
python3 ~/.local/share/leos-agent/scripts/leo-install.py opencode
|
|
421
128
|
```
|
|
422
129
|
|
|
423
|
-
|
|
130
|
+
The installer registers the checkout's plugin URI, one rendered instruction,
|
|
131
|
+
native agent profiles, and skill/reference copies. It preserves JSONC comments
|
|
132
|
+
and unrelated configuration. Upgrade that checkout with `git pull --ff-only`
|
|
133
|
+
and rerun the same command. The npm package is also published as `leos-agent`;
|
|
134
|
+
if using a package cache, resolve its actual root and rerun the installer when
|
|
135
|
+
that path changes. Do not assume a fixed cache directory layout.
|
|
424
136
|
|
|
425
|
-
|
|
137
|
+
### Hermes
|
|
426
138
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
139
|
+
Use Hermes's local-plugin directory under your active HERMES_HOME/profile to
|
|
140
|
+
install this repository as `plugins/leos-agent`, then enable it through Hermes's
|
|
141
|
+
plugin manager. Run the registered `leo-install` command. The native plugin
|
|
142
|
+
registers portable skills, one frozen policy section, and dispatch diagnostics.
|
|
143
|
+
Hermes supports the policy for deciding whether to delegate, but not per-task
|
|
144
|
+
model tiers. The installer preserves its native delegation-model setting;
|
|
145
|
+
saved cheap/standard mappings are not applied. The guard can still check known
|
|
146
|
+
child/parent prices when both models are observable.
|
|
434
147
|
|
|
435
|
-
|
|
436
|
-
you made one. Your own `SOUL.md` content is left intact — only the block goes.
|
|
148
|
+
### Pi
|
|
437
149
|
|
|
438
|
-
|
|
439
|
-
child of a `delegate_task` call, so it cannot vary the model per spawn. A
|
|
440
|
-
routing config still renders a stanza for it, and the stanza says to inherit and
|
|
441
|
-
say so where a per-spawn model is not available.
|
|
442
|
-
|
|
443
|
-
---
|
|
444
|
-
|
|
445
|
-
## Pi
|
|
446
|
-
|
|
447
|
-
**Install**
|
|
448
|
-
|
|
449
|
-
```bash
|
|
150
|
+
```sh
|
|
450
151
|
pi install git:github.com/foxhatleo/leos-agent
|
|
451
152
|
```
|
|
452
153
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
Pi pins the git ref it installed and records the package in
|
|
460
|
-
`~/.pi/agent/settings.json`; re-running install is idempotent.
|
|
461
|
-
|
|
462
|
-
**Upgrade**
|
|
463
|
-
|
|
464
|
-
```bash
|
|
465
|
-
pi update git:github.com/foxhatleo/leos-agent
|
|
466
|
-
```
|
|
467
|
-
|
|
468
|
-
Pinned refs are reconciled, never silently advanced — to move to a new tag,
|
|
469
|
-
install it explicitly:
|
|
470
|
-
|
|
471
|
-
```bash
|
|
472
|
-
pi install git:github.com/foxhatleo/leos-agent@v10.7.2
|
|
473
|
-
```
|
|
474
|
-
|
|
475
|
-
Re-run `/skill:install` afterwards.
|
|
476
|
-
|
|
477
|
-
**Uninstall**
|
|
478
|
-
|
|
479
|
-
```bash
|
|
480
|
-
python3 ~/.pi/agent/git/github.com/foxhatleo/leos-agent/scripts/leo-install.py pi --uninstall
|
|
481
|
-
```
|
|
482
|
-
|
|
483
|
-
```bash
|
|
484
|
-
pi remove git:github.com/foxhatleo/leos-agent
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
---
|
|
488
|
-
|
|
489
|
-
## OpenCode
|
|
154
|
+
Invoke the installed `install` skill for `pi`, then start a new session.
|
|
155
|
+
Package metadata provides skill discovery once; the extension does not register
|
|
156
|
+
the same skills a second time. Upgrade through Pi's package manager and rerun
|
|
157
|
+
`install`. A subagent extension is required for delegation; this project does
|
|
158
|
+
not pretend that every such extension accepts model overrides.
|
|
490
159
|
|
|
491
|
-
|
|
492
|
-
`leos-agent`.
|
|
160
|
+
### Installer controls
|
|
493
161
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
```bash
|
|
497
|
-
opencode plugin leos-agent -g
|
|
498
|
-
```
|
|
499
|
-
|
|
500
|
-
That adds the package to the `plugin` array in `~/.config/opencode/opencode.json`
|
|
501
|
-
(or `.jsonc`) and caches it. Bootstrap the installer once by running the script from
|
|
502
|
-
the cache — OpenCode's plugin API cannot register skills or commands, so the
|
|
503
|
-
first run has to come from the package itself:
|
|
504
|
-
|
|
505
|
-
```bash
|
|
506
|
-
python3 ~/.cache/opencode/packages/leos-agent@latest/node_modules/leos-agent/scripts/leo-install.py opencode
|
|
507
|
-
```
|
|
162
|
+
From the resolved plugin root:
|
|
508
163
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
after clearing or moving the package cache to point them at the new location.
|
|
515
|
-
|
|
516
|
-
**Upgrade**
|
|
517
|
-
|
|
518
|
-
```bash
|
|
519
|
-
opencode plugin leos-agent -g -f
|
|
520
|
-
```
|
|
521
|
-
|
|
522
|
-
If the cache holds a stale copy, clear it and let OpenCode refetch:
|
|
523
|
-
|
|
524
|
-
```bash
|
|
525
|
-
rm -rf ~/.cache/opencode/packages/leos-agent@*
|
|
526
|
-
```
|
|
527
|
-
|
|
528
|
-
Re-run the bootstrap install command above to refresh the copied files.
|
|
529
|
-
|
|
530
|
-
**Uninstall**
|
|
531
|
-
|
|
532
|
-
```bash
|
|
533
|
-
python3 ~/.cache/opencode/packages/leos-agent@latest/node_modules/leos-agent/scripts/leo-install.py opencode --uninstall
|
|
534
|
-
```
|
|
535
|
-
|
|
536
|
-
OpenCode has no plugin-remove command, so delete the `"leos-agent"` entry from
|
|
537
|
-
the `plugin` array in `~/.config/opencode/opencode.json` **by hand**. The installer
|
|
538
|
-
never edits that file: it is JSONC, with your comments in it, and rewriting it
|
|
539
|
-
would destroy them. Then clear the cache:
|
|
540
|
-
|
|
541
|
-
```bash
|
|
542
|
-
rm -rf ~/.cache/opencode/packages/leos-agent@*
|
|
164
|
+
```sh
|
|
165
|
+
python3 scripts/leo-install.py <harness> --dry-run
|
|
166
|
+
python3 scripts/leo-install.py <harness> --check
|
|
167
|
+
python3 scripts/leo-install.py <harness> --rollback
|
|
168
|
+
python3 scripts/leo-install.py <harness> --uninstall
|
|
543
169
|
```
|
|
544
170
|
|
|
545
|
-
|
|
171
|
+
Normal installation stages and validates all changes first, writes a private
|
|
172
|
+
backup, and rolls back earlier writes if an operation fails. Rollback refuses
|
|
173
|
+
intervening edits and can recover a partially applied installation. Only owned
|
|
174
|
+
entries/files are managed. Unchanged legacy copies are recognized by complete
|
|
175
|
+
content hashes; edited or unrelated files are preserved. `--force` is for a
|
|
176
|
+
specific conflict you explicitly intend to replace.
|
|
546
177
|
|
|
547
|
-
|
|
178
|
+
Run `--uninstall` before removing the native plugin/source. It removes owned
|
|
179
|
+
integration artifacts, not routing preferences, handoffs, or logs. Supported
|
|
180
|
+
config overrides include CODEX_HOME, CLAUDE_CONFIG_DIR, HERMES_HOME,
|
|
181
|
+
PI_CODING_AGENT_DIR, OPENCODE_CONFIG_DIR, OPENCODE_CONFIG, and XDG_CONFIG_HOME.
|
|
548
182
|
|
|
549
|
-
|
|
550
|
-
does not upgrade in place — remove it first. Most skills that were invoked
|
|
551
|
-
as `leo:<name>` are gone; v10 ships a deliberately lean payload plus the three
|
|
552
|
-
GitHub skills above, now unprefixed (`review-pr`, not `leo:review-pr`). The
|
|
553
|
-
watcher no longer runs under `/loop`: it is a shell process streaming into
|
|
554
|
-
Claude Code's Monitor tool, so idle polling costs nothing.
|
|
183
|
+
## Per-machine model routing
|
|
555
184
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
185
|
+
Data lives in `~/.leos-agent-local`, or LEOS_AGENT_LOCAL_PATH, outside versioned
|
|
186
|
+
plugin caches. Configure concrete provider/harness IDs rather than assuming
|
|
187
|
+
that a familiar alias exists everywhere:
|
|
559
188
|
|
|
560
|
-
```
|
|
561
|
-
claude
|
|
189
|
+
```sh
|
|
190
|
+
python3 scripts/routing.py set --harness claude --cheap haiku --standard sonnet
|
|
191
|
+
python3 scripts/routing.py set --harness codex --cheap gpt-5.6-luna --standard gpt-5.6-terra
|
|
192
|
+
python3 scripts/routing.py show
|
|
193
|
+
python3 scripts/leo-install.py <harness>
|
|
562
194
|
```
|
|
563
195
|
|
|
564
|
-
|
|
565
|
-
|
|
196
|
+
`routing.json` accepts `cheap` and `standard` as strings or objects containing
|
|
197
|
+
`model` and optional `effort`. Legacy `runner`/`executor` keys remain readable.
|
|
198
|
+
Unknown model identifiers are retained and diagnosed, not silently corrected
|
|
199
|
+
to a different dispatch ID. Parent-level always means the current parent.
|
|
566
200
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
cache so it refetches v10.
|
|
201
|
+
Guard modes are `LEOS_AGENT_DISPATCH_GUARD=on` (default), `warn` (log proposed
|
|
202
|
+
corrections/blocks), and `off`. Unrelated tools and third-party MCP tools are
|
|
203
|
+
not routed. Failures are logged distinctly and fail open; this is not a
|
|
204
|
+
security boundary. Native or organization-level model substitutions may still
|
|
205
|
+
require investigation of actual execution.
|
|
573
206
|
|
|
574
|
-
|
|
575
|
-
it touched. v10 does not create backups — the block replacement is surgical, and
|
|
576
|
-
`--dry-run` shows you any change before it happens. These are safe to delete:
|
|
207
|
+
## Workflows and diagnostics
|
|
577
208
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
**Hooks** live in `hooks/`, wired but empty — v10 enforces its policy through
|
|
636
|
-
the payload rather than by intercepting tool calls. There are two files because
|
|
637
|
-
the formats genuinely differ: `hooks.json` (PascalCase events) serves Claude
|
|
638
|
-
Code and Codex, which both auto-load it and must never name it in their
|
|
639
|
-
manifests, and `hooks-cursor.json` (camelCase, `version: 1`) serves Cursor,
|
|
640
|
-
which does name it. See [`hooks/README.md`](hooks/README.md) for how to add one,
|
|
641
|
-
including the Hermes, OpenCode, and Pi equivalents, which are code rather than
|
|
642
|
-
JSON.
|
|
643
|
-
|
|
644
|
-
## Development
|
|
645
|
-
|
|
646
|
-
Run the checks:
|
|
647
|
-
|
|
648
|
-
```bash
|
|
209
|
+
| Skill | Purpose |
|
|
210
|
+
|---|---|
|
|
211
|
+
| install | Configure this harness's native artifacts; preview/check/uninstall/rollback. |
|
|
212
|
+
| doctor | Check installation, pricing, model references, and runtime evidence without paid calls. |
|
|
213
|
+
| tune-routing | Configure tiers and diagnose actual native model selection. |
|
|
214
|
+
| review-usage | Mechanical usage scan with reference-cost estimates and explicit gaps. |
|
|
215
|
+
| review-pr | Review a pinned GitHub PR; stage comments/replies as pending. |
|
|
216
|
+
| handoff / handon | Save concise context pointers and resume after checking drift. |
|
|
217
|
+
| watch-review | Claude Monitor watcher: code polls GitHub; models run only for eligible reviews. |
|
|
218
|
+
| attach-pr | Claude-specific attachment of an existing PR to the desktop session. |
|
|
219
|
+
|
|
220
|
+
Only small routing instructions and necessary metadata are always present.
|
|
221
|
+
Detailed review procedures remain in deferred reference files. Duplicate
|
|
222
|
+
slash-command wrappers are removed; native skills provide invocation. Explicit
|
|
223
|
+
invocation controls do not universally imply hidden metadata—measure both.
|
|
224
|
+
|
|
225
|
+
```sh
|
|
226
|
+
python3 scripts/doctor.py --harness claude --json
|
|
227
|
+
python3 scripts/usage_scan.py --since 7d --harness claude --json
|
|
228
|
+
python3 scripts/dispatch_log.py report
|
|
229
|
+
python3 scripts/measure_context.py --check
|
|
230
|
+
python3 scripts/pricing.py resolve claude-sonnet-5
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Default policy bodies are about 1.8–2.0 KB, with a 2.2 KB component budget.
|
|
234
|
+
Measurement counts metadata separately and treats bytes/4 only as a rough
|
|
235
|
+
prose-token proxy. Harness wrappers, history, tools, cache behavior, and child
|
|
236
|
+
work are outside that static measurement. No assertion is made that instruction
|
|
237
|
+
overhead always pays for itself.
|
|
238
|
+
|
|
239
|
+
Usage scanning handles Claude streaming duplicates, Codex cumulative/cache
|
|
240
|
+
accounting, and OpenCode message-time usage. Cursor/Hermes/Pi usage schemas are
|
|
241
|
+
currently unsupported and reported that way. Reference prices are not bills;
|
|
242
|
+
unknown cache/model costs remain explicit. Compaction pre-context counts are
|
|
243
|
+
not discarded tokens. Requested/corrected/blocked dispatches are distinct from
|
|
244
|
+
observed child models. Missing/rotated logs do not prove a broken install.
|
|
245
|
+
|
|
246
|
+
PR review pins the full head SHA; it never silently moves line anchors or
|
|
247
|
+
retries old findings against a new head. Replacing a pending review requires
|
|
248
|
+
an unchanged ownership receipt and saves recovery data. New comments/replies
|
|
249
|
+
remain pending. Only verified addressed threads rooted by the authenticated
|
|
250
|
+
user can be auto-resolved; resolution is public and requires SHA-bound evidence.
|
|
251
|
+
Watchers use cross-process leases, bounded retries, and completion reports;
|
|
252
|
+
emission alone never records a PR as reviewed.
|
|
253
|
+
|
|
254
|
+
Logs omit prompt text by default and rotate at 1 MiB plus one retained file.
|
|
255
|
+
`LEOS_AGENT_DISPATCH_LOG_PROMPTS=1` is an explicit debug option that retains
|
|
256
|
+
brief excerpts; avoid it for sensitive work. Installation backups and handoffs
|
|
257
|
+
stay local. Handoff names are validated, reservations avoid collisions, and
|
|
258
|
+
symlink escapes are refused by the helper.
|
|
259
|
+
|
|
260
|
+
## Development and releases
|
|
261
|
+
|
|
262
|
+
```sh
|
|
263
|
+
LEOS_AGENT_PRICE_REFRESH=off PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s tests
|
|
264
|
+
node --test tests/js/*.test.js
|
|
649
265
|
python3 scripts/check.py
|
|
650
|
-
```
|
|
651
|
-
|
|
652
|
-
The structural check asserts that the version matches across every manifest,
|
|
653
|
-
the marketplace entry, and this README; that each manifest carries what its
|
|
654
|
-
harness requires and every declared path exists; that both hook files parse in
|
|
655
|
-
their own format; and that injection is idempotent, uninstall round-trips, and
|
|
656
|
-
malformed markers are refused.
|
|
657
|
-
|
|
658
|
-
Run the behavioral tests:
|
|
659
|
-
|
|
660
|
-
```bash
|
|
661
|
-
python3 -m unittest discover -s tests -v
|
|
662
|
-
```
|
|
663
|
-
|
|
664
|
-
Measure the repository-controlled static prompt footprint and enforce its
|
|
665
|
-
committed ceilings:
|
|
666
|
-
|
|
667
|
-
```bash
|
|
668
266
|
python3 scripts/measure_context.py --check
|
|
669
267
|
```
|
|
670
268
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
or replace the cachebuster suffix in the Codex manifest with one in the form
|
|
692
|
-
`10.7.2+codex.local-YYYYMMDD-HHMMSS` and re-add. Either way, plugin changes only
|
|
693
|
-
reach a **new** session or thread.
|
|
694
|
-
|
|
695
|
-
`--check` exits non-zero when a file is out of date, and `--force` replaces a
|
|
696
|
-
copied file that something else has since overwritten.
|
|
697
|
-
|
|
698
|
-
To release: bump the version in `package.json`, the three `plugin.json` files,
|
|
699
|
-
`.claude-plugin/marketplace.json`, `plugin.yaml`, and every mention in this
|
|
700
|
-
README (the uninstall commands embed it in cache paths — `check.py` fails on any
|
|
701
|
-
stale one); run `scripts/check.py`; then push a `v`-prefixed tag.
|
|
702
|
-
|
|
703
|
-
Pushing that tag is the whole release. `.github/workflows/release.yml` runs the
|
|
704
|
-
tests and both checks, refuses a tag that disagrees with `package.json`,
|
|
705
|
-
inspects the tree npm would ship, and publishes to npm for OpenCode. It
|
|
706
|
-
authenticates by OIDC trusted publishing, so there is no token in the repository
|
|
707
|
-
— npm's configuration names this workflow by path, and renaming the file breaks
|
|
708
|
-
publishing until npm is updated to match. Publishing is idempotent: a version
|
|
709
|
-
already on the registry is a no-op, and a lookup that fails for any reason other
|
|
710
|
-
than a confirmed 404 aborts rather than assuming the version is absent.
|
|
711
|
-
|
|
712
|
-
Check what a publish would contain, without publishing:
|
|
713
|
-
|
|
714
|
-
```bash
|
|
715
|
-
python3 scripts/publish-npm.py --dry-run
|
|
716
|
-
```
|
|
717
|
-
|
|
718
|
-
MIT licensed.
|
|
269
|
+
Tests use fixtures and mock provider events; CI makes no paid model calls.
|
|
270
|
+
Native live smoke tests are separate, explicitly authorized, and budgeted.
|
|
271
|
+
Static/adapter tests establish contracts, not complete end-to-end parity on
|
|
272
|
+
all six installed harnesses.
|
|
273
|
+
|
|
274
|
+
Commits run validation only. Release versions use `12.YYYYMMDDXX.0`, with a UTC
|
|
275
|
+
calendar date and a two-digit serial from 00 to 99. Run `scripts/bump.py` only
|
|
276
|
+
when preparing a release, validate all manifests/package contents, commit on
|
|
277
|
+
main, and publish the matching tag through the release workflow. npm publishing
|
|
278
|
+
uses its existing trusted-publishing workflow. An ordinary code commit never
|
|
279
|
+
automatically changes versions or stages unrelated files.
|
|
280
|
+
|
|
281
|
+
Native references: [Claude subagents](https://code.claude.com/docs/en/sub-agents),
|
|
282
|
+
[Codex subagents](https://learn.chatgpt.com/docs/agent-configuration/subagents),
|
|
283
|
+
[Codex hooks](https://learn.chatgpt.com/docs/hooks),
|
|
284
|
+
[Cursor plugins](https://cursor.com/docs/reference/plugins),
|
|
285
|
+
[OpenCode plugins](https://opencode.ai/docs/plugins/),
|
|
286
|
+
[Hermes hooks](https://github.com/NousResearch/hermes-agent/blob/main/website/docs/user-guide/features/hooks.md),
|
|
287
|
+
[Pi extensions](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/extensions.md).
|