Complement to alice-emacs-mods. Covers what alice does not — ghostel mastery, multi-daemon orchestration, cross-session coordination, debug/recovery harness, REPL-as-dynamical-citizen, QRTP distribution, strobe internals, and the hard-won lessons from spawning and debugging live REPLs under the server daemon. Read alongside alice-emacs-mods; together they tile the total Emacs-mod space on this machine.
Scanned 9/6/2026
Install to Claude Code
npx -y skills add plurigrid/asi --skill bob-emacs-mods --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Bob Emacs Mods?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/plurigrid-bob-emacs-mods)More formats (shields.io, HTML) on the badges page.
---
name: bob-emacs-mods
description: Complement to alice-emacs-mods. Covers what alice does not — ghostel mastery, multi-daemon orchestration, cross-session coordination, debug/recovery harness, REPL-as-dynamical-citizen, QRTP distribution, strobe internals, and the hard-won lessons from spawning and debugging live REPLs under the server daemon. Read alongside alice-emacs-mods; together they tile the total Emacs-mod space on this machine.
---
# Bob's Emacs Mods — the other half
Read `alice-emacs-mods` first. That skill covers the *host-level* defaults: build (emacs-nox 30.2 from Nix), daemons (factory/server/claude-crdt/horsin-around), causal transients, org worlding, Gnus, keyboard, clipetty, takeover.bb. Bob covers everything else: the operational layer where live REPLs, cross-session coordination, and debug/recovery actually happen.
## Ghostel mastery (the real one, not the comint imposter)
### The imposter problem
`(make-comint "ghostel: <name>" prog)` yields a buffer named `*ghostel: <name>*` in `comint-mode`. This is **not** a ghostel buffer. It has no VT parsing, no OSC-133, no bridge, no TRAMP, no prompt-awareness. Many skills and my own earlier spawns emit comint imposters. Audit: `(cl-remove-if-not (lambda (b) (and (string-match-p "ghostel" (buffer-name b)) (eq (with-current-buffer b major-mode) 'comint-mode))) (buffer-list))`.
### The correct spawn
```elisp
(require 'ghostel)
(let ((ghostel-shell "/Users/alice/.juliaup/bin/julia")
(ghostel-buffer-name "*ghostel: julia-real*"))
(ghostel))
```
Buffer comes up in `ghostel-mode`, parses VT through `ghostel-module.dylib` (Zig, libghostty-vt). Everything downstream — strobe, prompt nav, bridge, OSC-52, TRAMP — starts working.
### Parallel-spawn hazard
Spawning ≥2 ghostel buffers that each launch a heavy REPL (julia, stack ghci) in the same redisplay frame **hangs the daemon**. The Zig module's VT parser is not reentrant against concurrent PTY floods. Julia's startup banner alone is ~100 KB of escape sequences per pane. Three parallel spawns = instant hang (observed twice in the session).
### Safe multi-spawn recipe
1. **Wrap shells with quiet flags** via a trivial script. `~/bin/julia-quiet`:
```sh
#!/bin/sh
exec /Users/alice/.juliaup/bin/julia --color=no --banner=no "$@"
```
2. **Serialize** spawns + poll for prompt between each:
```elisp
(defun bob/ghostel-spawn-wait (name shell &optional timeout)
(let ((ghostel-shell shell)
(ghostel-buffer-name (format "*ghostel: %s*" name))
(deadline (+ (float-time) (or timeout 15))))
(unless (get-buffer ghostel-buffer-name) (ghostel))
(while (and (< (float-time) deadline)
(not (with-current-buffer ghostel-buffer-name
(save-excursion
(goto-char (point-max))
(forward-line -1)
(looking-at ".*\\(julia\\|> \\|λ>\\) *$")))))
(sit-for 0.2))
ghostel-buffer-name))
```
3. **Throttle during the multi-spawn window**:
```elisp
(let ((ghostel-timer-delay 0.1)
(ghostel-immediate-redraw-threshold 4096)
(ghostel-input-coalesce-delay 0.05))
(bob/ghostel-spawn-wait "sd-minus" "/Users/alice/bin/julia-quiet")
(sit-for 2)
(bob/ghostel-spawn-wait "sd-ergodic" "/Users/alice/bin/julia-quiet")
(sit-for 2)
(bob/ghostel-spawn-wait "sd-plus" "/Users/alice/bin/julia-quiet"))
```
### Nuclear fallback — one daemon per tree
When the single-daemon pattern can't be made safe, fork per trit:
```sh
emacs --daemon=sd-minus -l ~/.claude/skills/emacs-strobe-walk/color-walk-gay.el
emacs --daemon=sd-ergodic -l ~/.claude/skills/emacs-strobe-walk/color-walk-gay.el
emacs --daemon=sd-plus -l ~/.claude/skills/emacs-strobe-walk/color-walk-gay.el
```
No shared VT parser. Cost: three frames. Win: true triadic parallelism, one GF(3) component per daemon. `emacsclient -s sd-minus -t` to attach.
## Ghostel feature table (what alice doesn't cover)
| Feature | Knob | Value / notes |
|---|---|---|
| VT render rate | `ghostel-timer-delay` | 0.033 → 30 fps (lower for multi-spawn) |
| Adaptive FPS | `ghostel-adaptive-fps` | t (idle buffers idle the timer) |
| Big-chunk bypass | `ghostel-immediate-redraw-threshold` | 256 chars default; raise to 4 KB during spawn |
| Input batching | `ghostel-input-coalesce-delay` | 3 ms default |
| Scrollback cap | `ghostel-max-scrollback` | 5 MB; raise to 64 MB for long-lived REPLs |
| Shell → Emacs bridge | `ghostel-eval-cmds` | defaults: find-file, find-file-other-window, dired, dired-other-window, message |
| Prompt nav hooks | `ghostel-command-{start,finish}-functions` | empty until shell sources `etc/ghostel.{zsh,bash,fish}` |
| SSH terminfo | `ghostel-ssh-install-terminfo` | `'auto` |
| TRAMP shells | `ghostel-tramp-shells` | per-host shell mapping |
| Compile mode | `M-x ghostel-compile` | replacement for `M-x compile`, full VT |
| Eshell bridge | load `ghostel-eshell` | eshell inside a ghostel buffer |
### Extend the bridge for this session
```elisp
(dolist (pair '(("gay-reseed" horsin/reseed)
("gay-strobe-on" horsin/enable)
("gay-strobe-off" horsin/disable)
("delta-append" (lambda (text) (append-to-file text nil "~/worlds/e/2026-04-21-delta.org")))))
(add-to-list 'ghostel-eval-cmds pair))
```
From any shell inside a ghostel buffer: `printf '\e]51;e;gay-reseed;305419896\a'` reseeds the strobe. No socket, no RPC, the VT stream *is* the control channel.
## Known Emacs-daemon cracks (observed this session)
### Crack 1: `proof-easy-config: PG already in use or name/symbol mismatch`
After `(require 'proof-general)`, narya.el's own `(proof-ready-for-assistant 'narya)` fails the macro's name-check and `define-derived-mode narya-mode` never lands. Workaround: set `narya-toolbar-entries` to nil *before* loading (handles one error) and either load narya *before* any other PG assistant OR do `(unload-feature 'proof-general t)` first. Escape valve: use `coq-mode` + a `.v` file — PG bindings work fine there.
### Crack 2: `wrong-type-argument integerp (HI . LO)` in horsin/tick
The strobe chain uses `logand (+ seed golden) mask` where seed can be a bignum. On Emacs 30.2 + aarch64, some path returns a `(hi . lo)` *cons pair* instead of a bignum integer, which `logand` can't handle. Observed every time `horsin/seed` exceeds fixnum range and the tick advances. Workaround: `(setq horsin/seed (logand (or (and (consp horsin/seed) (logior (ash (car horsin/seed) 64) (cdr horsin/seed))) horsin/seed) #xFFFFFFFFFFFFFFFF))` as a coerce-on-read.
### Crack 3: sequential narrow-terminal window splits silently drop panes
`(dotimes (_ 4) (split-window-right))` on a 120-col terminal silently fails after ~3 splits — Emacs reports "Window too small for splitting" only when the fifth split is attempted directly, not inside `dotimes`. Always check `(length (window-list))` after a split burst and fall back to vertical layout if short.
### Crack 4: daemon hang on multi-ghostel spawn
Symptom: `emacsclient -s server -e '(+ 1 2)'` → SIGALRM after 3-5 s. Cause: see "Parallel-spawn hazard" above. Recovery: `C-g` in the user's live Emacs frame. No emacsclient-side recovery exists (all `-e` calls queue behind the hung VT parser).
## Cross-session coordination (the L6 layer alice doesn't discuss)
The user routinely runs 4+ Claude Code sessions in parallel Ghostty tabs (⌘1–⌘4). These sessions share only:
- `/worlds/*` filesystem
- `~/.claude/skills/` (shared skill library)
- `~/.claude/projects/-Users-alice-worlds-*/memory/` (per-project memory dirs)
- the single Emacs daemon (PID 1831, `server` socket)
They do **not** share:
- conversation transcript (each session has its own `/tmp/claude-501/<uuid>/`)
- Monitor task outputs (same; each session's `tasks/*.output` is isolated)
- a messaging inbox
### Shared-state rendezvous patterns that work
- **Memory entries** under `~/.claude/projects/-Users-alice-worlds-e/memory/MEMORY.md` — indexed, one-line hooks. Multiple sessions can read + append (last-writer-wins, but entries are append-only by convention).
- **DuckDB on disk** — `/worlds/e/broadcast_e.duckdb` and `/worlds/i/ies_beeper.duckdb` are written by one session, queried by another. Tables like `barton_ies_messages` are durable rendezvous points.
- **Org buffers shared via the Emacs daemon** — all sessions driving `server` see the same `*ghostel: …*` buffers. Two sessions editing the same buffer is safe as long as only one writes to a given region (CRDT is optional; last-writer-wins OK for ephemeral).
### Anti-patterns observed
- Trying to SIGINT another session's Claude Code process → no cross-session permission.
- Polling `/tmp/claude-501/*/tasks/*.output` for another session's progress → works but slow; use a DuckDB table instead.
## REPL as dynamical citizen
Long-lived REPLs in ghostel buffers are not tools — they're citizens with state. Observed in this session:
- `*ghostel: nanoclj-zig*` retained seed-split hex history across multiple parallel agents.
- `*ghostel: julia-gay*` retained `gay_seed!(0xd8dbb2df5c81869c)` from one agent's earlier run.
- `*ghostel: duckdb*` on `broadcast_e.duckdb` holds the result cache across queries.
Implication: **source-verify before every REPL call** (established in prior memory) AND **state-verify** — read the prompt history's tail, don't assume a fresh REPL. Pattern:
```elisp
(defun bob/repl-tail (buf &optional n)
(with-current-buffer buf
(buffer-substring-no-properties
(max (point-min) (- (point-max) (or n 800)))
(point-max))))
```
## Team-red canonical parameters (this session's gauge)
- minus seed: `0x144d8132a6e983f5` (validator / `-.tree`)
- ergodic seed: `0xa4dd4adf1c71e889` (coordinator / `0.tree`)
- plus seed: `0x4fd68f19a3c21491` (generator / `+.tree`)
- pleasant-red locus: `LCH(55.5, 139.9, 12.4)` ≈ `#f34240`
- 3-MATCH triad: ghci (−1) ⊗ nanoclj-zig (0) ⊗ julia-gay (+1) = 0 ✓
Reseed the strobe:
```elisp
(horsin/reseed #x144d8132a6e983f5)
```
(note crack 2 — coerce the seed first if it's a bignum cons).
## The numeric horizons of the three REPL languages
| REPL | Native int | Max exact | Above that |
|---|---|---|---|
| GHCi | Word64 | 2^63−1 | bignum `Integer` |
| Julia | Int64 / UInt64 | 2^63−1 / 2^64−1 | `BigInt` on demand |
| nanoclj-zig | double (Int53) | 2^53−1 ≈ 9e15 | **literal rejected**: "invalid number" |
Implication for cross-REPL seeds: if the seed exceeds 2^53−1, **split into 32-bit hi/lo halves** and run paired SplitMix32. Reference code: `/worlds/e/sm32-split.cljc`. See memory `repl_numeric_horizons_2026_04_22.md`.
## Canonical Gay.jl path
Four directories claim the name "Gay.jl" with TWO distinct UUIDs:
- `/worlds/g/Gay.jl` — **CANONICAL** — UUID `f3dee6b2-1ce2-4cc9-bfb1-25e98f6f315b`, v0.3.0 (newest, richest src tree)
- `/worlds/g/Gay.jl_1` — sibling copy, same HEAD
- `/worlds/g/Gay.jl_2` — older snapshot (v0.2.1)
- `/worlds/e/exo__home1/exo/Gay.jl` — **DIFFERENT PACKAGE** (UUID `a8c5b8e4…`, v0.1.0) — do not load by accident
Global autoload already installed at `~/.julia/config/startup.jl`; takes effect for every future Julia REPL via `atreplinit`. See memory `canonical_gay_jl.md`.
## Layout patterns & their tradeoffs
| Grid | Use when | Gotchas |
|---|---|---|
| 1×3 horizontal | 3 REPLs, wide terminal | `split-window-right` ×2; narrow cols on small screens |
| 1×4 / 1×5 horizontal | 4–5 panes, wide | `Window too small for splitting` on < 160 col |
| 2×3 grid | 6 panes, balanced | need ≥ 120 col × 30 rows |
| 4×2 grid (tall) | 8 panes, narrow terminal | vertical-dominant; fall back if 2×4 horizontal fails |
| 3×1 vertical | 3 panes, narrow | each pane very short (7-8 rows) |
Always check `(length (window-list))` after splits; fall back on failure.
## QRTP distribution of a session
Full bundle template at `/worlds/e/ghostty-emacs-combo/`. Pack: `scripts/pack.bb` → `frames/*.png`. Play: `scripts/play.sh` at 8 fps. Receiver: `scripts/unpack.sh` via `zbarcam`. See README.org in that dir. ~228 KB bundle ≈ 395 frames ≈ 50 s / loop.
## bb-native MCP server template
When a skill wants an MCP server without Node/TypeScript, use `/worlds/e/bb-mcp.bb` (95 lines, pure babashka). Replaces a 40-file TypeScript babashka-mcp-server. Register in `~/.mcp.json` with stdio transport.
## Debug harness
Proposed but not yet scaffolded (TODO):
- `debug/scan-sessions.sh` — inventory all `/tmp/claude-501/*/tasks/` + last 5 outputs
- `debug/emacs-health.el` — `M-x bob/health` prints daemon-PID, seed, tick, layout, messages-tail
- `debug/shared-inbox/` — `fswatch`-triggered cross-session messaging
- `debug/pg-snapshot.el` — dump PG locked/processing offsets per `.v` buffer
## Things NOT to do (session-observed)
1. Don't `(julia-snail)` on a fresh project without killing PG state first — `proof-easy-config` collides with narya.el's init (see Crack 1).
2. Don't spawn ≥2 ghostel buffers in the same redisplay frame unless banner-silenced AND throttled.
3. Don't call `vterm-send-string` — we're in comint/ghostel land. Use `process-send-string (get-buffer-process BUF) STR`.
4. Don't assume a ghostel-prefixed buffer is in ghostel-mode. Grep `major-mode` first.
5. Don't use fish-shell `for` loops in Monitor scripts — they don't word-split `$VAR`. Use `bash -c '…'` explicitly OR inline values.
6. Don't `Pkg.add` in a ghostel pane *before* the prompt is visible — the resolver progress flood blocks the VT parser.
7. Don't assume the Emacs "daemon" is a daemon — on this machine it's `emacs -nw` (PID 1831) running interactively in a TTY that happens to host the `server` socket. `C-g` at the user's frame is the canonical recovery.
## Quick triage
| Symptom | Probe | Fix |
|---|---|---|
| `emacsclient -s server -e '(+ 1 2)'` → SIGALRM | daemon hung | user C-g |
| `*ghostel:…*` in comint-mode | comint imposter | kill + respawn with `(ghostel)` |
| horsin tick error `(HI . LO)` | seed overflow to cons | coerce with mask |
| narya-mode doesn't activate | PG macro collision | setq `narya-toolbar-entries`, then `unload-feature 'proof-general` |
| REPL pane tripled | narrow-terminal split collapse | fall back to vertical layout |
| shell commands in ghostel don't trigger OSC-133 | shell rc hasn't sourced `etc/ghostel.zsh` | source it |
## Session-specific memory hooks
- `memory/delta_2026_04_21.md` — team-red ladder + 3-MATCH triad + source-verify discipline + open-games verdict
- `memory/repl_numeric_horizons_2026_04_22.md` — three REPLs, three ints, canonical
- `memory/canonical_gay_jl.md` — Gay.jl path disambiguation (f3dee6b2 = canonical)
- `memory/team_red_locus.md` — LCH(55, 138, 12) locus, #f34240
- canonical Beeper archive: `/Users/alice/Library/Application Support/BeeperTexts/account.db` (352 MB) + `/worlds/i/ies_beeper.duckdb` (478 MB, pre-processed IES slice)
## GF(3) triadic composition
```
alice-emacs-mods (-1) ⊗ bob-emacs-mods (0) ⊗ plurigrid-asi-ghostel (+1) = 0 ✓
```
Alice anchors the host (validator of the install). Bob coordinates the live operation (ergodic). Plurigrid-asi-ghostel generates the substrate for new REPL/agent channels. The three together tile the Emacs-mod space.
## See also (bidirectional)
- [[alice-emacs-mods]] — host-level defaults; read first
- [[plurigrid-asi-ghostel]] — ghostel substrate for agent channels
- [[ghostel]] — the underlying terminal
- [[emacs-strobe-walk]] — horsin/color-walk; target of the bignum coerce workaround
- [[proofgeneral-narya]] — Narya PG integration; source of Crack 1
- [[three-match]] — the 3-MATCH triadic framework we instantiate on REPLs
- [[emacs-color-chain]] — sibling strobe skill
- [[julia-gay]] / [[clojure]] — language content layers
- [[bumpus-narratives]] / [[open-games]] — proof-target formalizations with open cracks
## Session cross-refs (2026-04-23, e-session)
This skill participates in the 32-skill working set assembled in /Users/alice/worlds/e session 2026-04-23 (15 new skills also created).
**Outgoing references** (this skill `src` → other skill `dest`):
- `bob-emacs-mods` → `plurigrid-asi-ghostel` — VT substrate (named ghostel-vt in ghostel-rooms)
- `bob-emacs-mods` → `three-match` — 3-MATCH framework bob's session instantiates
- `bob-emacs-mods` → `bumpus-narratives` — proof-target sheaf substrate
- `bob-emacs-mods` → `open-games` — proof-target formalization with open cracks
- `bob-emacs-mods` → `emacs-strobe-walk` — target of bignum-safe patch
- `bob-emacs-mods` → `proofgeneral-narya` — Crack #1 source skill
- `bob-emacs-mods` → `ies-triadic` — 3-MATCH triad instantiated in ghci/nanoclj/julia-gay
- `bob-emacs-mods` → `horsin-bignum-safe` — implements the Crack #2 workaround bob documents
- `bob-emacs-mods` → `ghostel-imposter-audit` — implements the imposter audit bob requests
- `bob-emacs-mods` → `ghostel-multi-spawn-safe` — implements bob's safe-multi-spawn recipe
- `bob-emacs-mods` → `three-repl-triad` — codifies bob's canonical team-red triad seeds
**Incoming references** (other skill `src` → this skill `dest`):
- `alice-emacs-mods` → `bob-emacs-mods` — operational complement to alice host-level
- `plurigrid-asi-ghostel` → `bob-emacs-mods` — ghostel mastery and multi-daemon orchestration
**Verified GF(3) triads containing this skill:**
- alice-emacs-mods (-1) ⊗ bob-emacs-mods (0) ⊗ plurigrid-asi-ghostel (+1) = 0 ✓
## REPL atlas
Part of: `repl-commons`. Family canonical: `emacs`.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!