Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
29 changes: 28 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ extensions/levelcode-hackability/ user init script + Atom/NPP keymap presets + p
extensions/levelcode-sync/ 'levelcode' auth provider that lights up the built-in Settings Sync (LevelCode Sync, S0)
extensions/levelcode-updater/ notify-only update checker (polls the update feed; never auto-applies)
patches/levelcode-core.patch our core source edits, applied on bootstrap
scripts/ bootstrap.sh, apply-branding.mjs, run-dev.sh, 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, build-macos.sh, make-dmg.sh, make-icon.sh; atom (CLI launcher) + install-level.sh
tools/ dependency-free reference servers: sync-server (/v1 Settings-Sync), update-server (/api/update feed)
vscode/ GITIGNORED upstream Code-OSS checkout (generated)
```
Expand All @@ -55,6 +55,33 @@ vscode/ GITIGNORED upstream Code-OSS checkout (generated)
./scripts/make-icon.sh # regenerate .icns from branding/icons/levelcode-source.png (sips+iconutil)
```

## The dev editor is its own app (keep it that way)

To macOS a run from source and the installed LevelCode used to be ONE app — same bundle id, same
`levelcode://` scheme — so a sign-in started in the dev editor was handed back to the app in
/Applications. `run-dev.sh` now gives the dev run its own identity (`scripts/editor-identity.mjs dev`):

- **Identity:** `branding/product.dev.json` — scheme `levelcode-dev`, bundle id `ai.levelcode.app.dev`.
Both must differ from the shipped ones; a scheme alone still lets macOS confuse the two apps.
- **Two halves, both required.** Runtime: `vscode/product.overrides.json` (Code-OSS reads it only when
running from source, never packages it). macOS: the dev Electron bundle's `Info.plist`, then
`lsregister`. The bundle is regenerated when Electron changes, so the step runs on every launch.
- **Both or neither, and confirmed.** The two files are replaced as one change (staged, renamed, undone
if the second rename fails). Then the step asks macOS which app opens `levelcode-dev://` and FAILS —
`run-dev.sh` stops before launching — unless the answer is this bundle. `lsregister` exiting 0 is
not that answer: it registers a bundle it will never route to.
- **`branding/product.overlay.json` is the product that ships — never put a dev value in it.**
`build-macos.sh` runs `editor-identity.mjs check-release` and fails a build that is not
`levelcode://` + `ai.levelcode.app`, or that carries an overrides file.
- **Auth code never spells a scheme.** `accountSignIn()` builds the callback from
`vscode.env.uriScheme`; that is why the dev identity needed no auth change. Keep it so.
- **The server must be told:** `LEVELCODE_EXTRA_EDITOR_SCHEMES=levelcode-dev` on the backend the dev
editor signs in to (thin.ly `Levelcode::EditorCallback`). Off by default, and it only ever accepts
`levelcode-<variant>`. Symptom when missing: the browser lands on the account page and the editor
hears nothing.
- A LaunchServices handler must live outside temp folders — a bundle under `/tmp` is registered but
never chosen. Tests therefore run on fixtures and do not register anything (`test/editorIdentity.test.js`).

## Toolchain (hard requirements — these bit us)

- **Node = `vscode/.nvmrc` (currently 24.15.0)**. Older majors fail to compile native modules.
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ LevelCode is a **clean overlay on top of Code-OSS**, not a vendored copy of the
./scripts/make-dmg.sh # wrap it into a distributable .dmg
```

**A run from source is its own app.** `run-dev.sh` gives the dev editor its own macOS identity — bundle id `ai.levelcode.app.dev` and the `levelcode-dev://` scheme (`branding/product.dev.json`) — so it can sit beside an installed LevelCode without the two answering each other's links. Signing in from it needs a server that accepts that scheme: set `LEVELCODE_EXTRA_EDITOR_SCHEMES=levelcode-dev` on the backend it signs in to. No server accepts it otherwise, and a sign-in that ends on the account page in the browser, with the editor hearing nothing, is the sign that it is not set.

See [`CLAUDE.md`](./CLAUDE.md) for the full repo map + build details and [`PLAN.md`](./PLAN.md) for the roadmap.

## Status
Expand Down
6 changes: 6 additions & 0 deletions branding/product.dev.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"_comment": "The identity of LevelCode RUN FROM SOURCE (scripts/run-dev.sh) — never of a build. To macOS the dev editor and the installed app were one app: same bundle id, same levelcode:// scheme, so a sign-in started in the dev editor was handed back to the app in /Applications. scripts/editor-identity.mjs gives the dev run these two values instead: at runtime through vscode/product.overrides.json (read only when running from source), and on the dev Electron bundle's Info.plist. branding/product.overlay.json — the product that ships — is not touched by any of it. The scheme must be levelcode-<variant>: that is the only shape a server can be told to accept (LEVELCODE_EXTRA_EDITOR_SCHEMES, thin.ly).",

"urlProtocol": "levelcode-dev",
"darwinBundleIdentifier": "ai.levelcode.app.dev"
}
Loading
Loading