Skip to content

feat(studio-desktop): Electron shell — Phase 1 (scaffold → buildable app)#144

Open
Necmttn wants to merge 6 commits into
feat/studio-extractfrom
feat/studio-desktop
Open

feat(studio-desktop): Electron shell — Phase 1 (scaffold → buildable app)#144
Necmttn wants to merge 6 commits into
feat/studio-extractfrom
feat/studio-desktop

Conversation

@Necmttn
Copy link
Copy Markdown
Owner

@Necmttn Necmttn commented Jun 7, 2026

Phase 1 of the studio-desktop plan (#139). Standalone Electron shell (Effect v4 + @effect/platform-node, mirroring .references/t3code/apps/desktop) that renders the @ax/studio SPA via a custom ax:// protocol pointed at the local daemon. Stacked on #143 (Phase 0) — base is feat/studio-extract; retarget to main after #143 merges.

Built task-by-task via subagent-driven-development (implementer per task; two-stage review; code-quality review over the full phase = approved).

What's here (apps/studio-desktop)

  • 1.1 package scaffold + tsdown CJS build (dist-electron/{main,preload}.cjs; electron external, effect bundled)
  • 1.2 foundation lifted from t3code: DesktopState, DesktopEnvironment, DesktopObservability (OTLP dropped → console logger + rotating file)
  • 1.3 electron integration: ElectronApp/Window/Protocol/Menu/Shell (scheme ax; traversal guard + scheme-privileges preserved)
  • 1.4 DesktopLifecycle (before-quit/activate/SIGINT/SIGTERM/Deferred shutdown) + DesktopWindow (loads studio dev-server in dev / ax://studio/index.html?endpoint=… in prod; setWindowOpenHandler deny + external routing)
  • 1.5 main.ts layer composition + minimal preload.ts + DesktopApp boot program

Verified

  • bun run build (studio dist-desktop + dist-electron): ✓
  • bun --filter @ax/studio-desktop typecheck + root bun run typecheck: exit 0
  • Code-quality review: approved — traversal guard un-bypassable, webPreferences (contextIsolation/no-nodeIntegration/sandbox) + window-open deny correct, Effect layer composition delivers FileSystem/Path/HttpClient correctly, lifecycle signals intact

NOT verified here (needs a human on a Mac)

Task 1.6 — GUI launch can't run in this headless environment. To verify:

# terminal A: surreal (real data dir) ; terminal B: bun apps/axctl/src/cli/index.ts serve --port=1738
cd apps/studio-desktop && bun run start   # expect: window opens, "Live. Connected" banner, real data

Tracked hardening (v0 pass, not blocking)

  • Add will-navigate top-level-nav guard (port t3code's same-origin check) — bounded UI-redress, no RCE under sandbox
  • Migrate prod protocol from deprecated registerFileProtocolprotocol.handle

Next: Phase 2 (two-process supervisor: surreal + bun ax serve, readiness/restart) — testable via bun:test. Phase 3 (packaging/codesign/notarize) is blocked on Apple Developer credentials.

🤖 Generated with Claude Code

Necmttn and others added 6 commits June 7, 2026 19:59
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add DesktopLifecycle (DesktopShutdown deferred backbone + before-quit/
activate/window-all-closed/SIGINT/SIGTERM wiring + relaunch) and
DesktopWindow (ax:// studio loading, external-link routing, nav-deny).
Theme sync dropped for v0. Adds DesktopEnvironment.preloadPath derived
from the bundled main dirname.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add the main-process integration for the Electron studio shell:

- preload.ts: minimal contextBridge exposing axDesktop marker
  (studio<->daemon is HTTP, so no IPC surface needed).
- app/DesktopApp.ts: boot program (Effect). Waits for app ready,
  registers the ax:// protocol in prod, installs the app menu, wires
  lifecycle listeners, then opens the window against a manually-running
  daemon via DesktopWindow.handleBackendReady. Phase 2 replaces that
  direct call with AxBackendManager.start driving readiness.
- main.ts: builds DesktopEnvironment input from electron/process/os,
  composes electron + foundation + window layers, provides platform
  deps (NodeServices = FileSystem+Path, NodeHttpClient.layerUndici),
  applies scheme privileges eagerly before app ready, and runs via
  NodeRuntime.runMain.

bun run build:main emits dist-electron/{main,preload}.cjs with electron
left external and effect bundled inline. Typecheck passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Jun 7, 2026

Deploying ax with  Cloudflare Pages  Cloudflare Pages

Latest commit: bbc17b5
Status: ✅  Deploy successful!
Preview URL: https://a53d44db.ax-62d.pages.dev
Branch Preview URL: https://feat-studio-desktop.ax-62d.pages.dev

View logs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant