agents-handoff 2.0.2 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +77 -6
- package/README.md +59 -12
- package/SKILL.md +12 -12
- package/capability-registry.json +1 -1
- package/docs/ARCHITECTURE.md +28 -5
- package/docs/CHANGELOG.md +91 -17
- package/docs/CLI.md +115 -12
- package/docs/COMPATIBILITY.md +24 -0
- package/docs/CONTRIBUTING.md +2 -2
- package/docs/FORMAT.md +28 -0
- package/docs/INSTALL.md +239 -24
- package/docs/INTEGRATION.md +4 -4
- package/docs/LEVEL4.md +10 -10
- package/docs/LEVEL5.md +1 -1
- package/docs/PERMISSIONS.md +2 -2
- package/docs/PROVENANCE.md +27 -0
- package/docs/SECURITY.md +1 -1
- package/docs/SESSIONS.md +31 -0
- package/docs/UNINSTALL.md +47 -21
- package/docs/UPGRADE.md +59 -21
- package/docs/_config.yml +3 -1
- package/docs/index.md +17 -6
- package/docs/sessions.json +34 -0
- package/install/CHANGELOG.md +1 -1
- package/install/README.md +7 -7
- package/install/install.mjs +746 -147
- package/install/package.json +2 -2
- package/package.json +2 -2
- package/permission-policy.json +1 -1
- package/refs/protocol.md +1 -1
- package/schemas/handoff.schema.json +1 -1
- package/skill.json +11 -11
- package/tests/acceptance/acceptance.yaml +2 -2
- package/tools/agent-handoff.mjs +16 -404
- package/tools/agents-handoff.mjs +410 -0
- package/tools/capability-registry.mjs +2 -2
- package/tools/handoff.test.mjs +203 -0
- package/tools/lib/handoff-root.mjs +1 -1
- package/tools/runtime-engine.mjs +2 -2
package/docs/CLI.md
CHANGED
|
@@ -9,8 +9,9 @@ dependencies; there is no build step and nothing to install to run them from a c
|
|
|
9
9
|
|
|
10
10
|
| Executable | Role | Invoked as |
|
|
11
11
|
|---|---|---|
|
|
12
|
-
| [`tools/handoff.mjs`](https://github.com/Alot1z/agent-handoff/blob/main/tools/handoff.mjs) | Capture engine: transcript in, handoff folder out. | `node tools/handoff.mjs <verb>`, or the published `
|
|
13
|
-
| [`tools/
|
|
12
|
+
| [`tools/handoff.mjs`](https://github.com/Alot1z/agent-handoff/blob/main/tools/handoff.mjs) | Capture engine: transcript in, handoff folder out. | `node tools/handoff.mjs <verb>`, or the published `agents-handoff` bin |
|
|
13
|
+
| [`tools/agents-handoff.mjs`](https://github.com/Alot1z/agent-handoff/blob/main/tools/agents-handoff.mjs) | Runtime layer: acts on the state of the store. | `node tools/agents-handoff.mjs <verb>` |
|
|
14
|
+
| [`tools/agent-handoff.mjs`](https://github.com/Alot1z/agent-handoff/blob/main/tools/agent-handoff.mjs) | Compatibility forwarder: the runtime layer's pre-rename path, kept so older notes and hooks keep working. | `node tools/agent-handoff.mjs <verb>` (forwards to `tools/agents-handoff.mjs`) |
|
|
14
15
|
| [`tools/runtime-engine.mjs`](https://github.com/Alot1z/agent-handoff/blob/main/tools/runtime-engine.mjs) | Bounded execution: evaluates an operation against the policy before running it. | `node tools/runtime-engine.mjs <verb>` |
|
|
15
16
|
| [`tools/capability-registry.mjs`](https://github.com/Alot1z/agent-handoff/blob/main/tools/capability-registry.mjs) | Health probes for declared capabilities. | `node tools/capability-registry.mjs <verb>` |
|
|
16
17
|
| [`install/install.mjs`](https://github.com/Alot1z/agent-handoff/blob/main/install/install.mjs) | Installs, updates and removes the skill. | `npx agents-handoff <verb>` |
|
|
@@ -60,7 +61,7 @@ source hash writes nothing and prints `handoff: up-to-date`.
|
|
|
60
61
|
| 3 | The id prefix matched more than one session, or none. |
|
|
61
62
|
| 4 | No match for `show`/`verify`/`rename`/`retitle`; also `build` when no turn could be parsed from the source. |
|
|
62
63
|
|
|
63
|
-
## `tools/
|
|
64
|
+
## `tools/agents-handoff.mjs` — runtime layer
|
|
64
65
|
|
|
65
66
|
Acts on the state of the store rather than being invoked per file. Every mutating command
|
|
66
67
|
takes a lock in `<root>/.locks/`, so two runs cannot capture or merge the same session at
|
|
@@ -77,6 +78,11 @@ once. Behaviour per command is described in [LEVEL4.md](LEVEL4.md).
|
|
|
77
78
|
| `self-improve` | Scan for brief shortfalls and write a rules candidate file. |
|
|
78
79
|
| `index` | Rebuild `INDEX.json` and report sessions with no `HANDOFF.md`. |
|
|
79
80
|
|
|
81
|
+
`tools/agent-handoff.mjs` is a forwarder, not a second implementation: it spawns
|
|
82
|
+
`tools/agents-handoff.mjs`, passes every argument through, and exits with the same code. Its
|
|
83
|
+
stdout and stderr are the runtime's own. Use the new path in anything you write today; the
|
|
84
|
+
old one exists only so a command that already names it does not break.
|
|
85
|
+
|
|
80
86
|
`auto` flags: `--source` (required), `--session`, `--harness`, `--project`, `--min-fresh-ms`.
|
|
81
87
|
`dispatch` flags: `--task` (required), `--role` (default `implementation-agent`), `--parent`
|
|
82
88
|
(default `handoff:<id>`), `--broker <root>`, `--live`.
|
|
@@ -147,21 +153,41 @@ Probe kinds: `file-exists`, `dir-writable`, `command` (with `command` and `args`
|
|
|
147
153
|
| 4 | Unknown capability id, or a usage error. |
|
|
148
154
|
|
|
149
155
|
State is written to `<state>/capability-state.json`, where `<state>` is
|
|
150
|
-
`AGENT_HANDOFF_STATE_DIR` or `.
|
|
156
|
+
`AGENT_HANDOFF_STATE_DIR` or `.agents-handoff/`.
|
|
151
157
|
|
|
152
158
|
## `install/install.mjs` — installer
|
|
153
159
|
|
|
154
160
|
Published as `agents-handoff`. Location resolution is documented in
|
|
155
161
|
[INSTALL.md](INSTALL.md).
|
|
156
162
|
|
|
157
|
-
|
|
163
|
+
A bare verb and its flag form are the same command: `npx agents-handoff update` and
|
|
164
|
+
`npx agents-handoff --update` behave identically.
|
|
165
|
+
|
|
166
|
+
| Verb | Flag form | Effect |
|
|
167
|
+
|---|---|---|
|
|
168
|
+
| `install` (default), `i` | `--install` | Install the skill into every selected target. |
|
|
169
|
+
| `update`, `u` | `--update` | Update to the latest or a named version. |
|
|
170
|
+
| `remove`, `rm` | `--remove` | Remove the installation, keeping everything that is not the installer's. |
|
|
171
|
+
| `verify`, `v` | `--verify` | Verify each installation against the record written when it was installed. |
|
|
172
|
+
| `verify-package`, `vp` | `--verify-package` | Verify each installation against the tarball npm publishes for its version. |
|
|
173
|
+
| `list`, `ls` | `--list` | List every installed location, with its provenance state. |
|
|
174
|
+
| `where` | — | Show the resolved global root and why it was chosen. |
|
|
175
|
+
| `doctor` | `--doctor` | Report which harnesses exist here, what is installed where, and whether each installation still matches its record. Read-only: it never installs. |
|
|
176
|
+
| `help` | `--help`, `-h` | Print the usage block. |
|
|
177
|
+
|
|
178
|
+
Harness targets. With no harness flag the installer keeps its historical single target
|
|
179
|
+
(`--location` / `--path`); any of these switches to named targets, and several may be combined
|
|
180
|
+
in one run — each target gets its own copy and its own install record.
|
|
181
|
+
|
|
182
|
+
| Flag | Target |
|
|
158
183
|
|---|---|
|
|
159
|
-
| `
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
162
|
-
|
|
|
163
|
-
| `
|
|
164
|
-
|
|
|
184
|
+
| `--claude` | `~/.claude/skills/` — Claude Code personal skills. |
|
|
185
|
+
| `--codex` | `~/.codex/skills/` — Codex CLI personal skills. |
|
|
186
|
+
| `--agents` | `~/.agents/skills/` — the harness-neutral store. |
|
|
187
|
+
| `--harness <a,b>` | Named harnesses, comma separated; repeatable. |
|
|
188
|
+
| `--all` | Every harness whose directory exists on this machine. |
|
|
189
|
+
| `--skills-dir <dir>` | Any other stack, exactly; repeatable. |
|
|
190
|
+
| `--project` | Use the per-repository form of the harness directories (`./.claude/skills`, `./.codex/skills`). |
|
|
165
191
|
|
|
166
192
|
| Flag | Meaning |
|
|
167
193
|
|---|---|
|
|
@@ -169,13 +195,89 @@ Published as `agents-handoff`. Location resolution is documented in
|
|
|
169
195
|
| `--path <dir>` | Install to an exact directory. |
|
|
170
196
|
| `--version latest\|<v>` | Version to install. Default `latest`. |
|
|
171
197
|
| `--force`, `-f` | Skip confirmations and overwrite. |
|
|
198
|
+
| `--provenance` | With `verify`: print the install record the check was run against. |
|
|
199
|
+
| `--record` | With `verify-package`: store the fetched tarball hashes in the install record. |
|
|
200
|
+
|
|
201
|
+
### `update` and `verify` with no harness flag
|
|
202
|
+
|
|
203
|
+
A machine can hold the same skill in several places at once — `~/.claude/skills` for Claude
|
|
204
|
+
Code, `~/.agents/skills` for a neutral store, an account-skill store a desktop client reads.
|
|
205
|
+
With no harness flag, `update` and `verify` act on **every** installation they can find rather
|
|
206
|
+
than on the single target the resolver happens to pick, because updating only the resolved one
|
|
207
|
+
is how a second harness keeps an old engine without anyone noticing.
|
|
208
|
+
|
|
209
|
+
The search covers the resolved global root, `./local/skills`, `./skills`, `~/.claude/skills`,
|
|
210
|
+
`~/.codex/skills`, `~/.agents/skills`, each harness's per-repository form, and every
|
|
211
|
+
account-skill root discovered under the platform's application-data directories. `update`
|
|
212
|
+
reports one line per installation, with the version before and after; `verify` fails the run
|
|
213
|
+
when any copy fails. Neither touches a store, `handoff.config.json` or any file the install
|
|
214
|
+
manifest does not name.
|
|
215
|
+
|
|
216
|
+
### Exit codes
|
|
217
|
+
|
|
218
|
+
| Code | Meaning |
|
|
219
|
+
|---|---|
|
|
220
|
+
| 0 | The command ran and everything it checked passed. |
|
|
221
|
+
| 1 | Any failure: a usage error, nothing installed to act on, a verification that did not match, or a `verify-package` mismatch. |
|
|
222
|
+
|
|
223
|
+
### The install record
|
|
224
|
+
|
|
225
|
+
Every install writes `.agents-handoff-install.json` into the copy it just made. [FORMAT.md](FORMAT.md)
|
|
226
|
+
lists the fields and [PROVENANCE.md](PROVENANCE.md) states what the record does and does not prove.
|
|
227
|
+
|
|
228
|
+
| Field | Contents |
|
|
229
|
+
|---|---|
|
|
230
|
+
| `schema_version` | `1.0-install-provenance`. |
|
|
231
|
+
| `product`, `version` | `agents-handoff`, and the version read back out of the installed `SKILL.md`. |
|
|
232
|
+
| `installer_version` | The installer package's own version. |
|
|
233
|
+
| `installed_at` | ISO timestamp of the write. |
|
|
234
|
+
| `harness` | The harness the copy went into, or `null` for the resolved single target. |
|
|
235
|
+
| `target` | Absolute install directory. |
|
|
236
|
+
| `source` | What the copy was made from: `{kind: "tree", path}` for a checkout or release archive, or `{kind: "archive", ref, label, archive_url, archive_sha256}` for a fetched tag archive. |
|
|
237
|
+
| `package` | The npm identity this install should match: `name`, `version`, `registry`, `tarball`, `sha256`, `sha512`, `integrity`, `shasum`, `verified_at`. The hashes are `null` until `verify-package --record` fills them, because a copy made from a tree is not the published tarball. |
|
|
238
|
+
| `file_count`, `manifest_entries` | Files present, and entries in the installer's manifest. |
|
|
239
|
+
| `files_sha256` | One sha256 folded over every manifest path together with that file's own hash. |
|
|
240
|
+
| `files` | Per-path sha256, or `missing` for a path this version does not have. |
|
|
241
|
+
|
|
242
|
+
### What `verify` compares
|
|
243
|
+
|
|
244
|
+
For each installation: that every manifest file exists (a path the version never had is
|
|
245
|
+
reported as not part of that version rather than failed), that `SKILL.md` carries a name and a
|
|
246
|
+
version, that the engine actually runs — `tools/handoff.mjs config` must exit 0 with its
|
|
247
|
+
resolved-root marker, which also proves the import graph resolves — and that a recomputed
|
|
248
|
+
`files_sha256` equals the recorded one. An installation made before this record existed is
|
|
249
|
+
reported as having none, never silently passed.
|
|
250
|
+
|
|
251
|
+
### What `verify-package` checks, and in what order
|
|
252
|
+
|
|
253
|
+
Each step makes the next one meaningful:
|
|
254
|
+
|
|
255
|
+
1. **The registry's own hashes.** The tarball is downloaded for the installed version and must
|
|
256
|
+
match the `integrity` (sha512) and `shasum` (sha1) the registry declares for it; otherwise
|
|
257
|
+
"the published package" is just whatever the network handed over.
|
|
258
|
+
2. **Per-file identity.** The manifest is compared file by file against the extracted tarball,
|
|
259
|
+
and every difference is named (`not installed`, `not in the published package`, or
|
|
260
|
+
`content differs`).
|
|
261
|
+
3. **The recorded hash.** When the install record already holds a package `sha256`, it must
|
|
262
|
+
match too.
|
|
263
|
+
|
|
264
|
+
Without `--record` nothing is written; with it, the fetched `sha256`, `sha512`, `integrity`
|
|
265
|
+
and `shasum` are stored in `package`. A version that is not on the registry cannot pass this
|
|
266
|
+
check, and it says so rather than reporting success.
|
|
267
|
+
|
|
268
|
+
### What `remove` deletes
|
|
269
|
+
|
|
270
|
+
`remove` deletes what the install manifest owns, plus the record it wrote itself and the
|
|
271
|
+
`private` `package.json` stub it created — and nothing else. Store directories, notes, a
|
|
272
|
+
`handoff.config.json`, and any file a later version treats as user data survive by default,
|
|
273
|
+
and every entry that was left is printed under `Kept — not the installer's to delete:`.
|
|
172
274
|
|
|
173
275
|
## Environment variables
|
|
174
276
|
|
|
175
277
|
| Variable | Read by | Effect |
|
|
176
278
|
|---|---|---|
|
|
177
279
|
| `HANDOFFS_ROOT` | capture engine, runtime layer | Store root. Always wins over every other rule. |
|
|
178
|
-
| `AGENT_HANDOFF_STATE_DIR` | runtime engine, capability registry | State directory for executions, checkpoints, jobs and capability state. Default `<repo>/.
|
|
280
|
+
| `AGENT_HANDOFF_STATE_DIR` | runtime engine, capability registry | State directory for executions, checkpoints, jobs and capability state. Default `<repo>/.agents-handoff`. |
|
|
179
281
|
| `AGENT_HANDOFF_GLOBAL_DIR` | installer | Overrides the resolved global install root. |
|
|
180
282
|
|
|
181
283
|
## Files written
|
|
@@ -191,6 +293,7 @@ Published as `agents-handoff`. Location resolution is documented in
|
|
|
191
293
|
| `<state>/jobs/<session>/work.log` | `runtime-engine job` |
|
|
192
294
|
| `<state>/capability-state.json` | `capability-registry check` |
|
|
193
295
|
| `<skill>/docs/self-improve-candidates.json` | `self-improve` |
|
|
296
|
+
| `<install>/.agents-handoff-install.json` | `install`, `update`, `verify-package --record` |
|
|
194
297
|
|
|
195
298
|
`self-improve` writes inside the skill directory on purpose: the candidate file describes the
|
|
196
299
|
skill's brief rules, so a configured store never collects rule candidates.
|
package/docs/COMPATIBILITY.md
CHANGED
|
@@ -37,8 +37,32 @@ dependencies.
|
|
|
37
37
|
| 18.x | SUPPORTED (minimum) |
|
|
38
38
|
| 20.x | SUPPORTED |
|
|
39
39
|
| 22.x | SUPPORTED |
|
|
40
|
+
| 26.x | VERIFIED (developed and released on it) |
|
|
40
41
|
| < 18 | UNSUPPORTED |
|
|
41
42
|
|
|
43
|
+
## Other runtimes: Bun, Deno, TypeScript
|
|
44
|
+
|
|
45
|
+
The tools are plain ESM with `node:` built-ins and no dependencies, so another runtime that
|
|
46
|
+
implements those APIs runs them unchanged. Bun was tested against this release:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
bun tools/handoff.mjs config
|
|
50
|
+
bun tools/handoff.mjs build --source transcript.jsonl --project my-project
|
|
51
|
+
bun tools/handoff.mjs verify my-project # PASS, same hashes as Node
|
|
52
|
+
bun tools/agents-handoff.mjs index
|
|
53
|
+
bun test --timeout 30000 tools/handoff.test.mjs # 34 pass, 0 fail
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
One caveat, and it is a property of the runner rather than of the tools: the suite spawns child
|
|
57
|
+
Node processes, and Bun's default per-test timeout is 5 seconds, so raising it
|
|
58
|
+
(`--timeout 30000`) is what makes all 34 tests pass — at the default, one test times out.
|
|
59
|
+
|
|
60
|
+
The published artifact is JavaScript, not TypeScript, and there is no build step to add one.
|
|
61
|
+
What TypeScript would have declared — the shape of a handoff, a manifest and the LLM payload —
|
|
62
|
+
is declared by the versioned JSON Schemas the runtime validates against
|
|
63
|
+
(`schemas/handoff.schema.json`, `templates/HANDOFF.llm.schema.json`,
|
|
64
|
+
`handoff.config.schema.json`), and `docs/CLI.md` is the interface of record for the commands.
|
|
65
|
+
|
|
42
66
|
## Input formats the engine parses
|
|
43
67
|
|
|
44
68
|
| Format | How it is detected | Fields read |
|
package/docs/CONTRIBUTING.md
CHANGED
|
@@ -91,7 +91,7 @@ Checklist:
|
|
|
91
91
|
- Keep the exit codes. They are contracts (see the table above and
|
|
92
92
|
[INTEGRATION.md](INTEGRATION.md)).
|
|
93
93
|
- Never commit session data or credentials: no `handoffs/`, `projects/`, `links/`,
|
|
94
|
-
`.
|
|
94
|
+
`.agents-handoff/`, no `*.key`, `*.pem`, `*.token`, and no transcript copied from a real
|
|
95
95
|
session. Test input belongs in `tests/fixtures/`.
|
|
96
96
|
- A behaviour change comes with a test in `tools/handoff.test.mjs` and an update to the
|
|
97
97
|
document that owns the contract: [FORMAT.md](FORMAT.md) for the files and fields,
|
|
@@ -108,7 +108,7 @@ Checklist:
|
|
|
108
108
|
| `docs/` | These documents. |
|
|
109
109
|
| `install/` | `install.mjs`, the `npx` installer, and its own README. |
|
|
110
110
|
| `tools/handoff.mjs` | The handoff engine: build, list, show, verify, rename, retitle, config. |
|
|
111
|
-
| `tools/
|
|
111
|
+
| `tools/agents-handoff.mjs` | The runtime verbs layered over the engine. |
|
|
112
112
|
| `tools/runtime-engine.mjs` | Permission policy, bounded execution, checkpoints and resume. |
|
|
113
113
|
| `tools/capability-registry.mjs` | Probes declared capabilities and reports honest verdicts. |
|
|
114
114
|
| `tools/handoff.test.mjs` | The test suite. |
|
package/docs/FORMAT.md
CHANGED
|
@@ -62,6 +62,34 @@ project recorded in its manifest.
|
|
|
62
62
|
Renders (`HANDOFF.md`, the two JSON payloads) are rewritten on every build; `timeline.jsonl`
|
|
63
63
|
is not.
|
|
64
64
|
|
|
65
|
+
## Installed-copy artifacts (not part of a session)
|
|
66
|
+
|
|
67
|
+
Two files belong to an INSTALLATION rather than to a session, and neither is written by the
|
|
68
|
+
capture engine. They sit in the directory the installer copied into, beside `SKILL.md`, and
|
|
69
|
+
nothing above in this document describes them.
|
|
70
|
+
|
|
71
|
+
| File | Written by | Contents |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| `package.json` | `install`, `update` | Only when the directory has none. A minimal manifest marked `private`, so the copy can report its own version and cannot be published to npm by accident. |
|
|
74
|
+
| `.agents-handoff-install.json` | `install`, `update` | The install record: what version landed, from which source, and a sha256 over the installed file set. |
|
|
75
|
+
|
|
76
|
+
The install record:
|
|
77
|
+
|
|
78
|
+
| Field | Meaning |
|
|
79
|
+
|---|---|
|
|
80
|
+
| `schema_version` | `1.0-install-provenance`. |
|
|
81
|
+
| `product`, `version` | The skill this is a copy of, and the version that landed, read back out of the installed `SKILL.md`. |
|
|
82
|
+
| `installer_version`, `installed_at` | The installer that wrote the record, and when. |
|
|
83
|
+
| `harness`, `target` | The harness the copy went to (`claude`, `codex`, `agents`) when one was named, else `null`, and the absolute target path. |
|
|
84
|
+
| `source` | `{kind: 'tree', path}` for a copy made from a tree beside the installer, or `{kind: 'archive', ref, label, archive_url, archive_sha256}` when the copy was fetched instead. |
|
|
85
|
+
| `file_count`, `files_sha256` | How many manifest files the copy holds, and one sha256 over all of them. |
|
|
86
|
+
| `files` | Per-path sha256 values, so a mismatch names the file that changed. |
|
|
87
|
+
|
|
88
|
+
`verify` re-hashes the manifest files, recomputes `files_sha256` and fails when one changed or
|
|
89
|
+
went missing. An installation made before this record existed has none: `verify` says so and
|
|
90
|
+
checks everything else, and treats the absence as neither a pass nor a failure.
|
|
91
|
+
[PROVENANCE.md](PROVENANCE.md) states what the record proves and what it cannot.
|
|
92
|
+
|
|
65
93
|
## manifest.json
|
|
66
94
|
|
|
67
95
|
| Field | Meaning |
|
package/docs/INSTALL.md
CHANGED
|
@@ -4,7 +4,7 @@ title: Installation
|
|
|
4
4
|
|
|
5
5
|
# Installation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
agents-handoff turns a working session into a portable handoff folder, and verifies that folder
|
|
8
8
|
later. It is a Node.js command-line skill with no runtime dependencies.
|
|
9
9
|
|
|
10
10
|
## Requirements
|
|
@@ -13,16 +13,23 @@ later. It is a Node.js command-line skill with no runtime dependencies.
|
|
|
13
13
|
|---|---|
|
|
14
14
|
| Node.js >= 18.0.0 | The engine uses ES modules and `node:fs`. |
|
|
15
15
|
| `unzip` | Only needed to extract a release archive by hand. |
|
|
16
|
-
|
|
|
16
|
+
| `tar` | Only needed when the installer fetches an archive instead of copying the tree beside it. |
|
|
17
|
+
| No network at run time | The engine never makes a network call. `npx` and `--verify-package` do. |
|
|
17
18
|
|
|
18
19
|
## Quick start
|
|
19
20
|
|
|
20
21
|
```bash
|
|
21
|
-
npx agents-handoff
|
|
22
|
+
npx agents-handoff --all # every harness found on this machine
|
|
22
23
|
```
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
One run covers one harness, several, or a directory of your own; the table in
|
|
26
|
+
[Install into the harness you use](#install-into-the-harness-you-use) has the whole set. The
|
|
27
|
+
installer copies the skill files into the resolved global root (or the harness directories
|
|
28
|
+
named), then reports how many files it copied. The published package carries the whole tree, so
|
|
29
|
+
this needs no download; only a bare copy of `install/` falls back to fetching the archive for
|
|
30
|
+
the requested version.
|
|
31
|
+
|
|
32
|
+
Confirm the installation:
|
|
26
33
|
|
|
27
34
|
```bash
|
|
28
35
|
node "<install-path>/tools/handoff.mjs" config
|
|
@@ -37,6 +44,99 @@ handoff: config file=none
|
|
|
37
44
|
handoff: config schema=<dir>/handoff.config.schema.json
|
|
38
45
|
```
|
|
39
46
|
|
|
47
|
+
## Installing from GitHub
|
|
48
|
+
|
|
49
|
+
Two ways, and both install the same tree:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# npm runs the repository's own package straight from GitHub — no registry copy involved
|
|
53
|
+
npx github:Alot1z/agent-handoff --all
|
|
54
|
+
|
|
55
|
+
# or clone it and run the installer from the checkout
|
|
56
|
+
git clone https://github.com/Alot1z/agent-handoff.git
|
|
57
|
+
cd agent-handoff
|
|
58
|
+
node install/install.mjs --all
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The clone is also the way to install a version that is not on npm at all: a branch, a commit or
|
|
62
|
+
a tag. The installer accepts the same flags either way, and a checkout installs the tree in front
|
|
63
|
+
of it.
|
|
64
|
+
|
|
65
|
+
## Install into the harness you use
|
|
66
|
+
|
|
67
|
+
With no harness flag the installer uses the resolved global root (next section). A harness flag
|
|
68
|
+
puts the skill where that tool reads its skills, and several flags cover several tools in one
|
|
69
|
+
run:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npx agents-handoff --claude # Claude Code
|
|
73
|
+
npx agents-handoff --codex # Codex CLI
|
|
74
|
+
npx agents-handoff --agents # the harness-neutral store
|
|
75
|
+
npx agents-handoff --all # every harness found on this machine
|
|
76
|
+
npx agents-handoff --claude --codex # exactly these two, one run
|
|
77
|
+
npx agents-handoff --harness claude,codex
|
|
78
|
+
npx agents-handoff --skills-dir ~/.config/mytool/skills
|
|
79
|
+
npx agents-handoff --project --claude # this repository only (./.claude/skills)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
| Flag | Harness | User-level directory | Per-repository directory, with `--project` |
|
|
83
|
+
|---|---|---|---|
|
|
84
|
+
| `--claude` | Claude Code | `~/.claude/skills` | `./.claude/skills` |
|
|
85
|
+
| `--codex` | Codex CLI | `~/.codex/skills` | `./.codex/skills` |
|
|
86
|
+
| `--agents` | the harness-neutral store | `~/.agents/skills` | `./.agents/skills` |
|
|
87
|
+
| `--harness <a,b>` | named harness(es), comma separated, repeatable | as above | as above |
|
|
88
|
+
| `--skills-dir <dir>` | any other stack, exactly | `<dir>` | `<dir>` |
|
|
89
|
+
| `--all` | every harness whose configuration directory exists here | as above | — |
|
|
90
|
+
|
|
91
|
+
Each target gets the skill folder `agents-handoff/` below that directory, so Claude Code finds
|
|
92
|
+
`~/.claude/skills/agents-handoff/`. Targets are installed, reported and recorded one by one,
|
|
93
|
+
and the run ends with a summary:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
── target 1 of 2: claude ──
|
|
97
|
+
✓ Installed agents-handoff v<version> to <dir>/agents-handoff
|
|
98
|
+
Provenance: the tree beside the installer (.) · file-set sha256 3dab5c0d754a27fd… (.agents-handoff-install.json)
|
|
99
|
+
|
|
100
|
+
── target 2 of 2: custom dir <dir> ──
|
|
101
|
+
…
|
|
102
|
+
|
|
103
|
+
Summary
|
|
104
|
+
✓ installed <dir> — v<version>
|
|
105
|
+
✓ installed <dir> — v<version>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`--all` installs into the harnesses whose configuration directory exists in your home directory
|
|
109
|
+
and names the ones it skipped; `--claude` and its siblings install there whether or not the
|
|
110
|
+
directory exists yet. Detection is a suggestion, never a decision.
|
|
111
|
+
|
|
112
|
+
Ask what this machine has, and whether what is installed is still intact:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
npx agents-handoff doctor
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
agents-handoff doctor
|
|
120
|
+
product v<version> · installer v<version> · node v<node version>
|
|
121
|
+
|
|
122
|
+
Harnesses
|
|
123
|
+
✓ claude present <home>/.claude/skills
|
|
124
|
+
v<version> · 39/39 files · provenance OK
|
|
125
|
+
· codex not found <home>/.codex/skills
|
|
126
|
+
✓ agents present <home>/.agents/skills
|
|
127
|
+
|
|
128
|
+
Global resolution
|
|
129
|
+
<dir> — <reason>
|
|
130
|
+
|
|
131
|
+
Store (where handoffs are written)
|
|
132
|
+
handoff: config root=<dir>
|
|
133
|
+
|
|
134
|
+
Verdict
|
|
135
|
+
1 harness installation(s) found.
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`doctor` reads and reports. It never installs, updates or removes anything.
|
|
139
|
+
|
|
40
140
|
## Where a global install goes
|
|
41
141
|
|
|
42
142
|
`--location global` does not point at a fixed directory. The installer searches for a store and
|
|
@@ -45,7 +145,7 @@ reports the reason it chose one. The order is:
|
|
|
45
145
|
| # | Condition | Result |
|
|
46
146
|
|---|---|---|
|
|
47
147
|
| 1 | `AGENT_HANDOFF_GLOBAL_DIR` is set | that directory |
|
|
48
|
-
| 2 | A skill store already holds an `
|
|
148
|
+
| 2 | A skill store already holds an `agents-handoff` install | the newest such location |
|
|
49
149
|
| 3 | `~/.agents/skills` exists | `~/.agents/skills` |
|
|
50
150
|
| 4 | A skill store exists | its first account-skill root |
|
|
51
151
|
| 5 | Nothing found | the default store, created on install |
|
|
@@ -53,7 +153,7 @@ reports the reason it chose one. The order is:
|
|
|
53
153
|
An account-skill store keeps skills two identifier levels below the store itself:
|
|
54
154
|
|
|
55
155
|
```
|
|
56
|
-
<store>/<account-id>/<profile-id>/
|
|
156
|
+
<store>/<account-id>/<profile-id>/agents-handoff/
|
|
57
157
|
```
|
|
58
158
|
|
|
59
159
|
`<store>` is `%APPDATA%\<client>\account-skills` on Windows, and `~/.<client>/account-skills` or
|
|
@@ -72,17 +172,18 @@ Global install root: <dir>
|
|
|
72
172
|
override with: AGENT_HANDOFF_GLOBAL_DIR=<dir> or --path <dir>
|
|
73
173
|
```
|
|
74
174
|
|
|
75
|
-
`--list` shows the resolved root, the local location, every candidate root,
|
|
76
|
-
|
|
77
|
-
with its version
|
|
175
|
+
`--list` shows the resolved root, the local location, every candidate root, each harness
|
|
176
|
+
directory (whether or not it exists on this machine), and — inside a git repository — the
|
|
177
|
+
project location. Each installation found is printed with its version, the number of manifest
|
|
178
|
+
files present, and whether it still matches its install record.
|
|
78
179
|
|
|
79
180
|
## Locations
|
|
80
181
|
|
|
81
182
|
| Location | Target directory |
|
|
82
183
|
|---|---|
|
|
83
|
-
| `global` (default) | `<resolved global root>/
|
|
84
|
-
| `local` | `./local/skills/
|
|
85
|
-
| `project` | `./skills/
|
|
184
|
+
| `global` (default) | `<resolved global root>/agents-handoff` |
|
|
185
|
+
| `local` | `./local/skills/agents-handoff` |
|
|
186
|
+
| `project` | `./skills/agents-handoff` |
|
|
86
187
|
| `--path <dir>` | exactly `<dir>` |
|
|
87
188
|
|
|
88
189
|
## Options
|
|
@@ -93,21 +194,31 @@ with its version and the number of manifest files present.
|
|
|
93
194
|
| `--path <dir>` | none | Use this directory instead of a resolved location. |
|
|
94
195
|
| `--version <v>` | `latest` | Request a version. Confirm what landed with `--verify`, which prints the installed version. |
|
|
95
196
|
| `--force`, `-f` | off | Skip confirmations and overwrite an existing installation. |
|
|
197
|
+
| `--claude`, `--codex`, `--agents` | none | Install into that harness's skills directory (table above). Repeatable, and combinable. |
|
|
198
|
+
| `--harness <a,b>` | none | Named harness(es), comma separated. Repeatable. |
|
|
199
|
+
| `--all` | none | Every harness whose configuration directory exists on this machine. |
|
|
200
|
+
| `--skills-dir <dir>` | none | Any other stack, exactly. Repeatable. |
|
|
201
|
+
| `--project` | off | With a harness flag: use the per-repository directory instead of the user-level one. |
|
|
202
|
+
| `--provenance` | off | With `verify`: print the install record the verification was checked against. |
|
|
203
|
+
| `--record` | off | With `verify-package`: store the tarball hashes in the install record. |
|
|
96
204
|
| `--help`, `-h` | — | Print the installer usage text. |
|
|
97
205
|
|
|
98
206
|
The installer accepts both bare verbs and flag forms: `install`/`--install`, `update`/`--update`,
|
|
99
|
-
`remove`/`--remove`, `verify`/`--verify`, `list`/`--list
|
|
207
|
+
`remove`/`--remove`, `verify`/`--verify`, `verify-package`/`--verify-package`, `list`/`--list`,
|
|
208
|
+
`doctor`/`--doctor`.
|
|
100
209
|
|
|
101
210
|
## Commands
|
|
102
211
|
|
|
103
212
|
| Command | Description |
|
|
104
213
|
|---|---|
|
|
105
214
|
| `install`, `i` (default) | Copy the skill files to the target. |
|
|
106
|
-
| `update`, `u` |
|
|
107
|
-
| `remove`, `rm` | Remove the
|
|
108
|
-
| `verify`, `v` | Check every manifest file, the skill metadata,
|
|
109
|
-
| `
|
|
215
|
+
| `update`, `u` | Update every installation found, or the harnesses named. See [UPGRADE.md](UPGRADE.md). |
|
|
216
|
+
| `remove`, `rm` | Remove an installation, keeping everything the manifest does not own. See [UNINSTALL.md](UNINSTALL.md). |
|
|
217
|
+
| `verify`, `v` | Check every installation found: each manifest file, the skill metadata, that the engine runs, and the install record. |
|
|
218
|
+
| `verify-package`, `vp` | Check an installation against the published npm tarball for its version. |
|
|
219
|
+
| `list`, `ls` | List installed locations with version, manifest file count and provenance state. |
|
|
110
220
|
| `where` | Print the global root and why it was chosen. |
|
|
221
|
+
| `doctor` | Which harnesses are present here, what is installed where, and whether each installation still matches its record. |
|
|
111
222
|
|
|
112
223
|
## Verify an installation
|
|
113
224
|
|
|
@@ -115,18 +226,115 @@ The installer accepts both bare verbs and flag forms: `install`/`--install`, `up
|
|
|
115
226
|
npx agents-handoff --verify
|
|
116
227
|
```
|
|
117
228
|
|
|
118
|
-
Verification runs
|
|
229
|
+
Verification runs four kinds of check:
|
|
119
230
|
|
|
120
231
|
1. every file named in the installer manifest exists in the target;
|
|
121
232
|
2. `SKILL.md` declares both `name` and `version`;
|
|
122
233
|
3. `node tools/handoff.mjs config` exits 0 and prints the `handoff: config root=` marker — this
|
|
123
|
-
exercises the engine's module graph, so a missing module fails here
|
|
234
|
+
exercises the engine's module graph, so a missing module fails here;
|
|
235
|
+
4. the installation still matches the provenance record written when it was installed.
|
|
124
236
|
|
|
125
237
|
Each check is printed with a pass or fail mark. On success the installer also prints the
|
|
126
|
-
installed location and version; on failure it exits non-zero and
|
|
238
|
+
installed location and version; on failure it exits non-zero and names the files that changed.
|
|
239
|
+
|
|
240
|
+
With no harness flag, `--verify` verifies **every installation found on this machine**, not just
|
|
241
|
+
the one the global resolver would pick: a machine that holds the skill in `~/.claude/skills` and
|
|
242
|
+
in `~/.agents/skills` has two copies, and both are checked. A harness flag or `--skills-dir`
|
|
243
|
+
scopes the run to those targets. The run fails if any installation fails.
|
|
127
244
|
|
|
128
245
|
There is no `--verbose` flag.
|
|
129
246
|
|
|
247
|
+
## Prove an installation matches the published package
|
|
248
|
+
|
|
249
|
+
`--verify` compares an installation with its own record. `--verify-package` compares it with the
|
|
250
|
+
artifact npm is actually serving for its version — the strongest check available, and it works
|
|
251
|
+
whichever way the install happened: from a tree, from a GitHub archive, or from `npx`.
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
npx agents-handoff --verify-package
|
|
255
|
+
npx agents-handoff --verify-package --record
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
It runs three checks, in this order, because each one makes the next meaningful:
|
|
259
|
+
|
|
260
|
+
1. the downloaded tarball matches the hashes the **registry declares** for that version
|
|
261
|
+
(`dist.integrity` and `dist.shasum`) — otherwise "the published package" would be whatever
|
|
262
|
+
the network handed over;
|
|
263
|
+
2. every file named in the installer manifest is byte-identical to the file of that name in the
|
|
264
|
+
published tarball — each difference is named, with `not installed`, `not in the published
|
|
265
|
+
package` or `content differs`;
|
|
266
|
+
3. the tarball's sha256 matches the one recorded for this installation, when one was recorded.
|
|
267
|
+
|
|
268
|
+
It prints the package name and version, the tarball URL and the tarball's sha256. `--record`
|
|
269
|
+
stores that sha256 (plus sha512, the integrity string and the shasum) in the `package` block of
|
|
270
|
+
the install record, so every later run compares against a stored value instead of re-deriving
|
|
271
|
+
one.
|
|
272
|
+
|
|
273
|
+
This check needs the network. When the registry cannot be reached, or the installed version is
|
|
274
|
+
not published, it fails and says so — it never passes by default.
|
|
275
|
+
|
|
276
|
+
## The install record (provenance)
|
|
277
|
+
|
|
278
|
+
Every install writes `.agents-handoff-install.json` inside the installed copy. It records what
|
|
279
|
+
landed and what it was made from:
|
|
280
|
+
|
|
281
|
+
| Field | Meaning |
|
|
282
|
+
|---|---|
|
|
283
|
+
| `product`, `version`, `installer_version` | What was installed, and which installer did it. |
|
|
284
|
+
| `installed_at` | When. |
|
|
285
|
+
| `harness`, `target` | Which harness flag selected the target, and its absolute path. |
|
|
286
|
+
| `source` | `the tree beside the installer`, or the tag archive with its URL and sha256. |
|
|
287
|
+
| `package` | The npm identity this installation should match: `name`, `version`, `registry`, `tarball`, and — once `--verify-package --record` has run — `sha256`, `sha512`, `integrity`, `shasum` and `verified_at`. |
|
|
288
|
+
| `file_count`, `files_sha256` | The installed file set, folded into one hash. |
|
|
289
|
+
| `files` | Every manifest path with its own sha256. |
|
|
290
|
+
|
|
291
|
+
`verify` re-hashes the same file set and compares it with the record, so a changed, missing or
|
|
292
|
+
renamed file fails the check and is named. That is the difference between an installation being
|
|
293
|
+
present and being checkable: the file that changed is reported, not just `verification failed`.
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
npx agents-handoff --verify --provenance
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
`--provenance` prints the record it checked against, so the verification can be read without
|
|
300
|
+
opening the file:
|
|
301
|
+
|
|
302
|
+
```
|
|
303
|
+
provenance record
|
|
304
|
+
installed_at: <iso timestamp>
|
|
305
|
+
source: the tree beside the installer (.)
|
|
306
|
+
harness: claude
|
|
307
|
+
files: 39 · file-set sha256 3dab5c0d754a27fd…
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
An installation made before the record existed reports
|
|
311
|
+
`· no provenance record — installed before 2.0.3; reinstall to record one` and is otherwise
|
|
312
|
+
verified as before. Reinstall to write one.
|
|
313
|
+
|
|
314
|
+
The `package` block is the hook for the published-tarball check: installing from a tree cannot
|
|
315
|
+
know the hash of a tarball it did not download, so the hash is recorded the first time
|
|
316
|
+
`npx agents-handoff --verify-package --record` runs, and compared on every run after that.
|
|
317
|
+
|
|
318
|
+
## What `remove` keeps
|
|
319
|
+
|
|
320
|
+
`remove` deletes exactly what the install manifest owns — the skill files, and the two files the
|
|
321
|
+
installer writes for itself — and nothing else. Everything the manifest does not own is kept and
|
|
322
|
+
listed:
|
|
323
|
+
|
|
324
|
+
```
|
|
325
|
+
Kept — not the installer's to delete:
|
|
326
|
+
.agent-handoff/
|
|
327
|
+
handoff-session.md
|
|
328
|
+
handoff.config.json
|
|
329
|
+
handoffs/
|
|
330
|
+
projects/
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
The rule is stated as a removal set rather than a keep list on purpose: a keep list deletes
|
|
334
|
+
whatever nobody remembered to name, so a store called anything other than the expected
|
|
335
|
+
directories would have gone with the skill. A `package.json` you wrote yourself is kept too; only
|
|
336
|
+
the installer's own private stub is removed.
|
|
337
|
+
|
|
130
338
|
## Installing again
|
|
131
339
|
|
|
132
340
|
Installing over an existing installation does nothing by default when the requested version is
|
|
@@ -137,8 +345,9 @@ Installing over an existing installation does nothing by default when the reques
|
|
|
137
345
|
|
|
138
346
|
Use the release archive when you cannot run `npx`.
|
|
139
347
|
|
|
140
|
-
1. Download the archive
|
|
141
|
-
|
|
348
|
+
1. Download the archive the release attaches: `agents-handoff-v<version>.zip` from the
|
|
349
|
+
[releases page](https://github.com/Alot1z/agent-handoff/releases) (there is no
|
|
350
|
+
`latest` asset — the newest release carries its own version in the file name).
|
|
142
351
|
2. Extract it into the target directory with `unzip`.
|
|
143
352
|
3. Confirm the engine runs: `node "<target>/tools/handoff.mjs" config`.
|
|
144
353
|
|
|
@@ -164,13 +373,19 @@ By default the engine stores handoff data under its own root, inside the install
|
|
|
164
373
|
| Symptom | Cause and fix |
|
|
165
374
|
|---|---|
|
|
166
375
|
| `Cannot write to <dir>` | The target is not writable. Pick another location with `--path`, or fix permissions. |
|
|
167
|
-
| `Not installed at <dir>` | `
|
|
376
|
+
| `Not installed at <dir>` | `--path` or a harness flag named a directory that holds no installation. Drop the flag to act on every installation found, or run `install` first. |
|
|
377
|
+
| `Nothing to update:` / `Nothing to verify:` | No installation was found anywhere the installer looks. Install one, or name a target with `--path`. |
|
|
378
|
+
| `verify-package` fails with `is not on the npm registry, or the registry is unreachable` | The installed version has no published tarball to compare against (a checkout install, or no network). The installation itself is untouched by that result. |
|
|
379
|
+
| `verify-package` fails with `does NOT match ... as published` | The check names each differing file. Reinstall with `--force`, then run it again; a file you edited on purpose will keep failing until it is reverted. |
|
|
168
380
|
| `Incomplete install: <n> of <m> file(s) missing — …` | The tree the installer reads from is not a complete one. Install from a fresh clone, or from a freshly downloaded archive. |
|
|
169
381
|
| `no published release found — fetching the main branch` | Not an error: `--version latest` found no release object, so the archive of `main` is used instead. Pass `--version <x>` to install a released tag. |
|
|
170
382
|
| `Cannot extract the archive (tar exited …)` | `tar` is missing, or the download did not arrive intact. The message prints the `curl` and `tar` commands that do the same job by hand. |
|
|
171
383
|
| The wrong root was chosen | Run `where` to see the reason, then set `AGENT_HANDOFF_GLOBAL_DIR` or pass `--path`. |
|
|
172
384
|
| `remove` did nothing | Removal asks for confirmation, and refuses in a non-interactive shell. Pass `--force`. |
|
|
173
385
|
| Verification fails | The output names the failing check. Fix it, or reinstall with `--force`. |
|
|
386
|
+
| `provenance: file-set sha256 matches the install record` fails | A file in the installation changed or went missing after it was installed. The changed paths are listed under the check; reinstall with `--force` to restore them, or keep the edit knowingly. |
|
|
387
|
+
| `no provenance record` | The installation predates the record. That is not a failure; reinstall to write one. |
|
|
388
|
+
| A harness install went somewhere unexpected | Harness directories are listed in the table above and by `doctor`/`list`. Use `--path` or `--skills-dir` to name the directory yourself. |
|
|
174
389
|
|
|
175
390
|
## See also
|
|
176
391
|
|