Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4b48bbb
feat(host): the extension asks one module what the machine it runs on…
ndemianc Oct 9, 2026
9a875a4
feat(web): LevelCode in your browser — the page, its entry, the scrat…
ndemianc Oct 9, 2026
8937f50
feat(web): the scratch workspace answers search, and the end-to-end c…
ndemianc Oct 9, 2026
29ceb87
feat(web): a browser manifest that promises only what a tab can do, a…
ndemianc Oct 9, 2026
044d71a
feat(web): scripts/build-web.mjs — one static directory, with the hos…
ndemianc Oct 9, 2026
0ebbca1
feat(web): the browser says where a key is kept, and a BYOK end-to-en…
ndemianc Oct 9, 2026
97c8af9
test(web): the end-to-end check also covers Keep and Undo, and runs a…
ndemianc Oct 9, 2026
ddd0e69
web: sign in without a second window
ndemianc Oct 9, 2026
146f0f3
test(web): the same-tab sign-in check also runs with the extension ho…
ndemianc Oct 9, 2026
325ad4b
test(web): the shim tests do not assume a global crypto, which Node 1…
ndemianc Oct 9, 2026
af55efb
web: the session store belongs to every tab, not to the tab that star…
ndemianc Oct 9, 2026
6895a7d
docs(web): LevelCode in your browser — architecture, build, deploy, s…
ndemianc Oct 9, 2026
8282fd0
web: resolve navigator.locks the way the page does, so the shared-sto…
ndemianc Oct 9, 2026
5393933
web: "Open Folder from Your Computer" reaches the browser's folder pi…
ndemianc Oct 10, 2026
9c86c94
web(build): the build id covers everything that ships under it
ndemianc Oct 10, 2026
c6d838b
web: --api-url, and how to try it against a real backend
ndemianc Oct 10, 2026
54b479f
docs(web): the real-backend recipe has no placeholder to paste, and s…
ndemianc Oct 10, 2026
17f85ca
web: a chat-first look, light and dark themes, and a layout switch
ndemianc Oct 10, 2026
b10b6c9
web(look): fixes from an independent review of the look
ndemianc Oct 10, 2026
633d0a8
fix(web): #105 review — a sign-in link nobody asked for signs nobody …
ndemianc Oct 14, 2026
1d32681
Merge branch 'feat/web-edition' into feat/web-look
ndemianc Oct 14, 2026
40c0d2a
web(look): the build id test hashes what was staged, as the build now…
ndemianc Oct 14, 2026
53c1039
fix(web): #106 review — comments and every other syntax colour can be…
ndemianc Oct 14, 2026
3925003
fix(web): #106 review — the layout switch never moves a file instead …
ndemianc Oct 14, 2026
86864f3
Merge pull request #106 from levelcodeai/feat/web-look
ndemianc Oct 14, 2026
c44f468
Merge branch 'develop' into feat/web-edition
ndemianc Oct 14, 2026
ee3ca41
test(web): #105 review — the stylesheet check no longer compares a st…
ndemianc Oct 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ jobs:
node-version: "24"
- name: Extension unit tests
# The gate itself lives in a script, so the pull-request workflow (test.yml) runs exactly what
# this does. It discovers every extensions/*/test/*.test.js and modules/*/test/*.test.js, and
# fails if it finds none.
# this does. It discovers every extensions/*/test/*.test.js, modules/*/test/*.test.js and
# web/test/unit/*.test.js, and fails if it finds none.
run: ./scripts/test-extensions.sh
- name: Open VSX still signs with a key this release trusts
# The app verifies extensions against Open VSX's signing key, and the key is pinned in the app
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,8 @@ node_modules/
.DS_Store
*.log
out/

# LevelCode in your browser: the release directory scripts/build-web.mjs writes, and the bundle's
# generated assets module (web/ai-extension/build.mjs removes it after bundling).
/dist-web/
/web/ai-extension/assets.generated.js
38 changes: 36 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ extensions/levelcode-sync/ 'levelcode' auth provider that lights up the bu
extensions/levelcode-updater/ notify-only update checker (polls the update feed; never auto-applies)
modules/extension-signature/ Open VSX signature verifier the built app loads as @vscode/vsce-sign, + the signing keys it trusts
patches/levelcode-core.patch our core source edits, applied on bootstrap
scripts/ bootstrap.sh, apply-branding.mjs, run-dev.sh, editor-identity.mjs, extension-signature.mjs, build-macos.sh, make-dmg.sh, make-icon.sh; atom (CLI launcher) + install-level.sh
scripts/ bootstrap.sh, apply-branding.mjs, run-dev.sh, editor-identity.mjs, extension-signature.mjs, build-macos.sh, make-dmg.sh, make-icon.sh, build-web.mjs; atom (CLI launcher) + install-level.sh
tools/ dependency-free reference servers: sync-server (/v1 Settings-Sync), update-server (/api/update feed)
web/ LevelCode in a browser tab: page entry + callback, scratch-workspace extension, layout, themes + chat skin, browser build of levelcode-ai, dev server, tests (docs/WEB.md)
vscode/ GITIGNORED upstream Code-OSS checkout (generated)
```

Expand Down Expand Up @@ -111,6 +112,39 @@ module for that slot. Full account + runbooks: `docs/EXTENSION-SIGNATURES.md`.
- Its tests live in `modules/extension-signature/test/` — outside `extensions/`, whose `test/` folders
ship in the app. `scripts/test-extensions.sh` discovers `modules/*/test/*.test.js` too.

## LevelCode in a tab (`web/`) — read `docs/WEB.md` first

The same `extensions/levelcode-ai` source runs in a browser tab (web-worker extension host). Rules that keep
the desktop app exactly as it was:

- **A workspace read or write goes through `extensions/levelcode-ai/host.js`**, never `fs` on a workspace path:
in a tab the workspace is whatever the editor's file-system provider says, and every read is asynchronous.
On the desktop each `host` function does what the call site did before, behind `await`.
- **Nothing outside `host.js` asks "am I in a browser?"** — a call site asks for a capability (`host.caps.shell`,
`.mcpStdio`, `.ripgrep`) or calls a function that already knows. A new tool that needs a shell/disk/process is
listed in `NEEDS_SHELL` (agent.js) so the browser neither offers it nor promises it.
- The browser build is `web/ai-extension/` (esbuild + shims for `fs`/`path`/`os`/`crypto`/`child_process`).
Strings that are true on a Mac and false in a tab are rewritten by `web/ai-extension/copy.js`, which fails the
build when the desktop text it expects is gone — change both together. `manifest.js` drops the commands and
settings a tab cannot honour.
- `web/main.js` is a plain ES module with a **top-level `await`**: a `const` declared lower in the file is not
initialised until that await finishes (this cleared a saved session once). Declare constants above the
`try`, and use function declarations for helpers it calls.
- **The look is web-only and lives in `web/`** (theme package, `chrome.css`, the chat skin, the layout commands;
`docs/WEB.md` "The look and the layout"). The chat skin is cut into the browser build's **copy** of
`media/chat.html` by `web/ai-extension/skin.js`; never edit the desktop file for it (its suites pin the page).
Every skin rule is under `body.lc-web`. An extension's `configurationDefaults` outrank the embedder's, so
`levelcode-themes`' pinned default theme is stripped from the staged copy (`withoutConfigurationDefaults`).
`node web/test/e2e-look.mjs --dist dist-web --stub-port <port>` is the check; look at its screenshots (`--shots`).
The embedder's command API is the module's `commands` (`api.commands.executeCommand`): `create()` returns a
disposable, so `workbench.commands` is `undefined` — a helper that used it ran inside a `try` and silently did
nothing until a browser test asked for its effect.
- The session store (`createSecretStorage`) belongs to every tab: no cache, one-key read-modify-write under a
Web Lock. The refresh token is rotated on use; do not reintroduce a start-up snapshot.
- Build: `node scripts/build-web.mjs --account <origin>` → `dist-web/`; serve with `node web/serve.mjs --dist dist-web`.
Tests: the unit gate (`scripts/test-extensions.sh` includes `web/test/unit/*.test.js`) and the end-to-end checks in
`web/test/e2e*.mjs` (headless Chrome, stand-in backend; Node 22+). What was not run is listed in `docs/WEB.md`.

## Toolchain (hard requirements — these bit us)

- **Node = `vscode/.nvmrc` (currently 24.15.0)**. Older majors fail to compile native modules.
Expand Down Expand Up @@ -242,7 +276,7 @@ big-file mode badge. Files: extension.js + fileOps/lineOps/columnOps/encodingEol
is not in the editor until you load it: `./scripts/run-dev.sh --extensionDevelopmentPath=<worktree>/extensions/levelcode-ai`
(from the main checkout; the dev extension replaces the built-in one). Uncommitted work is not "on the branch" —
checking the branch out somewhere else gets none of it. Run it in the editor before telling anyone to try it.
- Commit `extensions/`, `modules/`, `patches/`, `branding/`, `scripts/`, `docs/`, `PLAN.md`, `CLAUDE.md`. Never commit `vscode/`.
- Commit `extensions/`, `modules/`, `patches/`, `branding/`, `scripts/`, `web/`, `docs/`, `PLAN.md`, `CLAUDE.md`. Never commit `vscode/` or `dist-web/`.
- `extensions/levelcode-ai/diagram/` modules listed in `bundle.FILES` are pasted INTO a script block in `chat.html`.
They must never contain the text of a script tag or an HTML comment opener — not even in a comment — or the block
ends early; `bundle.js` refuses to build if one does. Keep them dependency-free and free of `require('vscode')`/`fs`.
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ LevelCode is a **clean overlay on top of Code-OSS**, not a vendored copy of the
- `branding/` — the LevelCode identity (`product.overlay.json`) + icons, deep-merged onto upstream `product.json`; the extension gallery wired to **Open VSX**.
- `modules/` — what ships in the app outside an extension: the Open VSX signature verifier and the signing keys it trusts.
- `patches/` — the small set of core source patches (each tagged `// [LevelCode]`).
- `scripts/` — bootstrap / run-dev / build / dmg / icon.
- `scripts/` — bootstrap / run-dev / build / dmg / icon, and `build-web.mjs` (LevelCode in a browser tab).
- `web/` — LevelCode in your browser: the same workbench and AI extension as a static site you can host; sign in with a LevelCode account or use your own key. See [`docs/WEB.md`](docs/WEB.md).
- `tools/` — dependency-free reference servers (Settings-Sync feed, update feed).
- `PLAN.md`, `docs/`, `CLAUDE.md` — the vision, roadmap, and repo map.

Expand Down
Loading
Loading