sessionpipe 0.7.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -6
- package/dist/cli.d.ts +11 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +5043 -2609
- package/dist/cli.js.map +4 -4
- package/dist/connect.d.ts.map +1 -1
- package/dist/control/aliases.d.ts +5 -0
- package/dist/control/aliases.d.ts.map +1 -1
- package/dist/control/autoupdate.d.ts +1 -18
- package/dist/control/autoupdate.d.ts.map +1 -1
- package/dist/control/cli.d.ts +8 -1
- package/dist/control/cli.d.ts.map +1 -1
- package/dist/control/daemon.d.ts +95 -9
- package/dist/control/daemon.d.ts.map +1 -1
- package/dist/control/files.d.ts +35 -0
- package/dist/control/files.d.ts.map +1 -0
- package/dist/control/pair.d.ts +22 -23
- package/dist/control/pair.d.ts.map +1 -1
- package/dist/control/route.d.ts +1 -1
- package/dist/control/route.d.ts.map +1 -1
- package/dist/control/sdk.d.ts.map +1 -1
- package/dist/control/store.d.ts +21 -2
- package/dist/control/store.d.ts.map +1 -1
- package/dist/control/stream.d.ts.map +1 -1
- package/dist/help.d.ts +3 -0
- package/dist/help.d.ts.map +1 -0
- package/dist/hook.d.ts +9 -1
- package/dist/hook.d.ts.map +1 -1
- package/dist/hook.js +190 -158
- package/dist/hook.js.map +3 -3
- package/dist/http-sink.d.ts +3 -0
- package/dist/http-sink.d.ts.map +1 -1
- package/dist/index.js +1038 -237
- package/dist/index.js.map +4 -4
- package/dist/launcher.d.ts.map +1 -1
- package/dist/run.d.ts +70 -8
- package/dist/run.d.ts.map +1 -1
- package/dist/runtime.d.ts +5 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/secrets.d.ts.map +1 -1
- package/dist/update.d.ts +1 -6
- package/dist/update.d.ts.map +1 -1
- package/dist/worker.d.ts +3 -1
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +1127 -287
- package/dist/worker.js.map +4 -4
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# sessionpipe
|
|
2
2
|
|
|
3
3
|
**An open protocol, and a client, for what your coding agents are doing.** One
|
|
4
|
-
install hooks Claude Code, Codex, Gemini CLI and
|
|
5
|
-
Droid, Kiro and OpenCode are next); every event is filtered to a privacy tier you
|
|
4
|
+
install hooks Claude Code, Codex, Gemini CLI, Antigravity and Devin (Cursor, Copilot
|
|
5
|
+
CLI, Droid, Kiro and OpenCode are next); every event is filtered to a privacy tier you
|
|
6
6
|
choose per destination; secrets are removed on your machine before anything leaves
|
|
7
7
|
it; it goes to your server, to a file, or nowhere at all.
|
|
8
8
|
|
|
@@ -14,6 +14,19 @@ sessionpipe doctor # what is wired, hook timing, sink state
|
|
|
14
14
|
sessionpipe uninstall # every config file byte-identical again
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
`connect` and `install` refuse to replace a newer global package or hook launcher
|
|
18
|
+
with an older build, including a newer prerelease (`0.9.0-devin.1` is newer than
|
|
19
|
+
`0.7.0`). The refusal prints both versions and exits before installing or writing
|
|
20
|
+
hooks. Use the installed newer CLI, or explicitly pass `--allow-downgrade` to
|
|
21
|
+
replace it. Already-published older CLIs do not gain this guard retroactively.
|
|
22
|
+
|
|
23
|
+
`--machine NAME` sets the initial name. On later runs, setup keeps the configured
|
|
24
|
+
name and says when it ignores a different `--machine`, so a copied setup command
|
|
25
|
+
cannot separate sessions from their daemon or reset the identity used for backoff.
|
|
26
|
+
`--machine NAME --rename-machine` explicitly renames it, the paired daemon included:
|
|
27
|
+
control.json takes the name and the daemon says it in its next hello. A receiver keys
|
|
28
|
+
machines by their id, so the pairing holds and its two cards become one.
|
|
29
|
+
|
|
17
30
|
| Tier | What leaves |
|
|
18
31
|
|-----:|-------------|
|
|
19
32
|
| 0 | session state and timing, folder, repo, branch, model, title, the *kind* of attention needed |
|
|
@@ -23,7 +36,7 @@ sessionpipe uninstall # every config file byte-identical again
|
|
|
23
36
|
|
|
24
37
|
No telemetry. Secrets never leave (`secrets@1` runs above tier 0, always). Your
|
|
25
38
|
server or none. Pre-release: the reference receiver is still being built; see the
|
|
26
|
-
[roadmap](https://github.com/
|
|
39
|
+
[roadmap](https://github.com/spacesheep-dev/sessionpipe/blob/main/ROADMAP.md).
|
|
27
40
|
|
|
28
41
|
## Control: messages to your sessions (M6: Claude Code, Codex, Antigravity)
|
|
29
42
|
|
|
@@ -34,6 +47,8 @@ enroll at this terminal; the receiver can queue a message but can never forge on
|
|
|
34
47
|
|
|
35
48
|
```sh
|
|
36
49
|
sessionpipe control pair spacesheep.dev # one link: approve with your passkey; installs the daemon (this folder by default)
|
|
50
|
+
sessionpipe control folders add ~/work/api # let messages reach sessions in another folder too (no new pairing)
|
|
51
|
+
sessionpipe control folders [remove <dir>] # the list, or stop allowing a folder
|
|
37
52
|
sessionpipe control status # receivers, parked waiters, sessions mid-turn, open permission prompts
|
|
38
53
|
sessionpipe control keys [remove <id>]
|
|
39
54
|
sessionpipe control off # tell the receiver, forget its token and keys
|
|
@@ -49,6 +64,12 @@ After upgrading, run `sessionpipe control pair <receiver>` again (without
|
|
|
49
64
|
already-running daemon afterward with `systemctl --user restart sessionpipe-control.service`;
|
|
50
65
|
macOS pairing reloads the LaunchAgent.
|
|
51
66
|
|
|
67
|
+
A new session started from the receiver may bring files (screenshots, PDFs: up to 10,
|
|
68
|
+
50 MiB together), whichever harness it is for. The daemon downloads each one, checks
|
|
69
|
+
it against the hash you signed, saves it under `<folder>/.sessionpipe/files/<session>/`
|
|
70
|
+
(a folder that git-ignores itself) and tells the session where they are. If any file
|
|
71
|
+
is missing or doesn't match, the session doesn't start.
|
|
72
|
+
|
|
52
73
|
One daemon per computer holds one long-poll per receiver and delivers each message the
|
|
53
74
|
cheapest way the session allows: to `sessionpipe wait` parked in the session's
|
|
54
75
|
background (in place, ~60 ms, no network), at the session's next Stop if it is
|
|
@@ -62,11 +83,22 @@ background command with the longest timeout it can (Claude Code: raise
|
|
|
62
83
|
sessionpipe wait # Claude Code: the session id comes from CLAUDE_CODE_SESSION_ID
|
|
63
84
|
```
|
|
64
85
|
|
|
86
|
+
The waiter and next-Stop modes work in any Claude Code session that runs your hooks,
|
|
87
|
+
the Claude desktop app's included, and need nothing else. The Agent SDK, resume and fork
|
|
88
|
+
modes run the `claude` command, which has its own login (`claude auth login`); the
|
|
89
|
+
desktop app doesn't share its login with that command.
|
|
90
|
+
|
|
65
91
|
Permission prompts can be answered from the receiver too: while the terminal shows
|
|
66
92
|
its prompt, the PermissionRequest hook waits for your signed answer, and whichever
|
|
67
93
|
comes first wins. Nothing is ever auto-allowed. Safe mode (the default) runs headless
|
|
68
94
|
turns with `--permission-mode dontAsk`, so nothing that needs approval runs while
|
|
69
|
-
you're away.
|
|
95
|
+
you're away. Auto mode runs them with `--permission-mode auto`; where Claude Code's
|
|
96
|
+
settings turn auto mode off (`permissions.disableAutoMode`), Claude Code runs them in
|
|
97
|
+
its default mode instead, which refuses whatever needs approval. Inherit mode
|
|
98
|
+
(`sessionpipe control mode inherit`, chosen only at the machine) passes no permission
|
|
99
|
+
flag, so each turn starts in the mode Claude Code picks by itself there, its
|
|
100
|
+
settings' `permissions.defaultMode`: messaged sessions run the way your own do,
|
|
101
|
+
`bypassPermissions` included if that is what you set.
|
|
70
102
|
|
|
71
103
|
Codex and Antigravity sessions are reached headlessly too, when `codex` or `agy` is
|
|
72
104
|
installed (the daemon looks on PATH, beside its own Node, in `~/.local/bin`, or where
|
|
@@ -75,7 +107,9 @@ installed (the daemon looks on PATH, beside its own Node, in `~/.local/bin`, or
|
|
|
75
107
|
message is `codex exec resume <thread>` or `agy --conversation <id>`. Safe mode runs
|
|
76
108
|
Codex in its `workspace-write` sandbox and agy with no permission flag (it denies, and
|
|
77
109
|
the reply lists, what it wasn't allowed to do); auto mode passes `--approve-for-me` /
|
|
78
|
-
`--mode accept-edits
|
|
110
|
+
`--mode accept-edits`; inherit mode passes no flag, so Codex follows the
|
|
111
|
+
`approval_policy` and `sandbox_mode` in your `config.toml`. The bypass flags are never
|
|
112
|
+
passed. Both CLIs pick a new
|
|
79
113
|
session's id themselves, so the daemon keeps the one your start named: it records the
|
|
80
114
|
pair in `~/.local/state/sessionpipe/control/aliases.json`, and your receiver keeps
|
|
81
115
|
seeing one session under one id. A message to a Codex session someone has open (its
|
|
@@ -83,6 +117,21 @@ rollout written in the last 90 seconds) is acked `unsupported` rather than resum
|
|
|
83
117
|
Before a Codex run the daemon checks `codex login status` (or `CODEX_API_KEY`) and says
|
|
84
118
|
`codex login --device-auth` if it isn't signed in.
|
|
85
119
|
|
|
120
|
+
Any other agent that speaks the [Agent Client Protocol](https://agentclientprotocol.com)
|
|
121
|
+
is reached the same way: Gemini CLI, OpenCode, goose, Copilot CLI, Cursor, Droid, Devin,
|
|
122
|
+
Kilo, Qwen Code, Cline and the rest of the ACP registry ([the list, with each one's
|
|
123
|
+
launch line](../../spec/ADAPTERS.md#agents-driven-through-acp-control-only)). The daemon
|
|
124
|
+
runs the agent's own CLI (`gemini --acp`, `opencode acp`, …) when it is installed, on
|
|
125
|
+
PATH or where `SESSIONPIPE_ACP_<HARNESS>` points (`SESSIONPIPE_ACP_GEMINI_CLI`), and
|
|
126
|
+
never downloads one. It is the agent's client: a start opens a session in your folder,
|
|
127
|
+
the reply streams back as the agent writes it, and the process stays up so the next
|
|
128
|
+
message lands in it with no cold start (`api` mode); `cancel` works there too. An agent
|
|
129
|
+
idle for ten minutes is closed, and a later message reopens the session where the agent
|
|
130
|
+
supports `session/load`. Safe mode answers every permission the agent asks with a
|
|
131
|
+
refusal, listed in the reply; auto mode allows. An agent that never asks (OpenCode, by
|
|
132
|
+
its own settings) runs its tools as it would at your terminal. Signing in is yours to do
|
|
133
|
+
at the terminal: an agent that wants it says so in the reply.
|
|
134
|
+
|
|
86
135
|
## Updates
|
|
87
136
|
|
|
88
137
|
The control daemon keeps its own copy current. About a minute after it starts, and then
|
|
@@ -127,6 +176,34 @@ sessionpipe update # install the latest now; the daemon restarts onto i
|
|
|
127
176
|
a launchd or systemd service doesn't inherit your shell's variables, while
|
|
128
177
|
`sessionpipe update off` reaches it (it re-reads the config every ten minutes).
|
|
129
178
|
|
|
179
|
+
## Help and status JSON
|
|
180
|
+
|
|
181
|
+
`sessionpipe <command> --help` (or `-h`) prints usage and exits successfully before
|
|
182
|
+
running the command. This also works after operands and for nested commands, such
|
|
183
|
+
as `sessionpipe sink remove example --help` and `sessionpipe control pair example --help`.
|
|
184
|
+
|
|
185
|
+
`sessionpipe status --json` prints one JSON object. Its shared fields use the same
|
|
186
|
+
names and meanings as `doctor --json`:
|
|
187
|
+
|
|
188
|
+
| Field | Shape / meaning |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `version`, `machine`, `state`, `config` | Strings; state and config are absolute paths. |
|
|
191
|
+
| `harnesses` | Object keyed by harness name; each value is an array of `{file, state, note?}` hook checks. `file` uses `~` for home, as doctor does. Includes detected **or configured** harnesses. |
|
|
192
|
+
| `sinks` | Array of `{name, url, tier, max_tier, pii, control, paused, pending_sessions}`. `tier` is the configured tier; the effective tier is `min(tier, max_tier ?? 3)`. `max_tier` and `paused` are `null` when unset. No token or secret is included. |
|
|
193
|
+
| `timing` | `{n, p50, p95}` from the last 100 local hook timings, in milliseconds; `null` when unavailable. |
|
|
194
|
+
| `update` | Doctor's update summary: `{auto, off, last_check, latest, last_error, pending, updated, failed}`. `auto` is boolean; absent details are `null`. |
|
|
195
|
+
| `jobs` | Number of entries waiting in the local jobs directory; zero when absent. |
|
|
196
|
+
|
|
197
|
+
`pending_sessions` counts outbox session files with bytes beyond that sink's cursor,
|
|
198
|
+
including paused sinks; it counts files, not individual events. Empty collections
|
|
199
|
+
are `{}` / `[]`. Status omits doctor's active hook benchmark, login/keychain checks,
|
|
200
|
+
and warnings. Both commands still check hook installation, which can run
|
|
201
|
+
`gemini --version` (up to four seconds) when `tools.enableHooks` is unset. JSON is an
|
|
202
|
+
output format, not a promise of constant-time diagnostics. Plain `sessionpipe status`
|
|
203
|
+
keeps its existing human output.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
130
207
|
Docs and the protocol: [sessionpipe.org](https://sessionpipe.org) · Source:
|
|
131
|
-
[github.com/
|
|
208
|
+
[github.com/spacesheep-dev/sessionpipe](https://github.com/spacesheep-dev/sessionpipe) · Apache-2.0.
|
|
132
209
|
Provided as-is; check what a sink receives with `sessionpipe tail` before you point it anywhere.
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export {
|
|
2
|
+
export interface Io {
|
|
3
|
+
/** One line of output. */
|
|
4
|
+
out: (s?: string) => void;
|
|
5
|
+
/** What a failed command says, then `exit(1)`. */
|
|
6
|
+
err: (s: string) => void;
|
|
7
|
+
exit: (code: number) => void;
|
|
8
|
+
}
|
|
9
|
+
/** Run one command: `argv` is what follows `sessionpipe`; `io` is this process by default. */
|
|
10
|
+
export declare function main(argv: string[], io?: Io): Promise<void>;
|
|
11
|
+
/** Is this file the process entrypoint? By real path: npm's bin link to it counts. */
|
|
12
|
+
export declare function isEntrypoint(argv1: string | undefined, url: string): boolean;
|
|
3
13
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAoEA,MAAM,WAAW,EAAE;IACjB,0BAA0B;IAC1B,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1B,kDAAkD;IAClD,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACzB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED,8FAA8F;AAC9F,wBAAsB,IAAI,CACxB,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,GAAE,EAA2F,GAC9F,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAM5E"}
|