hephaestus/docs/how-to/heph-pwa.md
Erich Blume 936c2635ef
All checks were successful
Build / validate (pull_request) Successful in 6m18s
doc(heph-pwa): production runbook — host the app from the hub (indri) with OIDC
Add host-heph-pwa.md: a deployment how-to for serving the PWA from the canonical
hub in the hub/spoke OIDC setup (post-release) — fetch the shell at the hub's
tag, add --web-root, terminate TLS (tailscale serve / reverse proxy), and the
token-paste caveat with the device-code-login follow-up. Cross-linked from
heph-pwa and the how-to index.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 17:17:25 -07:00

5.1 KiB
Raw Blame History

title modified tags
heph-pwa (mobile app) 2026-06-04
how-to

heph-pwa — the mobile app

heph-pwa is a phone-first, installable web app that mirrors v1-prototype-tech-spec: browse the built-in views and projects, triage tasks, and — the primary use case — capture tasks fast with the same quick-add syntax as the TUI's a / Cmd-' popover. Context/KB is read-only here (no Neovim editing surface).

It is a thin, online-only client: every read and write is a JSON-RPC call to a server-mode hephd (the sync hub, see set-up-sync-hub). There is no local replica or background sync — when the hub is unreachable, the app shows an error rather than queueing offline.

Why a PWA and not native iOS? A native Swift app cannot be signed, built, or installed without an Apple Developer account. A PWA delivers the primary use case today — installable to the home screen, full-screen, with home-screen launch and offline app-shell — and keeps the door open to a native wrapper later. This was a deliberate first-cut choice; revisit if a native app becomes worthwhile.

Serve it from the hub

The hub can serve the app shell same-origin (no CORS or separate static host needed). Point hephd at the heph-pwa/ directory:

hephd --mode server \
      --http-addr 0.0.0.0:8787 \
      --web-root /path/to/hephaestus/heph-pwa \
      --oidc-issuer  https://auth.example.com/... \
      --oidc-audience heph-mobile
  • --web-root is optional. Unset, the hub serves only its API routes (unchanged behavior). Set, it serves the static shell for any non-API path, with an index.html SPA fallback. The shell is unauthenticated (it's just HTML/JS); all data still flows through the auth-gated /rpc.
  • Every hub response now carries permissive CORS headers and answers the browser OPTIONS preflight, so you can alternatively host the shell anywhere (any static server, GitHub Pages, etc.) and still call the hub cross-origin.

Then open https://<hub-host>:8787/ on your phone and Add to Home Screen.

Connect

On first launch the app opens Settings:

  • Hub URL — the server-mode hephd base URL (e.g. https://hub.example.com:8787). When served from the hub, use that same origin.
  • Token — a bearer token, if the hub requires OIDC (--oidc-issuer/-audience). Leave blank for an unauthenticated hub (local network / dev). Tap Test to verify the connection (it calls the version RPC).

Settings persist in the browser's local storage.

The device-code OIDC login flow (RFC 8628) the CLI/daemon use is not yet wired into the PWA — for now paste a bearer token obtained out-of-band. Wiring the in-app device flow is the obvious next step.

Quick-add

Tap + (or press Cmd-' / Ctrl-' on a keyboard) to capture. The single input accepts the exact v1-prototype-tech-spec syntax, parsed live into preview chips before you submit:

Token Example Effect
p1p4 p1 attention: red / orange / blue / white
#Project #Camano Chores file under a project (greedy multi-word match)
date today tomorrow +3d fri 2026-07-01 do-date
every … every 3 days every other wed every workday recurrence (RRULE)

Unmatched #tags stay in the title verbatim. With no #Project token, the task files into the currently selected project (or Inbox). The parser is a faithful JS port of the Rust quickadd/datespec modules, covered by parity tests (heph-pwa/test/parsers.test.mjs, run with node --test).

Voice

The quick-add field supports voice two ways:

  • iOS / iPadOS: use the microphone key on the on-screen keyboard — Apple dictation works in the text field for free, no app permission needed.
  • Chrome / Android / desktop: a 🎤 button appears when the Web Speech API is available and dictates straight into the field.

(Anthropic has no speech-to-text endpoint, so transcription leans on the platform. A server-side transcription proxy could be added later if needed.)

Triage

Tap a task to expand its actions, mirroring the TUI keys: Done (x), Drop (d), Skip (S, recurring only), Attn (cycle attention, A), Date (reschedule, e), Move (project picker, m), Delete (tombstone, D). Done/Drop show an Undo. The expanded view also shows the task's canonical-context body + recent log tail (read-only).

Search (🔍 or /) runs full-text search across tasks and docs.

Known limitations (first cut)

  • Online-only; no offline write queue or CRDT replica.
  • No in-app OIDC device-code login yet (paste a token).
  • Context/KB is read-only (no wiki-link navigation or editing).
  • Undo covers Done/Drop only.