{"_id":"kitty-vt-wasm","_rev":"3-171753a1911aedf97d4e5775914c14b4","name":"kitty-vt-wasm","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"kitty-vt-wasm","version":"0.1.0","keywords":["terminal","vt100","kitty","webassembly","wasm","terminal-emulator","ansi","escape-codes"],"author":{"name":"Can Bölük","email":"me@can.ac"},"license":"GPL-3.0-only","_id":"kitty-vt-wasm@0.1.0","maintainers":[{"name":"can1357","email":"can.boluk89@gmail.com"}],"homepage":"https://github.com/can1357/libkitty-vt#readme","bugs":{"url":"https://github.com/can1357/libkitty-vt/issues"},"dist":{"shasum":"09f2316e2383cdbdfc6c12b69484885f0c85d20a","tarball":"https://registry.npmjs.org/kitty-vt-wasm/-/kitty-vt-wasm-0.1.0.tgz","fileCount":25,"integrity":"sha512-bAvn0V8v5uIhabyRiUvtA2ubipQFnVxnr5xEwdURVhkROHNikuocPR7KCyndvJMA9C1cbAEdTE3ZgfQICI5GKw==","signatures":[{"sig":"MEUCIQCKfepHh+EYSx+UF85bd0+LAr5NoNCP4kjna4Bu1LxvMgIgT02+TmVscfKJAL22KQdcTZUjOHguB/tMkpX1RTWomUg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":561757},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json","./kitty-vt.wasm":"./dist/kitty-vt.wasm"},"gitHead":"4fb5be1480a7c88c4a1afab083176961897f2b3e","scripts":{"lint":"biome check src test examples","test":"bun test","build":"bun run build:wasm && bun run build:ts","format":"biome check --write src test examples && prettier --write package.json","prepack":"bun run build","build:ts":"tsgo -p tsconfig.json","typecheck":"tsgo -p tsconfig.json --noEmit","build:wasm":"./build.sh","screenshot":"bun examples/screenshot.ts"},"_npmUser":{"name":"can1357","email":"can.boluk89@gmail.com"},"repository":{"url":"git+https://github.com/can1357/libkitty-vt.git","type":"git"},"_npmVersion":"12.0.2","description":"kitty's real terminal core (screen.c + vt-parser.c) compiled to WebAssembly, wrapped as a typed library with all I/O abstracted","directories":{},"sideEffects":false,"_nodeVersion":"26.2.0","_hasShrinkwrap":false,"devDependencies":{"prettier":"^3.9.6","@types/bun":"^1.3.4","@biomejs/biome":"^2.5.9","@napi-rs/canvas":"^0.1.89","@typescript/native-preview":"^7.0.0-dev.20260707.2"},"_npmOperationalInternal":{"tmp":"tmp/kitty-vt-wasm_0.1.0_1787371126794_0.0882194050444618","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"kitty-vt-wasm","version":"0.1.1","keywords":["terminal","vt100","kitty","webassembly","wasm","terminal-emulator","ansi","escape-codes"],"author":{"name":"Can Bölük","email":"me@can.ac"},"license":"GPL-3.0-only","_id":"kitty-vt-wasm@0.1.1","maintainers":[{"name":"can1357","email":"can.boluk89@gmail.com"}],"homepage":"https://github.com/can1357/libkitty-vt#readme","bugs":{"url":"https://github.com/can1357/libkitty-vt/issues"},"dist":{"shasum":"32e4a14f762f08c921009508e095f9052bfff42e","tarball":"https://registry.npmjs.org/kitty-vt-wasm/-/kitty-vt-wasm-0.1.1.tgz","fileCount":25,"integrity":"sha512-oX6xoHTCrAFc5w+gUQddH+5k1qIBQFDRP0nSE77UEfxpR/ui0SovYbCmxyamRUDjoTZiYfZMD5Bi78Cwc6CyFA==","signatures":[{"sig":"MEQCIH5G7pha7yg7srcNktUjJcqPE4oT7htbF9AMBec/2i/IAiBUyMAFXFNySPPk/wC6fiLR/7KyeAhbYClXVS1hZtCRBg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/kitty-vt-wasm@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":832048},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json","./kitty-vt.wasm":"./dist/kitty-vt.wasm"},"gitHead":"77973d167fe9740ebec3d094d94e4786c169cf82","scripts":{"lint":"biome check src test examples","test":"bun test","build":"bun run build:wasm && bun run build:ts","format":"biome check --write src test examples && prettier --write package.json","prepack":"bun run build","build:ts":"tsgo -p tsconfig.json","typecheck":"tsgo -p tsconfig.json --noEmit","build:wasm":"./build.sh","screenshot":"bun examples/screenshot.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:fea38b57-806c-4ee6-a85f-220694c69c88"}},"repository":{"url":"git+https://github.com/can1357/libkitty-vt.git","type":"git"},"_npmVersion":"11.17.0","description":"kitty's real terminal core (screen.c + vt-parser.c) compiled to WebAssembly, wrapped as a typed library with all I/O abstracted","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","_hasShrinkwrap":false,"devDependencies":{"prettier":"^3.9.6","@types/bun":"^1.3.4","@biomejs/biome":"^2.5.9","@napi-rs/canvas":"^0.1.89","@typescript/native-preview":"^7.0.0-dev.20260707.2"},"_npmOperationalInternal":{"tmp":"tmp/kitty-vt-wasm_0.1.1_1787371325356_0.686063933077196","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"kitty-vt-wasm","version":"0.2.0","description":"kitty's real terminal core (screen.c + vt-parser.c) compiled to WebAssembly, wrapped as a typed library with all I/O abstracted","author":{"name":"Can Bölük","email":"me@can.ac"},"license":"GPL-3.0-only","repository":{"type":"git","url":"git+https://github.com/can1357/libkitty-vt.git"},"homepage":"https://github.com/can1357/libkitty-vt#readme","bugs":{"url":"https://github.com/can1357/libkitty-vt/issues"},"keywords":["terminal","vt100","kitty","webassembly","wasm","terminal-emulator","ansi","escape-codes"],"type":"module","sideEffects":false,"main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./kitty-vt.wasm":"./dist/kitty-vt.wasm","./package.json":"./package.json"},"scripts":{"prepack":"bun run build","build":"bun run build:wasm && bun run build:ts","build:wasm":"./build.sh","build:ts":"tsgo -p tsconfig.json","typecheck":"tsgo -p tsconfig.json --noEmit","lint":"biome check src test examples","format":"biome check --write src test examples && prettier --write package.json","test":"bun test","screenshot":"bun examples/screenshot.ts"},"devDependencies":{"@biomejs/biome":"^2.5.9","@napi-rs/canvas":"^0.1.89","@types/bun":"^1.3.4","@typescript/native-preview":"^7.0.0-dev.20260707.2","prettier":"^3.9.6"},"gitHead":"fc99b724f9faf9fca811ed2c9b4a8325c900e481","_id":"kitty-vt-wasm@0.2.0","_nodeVersion":"24.19.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-RJNzy9r5ql8CKkocjkg0FKC1MZoWM0R8leb2VB5hsgrP/4HHlumeODHriOw4Jk2dDsCOmPxWuwFQyqDiy0m8Kw==","shasum":"4c2fb57ee976e500baec221629deca219eeb684b","tarball":"https://registry.npmjs.org/kitty-vt-wasm/-/kitty-vt-wasm-0.2.0.tgz","fileCount":25,"unpackedSize":835867,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/kitty-vt-wasm@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCb5J1RLbGnTPEdG0Du3t7qvpQvI5Kcyk5j05LnU7wqBAIhAKJhZzZdPxm7vrROfSPc/Ad+K1NX5Fbq+PsXOFkcAGE3"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:fea38b57-806c-4ee6-a85f-220694c69c88"}},"directories":{},"maintainers":[{"name":"can1357","email":"can.boluk89@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/kitty-vt-wasm_0.2.0_1787389478967_0.9496481673516259"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-22T03:58:46.661Z","modified":"2026-08-22T09:04:39.412Z","0.1.0":"2026-08-22T03:58:46.936Z","0.1.1":"2026-08-22T04:02:05.513Z","0.2.0":"2026-08-22T09:04:39.115Z"},"bugs":{"url":"https://github.com/can1357/libkitty-vt/issues"},"author":{"name":"Can Bölük","email":"me@can.ac"},"license":"GPL-3.0-only","homepage":"https://github.com/can1357/libkitty-vt#readme","keywords":["terminal","vt100","kitty","webassembly","wasm","terminal-emulator","ansi","escape-codes"],"repository":{"type":"git","url":"git+https://github.com/can1357/libkitty-vt.git"},"description":"kitty's real terminal core (screen.c + vt-parser.c) compiled to WebAssembly, wrapped as a typed library with all I/O abstracted","maintainers":[{"name":"can1357","email":"can.boluk89@gmail.com"}],"readme":"# kitty-vt-wasm\n\n[kitty](https://github.com/kovidgoyal/kitty)'s **real terminal core** — the\nactual `screen.c`, `vt-parser.c`, `line-buf.c`, `history.c`, Unicode tables and\nkey encoder, compiled unmodified to WebAssembly — wrapped as a typed\nTypeScript library with all I/O abstracted, in the spirit of libghostty.\n\n![styles demo](docs/styles.png)\n\nThat's kitty's own grid rendered from wasm state: real SGR handling, all five\nkitty underline styles, 256-color/truecolor, graphemes, wide chars, hyperlinks.\nHere is vim (with syntax highlighting) editing kitty's own `vt-parser.c`,\nreplayed byte-for-byte through the wasm terminal and rasterized with Menlo:\n\n![vim demo](docs/vim.png)\n\n## How it works\n\n```\n app/child bytes ──▶ term.write(bytes) ──▶ vt-parser.c ──▶ screen.c grid\n                                                │               │\n       onOutput(bytes) ◀── DA/DSR/DECRQSS/OSC replies           │\n       onEvent(ev)     ◀── window callbacks (title, bell,       │\n                           clipboard, graphics, notifications)  │\n       term.line(y) / term.cell(x,y) / term.lineCells(y) ◀──────┘\n       term.encodeKey() ──▶ kitty's key_encoding.c (kitty keyboard protocol)\n```\n\nkitty's C core talks to its Python side through two seams: the CPython API and\nwindow callbacks. This repo fakes the first and bridges the second:\n\n- `shim/Python.h` + `native/pyshim.c` — a minimal refcounted object runtime\n  (~140 CPython APIs: unicode as UCS-4, tuples, a working `PyArg_ParseTuple`,\n  `Py_BuildValue`, buffers). kitty's type objects, constructors and destructors\n  run as-is on top of it.\n- `PyObject_CallMethod` is the callback landing pad: kitty's `CALLBACK()`\n  invocations (`title_changed`, `clipboard_control`, `desktop_notify`,\n  graphics commands, ...) are serialized to JSON events the host consumes.\n  Queries kitty answers in Python (DA1) are answered in the bridge.\n- `shim/state.h` + `native/stubs.c` — kitty options with default values, output\n  capture for `schedule_write_to_child`, and no-op stubs for the windowing/\n  font/DnD/graphics-texture surfaces (pixels are the host's job; kitty\n  graphics protocol commands are surfaced as events with base64 payloads).\n- `native/exports.c` — the wasm ABI: terminals are kitty `Screen` objects\n  constructed through `Screen_Type.tp_new`; cell snapshots are flattened from\n  kitty's `CPUCell`/`GPUCell` + `TextCache` into a stable 8-word ABI.\n- `src/index.ts` — the library. It plays kitty's `window.py` role: consumes\n  the callback stream, owns dynamic-color/title-stack behavior (state stays in\n  kitty's `ColorProfile` in C), and exposes rendering + input encoding.\n\nWhat you get for free because it is kitty's real code: resize **rewraps** and\nrefills from scrollback, grapheme segmentation and East-Asian widths match\nkitty exactly, DECRQSS/DECRQM/DA responses are byte-identical to kitty 0.48.2,\nthe kitty keyboard protocol encoder is `key_encoding.c` itself, and upstream\nfixes arrive with a submodule bump.\nFeature parity with libghostty-vt's embedder surface: viewport scrolling over\nhistory (`scrollViewport`/`viewportLine`), row-level dirty tracking\n(`lineDirty`), kitty's real selection machinery (`selectionStart/Update`,\n`selectWord`, `selectLine`, plain/ANSI extraction), full-buffer dumps and\nVT-stream serialization (`dump`, `serialize` — kitty's `as_text` machinery),\nmouse/focus event encoders honoring the tracked modes, paste-safety checks,\nOSC 9;4 progress state, and bookkeeping of kitty-graphics placements\n(`graphicsPlacements()` — positions/z-order; pixels stay host-side).\n\n## Usage\n\n```ts\nimport { KittyTerminal, Key } from \"kitty-vt-wasm\";\n\nconst term = await KittyTerminal.create({\n  columns: 80,\n  rows: 24,\n  scrollback: 2000,\n  onOutput: (bytes) => pty.write(bytes), // query replies for the child\n  onEvent: (ev) => {\n    if (ev.type === \"title\") document.title = ev.title;\n    if (ev.type === \"graphics_command\") drawKittyImage(ev); // payload: base64\n  },\n});\n\npty.onData((bytes) => term.write(bytes)); // feed child output\n\n// render\nfor (let y = 0; y < term.rows; y++) draw(term.line(y), term.lineCells(y));\nconst cell = term.cell(0, 0); // { ch, fg, bg, bold, underline, hyperlinkId, ... }\n\n// user input — kitty's real encoder, honoring DECCKM and kitty keyboard flags\npty.write(term.encodeKey(Key.ArrowUp, { ctrl: true }));\npty.write(term.paste(clipboardText)); // honors bracketed paste\npty.write(term.encodeMouse({ x: 10, y: 3, button: \"left\" })); // honors 1000-1016\npty.write(term.encodeFocus(true)); // honors mode 1004\n\n// scrollback viewport, selection, dumps\nterm.scrollViewport(\"page-up\");\ndraw(term.viewportLine(0)); // what the user sees while scrolled\nconst word = term.selectWord(x, y); // kitty's word-boundary selection\nconst replay = term.serialize(); // VT stream reproducing screen + scrollback\n```\n\nRuns in browsers, node and bun. The wasm module imports only a 4-function WASI\nstub (stderr logging + clock), provided by the wrapper.\n\n### PNG screenshots\n\n`examples/screenshot.ts` rasterizes a terminal with a real font\n(Menlo + CJK/emoji fallbacks via `@napi-rs/canvas`):\n\n```sh\nbun examples/screenshot.ts out.png [raw-escape-stream-file]\n```\n\n## Building\n\nRequires a wasm32-capable clang, wasi-libc and wasm compiler builtins\n(`brew install llvm wasi-libc wasi-runtimes`), plus bun.\n\n```sh\ngit clone --recurse-submodules --shallow-submodules https://github.com/can1357/kitty-vt-wasm\ncd kitty-vt-wasm && bun install\nbun run build     # wasm (build.sh) + TypeScript (tsgo / TypeScript 7)\nbun test\n```\n(Already cloned? `git submodule update --init --depth 1` fetches kitty.)\n\n`build.sh` compiles kitty's sources from `upstream/` through a header overlay:\nkitty's own headers everywhere, except `state.h`/`fonts.h`/`base64.h` (the\nthree that drag in HarfBuzz/GLFW/SIMD-libbase64) and the fake `<Python.h>`.\n\n## Layout\n\n- `upstream/` — kitty, pinned as a git submodule (unmodified)\n- `shim/` — fake CPython + replacement headers\n- `native/` — pyshim runtime, host stubs, wasm exports\n- `src/index.ts` — the TypeScript library\n- `test/` — behavior suite (49 tests) · `examples/` — PNG renderer\n\n## License\n\nGPL-3.0-only. Copyright (C) 2026 Can Bölük <me@can.ac>.\nDerived from kitty, Copyright (C) Kovid Goyal — see `LICENSE` and `upstream/`.\n","readmeFilename":"README.md"}