feat(playground): run the engine in the browser, on a public repo - #13
Merged
Conversation
Adds site/playground/: paste a public GitHub repository and index it entirely client-side. Not a mockup and not a precomputed index — the same walk, the same tree-sitter grammars, the same link-graph, compiled for the browser and run in a Web Worker. The engine source is untouched. Node builtins are redirected at resolution time to shims in src/browser/ (an in-memory VFS, a synchronous SHA-1, a Buffer covering readText's four decode paths), and everything spawn-based degrades along the fallbacks the engine already ships and already tests: sh() reports its binary missing, so git.ts returns no commit and grep.ts uses its pure-JS backend. scripts/engine.mjs, engine.d.mts and cli.mjs are byte-identical to before. WALK DECIDES WHAT IS DOWNLOADED. A file list carries paths and sizes, and sizes alone satisfy lstatSync — so the tree is mounted with no contents, the real walk() runs on it, and its keep-list IS the download list. No ignore rule, size cap or `capped` flag is reimplemented in the UI, and pruneUnfetched() drops whatever was listed but never fetched so a file can never reach the index as a phantom empty one. Source ordering is measured, not assumed. jsDelivr's branch manifest is a snapshot rather than the branch head: on t3-oss/create-t3-turbo it listed 125 files of which 37 no longer existed (404 on raw too, so genuinely deleted). The GitHub trees API listed 141 blobs and all 141 fetched. So GitHub is primary and jsDelivr is the fallback for when the 60/hour API limit runs out, with the caveat shown rather than hidden — 88 -> 132 files indexed on that repo. The palette exposes the 24 commands that mean something here and lists the seven that do not with their reason, because a command that needs git history returning an empty result reads like a bug. Built by scripts/build-browser.mjs rather than a third tsup target: tsup registers its own node-protocol plugin ahead of user plugins and resolves node:fs to an external bare "fs", which no browser can load and which Node quietly satisfies from the real disk — a silent failure under test. Verified: tests/browser-build.test.ts indexes three fixtures through the VFS and asserts graph.json and symbols.json are byte-identical to the Node build, with the grammars asserted loaded so the comparison cannot pass vacuously. Shim behaviour is checked against the real node: modules, the whole palette runs against a real index, and the fetch pipeline has an opt-in live test (CODEINDEX_PLAYGROUND_E2E=1). check:build holds the committed bundle byte-reproducible.
github-actions Bot
pushed a commit
that referenced
this pull request
Aug 1, 2026
# [2.23.0](v2.22.1...v2.23.0) (2026-08-01) ### Features * **playground:** run the engine in the browser, on a public repo ([#13](#13)) ([6cd2dec](6cd2dec))
Contributor
|
🎉 This PR is included in version 2.23.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
site/playground/: paste a public GitHub repository and index it entirely client-side — the samewalk, the same tree-sitter grammars, the same link-graph, compiled for the browser and run in a Web Worker.The engine source is untouched
Node builtins are redirected at resolution time to shims in
src/browser/(an in-memory VFS, a synchronous SHA-1, aBuffercoveringreadText's four decode paths). Everything spawn-based degrades along fallbacks the engine already ships and already tests:sh()reports its binary missing, sogit.tsreturns no commit andgrep.tsuses its pure-JS backend.scripts/engine.mjs,engine.d.mtsandcli.mjsare byte-identical to before.Walk decides what is downloaded
A file list carries paths and sizes, and sizes alone satisfy
lstatSync— so the tree is mounted with no contents, the realwalk()runs on it, and its keep-list is the download list. No ignore rule, size cap orcappedflag is reimplemented in the UI.pruneUnfetched()drops whatever was listed but never fetched, so a file can never reach the index as a phantom empty one.Source ordering is measured, not assumed
jsDelivr's branch manifest is a snapshot rather than the branch head. On
t3-oss/create-t3-turboit listed 125 files of which 37 no longer existed (404 onrawtoo, so genuinely deleted). The GitHub trees API listed 141 blobs and all 141 fetched. So GitHub is primary, jsDelivr is the fallback for when the 60/hour API limit runs out, and the caveat is shown rather than hidden — 88 → 132 files indexed on that repo.Verified
gin-gonic/gin@mastert3-oss/create-t3-turbo@maintests/browser-build.test.tsindexes three fixtures through the VFS and assertsgraph.json/symbols.jsonare byte-identical to the Node build — with the grammars asserted loaded, so the comparison cannot pass vacuously.node:modules; the whole palette runs against a real index; the fetch pipeline has an opt-in live test (CODEINDEX_PLAYGROUND_E2E=1).pnpm test1 119 passing,typecheckclean,check:buildholds the committed bundle byte-reproducible.Note on the build
Built by
scripts/build-browser.mjsrather than a third tsup target: tsup registers its own node-protocol plugin ahead of user plugins and resolvesnode:fsto an external bare"fs"— which no browser can load, and which Node quietly satisfies from the real disk (a silent failure under test).