Skip to content
C.W.K.
Stream
Lesson 01 of 10 · published

One Session, Many Surfaces

~13 min · shared-input, surfaces, serialize, daemon, ruling

Level 0Spark
0 XP0/48 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"Smolder has the same problem. The structure snatches the session away: if iOS takes it, office cannot use it, and if office uses it, iOS cannot. Implement it the same way." — Dad, 2026-09-17

The Lease Worked, and It Was Wrong

The first mobile contract made input a lease. One attached surface held it; Take Control moved it; the surface that lost it became read-only. It was careful, serialized and tested, and it answered the wrong question. Dad does not use Smolder as two people fighting over one keyboard. He uses it as one person who walks from the desk to the kitchen. Picking up the phone made the office Mac read-only; sitting back down made the phone read-only. Every handoff was a ceremony between two glasses that both belonged to him. The ruling above withdrew it — for Firebrand and Smolder on the same day.

Every Surface Types

Now a session has a surface set. Every attachment that asks to write joins it, and every member can type from the moment it attaches. The daemon writes all of their bytes into the PTY in the order they arrive — the same semantics tmux gives two clients on one session. Nobody is told they lost anything. The phone shows Keyboard here on the pane you are typing into, and when more than one surface is attached it says how many:

Smolder on an iPhone: SMOLDER header with Anvil, chips for office (CWKOfficeM3U) and macbook, and an open shell on CWKOfficeM3U whose state strip reads "Keyboard here" beside 100%, My size and Hold; the office shell shows two launchctl kickstart commands and a prompt, with Esc, Ctrl, Tab, arrow and Return keys below.
A phone typing into an office shell beside the Mac — no Take Control, no read-only Mac.

Three things did not change. A device approved only to read is still an observer: it cannot type, resize or hold, whatever it taps. Stale input is still refused — but the fence is now the daemon's incarnation and the request's identity, not ownership: a byte from a connection to an owner that has since restarted is not a byte for this owner. And nothing a surface does — attaching, detaching, typing, resizing, disconnecting — ends a session. Only two things do: an explicit terminate, or the program inside the session exiting on its own.

Register the Device, Not the Session

The ruling had a second half. A device is approved once per Mac; after that every session on that Mac is visible from it and any surface may step into any session, without harming the session on the Mac. There is no per-session opt-in. The alternative — a switch you flip on a session before walking away so the phone may join it later — was considered and refused, because the failure mode is exactly the walk: you forget to flip it, and the phone in the kitchen sees nothing.

Bytes Interleave; That Is Honest

The old lesson's fear was a character from each glass in one command. That can now happen if two hands type at the same instant, and the product says so plainly instead of preventing it with a lease. It is the tmux answer, and it fits a family where the two glasses belong to one operator. When one line must stay whole — a paste, a Korean composition, a long command typed on a phone — there is a hold, the next lesson. Firebrand landed the same idea at the granularity of a conversational turn; Smolder's granularity is the byte, because a terminal has no turns.

One session, many surfaces. Every attached input surface types; the daemon serializes bytes in arrival order; observation-only devices stay observers; stale input is fenced by incarnation and request identity; only an explicit terminate, or the program exiting by itself, ends a session.

Code

The surface set, as the daemon keeps it·text
session S (one PTY, one child, one journal)
  surfaces: { Mac pane, iPhone, iPad }      # every attachment that asked to write
  observers: { an observation-only device }  # read-only permission, never types
  hold: none                                 # optional; next lesson

input from any surface
  -> daemon appends bytes to the PTY in ARRIVAL ORDER
  -> carries that surface's viewport (lesson 3: the grid follows the typist)

refused, with a typed error and a log line
  input from an observer
  input from a connection to a previous owner incarnation
  a mutating verb from a surface that is not attached

never a lifecycle event
  attach / detach / type / resize / disconnect
only ends S
  explicit terminate
  the child exiting on its own

withdrawn 2026-09-17
  one writer at a time; Take Control; previous writer becomes read-only

External links

Exercise

Think of a tool you use from two places (desk and phone, two laptops). Write what happens today when you switch: does the first place lose anything? Then write the two rules you would need to let both places type at once safely: who may never type, and what fences a keystroke from a world that no longer exists.
Hint
Permission answers the first (observers never type). Identity answers the second (an old incarnation's bytes are refused). Neither needs a lease.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign in — Please sign in to comment.

No comments yet — be the first.