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

Open
#252 0 comments 0 reactions 0 assignees View on GitHub

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

  1. The key is not the app's to pick. For a TS core, Cmd.ptySpawn names a string
    session key; ts_core_host.zig maps it to the first free slot in its own table and
    spawns the engine session at pty_key_base + index
    (pub const pty_key_base: u64 = 0x5453_5054_0000_0000). <terminal pty={n}> must
    name that engine key. Binding 1 mounts nothing — no diagnostic, no log, an empty
    grid. (Background in #229.)
  2. A computed key is not expressible. Cmd.ptyWrite/ptyKill take the key as a
    string literal (NS1027), so Cmd.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 from TerminalState.pty (#221).

Related: #229 (the binding gap this page post-dates), #224.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.