install
source · Clone the upstream repo
git clone https://github.com/plurigrid/asi
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/plurigrid/asi "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/libghostty-streaming" ~/.claude/skills/plurigrid-asi-libghostty-streaming && rm -rf "$T"
manifest:
skills/libghostty-streaming/SKILL.mdsource content
libghostty-vt Streaming Skill ⬜
Trit: 0 (ERGODIC - Coordinator) GF(3) Triad:
asciinema-play (-1) ⊗ libghostty-streaming (0) ⊗ vhs-server (+1) = 0
Overview
The white hole dual to libghostty-recording. Streams, plays back, and broadcasts terminal sessions. Where recording absorbs (black hole), streaming emits (white hole).
Recording (●) ←→ Streaming (○) absorb emit capture broadcast input output
Playback Methods
1. Asciinema Play (Local Replay)
# Play recording at original speed asciinema play session.cast # Speed up 2x asciinema play -s 2 session.cast # Idle time limit (skip long pauses) asciinema play -i 2 session.cast # Play from URL asciinema play https://asciinema.org/a/123456
2. asciinema-server (Self-Hosted Streaming)
# Run local asciinema server docker run -d -p 3000:3000 asciinema/asciinema-server # Stream to self-hosted asciinema rec -t "live session" http://localhost:3000 # Embed in docs <script src="https://asciinema.org/a/123456.js"></script>
3. Charmbracelet VHS Server
# Serve GIFs via HTTP vhs serve --port 8080 # Watch for .tape changes and regenerate vhs watch demo.tape # Continuous output to stdout vhs demo.tape --output -
4. libghostty-vt Stream Hooks
// Stream terminal output via libghostty const streamer = ghostty_vt.Streamer.init(.{ .source = .stdin, .format = .cast, .broadcast = "ws://localhost:9000/stream", }); // Emit frames while (streamer.next()) |frame| { try websocket.send(frame.render()); }
5. ttyd (Web Terminal)
# Stream terminal to web browser ttyd -p 7681 bash # Read-only broadcast mode ttyd -R -p 7681 asciinema play session.cast # With authentication ttyd -c user:pass -p 7681 bash
Streaming Transforms
Cast → WebSocket
# Stream .cast to WebSocket clients cat session.cast | websocat ws-listen:127.0.0.1:9000
Cast → NATS
# Broadcast to NATS subject asciinema play session.cast | nats pub terminal.stream
Cast → SSH (Remote Pair)
# Share session via SSH asciinema play session.cast | ssh user@remote 'cat' # Bidirectional with tmux tmux new-session -d -s shared tmux send-keys -t shared "asciinema play session.cast" Enter # Others join: tmux attach -t shared
White Hole Architecture
┌─────────────────────────────────────────────────────────┐ │ WHITE HOLE: Terminal Emission │ │ │ │ Sources (●→○) Sinks (○→) │ │ ├── .cast files ├── Web browsers (ttyd) │ │ ├── Live terminals ├── WebSocket clients │ │ ├── tmux sessions ├── NATS subscribers │ │ └── libghostty-vt ├── SSH remote │ │ └── GIF/MP4 renders │ │ │ │ GF(3): input(-1) ⊗ transform(0) ⊗ output(+1) = 0 │ └─────────────────────────────────────────────────────────┘
LLM Training Pipeline
# 1. Record sessions (black hole - absorb) asciinema rec session.cast # 2. Transform (ergodic - process) cat session.cast | jq -r '.[] | select(.[0] == "o") | .[2]' # 3. Stream to training (white hole - emit) asciinema play session.cast | tee training-corpus.txt
Justfile Recipes
# Play latest recording play-latest: asciinema play $(ls -t ~/recordings/*.cast | head -1) # Stream to web stream-web port="7681": ttyd -R -p {{port}} asciinema play $(ls -t ~/recordings/*.cast | head -1) # Broadcast to NATS stream-nats subject="terminal.live": asciinema play ~/recordings/latest.cast | nats pub {{subject}} # Convert to GIF cast-to-gif file: agg {{file}} {{file}}.gif
Duality Table
| Recording (●) | Streaming (○) |
|---|---|
| |
| |
| |
| Input capture | Output broadcast |
| Black hole | White hole |
| Trit -1 (absorb) | Trit +1 (emit) |
Integration with Gay.jl
# Color-coded streaming sessions using Gay seed!(1069) session_color = color_at(session_id) stream_trit = trit_at(session_id) # -1, 0, or +1 # Route by trit if stream_trit == -1 record_session() # Black hole elseif stream_trit == 0 transform_session() # Ergodic else broadcast_session() # White hole end
See Also
- The black hole dual (recording/capture)libghostty-recording
- Terminal session recorderasciinema
- Charmbracelet tape automationvhs
- Web terminal streamingttyd
- Terminal multiplexing for sharingtmux
Autopoietic Marginalia
The interaction IS the skill improving itself.
Every use of this skill is an opportunity for worlding:
- MEMORY (-1): Record what was learned
- REMEMBERING (0): Connect patterns to other skills
- WORLDING (+1): Evolve the skill based on use
Add Interaction Exemplars here as the skill is used.