Skip to content

Experimental GPUI mobile app (mobile-gpui) with an installable Android debug APK - #744

Merged
Ziinc merged 5 commits into
mainfrom
ccr-abfcd600-eoaphz
Oct 10, 2026
Merged

Ziinc merged 5 commits into
mainfrom
ccr-abfcd600-eoaphz

Conversation

@Ziinc

@Ziinc Ziinc commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator

Adds mobile-gpui/, an experimental Treq mobile app whose interface is rebuilt from scratch in GPUI (gpui-kit), rendered inside a Tauri Android app through tauri-plugin-gpui. CI builds an installable debug APK.

What it is

  • A separate Tauri app (dev.treq.gpui, "Treq GPUI") in its own Cargo workspace, so it installs next to the regular mobile build and leaves the desktop lockfile alone.
  • Links treq_lib directly: screens call the SSH transport, the remote command protocol, the PTY manager and the settings database without IPC.
  • Ports the logic that only existed in TypeScript to Rust: Supabase sign-in through treq://auth/callback (refreshed tokens are now persisted), the control-plane Edge Functions, and the managed-instance flow (wake, device key, certificate issue, renewal at 80% of the lifetime, relay token sync, cutoff and reauthentication).
  • Screens: home (account, managed instance, saved SSH hosts), add SSH host with explicit host-key trust and the device public key, repositories, workspaces, workspace status and changes, diff, commits, conflicts, agent, and a remote terminal (persistent sessions, vt100 grid, soft keyboard, key toolbar). Mutations take two taps, use idempotency keys and report ambiguous outcomes instead of retrying.
  • Restores the last host, repository and workspace on launch; refetches after returning to the foreground.
  • Fixes two problems in the React mobile shell it replaces (see mobile-gpui/SPEC.md §0): remote requests send the numeric workspace id, and ListCommits is read as JjLogResult.
    The only change outside mobile-gpui/ is a src-tauri feature, embed, which leaves out run()'s mobile entry point so treq_lib can be linked into another Android app without duplicate JNI symbols.

CI

The Mobile GPUI workflow runs unit tests, builds a debug APK for arm64 and x86_64 (artifact treq-gpui-debug-apk), and runs it on an emulator. The smoke test fails unless GPUI mounts a surface and uploads screenshots and logcat (treq-gpui-emulator-screenshots).

Testing

  • cargo test --lib in mobile-gpui: 21 tests (auth link parsing and refresh, control-plane error mapping, renewal timing and cutoff classification, path canonicalization, idempotency keys, two-tap confirm, diff colouring, terminal key encoding and rendering).
  • Desktop end to end against a local sshd with a fixture treq CLI: add host, connect, repositories, workspaces, diff, commits, conflicts, agent, a confirmed push, restore on relaunch, and a live terminal.
  • Android emulator in CI: launches, renders the home screen with icons and bold text, survives background and foreground.
  • Not yet verified on a physical device: browser sign-in, the keystore device key with biometrics, and the managed-instance connection.

Notes

  • tauri-plugin-gpui is a git dependency on its ccr-abfcd600-eoaphz branch; point it at main (or a release) once ziinc/tauri-gpui's Android PR lands.
  • The UI font is Inter (OFL 1.1, mobile-gpui/assets/fonts/OFL.txt), bundled because Android's variable Roboto renders a single weight.
    🤖 Generated with Claude Code
    https://claude.ai/code/session_01CqhEsLVY2tp9BxqMC3NfTB
    Generated by Claude Code

claude added 5 commits October 9, 2026 23:15
…in CI

A separate Tauri app (dev.treq.gpui) that rebuilds the mobile interface
with GPUI through tauri-plugin-gpui and gpui-kit, linking treq_lib
directly instead of going through IPC:

- Supabase sign-in via the treq://auth/callback deep link, ported to
  Rust; refreshed tokens are persisted.
- Managed instance connect (wake, wait, device key, certificate),
  renewal at 80% of the lifetime, relay token sync, cutoff and
  reauthentication.
- Self-managed SSH hosts with explicit host-key trust, and the device
  public key for authorized_keys.
- Repository picker, workspaces, workspace status/changes, diff, commits,
  conflicts and the agent screen; mutations use two-tap confirmation,
  idempotency keys and verify-before-retry.
- Session restore on launch and refetch on resume.

src-tauri gains an `embed` feature that drops its mobile entry point,
whose JNI symbols would clash with the host app's.

The Mobile GPUI workflow builds an installable debug APK (arm64 +
x86_64) as the treq-gpui-debug-apk artifact and smoke-tests it on an
emulator.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CqhEsLVY2tp9BxqMC3NfTB
- Terminal screen: lists persistent pty-remote sessions, starts or
  reattaches one through treq's RemotePtyManager, detaches or stops it.
  A vt100 grid renders colors, cursor and scrollback; the view is GPUI's
  text input handler so the soft keyboard and IME commits write to the
  PTY; named keys and Ctrl/Alt combos are encoded; a key toolbar covers
  Esc, Tab, Ctrl+C/D/Z and arrows.
- TAO reports Resumed before setup on desktop; ignore it until the
  backend exists.
- Empty-state for saved hosts, delete control before the chevron, armed
  mutations shown in the warning style.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CqhEsLVY2tp9BxqMC3NfTB
…perseded runs

SwiftShader's host Vulkan crashes the CI emulator on wgpu's shaders, so
the emulator runs without guest Vulkan and wgpu uses GLES (phones keep
Vulkan). Every adb call and the emulator step are time-bounded, logcat
streams to the artifacts, and a new push cancels the previous run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CqhEsLVY2tp9BxqMC3NfTB
wgpu-types is built without debug assertions so wgpu omits shader debug
info, which the emulator's SwiftShader Vulkan rejects. The GLES fallback
lacks the compute limits the renderer needs, so the emulator keeps
Vulkan. The smoke test now waits for tauri-plugin-gpui's mount log and
fails on 'attaching GPUI failed'. Picks up tauri-plugin-gpui 0ed7515.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CqhEsLVY2tp9BxqMC3NfTB
…dialogs in CI

- Android's only UI font is a variable Roboto, which loads as a single
  regular face, so bold text rendered regular. Bundle static Inter
  (OFL 1.1, assets/fonts/OFL.txt) and make it the UI font everywhere.
- rust-embed reads assets from the build machine's disk in debug builds
  unless debug-embed is on, so gpui-kit's icons were missing on Android.
- The emulator smoke test hides error dialogs and closes system dialogs
  before interacting; launcher ANR dialogs were swallowing input.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CqhEsLVY2tp9BxqMC3NfTB
@Ziinc
Ziinc merged commit 91a42e6 into main Oct 10, 2026
29 of 32 checks passed
@Ziinc
Ziinc deleted the ccr-abfcd600-eoaphz branch October 10, 2026 08:59

This branch was successfully deployed

1 active deployment
preview — b5b4f577 Deployed Oct 10, 2026 by Ziinc via build #1761
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