Skip to content

RN/Expo GUI rebuild + remote access via Cloudflare relay#2

Closed
TraderSamwise wants to merge 20 commits into
masterfrom
feat/rn-gui-rebuild
Closed

RN/Expo GUI rebuild + remote access via Cloudflare relay#2
TraderSamwise wants to merge 20 commits into
masterfrom
feat/rn-gui-rebuild

Conversation

@TraderSamwise

Copy link
Copy Markdown
Owner

Summary

Replaces the Tauri/Svelte desktop UI with a single Expo Router codebase (web + iOS + Android), and adds remote agent control through a Cloudflare Workers + Durable Objects relay so users can drive their local daemon from anywhere via aimux.com.

Architecture

  • desktop-ui/ + src-tauri/ removed, replaced by app/ (Expo Router, NativeWind, Jotai)
  • relay/ — Cloudflare Worker that brokers WS tunnels between authenticated app sessions and the local daemon
  • Clerk for user auth (frontend @clerk/clerk-expo, server-side @clerk/backend verifyToken)
  • HS256 daemon tokens minted by the relay (90d TTL) after browser-based aimux login — decouples daemon auth from Clerk's short JWT TTL
  • Daemon relay client dials the WS tunnel; app relay transport wraps the same surface so the UI works identically over local HTTP or remote WS

Polished CLI UX

  • aimux login — browser-based auth flow (localhost callback, no token pasting)
  • aimux logout / aimux whoami
  • aimux remote enable | disable | status — toggle the relay without restarting the daemon
  • aimux daemon status now reports relay connection state
  • App shows a colored "Remote" pill in the TopBar (connected / connecting / host offline / offline)

Test-isolation fixes (caught in this PR's pre-push)

paths.ts:resolveRepoRoot, worktree.ts:findMainRepo, and instance-registry.test.ts all shell out to git with cwd. Inherited GIT_DIR/GIT_WORK_TREE (set by any git hook) made git ignore cwd, which silently routed tests to the outer repo — leaking empty "init" commits onto the branch and causing ~30 unrelated multiplexer test failures. All three call sites now strip GIT_* before invoking git.

Test plan

  • yarn verify passes 566/566 standalone
  • yarn verify passes 566/566 under pre-push hook env (the previously-flaky case)
  • Browser-driven aimux login flow end-to-end (Chrome DevTools MCP)
  • Deploy relay to Cloudflare + app to Vercel; verify production tunnel
  • Mobile (iOS / Android) smoke test via Expo Go

TraderSamwise and others added 20 commits May 19, 2026 22:37
- Scaffold transplant from jiten donor (Expo Router + Zustand + NativeWind + Clerk LOCAL_MODE)
- Add /plans GET/PUT endpoints to metadata-server with 8 tests
- Build sidebar + chat + plan editor + threads + graveyard screens
- HTTP client, EventSource heartbeat, image picker (web/native)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Remove Svelte + Tauri implementation now superseded by app/
- Strip @tauri-apps/api and @xterm/* from root package.json
- Update root README and CLAUDE.md to describe RN/Expo client
- Mark desktop-ui-contract and desktop-shell-phase1-spec docs as superseded

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Migrate stores from Zustand to Jotai (mirror jiten patterns)
- Add atomWithStorage-backed themePreference, default dark
- Add useThemeEffect + React Navigation ThemeProvider wrap
- Add settings screen with theme picker, sidebar footer link
- Configure metro to resolve jotai/jotai-optics ESM to CJS on web

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirrors the TUI's information architecture. Fetches /desktop-state from
the per-project metadata server (every 2s, refresh-nonce on mutation),
groups sessions + services into worktree buckets, renders the tree in
both the sidebar and the main panel. Persists selected project across
reloads.

- Sidebar: project picker ↔ tree view with inline Stop/Resume/Remove
- Main panel: same tree as cards, with denser detail (headline, path)
- Service detail screen at /(main)/service/[serviceId]
- Shared ServiceActions component + status-tone helpers
- New api wrappers for agents/services/worktrees CRUD

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Push type ladder: project title 28px / worktree 18px / row 15px /
  section heading 11px uppercase tracking-widest
- Worktree groups now render as real cards with bg-card lift + colored
  left rail (emerald for main checkout, sky for feature worktrees)
- New StatusDot + StatusPill components replace the `●` text glyph;
  status reads at a glance via color + uppercase pill
- Branch shown as a chip with GitBranch icon; ellipsize-middle on long
  branches and paths so titles never wrap
- Bump dark-mode --card / --border / --secondary tokens so card
  boundaries are actually visible against the bg
- Widen sidebar to w-80; add "PROJECT" eyebrow above the project name
- Section headings now show counts: "Agents · 3", "Services · 1"

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hand-rolled card + icon-button wrappers were inconsistent with the
existing shadcn-style primitives at components/ui/. Wire everything
through Card / PressableCard / Button so radius, borders, and active
states are standardized.

- WorktreeGroup outer → Card (sidebar + main panel)
- AgentCard → PressableCard
- ServiceCard → Card with internal Pressable for body click
- ServiceActions: Stop/Resume/Remove buttons → Button variant="outline"
  size="icon" with compact=h-7w-7 (sidebar) / default h-9w-9 (panel)
- Service detail screen: header restructured with eyebrow + ServiceActions
  cluster, status row + Card body for metadata

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Responsive shell with three breakpoints: persistent sidebar on
desktop (≥1024), togglable sidebar on tablet (640–1023), animated
drawer + bottom tab bar on mobile (<640). Auth menu supports
LOCAL_MODE badge, sign-in redirect, and avatar dropdown with
full-window backdrop dismiss.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auth gate now redirects unauthenticated users to /sign-in (LOCAL_MODE
bypasses). Daemon validates Bearer JWTs via @clerk/backend on all
routes except /health; skips validation when CLERK_SECRET_KEY is unset.
Sign-out navigates to /sign-in, auth screens use theme tokens.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CF Worker + Durable Object per user. Daemon and web/mobile clients
connect via WebSocket, relay routes messages between them. Clerk JWT
verification on all WS upgrades. Heartbeat via DO alarm, daemon
replacement on reconnect, client fan-out for multi-device support.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Daemon connects to the Cloudflare relay when AIMUX_RELAY_URL and
AIMUX_RELAY_TOKEN env vars are set. Relay forwards client requests
through the WS; daemon routes them via the same logic as direct HTTP.
Exponential backoff reconnect (1s–30s), clean shutdown on daemon stop.
Refactored daemon routing into public routeRequest() for reuse.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
App-side RelayTransport class connects to the relay as a client,
wraps HTTP requests as relay messages, and tracks daemon online
status. API layer seamlessly switches between direct HTTP and relay
based on connection state. Daemon gains /proxy/:host/:port/* route
to forward metadata server requests through the tunnel.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Unauthenticated users see a landing page with sign-up/sign-in CTAs
and feature highlights instead of jumping straight to sign-in.
Production wrangler config adds relay.aimux.com custom domain.
Deployment guide covers Clerk, relay, web app, daemon, and native.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Relay mints long-lived (90d) HS256 daemon tokens via POST /cli/issue-token
after verifying a Clerk session JWT. /daemon/connect now accepts both
relay-signed daemon tokens and Clerk JWTs, dispatching by token shape.
CLI gains ~/.aimux/auth.json credential storage (0600) with a
remoteEnabled flag for runtime toggling.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
`aimux login` spins up a localhost callback server, opens the browser to
the web app's /cli-auth page, and captures a minted daemon token — no
token pasting. The cli-auth page issues the token from the relay using
the user's Clerk session and redirects to the callback. Adds `aimux
logout` and `aimux whoami`. Verified end-to-end against local relay.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Daemon now reads relay config from stored credentials (env-var override
retained) and connects only when remote access is enabled. RelayClient
tracks connection status (connecting/connected/reconnecting/auth_failed)
and surfaces it via /relay/status. New `aimux remote enable|disable|
status` commands toggle the relay at runtime without restarting the
daemon; `aimux daemon status` now shows relay state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
RelayTransport now connects on mount when EXPO_PUBLIC_AIMUX_RELAY_URL is
set, syncs status into a Jotai atom, and registers with the API layer so
requests route through the tunnel. New RelayIndicator pill in the TopBar
shows live connection state (Remote / Connecting / Host offline),
hidden entirely for local-only deployments. Verified end-to-end:
browser → relay → daemon project list over the WS tunnel.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts:
#	desktop-ui/src/lib/WorktreePanel.svelte
#	desktop-ui/src/stores/state.svelte.js
The instance-registry tests create a tmp git repo via execSync. When
yarn test runs under a git hook (pre-push, pre-commit), git sets GIT_DIR
in the environment; execSync inherits it, so `cwd: dir` is ignored and
test commits leak into the outer repo as empty "init" commits on the
current branch.

Strip GIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE/GIT_OBJECT_DIRECTORY/GIT_COMMON_DIR
before invoking git in the helper.
resolveRepoRoot (paths.ts) and findMainRepo (worktree.ts) both shell out
to `git` with `cwd` set, but inherited GIT_DIR/GIT_WORK_TREE makes git
ignore cwd. Tests that pass a temp cwd ended up resolving to the outer
repo when yarn test ran under a git hook (pre-push, pre-commit), causing
~30 unrelated multiplexer test failures and cross-test contamination of
this repo's .aimux/instances.json.

Strip GIT_* env in both call sites. In normal production usage (no
GIT_DIR set), behavior is identical.
@TraderSamwise
TraderSamwise requested a review from Copilot May 21, 2026 05:22

Copilot AI 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.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

@TraderSamwise

Copy link
Copy Markdown
Owner Author

Closing in favor of split PRs: #3 (GUI rebuild) and #4 (remote access, stacked on #3) — Copilot can review #4 cleanly.

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.

2 participants