Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
5e302b6
feat(events): define push-event JSON schema
GeoffChurch Apr 27, 2026
bb71939
feat(events): add EventBus and sibling events socket listener
GeoffChurch Apr 27, 2026
fd40940
feat(events): publish deltas from session lifecycle mutations
GeoffChurch Apr 27, 2026
a8e11c0
feat(events): add `shpool events` subcommand
GeoffChurch Apr 27, 2026
cab78b5
test(events): integration tests for the events socket
GeoffChurch Apr 27, 2026
a336742
fix(events): de-duplicate lifecycle deltas; clean socket on signal exit
GeoffChurch Apr 27, 2026
3f38bb7
refactor(events): trim event payloads to type fields only
GeoffChurch Apr 28, 2026
0b99ca0
docs(events): add EVENTS.md describing the events protocol
GeoffChurch Apr 28, 2026
47ac2d8
EVENTS.md: fix main socket description and remove "Ordering" section
GeoffChurch Apr 30, 2026
aff5279
events: polish error contexts, naming, and module boundary
GeoffChurch May 5, 2026
4865abd
events: add tests for bus isolation, latency, and lock ordering
GeoffChurch May 5, 2026
8f5e08c
events: replace thread-per-subscriber writers with a single-sink poll…
GeoffChurch May 7, 2026
46e6047
tests(events): use daemon::Proc methods; rephrase invariant docstring
GeoffChurch May 12, 2026
3647032
events: rename subscribe_to_stdout to run
GeoffChurch May 12, 2026
8237a4d
events: polish docs, tests, and sink-loop buffer reuse
GeoffChurch May 12, 2026
9047e3b
events: drop snapshot help; simplify stdout/wake/collect usage
GeoffChurch May 13, 2026
0c885aa
tests(events): cover the force-reattach (attach -f) event sequence
GeoffChurch May 15, 2026
1b308a9
events: #[ignore] the timing-sensitive publish-scaling test
GeoffChurch May 15, 2026
bfce3bf
events: surface unexpected wake-pipe write errors, ignore EAGAIN
GeoffChurch May 15, 2026
b23532b
events: move the daemon-side machinery into daemon::events
GeoffChurch May 15, 2026
358d893
events: own the sink lifetime via a single start entrypoint
GeoffChurch May 16, 2026
26e1bf0
Resolve cranky "unneeded `return` statement with `?` operator"
GeoffChurch May 17, 2026
ef4772f
Use a socketpair for the events self-pipe instead of pipe2
GeoffChurch May 17, 2026
92b1c96
events: point to EVENTS.md in `events` subcommand help
GeoffChurch May 17, 2026
dcdd47a
events: add error context to SubscriberWriter::new
GeoffChurch May 17, 2026
88a7612
events: document why EventBusHandle is split from EventBus
GeoffChurch May 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions EVENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Events

`shpool` exposes an event stream so that external programs can react to changes
without polling. This way, a program (e.g. a TUI) can call `shpool list` (or the
equivalent `ConnectHeader::List` request over the main socket; see the
[`shpool-protocol`](./shpool-protocol) crate) after each event so that its model
is always consistent with shpool's state.

## The events socket

The daemon binds a sibling Unix socket next to the main shpool socket:

```bash
<runtime_dir>/shpool/shpool.socket # main socket
<runtime_dir>/shpool/events.socket # events socket (this protocol)
```

A subscriber connects to `events.socket` and reads events. The daemon ignores anything written to the events socket, so for subscribers it's effectively read-only.

## Event types

| `type` | Meaning |
| ------------------ | -------------------------------------------------------- |
| `session.created` | A new session was added to the table. |
| `session.attached` | A client attached or reattached to a session. |
| `session.detached` | A client disconnected from a still-running session. |
| `session.removed` | A session was removed (shell exited, killed, or reaped). |

Subscribers should ignore unknown `type` values so that future event types do
not break older consumers.

## Wire format

The daemon writes one JSON object per line (JSONL). Each event looks like:

```json
{"type":"<event-type>"}
```

There are no other fields. To learn what the event refers to (which session,
when, etc.), call `shpool list` (or use `ConnectHeader::List`).

The format is robust: literal newline characters only appear as delimiters
between events. Any newlines within JSON string values are automatically
escaped (as `\n`) by the daemon.

## Subscribing

For ad-hoc use, `shpool events` connects to the events socket and prints each
event line to stdout, flushing after each line:

```bash
shpool events | while read -r ev; do
echo "got: $ev"
shpool list
done

shpool events | jq .
```

## Slow subscribers

Each subscriber has a bounded outbound queue. A subscriber that falls too far
behind is dropped by the daemon (in which case the subscriber can always reconnect).
There is no replay, so events that fired while a subscriber was disconnected are
lost.
Loading