@manyoars/oars 0.4.1 → 0.5.1
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 +79 -29
- package/dist/bin.js +3 -1
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +206 -20
- package/dist/club.d.ts +19 -0
- package/dist/club.js +132 -0
- package/dist/gate/hook-fill-main.js +1 -1
- package/dist/gate/hook-fill.d.ts +1 -1
- package/dist/gate/hook-fill.js +1 -1
- package/dist/gate/hook-main.js +7 -5
- package/dist/gate/hook.d.ts +12 -1
- package/dist/gate/hook.js +38 -7
- package/dist/hook-bin.js +23 -4
- package/dist/main.js +5 -0
- package/dist/node-floor.d.ts +10 -0
- package/dist/node-floor.js +23 -0
- package/dist/oars-hook.d.ts +2 -0
- package/dist/oars-hook.js +7 -0
- package/dist/sessions/allow.d.ts +1 -0
- package/dist/sessions/allow.js +1 -1
- package/dist/sessions/call-shape.d.ts +111 -0
- package/dist/sessions/call-shape.js +464 -0
- package/dist/sessions/candidates.d.ts +65 -0
- package/dist/sessions/candidates.js +236 -0
- package/dist/sessions/card-command.d.ts +24 -0
- package/dist/sessions/card-command.js +71 -0
- package/dist/sessions/card-font.d.ts +6 -0
- package/dist/sessions/card-font.js +36 -0
- package/dist/sessions/card-line.d.ts +30 -0
- package/dist/sessions/card-line.js +105 -0
- package/dist/sessions/card-render.d.ts +15 -0
- package/dist/sessions/card-render.js +146 -0
- package/dist/sessions/card.d.ts +59 -0
- package/dist/sessions/card.js +107 -0
- package/dist/sessions/cell-increments.d.ts +14 -3
- package/dist/sessions/cell-increments.js +79 -12
- package/dist/sessions/cells.d.ts +42 -4
- package/dist/sessions/cells.js +72 -18
- package/dist/sessions/codex-hook-bin.d.ts +1 -0
- package/dist/sessions/codex-hook-bin.js +24 -0
- package/dist/sessions/codex-hook-install.d.ts +21 -0
- package/dist/sessions/codex-hook-install.js +47 -0
- package/dist/sessions/codex-hook-view.d.ts +20 -0
- package/dist/sessions/codex-hook-view.js +20 -0
- package/dist/sessions/codex-hook.d.ts +77 -0
- package/dist/sessions/codex-hook.js +255 -0
- package/dist/sessions/codex.d.ts +9 -0
- package/dist/sessions/codex.js +104 -18
- package/dist/sessions/command.d.ts +17 -2
- package/dist/sessions/command.js +145 -33
- package/dist/sessions/copilot.d.ts +3 -0
- package/dist/sessions/copilot.js +12 -4
- package/dist/sessions/derive.js +2 -1
- package/dist/sessions/empty-state.d.ts +17 -0
- package/dist/sessions/empty-state.js +38 -0
- package/dist/sessions/exclusion.js +48 -3
- package/dist/sessions/extract.d.ts +16 -3
- package/dist/sessions/extract.js +281 -24
- package/dist/sessions/gemini.d.ts +2 -0
- package/dist/sessions/gemini.js +29 -2
- package/dist/sessions/harness-files.d.ts +27 -0
- package/dist/sessions/harness-files.js +109 -0
- package/dist/sessions/head-only.d.ts +7 -0
- package/dist/sessions/head-only.js +21 -0
- package/dist/sessions/hook-calls.js +4 -3
- package/dist/sessions/hooks.d.ts +1 -1
- package/dist/sessions/hooks.js +6 -2
- package/dist/sessions/identity.d.ts +6 -0
- package/dist/sessions/injected.d.ts +13 -0
- package/dist/sessions/injected.js +212 -0
- package/dist/sessions/install.d.ts +31 -20
- package/dist/sessions/install.js +80 -82
- package/dist/sessions/load-status.d.ts +41 -0
- package/dist/sessions/load-status.js +156 -0
- package/dist/sessions/machine-child-deps.d.ts +5 -0
- package/dist/sessions/machine-child-deps.js +83 -0
- package/dist/sessions/machine-child.d.ts +43 -0
- package/dist/sessions/machine-child.js +120 -0
- package/dist/sessions/machine-credential.d.ts +10 -0
- package/dist/sessions/machine-credential.js +20 -0
- package/dist/sessions/machine-enroll.d.ts +47 -0
- package/dist/sessions/machine-enroll.js +230 -0
- package/dist/sessions/machine-hold.d.ts +49 -0
- package/dist/sessions/machine-hold.js +88 -0
- package/dist/sessions/machine-ids.d.ts +6 -0
- package/dist/sessions/machine-ids.js +9 -0
- package/dist/sessions/machine-notice.d.ts +21 -0
- package/dist/sessions/machine-notice.js +89 -0
- package/dist/sessions/machine-pull.d.ts +40 -0
- package/dist/sessions/machine-pull.js +220 -0
- package/dist/sessions/machine-repo.d.ts +7 -0
- package/dist/sessions/machine-repo.js +30 -0
- package/dist/sessions/machine-scan-cache.d.ts +12 -0
- package/dist/sessions/machine-scan-cache.js +47 -0
- package/dist/sessions/machine-send.d.ts +12 -0
- package/dist/sessions/machine-send.js +156 -0
- package/dist/sessions/machine-stop.d.ts +22 -0
- package/dist/sessions/machine-stop.js +53 -0
- package/dist/sessions/machine.d.ts +41 -0
- package/dist/sessions/machine.js +89 -0
- package/dist/sessions/opencode.d.ts +2 -0
- package/dist/sessions/opencode.js +6 -0
- package/dist/sessions/otel.d.ts +21 -0
- package/dist/sessions/otel.js +109 -38
- package/dist/sessions/owner-only.d.ts +7 -0
- package/dist/sessions/owner-only.js +34 -0
- package/dist/sessions/pi.d.ts +13 -1
- package/dist/sessions/pi.js +27 -13
- package/dist/sessions/pool-books.d.ts +1 -1
- package/dist/sessions/pool-books.js +1 -1
- package/dist/sessions/pool-choices.d.ts +4 -2
- package/dist/sessions/pool-choices.js +4 -2
- package/dist/sessions/pool-command.d.ts +46 -6
- package/dist/sessions/pool-command.js +577 -133
- package/dist/sessions/pool-delta.d.ts +7 -0
- package/dist/sessions/pool-delta.js +28 -5
- package/dist/sessions/pool-due.d.ts +43 -0
- package/dist/sessions/pool-due.js +113 -0
- package/dist/sessions/pool-nightly.d.ts +9 -1
- package/dist/sessions/pool-nightly.js +65 -21
- package/dist/sessions/pool-outbox.d.ts +51 -5
- package/dist/sessions/pool-outbox.js +217 -24
- package/dist/sessions/pool-print.d.ts +1 -1
- package/dist/sessions/pool-raw.js +4 -3
- package/dist/sessions/pool-replica.d.ts +4 -4
- package/dist/sessions/pool-replica.js +26 -7
- package/dist/sessions/pool-send-lock.js +1 -1
- package/dist/sessions/pool-sent.d.ts +2 -0
- package/dist/sessions/pool-sent.js +21 -4
- package/dist/sessions/pool-wire.d.ts +172 -12
- package/dist/sessions/pool-wire.js +284 -30
- package/dist/sessions/pool.js +4 -2
- package/dist/sessions/public-vocabulary.d.ts +5 -0
- package/dist/sessions/public-vocabulary.js +16 -0
- package/dist/sessions/read-call-shape.js +12 -6
- package/dist/sessions/read-fit.d.ts +5 -0
- package/dist/sessions/read-fit.js +23 -2
- package/dist/sessions/read.d.ts +1 -1
- package/dist/sessions/recall-consequence.d.ts +2 -2
- package/dist/sessions/recall-consequence.js +14 -9
- package/dist/sessions/recall-object.d.ts +9 -2
- package/dist/sessions/receipt.d.ts +8 -0
- package/dist/sessions/receipt.js +78 -0
- package/dist/sessions/recovery-calls.d.ts +3 -2
- package/dist/sessions/recovery-calls.js +9 -3
- package/dist/sessions/redact.d.ts +2 -2
- package/dist/sessions/redact.js +116 -14
- package/dist/sessions/reversion.d.ts +8 -0
- package/dist/sessions/reversion.js +114 -0
- package/dist/sessions/schema.d.ts +78 -4
- package/dist/sessions/schema.js +31 -1
- package/dist/sessions/session-shape.d.ts +2 -1
- package/dist/sessions/session-shape.js +15 -0
- package/dist/sessions/sources.d.ts +9 -0
- package/dist/sessions/sources.js +16 -5
- package/dist/sessions/steps.js +3 -2
- package/dist/sessions/store.d.ts +41 -2
- package/dist/sessions/store.js +68 -16
- package/dist/sessions/try-demo.d.ts +8 -0
- package/dist/sessions/try-demo.js +90 -0
- package/dist/sessions/try.d.ts +13 -0
- package/dist/sessions/try.js +50 -0
- package/dist/sessions/vscode-copilot.d.ts +4 -0
- package/dist/sessions/vscode-copilot.js +25 -18
- package/dist/telemetry/command.js +12 -6
- package/dist/telemetry/consent.d.ts +9 -3
- package/dist/telemetry/consent.js +25 -9
- package/dist/telemetry/fields.d.ts +11 -0
- package/dist/telemetry/fields.js +56 -0
- package/dist/telemetry/measures.d.ts +13 -0
- package/dist/telemetry/measures.js +30 -0
- package/dist/telemetry/observe.d.ts +15 -2
- package/dist/telemetry/observe.js +34 -7
- package/dist/telemetry/region.d.ts +6 -0
- package/dist/telemetry/region.js +28 -0
- package/dist/telemetry/report.js +1 -1
- package/dist/telemetry/schema.d.ts +3 -0
- package/dist/telemetry/schema.js +11 -1
- package/dist/telemetry/send.d.ts +5 -2
- package/dist/telemetry/send.js +15 -7
- package/dist/telemetry/words.d.ts +6 -0
- package/dist/telemetry/words.js +6 -0
- package/package.json +23 -4
package/README.md
CHANGED
|
@@ -1,24 +1,37 @@
|
|
|
1
1
|
# @manyoars/oars
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Accounts are not open yet: `oars login` uses the Many Oars issuer by default, and until Many Oars sign-in at `login.manyoars.com` is deployed it exits 2 with an error that names `login.manyoars.com`.
|
|
6
|
-
|
|
7
|
-
Node 24 or later. ESM only.
|
|
3
|
+
oars keeps a local, searchable record of your coding agent sessions, across Claude Code, Cursor, Codex, and other harnesses. Ask it about an error and it shows how many past sessions hit it, when, and which tools came next. More at [manyoars.com](https://manyoars.com/).
|
|
8
4
|
|
|
9
5
|
## Install
|
|
10
6
|
|
|
11
7
|
```sh
|
|
12
8
|
npm install --global @manyoars/oars
|
|
13
|
-
oars --help
|
|
14
9
|
```
|
|
15
10
|
|
|
11
|
+
Node 22.23.4 or later. ESM only. Local recall needs no account.
|
|
12
|
+
|
|
16
13
|
Or run it once without installing:
|
|
17
14
|
|
|
18
15
|
```sh
|
|
19
|
-
npx @manyoars/oars
|
|
16
|
+
npx @manyoars/oars sessions try
|
|
20
17
|
```
|
|
21
18
|
|
|
19
|
+
Sample output (made-up sessions, from `oars sessions try`):
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
$ oars sessions recall --error "unexpected EOF while looking for matching quote"
|
|
23
|
+
Bash | bash: -c: line <n>: unexpected EOF while looking for matching quote
|
|
24
|
+
3 sessions, 3 errors, first 2026-10-06T10:00:15.000Z, last 2026-10-20T10:00:27.000Z
|
|
25
|
+
harness 2.1.300; followed by Bash x2, Read x1, Write x1; an edit followed 1 times
|
|
26
|
+
|
|
27
|
+
$ oars sessions recall --context --cwd C:\work\demo
|
|
28
|
+
oars recall: errors that recur in this repository's earlier sessions. Check these before retrying:
|
|
29
|
+
- Bash | bash: -c: line <n>: unexpected EOF while looking for matching quote (3 sessions in the last 300; next: Bash, Read, Write)
|
|
30
|
+
- Write | File has not been read yet. Read it first before writing to it. (2 sessions in the last 300; next: Read, Bash, Write)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
No coding-agent history yet? `oars sessions try` runs recall, books, and the hook line over made-up sessions in a throwaway store under your temp folder, labeled synthetic and deleted on exit, and never touches your own store.
|
|
34
|
+
|
|
22
35
|
## Commands
|
|
23
36
|
|
|
24
37
|
`oars --help` lists the commands below (`oars help <command>` shows one command's flags). `oars --version` prints the version.
|
|
@@ -33,6 +46,8 @@ These flags work on every command:
|
|
|
33
46
|
|
|
34
47
|
Signs in with your browser (RFC 8628 device flow) and stores the login.
|
|
35
48
|
|
|
49
|
+
Accounts are not open yet: `oars login` uses the Many Oars issuer by default, and until Many Oars sign-in at `login.manyoars.com` is deployed it exits 2 with an error that names `login.manyoars.com`.
|
|
50
|
+
|
|
36
51
|
- `--no-browser` prints the link and code without opening a browser.
|
|
37
52
|
- `--issuer-url <url>` is the Keycloak realm URL. The default is `OARS_ISSUER_URL`. With neither, `login` uses the built-in Many Oars issuer, `https://login.manyoars.com/realms/aor`; nothing has to be switched on first. When the built-in issuer does not answer discovery (it may not be deployed yet), with no `--issuer-url` or `OARS_ISSUER_URL`, the command prints "Cannot reach Many Oars sign-in at login.manyoars.com (it may not be deployed yet). Pass --issuer-url or set OARS_ISSUER_URL to use another issuer." and exits 2.
|
|
38
53
|
|
|
@@ -53,23 +68,37 @@ Revokes the stored login and deletes it.
|
|
|
53
68
|
|
|
54
69
|
### telemetry
|
|
55
70
|
|
|
56
|
-
|
|
71
|
+
- On by default: each command leaves an event in a local spool under `<config>/oars/telemetry/`, with counts, sizes, and closed words. It never holds session content, prompt text, a file path, a URL, or an argument.
|
|
72
|
+
- oars sends the events in batches, at most once a day, to the pool server in `OARS_POOL_URL` if you set one, else to the Many Oars pool (`https://pool.manyoars.com`), which is live. A per-install random id is in each event. Telemetry is off, with no prompt, on a machine whose time zone is in the EU, the EEA, or the UK (no switch overrides that); everywhere else, Many Oars Co. may license Usage Data, the events oars sends, as the first-run notice states.
|
|
73
|
+
- `oars telemetry status` says whether it is on and why; `oars telemetry show` prints the spool as stored; `oars telemetry report` prints your own numbers from it.
|
|
74
|
+
- `oars telemetry off` stops recording and sending; `oars telemetry on` resumes it. `OARS_TELEMETRY=0` or `DO_NOT_TRACK=1` turns it off for the process and wins over `on`.
|
|
75
|
+
- Every event type and field, with an example, is in [docs/telemetry.md](https://github.com/manyoars/oars/blob/main/docs/telemetry.md).
|
|
57
76
|
|
|
58
|
-
|
|
59
|
-
- `oars telemetry off` stops recording and sending; `oars telemetry on` resumes it and prints the notice again.
|
|
60
|
-
- `oars telemetry show` prints the spool exactly as stored, oldest first.
|
|
61
|
-
- `oars telemetry report` prints your own numbers from the spool (hook latency percentiles, hit rates, and store health over the last 7 and 30 days) with no server and no account, and the fleet's percentile beside each when `OARS_POOL_URL` names a server that serves it.
|
|
62
|
-
- `OARS_TELEMETRY=0` or `DO_NOT_TRACK=1` turns it off for the process, and wins over `oars telemetry on`.
|
|
77
|
+
### card
|
|
63
78
|
|
|
64
|
-
|
|
79
|
+
```
|
|
80
|
+
oars card --text # your week as a table, sized for a screenshot
|
|
81
|
+
oars card --month # the last 30 days as a picture: oars-card-month.png and .svg in this folder
|
|
82
|
+
oars card --year --out me.png # the last 365 days, saved as me.png and me.svg
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`oars card` makes a share-ready card of your own week (the default, the last 7 days), month, or year across every harness, read from the local session store only. It shows your sessions and active days, the harnesses and models you used, tokens by model, tool calls, failed calls and how many were followed by a different next step, how often an edit was verified, commits and how many survived, and cost only where the harness recorded one. A count under the same floor `oars sessions books` uses prints `too few`. The depositor row reads `ashore: run oars pool login` until you sign in; signed in, it reads the number of weeks in which this machine sent a deposit, from the local sent record, and says it is this machine's.
|
|
86
|
+
|
|
87
|
+
Once a week, the first command you run in a terminal on or after Friday prints one line to stderr, `Your week: N sessions, M strokes. \`oars card --text\` for the table.`, never with `--json`, from a hook, from the MCP server, from a recall, from `oars sessions try`, or from `oars card` itself, and only when the week has a session. About one install in ten never sees it; `card-line.json` in the session store folder records the week and whether it was `shown`, `held`, or `not_due`, and `card-line-id` holds the id the holdback hashes, copied once from the telemetry install id when there is one, else random, so the arm never changes.
|
|
88
|
+
|
|
89
|
+
Nothing is uploaded and nothing is sent anywhere: the command makes no network call and prints one prefilled `x.com` link whose text is the card's own numbers, for you to post if you choose. The card carries no folder name, path, prompt or response text, repository name, or long-tail tool or model name, and posting it unlocks nothing. The picture is a byte-stable SVG and a PNG drawn from it with a built-in font; `--text` prints the table and writes nothing. `--no-cost` leaves the cost row out of the picture, the table, and `--json`.
|
|
65
90
|
|
|
66
91
|
### sessions
|
|
67
92
|
|
|
68
93
|
`oars sessions` keeps a local, deterministic memory of your own coding-agent sessions. The session commands make no model call and no network call, except `gold arms`, which sends redacted text through your own Claude subscription. oars also records telemetry events (a command's path, its flag names, how long it took, its exit code, and its error class, with a random install id, the oars version, the OS, and the time; never session content, prompts, paths, URLs, or argument values), which oars sends in batches to the pool server in `OARS_POOL_URL`, else to the Many Oars pool (live) ([what telemetry records and how to turn it off](https://github.com/manyoars/oars/blob/main/docs/telemetry.md)).
|
|
69
94
|
|
|
70
|
-
What it captures: by default, the sessions of every Claude Code project folder and the sessions of Cursor, Codex, Copilot CLI, Gemini CLI, Grok Build, OpenCode, Pi, and VS Code Copilot Chat, plus OpenTelemetry GenAI agent traces (OTLP JSON files) from the folder `OARS_OTEL_TRACES` names (else `<config>/oars/otel-traces`), when there is one. `--allow` narrows that to the folders and stores you name (`--allow cursor`, `codex`, `copilot`, `gemini`, `grok`, `opencode`, `pi`, `vscode-copilot`, `otel` name the stores), and `--deny` keeps one out. Where it stores them: `<config>/oars/sessions/` on your machine (`<config>` is `%APPDATA%` on Windows, `$XDG_CONFIG_HOME` or `~/.config` elsewhere). The `raw/` folder in it is on by default and holds raw transcripts (a hard link or copy of each deposited one). Secret masking applies to the log, not to `raw/`: those files are unredacted and keep whatever the transcript held, secrets included. They stay on your machine: apart from `gold arms`, no session command uploads them, telemetry carries nothing from them, and after a yes to the raw prompt (`oars pool raw`) and covenant acceptance, the
|
|
95
|
+
What it captures: by default, the sessions of every Claude Code project folder and the sessions of Cursor, Codex, Copilot CLI, Gemini CLI, Grok Build, OpenCode, Pi, and VS Code Copilot Chat, plus OpenTelemetry GenAI agent traces (OTLP JSON files) from the folder `OARS_OTEL_TRACES` names (else `<config>/oars/otel-traces`), when there is one. `--allow` narrows that to the folders and stores you name (`--allow cursor`, `codex`, `copilot`, `gemini`, `grok`, `opencode`, `pi`, `vscode-copilot`, `otel` name the stores), and `--deny` keeps one out. Where it stores them: `<config>/oars/sessions/` on your machine (`<config>` is `%APPDATA%` on Windows, `$XDG_CONFIG_HOME` or `~/.config` elsewhere). The `raw/` folder in it is on by default and holds raw transcripts (a hard link or copy of each deposited one). Secret masking applies to the log, not to `raw/`: those files are unredacted and keep whatever the transcript held, secrets included. They stay on your machine: apart from `gold arms`, no session command uploads them, telemetry carries nothing from them, and after a yes to the raw prompt (`oars pool raw`) and covenant acceptance, the sender uploads a redacted copy of each (never the file itself), except from a folder set to skeleton only or off. To remove them, see [Remove everything](#remove-everything).
|
|
71
96
|
|
|
72
|
-
|
|
97
|
+
A machine that deposits for you (a cloud environment, a VPS, a CI runner) has its own deposit-only key, enrolled and revoked from your machine. `oars pool enroll --host-class <vps|cloud|ci> --launcher <interactive|orchestrated|scheduled> --name <label> --allow-repos <owner/name,...> [--days <n>]` (after `oars pool login`) refuses any repository it cannot confirm is private (it needs `GH_TOKEN` or `GITHUB_TOKEN`), then prints a one-time enrollment token, good for 24 hours to activate, and the environment block the machine reads; the token comes only from the pool, so keep it as the environment's secret, not in a repository. `oars pool machines` lists your machines with each one's last deposit day and expiry, and `oars pool machines revoke <id>` ends one. `--hold-only` prints the block with no pool credential and no token, and with `OARS_HOLD_ONLY=1`. See [docs/pool.md](https://github.com/manyoars/oars/blob/main/docs/pool.md).
|
|
98
|
+
|
|
99
|
+
Apart from that and telemetry (on by default, off with `oars telemetry off`, `OARS_TELEMETRY=0`, or `DO_NOT_TRACK=1`; it sends to the pool server in `OARS_POOL_URL`, else to the Many Oars pool at `pool.manyoars.com`, which is live), oars itself sends nothing, except what you opted into with a pool server: after you accept its covenant, the detached sender that a session-end hook or any `oars` command starts, at most about once an hour, sends closed-vocabulary session skeletons, and, only after a separate yes to the raw prompt, a locally redacted (best-effort) copy of each full transcript; `oars pool outbox` prints what is queued when you run it, but the sender builds new batches and sends them in the same run without printing them first, and a session leaves your machine no sooner than an hour after it ends, and a folder can be switched to skeleton only or off; the hooks and the MCP tool add recall text to the running session, and your harness sends that to its model like any other context.
|
|
100
|
+
|
|
101
|
+
After you accept the covenant, a deposit may be licensed under it. The pool is not offered in the EU, the EEA, or the UK.
|
|
73
102
|
|
|
74
103
|
```bash
|
|
75
104
|
# Read every folder; or only the ones you name (a path, or its name under ~/.claude/projects); --deny keeps one out.
|
|
@@ -84,6 +113,7 @@ oars sessions recall --entity Monitor # what is known about a pub
|
|
|
84
113
|
oars sessions recall --text "wrong input" # look for text in the local record (counts all time)
|
|
85
114
|
oars sessions recall --pattern <readId> --pattern <readId> # what happened from here, from the read IDs of your steps so far (repeatable; counts all time)
|
|
86
115
|
oars sessions recall --error "..." --session <id> # name the asking session, so what it did next can be read for this recall
|
|
116
|
+
oars sessions recall --error "..." --receipt # a paste-ready Markdown block for an issue on the failing tool: listed tool and harness names, the normalized signature, earlier sessions and weeks, what they did next (the next tools), redacted
|
|
87
117
|
|
|
88
118
|
# Serve the same query to a running agent as one MCP tool, oars_recall (stdio):
|
|
89
119
|
oars sessions recall --mcp
|
|
@@ -112,7 +142,7 @@ before a line is written (redaction runs on the full text, then the text is cut)
|
|
|
112
142
|
text, never raw content. It keeps these text fields and no others: the first 300 characters of each prompt, the first informative line of a
|
|
113
143
|
tool error (cut to 1,000 characters in the error-line record, 160 characters in a derived example), TLDR lines (400) and Confidence lines (120) from assistant text, WebSearch queries, fetched URLs, file
|
|
114
144
|
paths, and git branch names (the last four have no length limit), all redacted first; plus the project folder slug (not redacted, so it
|
|
115
|
-
carries your username and directory names; the log stays local), skill names, effort values, model names, harness versions, tool names (including MCP server names), a shell call's program and subcommand, and tool-input key names. A tool call's file target is a salted hash, never the path. Apart from `gold arms`, no `oars sessions` command uploads anything, and telemetry carries none of these fields; `oars pool` and the
|
|
145
|
+
carries your username and directory names; the log stays local), skill names, effort values, model names, harness versions, tool names (including MCP server names), a shell call's program and subcommand, and tool-input key names. A tool call's file target is a salted hash, never the path. Apart from `gold arms`, no `oars sessions` command uploads anything, and telemetry carries none of these fields; `oars pool` and the sender send skeletons that carry some of these names after redaction (skill, effort, model, harness version, tool, and MCP server names, a shell call's program, subcommand, and flag names, tool-input key names, the file, directory, and variable names of a call's values (a folder called `ledger-core` is sent as `ledger-core`; never a folder above the session root, never a path or an argument), a pulled package's name (and its version only when a public list holds it), and a web host (sent as it is after redaction; the pool hashes it on arrival), each after redaction; see `docs/pool.md`, "Wire field register").
|
|
116
146
|
Subagent transcripts (`<project>/<session>/subagents/`) are deposited with their parent session and subagent type; `books --by class`
|
|
117
147
|
shows their tokens as the `delegated` column, and their errors are in the signatures, `measure`, and recall under the session that
|
|
118
148
|
spawned them, so per-session counts still count main sessions. Every deposited transcript is also
|
|
@@ -122,21 +152,21 @@ field, and a Merkle root over the raw lines) that `verify` checks; the skeleton
|
|
|
122
152
|
per hundred sessions and, on a second line, the distinct recurring signatures in the window.
|
|
123
153
|
#### Many folders: `--allow` prefixes, globs, and `--allow-file`
|
|
124
154
|
|
|
125
|
-
An `--allow` entry is a folder (or its slug), a folder prefix with a trailing slash (`~/work/` reads that folder and every project under it), or a glob (`*` any run of characters, `?` one character, matched against the project-folder name Claude Code derives from the path). `--allow-file <list>` reads entries from a file, one per line (blank lines and `#` comments skipped), so hundreds of folders need no batching and no long command line. A leading `~` is expanded to your home folder, in a list file or quoted entry too. Both repeat and combine. With neither, a deposit reads every folder. `--deny <entry>` (or `!<entry>` in a list file) keeps the folders it names out, in any of those forms; it is saved, and it wins over every `--allow` until that exact entry is named with `--allow` again. Naming it again lifts the denial and nothing else when the saved list names no folder (every folder stays in scope); when the saved list names folders, the entry joins them. Entries a deposit saves are what the SessionEnd hook, the
|
|
155
|
+
An `--allow` entry is a folder (or its slug), a folder prefix with a trailing slash (`~/work/` reads that folder and every project under it), or a glob (`*` any run of characters, `?` one character, matched against the project-folder name Claude Code derives from the path). `--allow-file <list>` reads entries from a file, one per line (blank lines and `#` comments skipped), so hundreds of folders need no batching and no long command line. A leading `~` is expanded to your home folder, in a list file or quoted entry too. Both repeat and combine. With neither, a deposit reads every folder. `--deny <entry>` (or `!<entry>` in a list file) keeps the folders it names out, in any of those forms; it is saved, and it wins over every `--allow` until that exact entry is named with `--allow` again. Naming it again lifts the denial and nothing else when the saved list names no folder (every folder stays in scope); when the saved list names folders, the entry joins them. Entries a deposit saves are what the SessionEnd hook, the sender, `oars pool deposit`, and `oars gate replay` reuse; with none saved, they read every folder. An `--allow-file` that names nothing is refused.
|
|
126
156
|
|
|
127
157
|
#### Recall in a running session: hooks
|
|
128
158
|
|
|
129
|
-
`oars sessions hook install` writes five entries into one Claude Code settings file. Each is a deterministic, local, fail-open call into the store (no model, no network); an error inside a hook exits 0 with no output, so a hook never blocks or fails a session.
|
|
159
|
+
`oars sessions hook install` writes five entries into one Claude Code settings file. With `--machine` it writes only the `Stop` and `SessionEnd` entries instead (for a VPS or cloud machine; `--env NAME=value` and `--terms-file <path>` go with it), described in the paragraph below the install examples. Each is a deterministic, local, fail-open call into the store (no model, no network); an error inside a hook exits 0 with no output, so a hook never blocks or fails a session.
|
|
130
160
|
|
|
131
161
|
| Event | Does | Timeout written at install |
|
|
132
162
|
|---|---|---|
|
|
133
163
|
| `SessionStart` | injects `oars sessions recall --context` for the session's cwd as additional context: the top 5 errors by sessions within the latest 300 sessions of the repository (the `measure --last 300 --repo` window) and what usually followed. Then, when any position qualifies, a table of the positions where earlier sessions split on the next step (a leading step at 20 to 80 percent of at least 20 observations; names and counts only, at most 600 bytes), from the kept pool bundle for the session's harness and version first and this store's pool second (the local half is derived over that harness and version bucket only, or over the harness's versions when the transcript states none). The table is one `recalls.jsonl` row and falls under the 10 percent holdback | under 500 ms |
|
|
134
164
|
| `UserPromptSubmit` | the same table again, only when it differs from the one this session was last sent (shown or held), so an unchanged table costs a prompt nothing (the check reads the last 64 KB of the recall log, shared by every session, so in a long or parallel session the last table row can fall out of the window and an unchanged table is sent again) | under 500 ms |
|
|
135
|
-
| `PreToolUse` (no matcher: every tool) | the gate hook's role: it fires after the call is decided, so it is a warning and does not claim to move the next step. For a call whose tool and input key names match a shape that fails at least half its calls (of at least 20 calls in at least 3 sessions), and at least twice as often as its action does, injects its counts as additional context, once per session and shape (the check reads the last 64 KB of the recall log, about 44 rows, so a very long session can be told again, and the arm redraws when the
|
|
165
|
+
| `PreToolUse` (no matcher: every tool) | the gate hook's role: it fires after the call is decided, so it is a warning and does not claim to move the next step. For a call whose tool and input key names match a shape that fails at least half its calls (of at least 20 calls in at least 3 sessions), and at least twice as often as its action does, injects its counts as additional context, once per session and shape (the check reads the last 64 KB of the recall log, about 44 rows, so a very long session can be told again, and the arm redraws when the index moves), and records the recall. 10 percent of those sessions and shapes are held back: a held arm records what it would have shown and injects nothing. Starts node per call | under 500 ms |
|
|
136
166
|
| `PostToolUseFailure` (matcher: every tool the action table maps, and `mcp__.*`) | the recovery edge: for a failed call it reads what followed this failure (same action and error class) in the kept pool bundle, else in this store, and adds "after a failed X (code), the next step was Y xN". It stays silent when the top next step is the failed action again (a retry), when a local edge has fewer than 5 followed steps, and when nothing followed. A call the cells do not cover keeps the older line, "seen in N sessions; what followed: X", under the same holdback, silent on a strict retry lead. Every served or held line is a `recalls.jsonl` row; 10 percent of sessions are held. For Bash and PowerShell a shell pre-filter in the registered command reads the event first and starts node only when it carries `Exit code` | pre-filter: shell builtins only, no node start; whole path under 1 s |
|
|
137
|
-
| `SessionEnd` | deposits that one transcript (idempotent by size and mtime), only from a folder the saved allowlist holds (every folder until a deposit names some, less any `--deny`). Once per session: `Stop` fires after every turn and would append a new revision of the growing transcript each time. A session the harness ends without `SessionEnd` is picked up by the
|
|
167
|
+
| `SessionEnd` | deposits that one transcript (idempotent by size and mtime), only from a folder the saved allowlist holds (every folder until a deposit names some, less any `--deny`). Once per session: `Stop` fires after every turn and would append a new revision of the growing transcript each time. A session the harness ends without `SessionEnd` is picked up by the next sweep | under 5 s |
|
|
138
168
|
|
|
139
|
-
Claude Code fires `PostToolUse` on success only; a failed Bash call arrives as `PostToolUseFailure`, so that is the event registered. The pre-filter is a `read`, a `case`, and a `printf | node` in the shell the harness runs hooks in (Git Bash on Windows), so it needs no `findstr` and no extra dependency. Writers of the store (`SessionEnd`, the
|
|
169
|
+
Claude Code fires `PostToolUse` on success only; a failed Bash call arrives as `PostToolUseFailure`, so that is the event registered. The pre-filter is a `read`, a `case`, and a `printf | node` in the shell the harness runs hooks in (Git Bash on Windows), so it needs no `findstr` and no extra dependency. Writers of the store (`SessionEnd`, the sweep, `deposit`) take `store.lock`, so parallel sessions cannot lose each other's `state.json` entries; a lock older than ten minutes is broken.
|
|
140
170
|
|
|
141
171
|
```bash
|
|
142
172
|
# The default is the user settings file; --scope project or --file names another.
|
|
@@ -144,15 +174,15 @@ oars sessions hook install # ~/.claude/settings.jso
|
|
|
144
174
|
oars sessions hook install --scope file --file ./.claude/settings.local.json
|
|
145
175
|
oars sessions hook install --scope project # ./.claude/settings.json
|
|
146
176
|
oars sessions hook install --file my-settings.json --keep-retention
|
|
147
|
-
oars sessions hook status # user, project, and
|
|
177
|
+
oars sessions hook status # user, project, and a task left by an earlier version
|
|
148
178
|
oars sessions hook uninstall --scope user # removes only the entries install wrote
|
|
149
179
|
```
|
|
150
180
|
|
|
151
|
-
Install merges: existing hooks (a Stop hook that rotates sessions, say) stay, even inside a group that also holds ours or under a name that contains `hook-bin`; re-running replaces only its own entries (the commands ending `hook-bin.js" <session-start|post-tool|stop>`), and a per-turn `Stop` entry of ours from the first build is removed. A settings file that exists but cannot be read is an error that changes nothing. The harness deletes raw transcripts after `cleanupPeriodDays` (30 when unset), which would erase what `deposit` reads, so install raises it to at least 365 in the file it writes, prints the old and new value, and never lowers a higher one. `--keep-retention` leaves it alone and says so. Uninstall does not touch `cleanupPeriodDays`. For a `claude --settings <file>` launch, install into that file with `--scope file`.
|
|
181
|
+
Install merges: existing hooks (a Stop hook that rotates sessions, say) stay, even inside a group that also holds ours or under a name that contains `hook-bin`; re-running replaces only its own entries (the commands ending `hook-bin.js" <session-start|post-tool|stop>`), and a per-turn `Stop` entry of ours from the first build is removed. A settings file that exists but cannot be read is an error that changes nothing. `oars sessions hook install --machine` writes only the `Stop` and `SessionEnd` entries of a cloud VM, a VPS, or a runner (`--scope project` or `--scope user`), and it and a plain install each leave the other's entries alone; `--env NAME=value` (user scope) writes the enrollment block into that file's `env`, and `--terms-file <path>` moves the inline exclusion terms into an owner-only file. See `docs/sessions-store.md`. The harness deletes raw transcripts after `cleanupPeriodDays` (30 when unset), which would erase what `deposit` reads, so install raises it to at least 365 in the file it writes, prints the old and new value, and never lowers a higher one. `--keep-retention` leaves it alone and says so. Uninstall does not touch `cleanupPeriodDays`. For a `claude --settings <file>` launch, install into that file with `--scope file`.
|
|
152
182
|
|
|
153
|
-
####
|
|
183
|
+
#### Sends ride the hook and your commands
|
|
154
184
|
|
|
155
|
-
|
|
185
|
+
oars installs no scheduled task and no cron entry. After a session ends, the `SessionEnd` hook deposits that transcript and then starts a detached sender, and any other `oars` command starts one too (except `oars gate hook`, `oars sessions hook uninstall`, and `oars sessions try`), at most about once an hour, so the hook stays fast. The start is marked before it is made, so a failed start is retried by the next trigger after the hourly debounce. The sender runs the full deposit over the saved `--allow` and `--redact-domain` entries, which also reaches the harnesses that have no session-end hook (Cursor, Codex, and the rest), refreshes the recurrence index the hooks read, and sends only after the consent gates in the README. A session leaves your machine no sooner than an hour after it ends, which leaves time for `--deny` or a delete. `oars pool deposit --send <hash>` stays as the manual path. A Windows task `OarsSessionsNightly` registered by an earlier version is removed by `oars sessions hook install` or `uninstall`; `--schedule nightly` is refused. `--schedule off` removes that task if it is there and turns off the background sweep and the pool send (telemetry has its own switch: `oars telemetry off`; it records `{"schedule":"off"}` in `<store>/schedule.json`, which the hook and every command read); `--schedule on` turns them back on.
|
|
156
186
|
|
|
157
187
|
#### Reading `measure` before and after
|
|
158
188
|
|
|
@@ -179,13 +209,33 @@ Replay is local and read-only on your transcripts; it writes `crossings.jsonl` a
|
|
|
179
209
|
|
|
180
210
|
`oars pool` uses the Many Oars pool, `https://pool.manyoars.com`, which is live (deposits there are closed until its covenant is published), or a pool server you name with `--server <url>` or `OARS_POOL_URL`. Every other command works without it.
|
|
181
211
|
|
|
182
|
-
- `oars pool login --provider github|google`
|
|
183
|
-
- `oars pool
|
|
184
|
-
- `deposit
|
|
212
|
+
- `oars pool login --provider github|google` asks the pool to start the provider's device flow, prints the user code and link, and polls the pool until you approve; with `--verbose`, every request prints before it is sent. The pool holds the OAuth client and its secret, so the CLI needs no client ID or secret, and the provider's tokens never reach this machine.
|
|
213
|
+
- `oars pool logout` revokes this machine's credential at the pool, then removes the local sign-in. If the pool cannot be reached it still removes the local sign-in and says the credential was not revoked there.
|
|
214
|
+
- `oars pool deposit` writes a batch of session skeletons (a closed list of fields, each value redacted first; a host is hashed by the pool on arrival) to an outbox for each session that passes your folder allowlist and the exclusion check, and stops: no session data is sent. `--send <hash>` sends one batch that `outbox` printed and that is unchanged on disk, once this account has accepted the pool covenant (a person types the phrase the covenant screen states, at a terminal; `--accept-covenant <version>` only names the version expected and accepts nothing; the screen then asks "Are you in the EU, the EEA, or the UK? (yes/no)" and sends the answer, and `--in-eu-eea-uk <yes|no>` answers it without asking; while the pool is closed to those regions a yes, or a request from them, is refused with `region_closed` and nothing is accepted); before that it reads the covenant, sends no batch, and exits 3 with `covenant_not_accepted`. A hash that was never shown, or a batch that changed, is refused before any request. The detached sender is the other sender: after the pool says your account accepted its covenant, it sends new batches, and raw copies only if you said yes to the raw prompt (`oars pool raw --consent yes`, answered by typing the phrase `I consent to sending raw copies` at a terminal; a yes also tells the pool, and `--consent no` tells it to stop accepting raw copies, whatever a later request states (a machine that held a yes and is signed out exits nonzero: the pool was not told), and the pool's nightly job then erases the raw copies it already holds, starting that night; a large account can take more than one night). With no sign-in, no acceptance, or an unreachable server it sends nothing.
|
|
215
|
+
- `deposit`, `outbox`, `export`, and `fetch` need `oars pool login` first; without it they exit 3 and name the server.
|
|
185
216
|
- `oars pool coverage [--org-size <band>] [--repo-visibility public|private|unknown]` sets the two coverage bands only you can state, read locally and never from the network; an unset band goes on the wire as `unknown`.
|
|
217
|
+
- `oars pool export --out <folder> [--raw]` saves a copy of what the pool holds about your account (GDPR Articles 15(3) and 20), as JSON, one file a page, readable by you only. It covers your account row (with your raw consent record), when your sign-ins end (never the credential), your covenant acceptances, your machines (without their keys, with the day of each one's last deposit and its key days), your repository keys, your deposit hours, your deposits as they now read (with the machine, host class, and launcher each came from, and the host class and launcher the batch claimed), your raw ledger, your staged deposit parts, your erasure audit rows, and your telemetry days. `--raw` also saves each raw transcript you deposited that has not been erased, checked against its hash. It needs `oars pool login`, writes nothing to the pool, prints what it saved, and exits nonzero naming any page or object that failed; a rerun overwrites the same files. Totals the pool derives from many accounts are not yours to export and are not in it.
|
|
218
|
+
- On an enrolled machine the hook child activates its key before its first deposit, rotates it where the disk is durable (`vps`, `ci`; the key lives in `<store>/machine-key`, owner-only), deposits under it, sends the batches its outbox held once the covenant is accepted, and tells you at the next Stop when the key expires within 14 days, has expired, or was revoked (`oars pool machines` lists it). A `cloud` machine's key is held by the network proxy and the child sends no credential of its own. Details: `docs/pool.md`, "Machine keys".
|
|
186
219
|
- `oars pool outbox` prints each batch exactly as it would be sent, with its SHA-256, and `--explain` adds each field's rule.
|
|
187
220
|
- `oars pool fetch --harness-version <version>` fetches that version's signed bundle, verifies it against the key pinned at login, and keeps it locally. It prints the public and disclosure floors the bundle states (and any read family on a floor of its own) and holds no floor of its own: the pool sets them, so a change is a deploy and never a new release of oars.
|
|
188
221
|
|
|
222
|
+
### club
|
|
223
|
+
|
|
224
|
+
A club shares your counts with the people who hold its code, and nothing else. Members see your nickname, weeks rowing, active days, sessions, and strokes this week. They never see your sessions, projects, prompts, or tokens. You need `oars pool login` first, except for `oars board`.
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
oars club create "Friday crew" --nickname skipper # prints the join code once
|
|
228
|
+
oars club join K7M2QX --nickname bow # a club you were invited to
|
|
229
|
+
oars club join open --nickname bow # the open board; your row shows once your account has standing
|
|
230
|
+
oars club show <club> # the members in the pool's order
|
|
231
|
+
oars club leave <club> # your row leaves view at once
|
|
232
|
+
oars board # the open board; no sign-in
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Create and join show the pool's consent text and wait for you to type `yes` at a terminal. A script on stdin cannot agree for you, and nothing is sent until you do. Send the code only to people you want in the club: it admits, and a member can leave at any time.
|
|
236
|
+
|
|
237
|
+
A nickname is 2 to 24 letters, digits, spaces, dots, underscores, or hyphens, with no space at either end, no `@`, and no web address. The pool slows wrong codes to 10 an hour and club creation to 5 a day for each account; past that you get `rate_limited` and when to try again. Each command takes `--json`. Errors lead with the cause: `not_signed_in`, `club_full`, `nickname_taken`, `nickname_invalid`, `rate_limited`.
|
|
238
|
+
|
|
189
239
|
## The `--json` contract
|
|
190
240
|
|
|
191
241
|
With `--json`, stdout carries exactly one JSON document and a success exits 0.
|
package/dist/bin.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { exitIfTooOld } from './node-floor.js';
|
|
3
|
+
// An older Node gets one line and exit 1, before anything loads that would fail on it.
|
|
4
|
+
exitIfTooOld(process.versions.node, (text) => process.stderr.write(text), (code) => process.exit(code));
|
|
2
5
|
// The `oars` executable. It decides which program to load before loading any: `oars gate hook` is run by the harness before every matching tool call and has under a
|
|
3
6
|
// second to finish, so it must not pay for the whole CLI (its command tree, its sign-in, its HTTP client) just to start. Everything else loads `main.js`, as before.
|
|
4
7
|
// Only the bare command: with an argument (`--help`) the full CLI answers, so its description shows.
|
|
5
8
|
const hook = process.argv.length === 4 && process.argv[2] === 'gate' && process.argv[3] === 'hook';
|
|
6
9
|
await (hook ? import('./gate/hook-main.js') : import('./main.js'));
|
|
7
|
-
export {};
|
package/dist/cli.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ export interface RunDeps {
|
|
|
25
25
|
install?: InstallRuntime;
|
|
26
26
|
/** Where telemetry keeps its id, settings, and spool; absent in a run that has none, which records nothing. */
|
|
27
27
|
telemetry?: TelemetryRuntime | undefined;
|
|
28
|
+
/** The catch-up every command that is not a hook runs after it ends: starts a due sweep and send, detached. Absent in a run that has none. */
|
|
29
|
+
catchUp?: (() => Promise<unknown>) | undefined;
|
|
28
30
|
}
|
|
29
31
|
/** What a command produced: the `--json` document, and the line a human sees instead. */
|
|
30
32
|
export interface Outcome {
|