S14 — Pubsub watch
Earlier docs (and the file name
s15-pubsub.md) called this S15. The screen is now the 14th (and last) tab — the file name is kept for stable links.
Live tail of PSS topic subscriptions and GSOC (owner, identifier)
subscriptions, merged into a single chronological timeline.
The receiver-side complement to v1.3's
:gsoc-mine and :pss-target writer verbs:
operators can finally see the messages those senders produce
without leaving the cockpit.
How to start a subscription
The screen has no auto-load. Subscriptions are started by verb:
:pubsub-pss <topic>
:pubsub-gsoc <owner> <identifier>
<topic> accepts the same forms as :feed-probe:
- 64 hex chars (with or without
0x) is the raw 32-byte topic. - Anything else is
keccak256(utf8(s)), mirroring bee-js'sTopic.fromString.
<owner> is a 20-byte Ethereum address (0x-prefixed or bare).
<identifier> is a 32-byte SOC identifier (64 hex chars,
0x-prefixed or bare).
Each subscription opens a WebSocket against Bee's
/pss/subscribe/{topic} or /gsoc/subscribe/{soc-address} and
forwards every delivered frame into the screen's ring buffer.
The verb switches to S15 immediately so the operator sees the
"0 messages" state until the first frame arrives.
Re-issuing for an already-watched (topic) or (owner, identifier)
errors with a clear message — no silent duplicate sockets.
Layout
┌ PUBSUB WATCH · 2 active subs · 17 messages ─────────────────────────────┐
│ │
│ TIME KIND CHANNEL SIZE PREVIEW │
│ 10:14:32 PSS abc1234567… 18 hello cockpit! │
│ 10:14:31 GSOC ee7f3a2018… 32 deadbeef… │
│ 10:14:30 PSS abc1234567… 42 {"event":"ping","seq":12} │
│ ... │
│ │
│ channel: 0xabc1234567890abcdef…fedcba0987654321 · 18 bytes │
│ data: hello cockpit! │
│ │
│ ↑↓/jk select c clear timeline Tab switch screen : command q quit │
└───────────────────────────────────────────────────────────────────────────┘
The cursor row is reverse-styled. GSOC rows tint blue so PSS and GSOC are distinguishable at a glance even after the kind column scrolls offscreen.
The two-line detail strip shows the full channel hex and the
smart-preview of the cursored row's payload (capped at 200 chars).
"Smart" means: ASCII when ≥ 75 % of bytes are printable, hex
otherwise. Empty payloads render as (empty).
Keymap
| Key | Action |
|---|---|
↑ / k | Move cursor up |
↓ / j | Move cursor down |
PgUp / PgDn | Jump 10 rows |
c | Clear the timeline (subscriptions stay open) |
Tab | Cycle to the next screen |
: | Open the command bar |
Stopping subscriptions
:pubsub-stop # cancels every active subscription
:pubsub-stop pss:abc1234567… # cancels just the matching one
:pubsub-stop gsoc:0xabc…:def0… # GSOC subs are keyed by owner:id
Sub-IDs are reported by the :pubsub-pss / :pubsub-gsoc
"subscribed: …" line. The cockpit's root cancellation token also
fires on quit, so operators don't need to remember to issue
:pubsub-stop before exiting.
Filtering the timeline
:pubsub-filter <substring> # show only matching rows
:pubsub-filter-clear # remove the active filter
Case-insensitive substring match against the channel hex OR the smart-preview of the payload. The underlying ring still receives every message — filtering is presentation-only, so clearing the filter restores the full view without re-subscribing.
Persisting + replaying history (v1.8 / v1.9)
Set [pubsub].history_file in config.toml to write every
delivered frame to a JSONL file:
[pubsub]
history_file = "/var/lib/bee-tui/pubsub.jsonl"
rotate_size_mb = 64 # roll over at 64 MiB (default; 0 disables)
keep_files = 5 # retain .1 .. .5 (default)
Files are created with mode 0600 (owner-only). When the active
file crosses rotate_size_mb, it's renamed to <path>.1 (older
rotations shift to .2 .. .N; oldest beyond keep_files is
unlinked) and a fresh empty file takes its place.
To browse a past session without re-subscribing:
:pubsub-replay <path>
Loads the file back into the S15 ring (oldest → newest, capped at 500 entries). Bad lines are skipped with a warn log; replay does not start any watchers.
What it doesn't do
- No live "tail since T-30s". WebSocket subscriptions only
deliver messages sent after the subscription opens — start the
sub before the publisher does. (Past sessions can be loaded via
:pubsub-replay; live ones cannot be rewound.) - No write side. Sending PSS / GSOC requires a stamp + private key, both outside the cockpit's current write surface. Use bee-cli or a dApp for that.
- No
--oncemode. A live tail doesn't fit one-shot exit semantics; if you want to gate on "did this topic see N messages in T seconds", script it with a separate tool.