@ucsandman/legcli 0.7.0 → 0.9.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/CHANGELOG.md +57 -0
- package/NOTICE +8 -0
- package/README.md +601 -558
- package/bin/fake-agent.mjs +4 -4
- package/bin/leg.mjs +64 -34
- package/docs/DECISIONS.md +20 -2
- package/docs/ERRORS.md +71 -0
- package/docs/README.md +2 -0
- package/docs/REUSE.md +1 -1
- package/docs/VOCABULARY.md +21 -0
- package/docs/adapters.md +17 -3
- package/docs/board-guide.md +13 -0
- package/docs/cli-contracts.md +57 -3
- package/docs/concepts.md +42 -3
- package/docs/configuration.md +42 -2
- package/docs/faq.md +19 -0
- package/docs/getting-started.md +272 -251
- package/docs/harness.md +319 -0
- package/fixtures/limits/grok/grok-rate-limit.json +11 -0
- package/fixtures/live/agy/limit-agy-resource-exhausted.json +11 -0
- package/fixtures/verified.json +1 -1
- package/package.json +8 -4
- package/scripts/build-docs-site.mjs +15 -7
- package/scripts/check-branding.mjs +118 -0
- package/scripts/check-claims.mjs +1 -1
- package/scripts/license-sign.mjs +1 -1
- package/scripts/limits-table.mjs +1 -1
- package/scripts/live-limits.mjs +1 -1
- package/scripts/npm-publish-gate.mjs +114 -0
- package/scripts/probe.mjs +4 -3
- package/scripts/seed-fake-cards.mjs +4 -3
- package/scripts/seed-floor-board.mjs +5 -4
- package/scripts/seed-wes-board.mjs +5 -4
- package/scripts/stripe-setup.mjs +1 -1
- package/scripts/sync-harness-engine.mjs +159 -0
- package/scripts/sync-leg-agents.mjs +127 -0
- package/src/accounts.mjs +10 -2
- package/src/adapters/codex.mjs +1 -1
- package/src/adapters/grok.mjs +4 -7
- package/src/attach.mjs +162 -37
- package/src/auth.mjs +2 -2
- package/src/board/board.css +45 -17
- package/src/board/board.js +4 -4
- package/src/board/floor.js +2 -2
- package/src/board/sessions.js +181 -38
- package/src/bundle.mjs +54 -8
- package/src/chain.mjs +1 -1
- package/src/contract.mjs +4 -3
- package/src/fsx.mjs +5 -2
- package/src/handoff.mjs +6 -6
- package/src/harness/cli.mjs +281 -0
- package/src/harness/fingerprint.mjs +68 -0
- package/src/harness/index.mjs +407 -0
- package/src/harness/registry.mjs +124 -0
- package/src/harness/vendor/agnostic-ai/LICENSE +21 -0
- package/src/harness/vendor/agnostic-ai/UPSTREAM.json +30 -0
- package/src/harness/vendor/agnostic-ai/core/safety/guards.json +96 -0
- package/src/harness/vendor/agnostic-ai/core/templates/targets.json +252 -0
- package/src/harness/vendor/agnostic-ai/engine/harness/README.md +199 -0
- package/src/harness/vendor/agnostic-ai/engine/harness/apply.cjs +247 -0
- package/src/harness/vendor/agnostic-ai/engine/harness/bundle.cjs +243 -0
- package/src/harness/vendor/agnostic-ai/engine/harness/capture.cjs +119 -0
- package/src/harness/vendor/agnostic-ai/engine/harness/common.cjs +375 -0
- package/src/harness/vendor/agnostic-ai/engine/harness/index.cjs +55 -0
- package/src/harness/vendor/agnostic-ai/engine/harness/sources/claude.cjs +330 -0
- package/src/harness/vendor/agnostic-ai/engine/harness/sources/codex.cjs +314 -0
- package/src/harness/vendor/agnostic-ai/engine/harness/status.cjs +171 -0
- package/src/harness/vendor/agnostic-ai/engine/harness/targets/agy.cjs +113 -0
- package/src/harness/vendor/agnostic-ai/engine/harness/targets/claude.cjs +158 -0
- package/src/harness/vendor/agnostic-ai/engine/harness/targets/codex.cjs +832 -0
- package/src/harness/vendor/agnostic-ai/engine/harness/targets/cursor.cjs +87 -0
- package/src/harness/vendor/agnostic-ai/engine/harness/targets/gemini.cjs +128 -0
- package/src/harness/vendor/agnostic-ai/engine/harness/targets/generic.cjs +424 -0
- package/src/harness/vendor/agnostic-ai/engine/harness/toml.cjs +149 -0
- package/src/harness/vendor/agnostic-ai/engine/hooks/shim.cjs +431 -0
- package/src/hook.mjs +49 -49
- package/src/land.mjs +660 -47
- package/src/launcher.mjs +40 -27
- package/src/ledger.mjs +6 -6
- package/src/license.mjs +10 -9
- package/src/live-capture.mjs +1 -1
- package/src/mergequeue.mjs +6 -6
- package/src/orchestrator.mjs +28 -4
- package/src/preferences.mjs +63 -9
- package/src/redact.mjs +1 -1
- package/src/resume.mjs +17 -15
- package/src/runner.mjs +3 -3
- package/src/scheduler.mjs +1 -1
- package/src/server.mjs +69 -20
- package/src/session-detail.mjs +15 -1
- package/src/sessions.mjs +9 -5
- package/src/share.mjs +2 -2
- package/src/stations/agent.mjs +1 -1
- package/src/sync/dashclaw.mjs +4 -4
- package/src/synthesis.mjs +165 -0
- package/src/taps/agy.mjs +2 -2
- package/src/taps/claude-usage.mjs +1 -1
- package/src/taps/claude.mjs +170 -170
- package/src/taps/codex.mjs +286 -286
- package/src/taps/grok.mjs +251 -0
- package/src/trust.mjs +205 -36
- package/src/usage.mjs +5 -1
- package/src/worktree.mjs +5 -4
- package/fixtures/live/agy/attempt-1-scratch-workspace.out.log +0 -1
- package/fixtures/live/agy/err.log +0 -0
- package/fixtures/live/agy/out.log +0 -1
- package/fixtures/live/agy/supervisor.log +0 -2
- package/fixtures/live/claude/err.log +0 -0
- package/fixtures/live/claude/out.log +0 -1
- package/fixtures/live/claude/supervisor.log +0 -2
- package/fixtures/live/codex/err.log +0 -1
- package/fixtures/live/codex/out.log +0 -8
- package/fixtures/live/codex/supervisor.log +0 -2
- package/fixtures/live/grok/err.log +0 -32
- package/fixtures/live/grok/out.log +0 -7
- package/fixtures/live/grok/supervisor.log +0 -2
package/docs/concepts.md
CHANGED
|
@@ -108,12 +108,14 @@ things in order (`src/attach.mjs`, `src/bundle.mjs`):
|
|
|
108
108
|
it again at the transition and during all-out waiting. Machine Settings is
|
|
109
109
|
copied only when a new terminal starts.
|
|
110
110
|
3. **Switch.** The agent process is stopped and the terminal restored. The
|
|
111
|
-
bundle's `context-handoff-bundle load <id>` output
|
|
111
|
+
bundle's `context-handoff-bundle load <id>` output (with the `## Synthesis`
|
|
112
|
+
section prepended if `.leg/SYNTHESIS-<session-id>.md` is present) is written to
|
|
112
113
|
`.leg/RESUME-<session-id>.md` and copied to `.leg/RESUME.md`, and the next
|
|
113
114
|
agent starts in the same terminal with a short pointer prompt as its first
|
|
114
115
|
positional argument: `claude "<prompt>"`, `codex "<prompt>"`,
|
|
115
|
-
`agy -i "<prompt>"`. The prompt names the per-session file,
|
|
116
|
-
|
|
116
|
+
`agy -i "<prompt>"`. The prompt names the per-session file, directs the agent
|
|
117
|
+
to read Synthesis first and treat ruled-out approaches as settled, and says to
|
|
118
|
+
check `git status` and `git diff`, continue, and not ask the human to restate the
|
|
117
119
|
task.
|
|
118
120
|
4. **All out.** If every option is walled, Leg prints each one with its reset
|
|
119
121
|
time, soonest first, then waits in the terminal with a one-line countdown
|
|
@@ -123,6 +125,33 @@ things in order (`src/attach.mjs`, `src/bundle.mjs`):
|
|
|
123
125
|
(`{ agent, account, resets_at, since }`) and shows status `waiting`. Ctrl-C
|
|
124
126
|
in the terminal, or End on the card, quits with exit 3.
|
|
125
127
|
|
|
128
|
+
## The portable harness
|
|
129
|
+
|
|
130
|
+
Off by default. `leg harness enable` adds a step to the hand-off, between
|
|
131
|
+
**Choose** and **Switch**: the destination's working environment is prepared
|
|
132
|
+
before the destination starts. The source client (the one you actually
|
|
133
|
+
configure: Claude Code or Codex) is captured into a client-neutral bundle
|
|
134
|
+
under `~/.leg/harness/bundle/` (rules with their imports inlined, identity,
|
|
135
|
+
hooks, skills, subagents, slash commands, MCP servers with every credential
|
|
136
|
+
replaced by `${NAME}`, permissions), and that bundle is rendered into the
|
|
137
|
+
destination client's own files: `AGENTS.md`, `config.toml` regions and hook
|
|
138
|
+
trust entries for Codex; `GEMINI.md`, `hooks.json` and `mcp_config.json` for
|
|
139
|
+
agy; `leg-rules.md` plus one import line, hook groups and MCP servers for
|
|
140
|
+
Claude Code. Skills are linked, not copied. What a destination cannot
|
|
141
|
+
represent is dropped with a reason, and the session records exactly what
|
|
142
|
+
transferred (`session.harness`, the `harness` event, the **Harness** section
|
|
143
|
+
of the drawer).
|
|
144
|
+
|
|
145
|
+
The saved policy decides what an unattended hand-off may do: `warn` reports
|
|
146
|
+
and writes nothing, `sync` writes managed state when that is safe, `strict`
|
|
147
|
+
refuses a destination it cannot make safe and tries the next option. A
|
|
148
|
+
fingerprint of the source's files makes an unchanged environment free to
|
|
149
|
+
check. Everything Leg writes this way carries `GENERATED by Leg harness`, sits
|
|
150
|
+
in a marked region or an owned key inside files you also own, is backed up
|
|
151
|
+
before it is overwritten, and is skipped when you hand-edited it. The source
|
|
152
|
+
client is never written; credentials never move; which login runs is still the
|
|
153
|
+
account layer's decision. The whole contract is in [harness.md](harness.md).
|
|
154
|
+
|
|
126
155
|
## The resume pointer
|
|
127
156
|
|
|
128
157
|
`.leg/RESUME.md` is the file humans and other agents open by habit, so Leg
|
|
@@ -303,6 +332,16 @@ notes carry six sections in the bundle's own vocabulary:
|
|
|
303
332
|
The next leg's prompt starts with the bundle's `load` output (the resume
|
|
304
333
|
text) followed by the same contract.
|
|
305
334
|
|
|
335
|
+
### The synthesis layer
|
|
336
|
+
|
|
337
|
+
Alongside raw state, Leg supports an agent-maintained judgment record in `.leg/SYNTHESIS-<session-id>.md`. At handoff time, Leg reads this file and inlines it verbatim into `.leg/RESUME-<session-id>.md` and `.leg/RESUME.md` as a `## Synthesis` section before the raw bundle dump.
|
|
338
|
+
|
|
339
|
+
- **Schema v1**: A 2-line header (`synthesis_version: 1`, `session: <id> updated: <ISO-8601 UTC>`) followed by up to four optional sections in fixed order: `## Ruled out`, `## Decisions`, `## Next steps`, `## Open questions` (max 5 bullets each, one line per bullet).
|
|
340
|
+
- **Size cap**: 4 KB. Beyond that, Leg includes the first 4 KB plus a trailing `[synthesis truncated]` marker.
|
|
341
|
+
- **Resilience**: If the header is malformed, Leg still inlines the body prefixed with `[synthesis header invalid, rendering body as-is]`. If the file is absent or empty, no `## Synthesis` section is emitted and handoff degrades to today's raw dump.
|
|
342
|
+
- **Pointer prompt**: Directs the taking-over agent to read the Synthesis section first if present, treat ruled-out approaches as settled, and start from the top-ranked next step.
|
|
343
|
+
- **Board indicator**: Shows a `synthesis` chip on the terminal card when the synthesis file exists and was modified within the last 3 checkpoints.
|
|
344
|
+
|
|
306
345
|
## Worktrees
|
|
307
346
|
|
|
308
347
|
Every card runs in its own git worktree: `<repo>/.leg-worktrees/<card-id>`
|
package/docs/configuration.md
CHANGED
|
@@ -20,13 +20,16 @@ variables yourself in that case.
|
|
|
20
20
|
|
|
21
21
|
## Interactive sessions
|
|
22
22
|
|
|
23
|
-
These apply to `leg claude|codex|agy`.
|
|
23
|
+
These apply to `leg claude|codex|agy|grok`.
|
|
24
24
|
|
|
25
25
|
| variable | default | meaning | read in |
|
|
26
26
|
|----------|---------|---------|---------|
|
|
27
27
|
| `LEG_ACCOUNT` | `default` | start the session on a named login instead of the CLI's own home | `src/attach.mjs` |
|
|
28
|
+
| `LEG_AUTO_APPROVE` | `1` | launch interactive agents in auto-approve mode (set to `0`, `false`, or `off` to disable) | `src/preferences.mjs` |
|
|
29
|
+
| `LEG_NO_AUTO_APPROVE` | (unset) | set to `1` to opt out of auto-approve mode | `src/preferences.mjs` |
|
|
28
30
|
| `LEG_WARN_PCT` | `85` | the percentage of either usage window that turns the card amber, records a `warning` event and rings the terminal bell once | `src/usage.mjs` |
|
|
29
31
|
| `LEG_NO_HANDOFF` | (unset, hand-off on) | set to `1` to warn and record but never switch agents | `src/attach.mjs` |
|
|
32
|
+
| `LEG_HARNESS_HOME` | the OS home | where the portable harness reads and writes client configuration (`~/.claude`, `~/.codex`, `~/.gemini` under it); the test suite points it at a throwaway directory. `CLAUDE_CONFIG_DIR`, `CODEX_HOME` and `GEMINI_CONFIG_DIR` move one client each, as everywhere else in Leg | `src/harness/registry.mjs` |
|
|
30
33
|
| `LEG_NO_OPEN` | (unset, opens once) | set to `1` to start the board without opening a browser | `bin/leg.mjs` |
|
|
31
34
|
| `LEG_NO_BOARD` | (unset) | set to `1` to run a session with no board at all (the record under `$LEG_HOME/sessions/` is still kept; the test suite uses this) | `src/attach.mjs` |
|
|
32
35
|
| `LEG_WAIT_TICK_MS` | `1000` | how often the all-out countdown redraws and re-checks Ctrl-C / End while waiting for the first reset | `src/attach.mjs` |
|
|
@@ -45,6 +48,23 @@ record under `$LEG_HOME/sessions/`.
|
|
|
45
48
|
`CLAUDE_CONFIG_DIR` and `CODEX_HOME` are set for the child when the session
|
|
46
49
|
runs on a named account; see [Accounts](#accounts) below.
|
|
47
50
|
|
|
51
|
+
### Auto-approve launch mode
|
|
52
|
+
|
|
53
|
+
By default, Leg starts interactive sessions (`leg claude`, `leg codex`, `leg agy`, and `leg grok`) in permissive auto-approve mode so you never sit through repetitive tool permission prompts:
|
|
54
|
+
|
|
55
|
+
- Claude: `--dangerously-skip-permissions`
|
|
56
|
+
- Codex: `--ask-for-approval never`
|
|
57
|
+
- agy: `--dangerously-skip-permissions`
|
|
58
|
+
- Grok: `--always-approve`
|
|
59
|
+
|
|
60
|
+
These flags are injected at spawn time and only affect sessions launched through Leg. Your global CLI configurations (`~/.claude.json`, `~/.codex/config.toml`, `~/.gemini/settings.json`) remain untouched.
|
|
61
|
+
|
|
62
|
+
To opt out and keep standard approval prompts:
|
|
63
|
+
|
|
64
|
+
1. CLI flag: pass `--no-auto-approve` when starting a session (e.g. `leg claude --no-auto-approve`).
|
|
65
|
+
2. Environment variable: set `LEG_AUTO_APPROVE=0` or `LEG_NO_AUTO_APPROVE=1` (or legacy `BATON_AUTO_APPROVE=0` / `BATON_NO_AUTO_APPROVE=1`).
|
|
66
|
+
3. Persistent preference: set `"auto_approve": false` in `~/.leg/preferences.json`.
|
|
67
|
+
|
|
48
68
|
## Core
|
|
49
69
|
|
|
50
70
|
| variable | default | meaning | read in |
|
|
@@ -80,7 +100,7 @@ Off unless explicitly enabled; a sync failure never blocks or fails a card
|
|
|
80
100
|
## Seller and checkout site
|
|
81
101
|
|
|
82
102
|
These are for the checkout/key-delivery site and its deployment helpers, not
|
|
83
|
-
normal Leg
|
|
103
|
+
normal Leg use.
|
|
84
104
|
|
|
85
105
|
| variable | meaning | read in |
|
|
86
106
|
|----------|---------|---------|
|
|
@@ -152,6 +172,26 @@ junctions as links, never following them, then deletes the directory. Nothing
|
|
|
152
172
|
under your real home is written at any point. Start a session on a named
|
|
153
173
|
account with `LEG_ACCOUNT=<name>`, or let a limit hand off to it.
|
|
154
174
|
|
|
175
|
+
## The portable harness
|
|
176
|
+
|
|
177
|
+
Off until `leg harness enable`. Its settings live in `~/.leg/preferences.json`
|
|
178
|
+
beside the hand-off order:
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{ "harness": { "enabled": true, "policy": "sync", "source": "claude" } }
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
| key | values | meaning |
|
|
185
|
+
|-----|--------|---------|
|
|
186
|
+
| `enabled` | `true`, `false` (default) | the consent `leg harness enable` records; `leg harness disable` clears it and removes nothing |
|
|
187
|
+
| `policy` | `warn`, `sync` (default on enable), `strict` | what an unattended hand-off may do: report only; write managed state when safe; refuse a destination that cannot be made safe |
|
|
188
|
+
| `source` | `claude`, `codex` | the client whose harness is carried; auto-detected from `~/.claude/CLAUDE.md` then `~/.codex/AGENTS.md` when unset |
|
|
189
|
+
|
|
190
|
+
`~/.leg/harness/policy.json` (optional) names what is deliberately not
|
|
191
|
+
carried: sections to drop, hooks, skills and MCP servers to exclude, each with
|
|
192
|
+
a reason, and the Codex model ladder. State, backups and the evidence trail
|
|
193
|
+
live under `~/.leg/harness/`. Every detail: [harness.md](harness.md).
|
|
194
|
+
|
|
155
195
|
## Test and development seams
|
|
156
196
|
|
|
157
197
|
Not meant for normal use; documented for completeness.
|
package/docs/faq.md
CHANGED
|
@@ -162,6 +162,25 @@ pre-commit hook both run `scripts/privacy-check.mjs`, which additionally
|
|
|
162
162
|
scans the whole tree for a short list of strings specific to the private
|
|
163
163
|
codebase Leg's runner/ledger were ported from.
|
|
164
164
|
|
|
165
|
+
**Does the next agent get my rules, hooks, skills and MCP servers, or just the task?**
|
|
166
|
+
Just the task, unless you turn on the [portable harness](harness.md)
|
|
167
|
+
(`leg harness enable`). Then a hand-off also renders the source client's
|
|
168
|
+
global working agreement, identity, hooks, skills, subagents, slash commands,
|
|
169
|
+
MCP servers and permissions into the destination's own files, as far as that
|
|
170
|
+
client can represent them, and the terminal's details say what was dropped and
|
|
171
|
+
why (Codex has no SSE transport; agy has no `SessionStart` hook; a skill that
|
|
172
|
+
already exists as a real directory is left alone). Credentials never move: an
|
|
173
|
+
MCP key becomes `${NAME}` and you export it for each client. Off by default,
|
|
174
|
+
and `leg harness disable` turns it off without removing anything.
|
|
175
|
+
|
|
176
|
+
**Will the portable harness overwrite a file I edited?**
|
|
177
|
+
No. Every file it writes carries `GENERATED by Leg harness` in its first lines,
|
|
178
|
+
and inside a file you also own it writes a marked `leg harness` region. A
|
|
179
|
+
file whose content changed since Leg wrote it is backed up once under
|
|
180
|
+
`~/.leg/harness/backups` and skipped; the sync reports `attention` with the
|
|
181
|
+
path, and `leg harness sync --force` is the only way it gets replaced. The
|
|
182
|
+
source client is never written at all.
|
|
183
|
+
|
|
165
184
|
**What happens if I close the terminal instead of Ctrl-C?**
|
|
166
185
|
The board server and any running agents keep running as detached processes.
|
|
167
186
|
Run `node bin/leg.mjs down` (or `npm run stop`) from another terminal to
|