vercel-labs / vercel-labs/native
The /terminal docs page's TypeScript column is wrong: the pty key it shows binds nothing and its `ptyWrite` call does not transpile
Nobody has claimed this yet.
- Dominant language
- Zig
- Stars
- 7.7k
- Forks
- 314
- Avg merge
- 5h
- Merged PRs (30d)
- 13
Description
Summary
The /terminal docs page's TypeScript column shows a pty key that names nothing the
bridge spawns into, and an effect call the emitter refuses. Following it produces a
blank terminal with no error anywhere. The Zig column on the same page is correct.
Checked against the live page and v0.7.1 (19519dd5), 2026-08-01.
What the page shows
const shellKey = 1;
...
case "type": return [model, Cmd.ptyWrite(shellKey, msg.bytes)];
case "viewport": return [model, Cmd.ptyResize(shellKey, msg.cols, msg.rows)];
and, in prose: "The pty key is ordinary model data — pick it like an effect key."
Why it does not work
- The key is not the app's to pick. For a TS core,
Cmd.ptySpawnnames a string
session key;ts_core_host.zigmaps it to the first free slot in its own table and
spawns the engine session atpty_key_base + index
(pub const pty_key_base: u64 = 0x5453_5054_0000_0000).<terminal pty={n}>must
name that engine key. Binding1mounts nothing — no diagnostic, no log, an empty
grid. (Background in #229.) - A computed key is not expressible.
Cmd.ptyWrite/ptyKilltake the key as a
string literal (NS1027), soCmd.ptyWrite(shellKey, …)— a variable — does not
transpile at all. The page's own snippet fails the checker.
Why it survived
None of the three core.ts examples the SDK ships (ai-chat-ts, soundboard-ts,
system-monitor-ts) mounts a <terminal>, so the TS-core + terminal combination has no
example holding the page honest.
What a correct column needs to say
- the spawn key is a string literal, and every later op naming it is a literal too;
- the value
<terminal pty>binds is the engine key,pty_key_base + slot, not the
string and not an app-chosen number; - the core is never told its slot, so it either mirrors the bridge's first-free-slot
allocation or reads the bound key back fromTerminalState.pty(#221).
Related: #229 (the binding gap this page post-dates), #224.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the /terminal documentation page and compare its TypeScript column with the behavior described in ts_core_host.zig, including pty_key_base and first-free-slot allocation. Check the Cmd.ptySpawn, Cmd.ptyWrite, and Cmd.ptyKill examples against the transpiler, then verify the corrected prose and snippets explain engine-key binding and literal-key requirements without contradicting #221 or #229.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript, zig
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100