Skip to content

feat(frontend): rebuild Electron desktop UI as a React + Vite renderer#1

Closed
yyovil wants to merge 9 commits into
mainfrom
feat/electron-renderer-clean
Closed

feat(frontend): rebuild Electron desktop UI as a React + Vite renderer#1
yyovil wants to merge 9 commits into
mainfrom
feat/electron-renderer-clean

Conversation

@yyovil

@yyovil yyovil commented Jun 10, 2026

Copy link
Copy Markdown
Owner

What

Clean extraction of @ashish921998's renderer work from the upstream aoagents#156, without the Prettier mass-reformat and husky/lint-staged tooling that made that PR hard to review.

Stack

Layer Choice
Shell Electron + child_process daemon supervision
UI React 19 + TypeScript renderer (Vite, contextBridge preload)
Routing TanStack Router (file-system routes, hash history for Electron file://)
Data TanStack Query + EventTransport — CDC SSE on /api/v1/events
API types openapi-typescript + openapi-fetch off openapi.yaml
Styling Tailwind + shadcn/ui
Layout react-resizable-panels, sizes persisted to Zustand
Terminal @xterm/xterm per-session PTY over /mux WebSocket + WebGL addon
UI state Zustand
Packaging electron-forge (Vite template) + update-electron-app auto-updater
Testing Vitest + RTL · Playwright

Backend additions

  • cors.go — allowlist-only CORS middleware, never * or null, handles Private Network Access preflight for file:// → loopback
  • session.TerminalHandleID exposed in domain + OpenAPI spec
  • project.Path added to OpenAPI spec, service, store, and tests
  • CORS origin config threaded through config.go

Design

DESIGN.md is the source of truth for the emdash-matched dark UI (emdash tokens, blue accent, status glyph spec, orchestrator-led layout).

Credit

All renderer implementation by @ashish921998 — this PR is a clean split of his work, retargeted to the fork.

🤖 Generated with Claude Code

yyovil and others added 6 commits June 10, 2026 07:54
Full renderer rewrite by @ashish921998 in aoagents#156, extracted without the
Prettier mass-reformat and husky/lint-staged tooling (those land separately
in the chore/prettier-ci PR).

Stack:
- Shell: Electron + child_process daemon supervision with stale-handle guard
- UI: React 19 + TypeScript renderer (Vite, contextBridge preload)
- Data: TanStack Query + EventTransport (CDC SSE on /api/v1/events)
- API types: openapi-typescript + openapi-fetch off openapi.yaml
- Styling: Tailwind + shadcn/ui (Badge, Tabs, Button, Input, Tooltip)
- Layout: react-resizable-panels, sizes persisted to Zustand
- Terminal: @xterm/xterm per-session PTY over /mux WebSocket + WebGL addon
- UI state: Zustand (selection, active pane, theme, layout sizes)
- Testing: Vitest + RTL + Playwright

Backend additions:
- CORS middleware (cors.go) — allowlist-only, never * or null, handles
  Private Network Access preflight for file:// → loopback requests
- session.TerminalHandleID field exposed in domain + OpenAPI spec
- project.Path field added to OpenAPI spec + service/store/tests
- CORS origin config wired through config.go

Design: DESIGN.md added as source of truth for the emdash-matched dark UI.

Co-Authored-By: Ashish Huddar <ashish921998@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 9fd9e7f48ec8
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: a14c9f9aec7b
Replace vite-plugin-electron + electron-builder with electron-forge's
blessed Vite template. Split vite.config.ts into three configs
(main/preload/renderer), add forge.config.ts with 4 makers and
publisher-github, update main.ts to use forge-injected globals and
update-electron-app, and update the release workflow to use
`electron-forge publish`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace code-based route tree with file-system routing via @tanstack/router-plugin
- createAppRouter() factory injects QueryClient into router context for loaders
- createHashHistory() preserved for Electron file:// renderer origin
- Routes: __root.tsx, index.tsx, workspaces.$workspaceId.tsx, workspaces.$workspaceId_.sessions.$sessionId.tsx
- TanStackRouterVite plugin wired into vite.renderer.config.ts (before react plugin)
- defaultPreload: 'intent', defaultPreloadStaleTime: 0, scrollRestoration: true
- declare module Register moved to main.tsx alongside router instantiation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 64aa08569fed
__root.tsx already wraps every route in TooltipProvider.
All routes render <App>, so every render was double-nesting the provider.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: f466c24a4356
The migration to electron-forge made the release doc stale:
- electron-builder → electron-forge (npm run publish)
- electron-updater → update-electron-app (reads Releases API, no latest-mac.yml feed files)
- package.json build.publish → forge.config.ts publishers
- "identity": null removal → osxSign/osxNotarize already gated on CSC_LINK/APPLE_ID env vars

Also fix the now-stale initAutoUpdates() comment in main.ts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: a93e60c1314e

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6061f76932

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +286 to +288
/api/v1/projects/{id}/config:
put:
operationId: setProjectConfig

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Register the advertised project config route

This OpenAPI path is now advertised, and the service has SetConfig, but ProjectsController.Register still only mounts list/add/get/delete for /projects, so PUT /api/v1/projects/{id}/config always falls through to the JSON 404 instead of updating config or returning the documented validation errors. This breaks generated clients and the new config endpoint tests for any caller trying to set per-project config.

Useful? React with 👍 / 👎.

Comment on lines +682 to +684
/api/v1/sessions/{sessionId}/pr:
get:
operationId: listSessionPRs

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Register the advertised session PR routes

The PR endpoints are added to the API spec and the session service/test fakes now expose ListPRs/ClaimPR, but SessionsController.Register does not mount /sessions/{sessionId}/pr or /sessions/{sessionId}/pr/claim, so both documented routes return 404 for all sessions. Clients generated from this spec will call endpoints the daemon never serves, including the new tests that expect these routes to work.

Useful? React with 👍 / 👎.

yyovil and others added 3 commits June 10, 2026 09:57
…ck-query/router

Branch was cut before portless/stack landed on main, so its skills-lock.json
would have dropped them on merge. Union all four so nothing is lost.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: db30ea05f345
Match the std skills layout (as in yyork): commit canonical skill content
under .agents/skills/ and gitignore the per-agent dirs (.claude/.codex/etc),
which only hold symlinks regenerated locally by `skills experimental_install`.

- Vendor portless, stack, tanstack-query, tanstack-router under .agents/skills/
- Move portless out of the stray .claude/skills/portless/ into .agents/
- skills-lock.json: portless hash refreshed to match vendored content

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 2216545f536d
@yyovil

yyovil commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

Renderer now goes upstream via aoagents#168 (clean branch off upstream/main, fork-infra stripped). Closing this fork-internal copy. The skills-vendoring work lives on the feat/electron-renderer-clean branch if needed later.

@yyovil yyovil closed this Jun 10, 2026
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