agent_reel_deploy 0.1.0

projection-safe feed for local coding-agent activity
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
# agent_reel ✨🎞️

`agent_reel` turns local coding-agent activity into a projection-safe live reel.

agent activity, reduced to signal.

![feed projection showing a redacted codex file-change bulletin](docs/image/hero.png)

core shape:

* adapters observe codex, claude, mcp, shell, and telemetry surfaces
* events are normalized before storage
* redaction is applied before display
* story windows settle noisy streams into contextual bulletins
* highlight scoring prefers completion, failure, risk, novelty, and changed state
* the browser surface advances on its own; no scrolling, no controls, no cloud

the product is not a dashboard. it is a local broadcast layer.

## install

```sh
cargo install agent_reel_cli --locked
agent-reel init --auto
agent-reel serve
```

## happy path

```sh
agent-reel open
```

the reel is served at:

```text
http://127.0.0.1:7777/reel
```

after setup, the page requires no scrolling, clicking, refreshing, or human control.
new agent activity becomes a sequence of display-safe bulletins that advance through time.

## inputs

first-class inputs:

* codex `exec --json`
* codex app-server streams
* codex hooks
* claude code `--output-format stream-json`
* claude code hooks
* mcp JSON-RPC streams
* generic local telemetry

the daemon may discover active tools, but it is honest about capture limits.
already-running private TUI sessions are only observable when they expose a stream, hook,
app-server, telemetry surface, transcript, or were launched through an `agent_reel` shim.

## safety boundary

raw prompts, secrets, absolute home paths, command output, and file diffs are not display
material by default.

default posture:

* bind to `127.0.0.1`
* no cloud
* no analytics
* no raw prompt display
* no raw command output display
* no raw diff display
* raw event storage off
* aggressive redaction on
* path hashing on
* non-loopback bind requires a display token

security invariants:

* redaction runs before store
* redaction runs before SSE
* query params cannot disable redaction
* raw-event quarantine is local-only
* uninstall restores edited config files
* hook helper never prints secrets
* adapter errors never panic the daemon

the reel is a view of agent activity, not an agent control plane.

## quick ingest

start the daemon:

```sh
agent-reel serve
```

send a safe generic event:

```sh
curl -sS http://127.0.0.1:7777/ingest/generic \
  -H 'content-type: application/json' \
  -d '{
    "agent": "codex",
    "project": "agent_reel",
    "kind": "turn.complete",
    "title": "signal path is live",
    "summary": "generic ingest produced one redacted bulletin.",
    "tags": ["m0", "redacted"]
  }'
```

open:

```sh
agent-reel open
```

## commands

```text
agent-reel doctor
agent-reel init --auto
agent-reel init --codex
agent-reel init --claude
agent-reel serve
agent-reel open
agent-reel auth github
agent-reel auth status
agent-reel auth logout
agent-reel ingest --source generic < event.json
agent-reel ingest --source codex-jsonl < events.jsonl
agent-reel ingest --source claude-stream-json < events.jsonl
agent-reel codex active --sessions 2
agent-reel codex active --sessions 2 --watch
agent-reel codex import ~/.codex/sessions/2026/04/23/rollout-...jsonl
agent-reel codex stories --sessions 2
agent-reel claude stream < stream.jsonl
agent-reel claude active --sessions 2
agent-reel claude active --sessions 2 --watch
agent-reel claude import ~/.claude/projects/.../session.jsonl
agent-reel claude stories --sessions 2
agent-reel p2p init
agent-reel p2p join mainnet
agent-reel p2p discover github mosure --all --explain
agent-reel p2p share --feed workstation --visibility private
agent-reel p2p publish --dry-run --agents codex,claude --sessions 2
agent-reel p2p publish --dry-run --sessions 2 --per-story
agent-reel p2p publish --dry-run --summarizer codex-exec
agent-reel p2p publish --dry-run --summarizer claude-code
agent-reel p2p publish --dry-run --images --image-processor codex-exec
agent-reel p2p publish --dry-run --images --image-processor process --image-command ./summarize-image
agent-reel p2p publish --dry-run --images --image-processor http-endpoint --image-endpoint http://127.0.0.1:8787/summarize-image
agent-reel hook --source claude --event PreToolUse
agent-reel uninstall --restore-hooks
```

`codex active` reads `~/.codex/history.jsonl`, selects the most recent distinct
session ids, finds their transcript JSONL files under `~/.codex/sessions`, and
imports display-safe lifecycle/tool/file-change events through the normal
redaction path.

`codex stories` uses the same active-session discovery, but it does not post to
the daemon. it compiles selected transcripts into settled story summaries.

`claude stream` reads Claude Code `--output-format stream-json` JSONL from stdin
and posts display-safe events to the local daemon. `claude active` discovers the
newest transcript JSONL files under `~/.claude/projects` and can watch appended
events. hook JSON from Claude Code can also be piped through `agent-reel hook
--source claude --event PreToolUse`; failures are logged and fail open.

the hook helper reads stdin, posts to loopback, exits `0` on daemon failure, and never
blocks the agent unless explicitly installed as a policy hook. telemetry hooks are
fail-open.

## github auth

native github auth is edge-mediated. the cli never needs a github client
secret.

```text
agent-reel auth github
```

the command binds a one-shot loopback callback, opens the edge github sign-in
URL in the browser, validates the returned `state`, and writes the resulting
github profile/session to `~/.agent_reel/auth/github.json` with owner-only file
permissions.

useful variants:

```text
agent-reel auth github --print-url
agent-reel auth github --no-browser
agent-reel auth github --edge https://edge.feed.aberration.technology
agent-reel auth github --callback-bind 127.0.0.1:0
```

the hosted browser shell uses the same edge authority. `/network` is the
interactive surface for github sign-in, private feed grants, and browser seed
material. projection routes stay story-only and do not become raw stream access
after sign-in.

## story compiler

the display path is:

```text
event -> story window -> settled story -> bulletin
```

low-context token streams, shell polling, session starts, and file reads are stored but
not shown. a story settles on changed files, failed tools, failed turns, permission
events, test signals, plan updates, or a final flush. summaries are deterministic and
do not copy raw prompts, command output, or diffs.

## p2p

p2p is opt-in. the local reel remains the default.

```text
agent streams -> redaction -> story compiler -> signed story capsules -> p2p feed
```

the p2p publish layer accepts signed story capsules, not raw events. private feeds
require subscription grants. public topic names hash feed ids and do not include handles,
repo names, hostnames, or local usernames.

network participation is not a feed subscription. native peers may join the fabric,
cache signed directory records, serve rendezvous/kad/provider lookups, or host
browser handoff transports without receiving story capsules. a feed starts delivering
only after an explicit follow/subscription grant path.

summarization is publisher-side. subscribers receive already-summarized capsules and do
not spend tokens or run external processors. the default p2p publisher uses a deterministic
feed rollup, so a noisy window becomes one small recap capsule. `--per-story` keeps one
capsule per settled story when an operator wants more detail.

external summarizers are opt-in and still pass through the same guardrails before signing:

```text
deterministic
codex-exec
claude-code
process
http-endpoint
```

`codex-exec` and `claude-code` are built-in process profiles. custom processes,
HTTP endpoints, and in-process adapters receive only redacted story facts, never
raw prompts, raw command output, raw diffs, or absolute paths. their output is
guarded again before a capsule is signed.

headline images are also publisher-side and disabled by default. when enabled,
the image processor receives the settled headline, deck, lower-third, chips, and
style policy, then may return either a cached image reference or `null`. not
every headline needs art. image output is still guardrailed: no raw prompts,
readable code, command output, diffs, absolute paths, repo names, credentials,
or personal data. subscribers do not run image generation.

the projection UI is text-only by default. a viewer may opt in with
`?images=on` or local storage key `agent_reel.images=enabled`; `?images=off`,
`text=only`, or `text_only=true` force text-only mode.

## github routes

the hosted browser shell treats a single path segment as a github user lookup:

```text
https://feed.aberration.technology/mosure
https://feed.aberration.technology/@mosure
https://feed.aberration.technology/mosure/*
https://feed.aberration.technology/mosure/workstation
https://feed.aberration.technology/mosure?all
https://feed.aberration.technology/mosure?streams=workstation,release
https://feed.aberration.technology/mosure?agents=codex,claude&kinds=turn.complete,test.fail&min_score=75
https://feed.aberration.technology/mosure/workstation?view=timeline
```

the path login is only a human-readable alias. the edge resolves it to the
durable github numeric user id, then issues a signed discovery ticket containing
the verified profile, visible feed records, bootstrap peers, rendezvous
namespaces, provider keys, and a signed browser seed.

remote headlines render the publisher from the signed feed owner, not from raw
capsule text. the browser shows the cached github avatar and `@login` beside the
headline when the feed record or capsule carries a verified github publisher.

feed names are logical labels. one account may publish multiple logical feeds,
and more than one node may announce the same logical feed name:

```text
mosure/workstation
mosure/release
mosure/*
```

`mosure/*` means all visible settled story streams for that github identity. it
does not mean raw stream access.

the default route remains automated projection. interactive browsing is opt-in:

```text
?view=timeline
?timeline=1
```

timeline mode is a vertical, scroll-snapped view over the selected user/feed.
it keeps a bounded ring buffer of recent settled story capsules and never
subscribes to private feeds without an explicit grant. `/reel` and the normal
deep links stay hands-free.

`?all` means all visible settled story streams:

```text
story_only = true
raw_events = false
require_settled = true
```

privacy-weakening query params such as `redact=off`, `raw=true`, and `diffs=true`
are ignored by the route compiler.

waiting states are explicit:

```text
resolving github identity
finding feeds on mainnet
dialing p2p peers
waiting for story capsules
```

the projection page does not show raw network errors. detailed failure state
belongs in `/network/debug`.

## local api

```text
GET  /reel
GET  /reel/{view}
GET  /events.sse

GET  /api/reel/snapshot
GET  /api/bulletins
GET  /api/events
GET  /api/agents
GET  /api/sessions
GET  /api/adapters
GET  /api/health

POST /ingest/codex/jsonl
POST /ingest/codex/hook
POST /ingest/claude/stream-json
POST /ingest/claude/hook
POST /ingest/mcp
POST /ingest/otel
POST /ingest/generic
```

edge api:

```text
GET  /auth/github
GET  /callback/github
GET  /resolve/github/{login}
GET  /directory/github/{github_user_id}
GET  /directory/feed/{feed_id}
GET  /browser-seed
GET  /avatar/github/{github_user_id}
POST /subscription/request
POST /subscription/approve
GET  /network/snapshot
GET  /healthz
GET  /readyz
```

## config

```toml
[server]
bind = "127.0.0.1:7777"
public_bind_requires_token = true
snapshot_interval_ms = 5000

[store]
path = "~/.agent_reel/events.db"
raw_events = "off"
retention_days = 7
max_events = 100_000

[privacy]
mode = "aggressive"
hash_paths = true
mask_home = true
show_prompts = false
show_command_output = false
show_diffs = false

[reel]
layout = "stage"
density = "projection"
ticker = true
default_dwell_ms = 14000
urgent_dwell_ms = 20000
idle_dwell_ms = 30000
max_visible_words = 90
recap_every_secs = 420

[story]
mode = "settled"
min_score = 65
min_context_score = 70
dedupe_window_secs = 300
per_feed_max_capsules_per_min = 4

[summarize]
mode = "feed_rollup"          # feed_rollup | per_story
processor = "deterministic"   # deterministic | codex-exec | claude-code | process | http-endpoint
max_capsule_chars = 720
max_feed_rollup_stories = 32

[summarize.image]
enabled = false
processor = "disabled"        # disabled | codex-exec | claude-code | process | http-endpoint
decision = "best_judgement"   # best_judgement | always_ask | never
allow_remote_urls = false
allowed_uri_prefixes = ["/assets/headlines/", "/media/headlines/"]

[summarize.guardrails]
name = "p2p-strict"
allow_project_names = false
allow_local_paths = false
allow_command_text = false

[[summarize.guardrails.patterns]]
name = "credential"
pattern = "(?i)(password|credential|secret|token|api[_-]?key)"
action = "mask"

[p2p]
enabled = false
network_id = "agent-reel-mainnet"
profile = "local"

[p2p.discovery]
edge_directory = true
rendezvous = true
kad = true
presence_gossip = true
resolve_timeout_ms = 20000

[p2p.fabric]
enabled = true
subscribe = false              # fabric/routing participation does not imply follow
browser_handoff = true

[p2p.gossipsub]
signed_messages = true
validate_messages = true
hash_topics = true
peer_score = true

[p2p.publish]
enabled = false
summary_only = true
raw_events = false
summarizer = "deterministic"
images = false

[p2p.subscribe]
enabled = true
auto_follow_public = false
request_private_grants = true

[remote_routes]
default_mode = "settled"
allow_immediate = false
story_only = true
min_score = 75
min_context_score = 70
max_cards_per_min = 4
```

URI filters may narrow the view:

```text
/reel?agents=codex,claude
/reel?kinds=turn.complete,tool.fail,permission.request
/reel?project=burn_dragon
/reel?layout=incident
/reel?density=ambient
/reel?since=30m
```

URI filters may not weaken privacy. `?redact=off` is ignored unless the daemon is
started in explicit debug mode.

## workspace map

```text
agent_reel/
  Cargo.toml
  README.md
  LICENSE-APACHE
  LICENSE-MIT
  deny.toml
  justfile
  xtask/

  crates/
    agent_reel/           public facade, stable types, extension traits
    agent_reel_cli/       binary: agent-reel
    agent_reel_core/      ids, time, event model, score model, typed errors
    agent_reel_adapters/  codex, claude, mcp, otel, shim, process discovery
    agent_reel_ingest/    HTTP ingest, JSONL ingest, hook helper protocol
    agent_reel_redaction/ secret scanning, path masking, prompt/output policy
    agent_reel_filter/    allow/deny rules, URI filters, project filters
    agent_reel_highlight/ scoring, clustering, deduplication, recap generation
    agent_reel_story/     story windows, settle rules, p2p-safe summaries
    agent_reel_summarize/ feed rollups, guardrails, external processors
    agent_reel_reel/      bulletin scheduler, dwell rules, urgent queue
    agent_reel_store/     sqlite store, ring buffer, retention, raw-event policy
    agent_reel_server/    axum routes, SSE, auth, embedded UI assets
    agent_reel_views/     read models consumed by /api and UI
    agent_reel_security/  display tokens, LAN mode, CORS, mutation safety
    agent_reel_metrics/   counters, health, adapter lag, dropped events
    agent_reel_install/   doctor, discovery, shims, hook merge/uninstall
    agent_reel_identity/  provider-neutral identity model
    agent_reel_identity_github/ github login/id/profile resolver
    agent_reel_directory/ route parser, signed feed directory, tickets
    agent_reel_p2p_proto/ signed feed profiles, story capsules, grants
    agent_reel_p2p/       native publish/subscribe runtime boundary
    agent_reel_auth/      provider-neutral identity model
    agent_reel_auth_github/ github profile and device-flow boundary
    agent_reel_social/    feed directory and follow request state
    agent_reel_browser/   wasm/browser peer bootstrap boundary
    agent_reel_p2p_browser/ browser route states and discovery view models
    agent_reel_edge/      bootstrap, auth, directory, browser seed edge
    agent_reel_deploy/    deployment templates and operator surfaces
    agent_reel_testkit/   fake streams, fixtures, projector snapshots
    agent_reel_ui/        self-contained HTML/CSS/TS broadcast client
```

## roadmap

m0 - signal path:

* local server
* embedded `/reel` page
* generic ingest endpoint
* canonical event model
* SSE stream
* one-card stage UI

m1 - codex / claude:

* codex `exec --json` adapter
* claude `stream-json` adapter
* basic hook helper
* redaction
* highlight scoring
* sqlite store

m2 - auto-init:

* doctor
* config discovery
* hook merge with backups
* shell shim install
* systemd or launchd service
* uninstall restore

m3 - broadcast UI:

* stage layout
* breaking layout
* ticker
* idle state
* recaps
* wall mode
* ambient mode
* projector snapshot tests

m4 - production safety:

* aggressive redaction suite
* display/admin token split
* raw quarantine
* retention policy
* adapter backpressure
* reconnect snapshots

m5 - story compiler:

* story windows
* settle conditions
* context scoring
* anti-spam policy
* p2p-safe capsule model
* publisher-side feed summaries
* modular guardrails and external summarizer processors

m6 - native p2p alpha:

* agent_reel_p2p_proto
* native p2p node boundary
* feed profiles
* public feed capsules
* snapshot request-response

m6.1 - username route model:

* remote user route parser
* privacy-preserving query compiler
* waiting-state browser view model

m6.2 - github identity resolver:

* github login to durable id model
* edge-mediated cli/browser github sign-in
* profile view and resolver trait
* signed discovery ticket
* fake github tests

m6.3 - directory records:

* feed directory entries
* stream descriptors
* signed browser seeds
* edge resolver API shape

m6.4 - native p2p discovery:

* github user directory announcements
* opaque github user topics
* provider-key fallback surface
* signed feed record discovery tests

m7 - protocol depth:

* codex app-server adapter
* mcp stream observer
* claude otel ingest
* adapter health cards
* schema generation

m8 - distribution:

* signed binaries
* homebrew tap
* nix flake
* cargo install path
* release checklist
* operator runbook

## development

```sh
cargo xtask check
```

`just check` is a thin wrapper over the same command.