Blog
[one spec, hello_world; only JavaScript runs in the browser; the native results are one macOS machine on one day; nothing posted on X] The t27 player now has a terminal: the compiler, as WebAssembly in the page, prints what each of its seven backends emits and runs the spec's tests. Each backend has its own share page. Every word the terminal says lives in the spec. Run natively, hello_world as committed builds in two of the seven languages, and the post says why.

The t27 player, the page that compiles a spec inside an X post, now has a terminal. Type t27c gen rust and the t27 compiler, running as WebAssembly in the page, prints the Rust it emits for the spec in the editor. t27c test runs the spec's own tests. Each of the compiler's seven backends has its own share page, so a link opens the terminal already typing the command for that language. Nothing is sent anywhere: every line is printed by the compiler in the page, or by the JavaScript it emitted.
t27 play · the terminal's own gates
Each page lives at t27.ai/play/hello-world/<backend>/ and has its own preview card, so a post shows which language the link opens. Opened with autoplay, the terminal types t27c gen <backend> at 45 ms a character and runs it. The longest of the seven, t27c gen verilog_hir, is 20 characters, or 0.9 s of typing. The generator refuses a demo longer than 32 characters and checks that 32 characters at that pace stay inside the ten seconds X allows anything in a player card to start by itself (AUTOPLAY_LIMIT_MS in the spec).
| Backend | Page | File | What run does |
|---|---|---|---|
| Zig | /zig/ | hello_world.zig | prints zig test hello_world.zig |
| C | /c/ | hello_world.c | prints cc -std=c11 -c hello_world.c |
| Rust | /rust/ | hello_world.rs | prints rustc --crate-type lib --edition 2021 hello_world.rs |
| Verilog | /verilog/ | HelloWorld.v | prints iverilog -g2012 -o /dev/null HelloWorld.v |
| Verilog (HIR) | /verilog-hir/ | HelloWorld.hir.v | prints iverilog -g2012 -o /dev/null HelloWorld.hir.v |
| JavaScript | /js/ | hello_world.js | imports it into the page and prints its 7 exports; calls nothing |
| TypeScript | /ts/ | hello_world.ts | prints tsc --noEmit --strict hello_world.ts |
Only JavaScript runs in a browser. For the other six backends, run says the page has no such toolchain, prints save <file> and the command for a machine that has one, and claims no result. The terminal also takes t27c gen-rust, the real t27c's spelling. gcc, cargo or yosys gets an answer saying the tool is not in the browser, instead of "command not found".
Everything the terminal says or knows is a constant in specs/x/player.t27:
The JavaScript that runs it, public/play/shell.js, holds no English of its own: it fills {names} into the spec's templates and lays out columns. The generator enforces this in both directions. It refuses:
SAY_ constant the terminal never says, or a phrase it says that the spec does not define;pub const BACKENDS : [7]str = ["zig", "c", "rust", "verilog", "verilog_hir", "js", "ts"];
; The backends whose output this page runs itself.
pub const RUNS_IN_BROWSER : [1]str = ["js"];
pub const SAY_WARN_NOT_HERE : str = "{lang} does not run in a browser: this page has no {tool}. On a machine that has it:";
The words are t27, and the behaviour is not yet: dispatching a line, filling a template, choosing a file name. That part is 361 hand-written lines, for a measured reason. gen-js lowers declarations only, by design. The issue that created it, t27#4471, says: "The emitted module is data. Nothing in it may run." That rule is right for a spec that describes a server. For a spec that is a terminal, it means the behaviour has to live beside the spec. t27#6101 asks for an opt-in lowering of function bodies that leaves today's output byte for byte unchanged. Once it exists, the dispatch and the templates move into player.t27, and shell.js shrinks to DOM glue.
A terminal that hands out a file and a command should know what the command does. We ran each one on the files the terminal gives for hello_world.t27, as committed, on one macOS machine:
| Backend | Command | Exit | First error |
|---|---|---|---|
| Zig | zig test | 1 | hello_world.zig:33:23: error: use of undeclared identifier 'cast' |
| C | cc -std=c11 -c | 1 | hello_world.c:57:22: error: call to undeclared function 'cast' |
| Rust | rustc --crate-type lib | 1 | error[E0425]: cannot find function cast in this scope |
| Verilog | iverilog -g2012 | 2 | HelloWorld.v:79: error: No function named cast found in this context |
| Verilog (HIR) | iverilog -g2012 | 2 | HelloWorld.hir.v:15: syntax error (the port config is not escaped) |
| JavaScript | node | 0 | none |
| TypeScript | tsc --noEmit --strict | 0 | none |
Line 47 of the spec computes an area with cast(config.width) * cast(config.height), and nothing declares cast. The typechecker accepts the call. The page's own test evaluator treats it as a conversion, so in the browser t27c test reports 4 pass, 0 fail, 0 skip. Zig, C and Rust refuse the same line. JavaScript and TypeScript pass only because they emit declarations, not the function. With the line rewritten as (config.width as u16) * (config.height as u16), six of the seven pass: zig test reports "All 2 tests passed", and the HIR Verilog still fails on its config port. Both are filed, as t27#6100 and t27#5966. The terminal does not hide this: it prints the command and never claims the result.
The repository ignores every directory called zig/, for downloaded Zig toolchains. That rule also matched public/play/hello-world/zig/. The build would have passed, the page would have existed on the machine that made it, and the published site would have answered 404 for the Zig link. One negation line in .gitignore fixes it. A test now asks git check-ignore about every backend page, with a control path under the same rule that must still be ignored.
X's player cards may not collect data entry. The terminal takes typed commands, though nothing leaves the page. Whether a terminal page is posted as a player card or only as a link is the owner's decision. Nothing has been posted.
/zig/, /c/, /verilog/, /verilog-hir/, /js/, /ts/)help, t27c test, t27c gen zig, run js, run rust, t27c checkWork with me
I work contract and part-time on hardware-AI, FPGA/RTL and ML systems — from specification and open toolchains to reproducible measurements.