← index2026-04-19 11:42 (Beirut)(backfill from DOCUMENTATION/)

Claude Code PWA — cli.jonahtebaa.com

Claude Code PWA — cli.jonahtebaa.com

Last updated: 2026-04-19 (Brian)
Status: live at https://cli.jonahtebaa.com/

What it is

The v3 Claude Code PWA (cli-pwa) — a web UI for Jonah to use Claude Code from any browser, with session management, voice dictation, subagents panel, and a live "working…" typing indicator above the input bar.

Previously served at cc.jonahtebaa.com/v3/. Migrated to cli.jonahtebaa.com/ (served at root) on 2026-04-19. The /v3/ path on cc.jonahtebaa.com has been removed.

Architecture

Browser → Caddy (cli.jonahtebaa.com:443)
        → reverse_proxy host.docker.internal:8111
        → cli-pwa-backend (systemd) serves:
            /api/*          → REST (sessions, skills, commands, enhance, archived)
            /ws/sessions/:id → WebSocket (session event stream)
            /               → Static files from /opt/agent/cli-pwa/frontend/dist

Key files

Path Purpose
/opt/agent/cli-pwa/backend/src/server.ts Fastify entrypoint, registers routes + static.
/opt/agent/cli-pwa/backend/src/sessions.ts Session lifecycle, CLI subprocess manager.
/opt/agent/cli-pwa/backend/src/routes/ws.ts WebSocket handler, replays buffer + forwards events.
/opt/agent/cli-pwa/backend/src/sdk.ts CLIProcess — spawns claude with stream-JSON IO.
/opt/agent/cli-pwa/frontend/src/routes/SessionView.tsx Live session view, status state machine, working indicator.
/opt/agent/cli-pwa/frontend/src/components/TopBar.tsx Top bar: model / permission / effort / plan toggles, ctx meter.
/opt/agent/cli-pwa/frontend/src/components/InputBar.tsx Input + voice dictation + interrupt.
/opt/agent/cli-pwa/frontend/src/components/ChatView.tsx Transcript.
/opt/agent/cli-pwa/frontend/src/components/SubagentDrawer.tsx Subagent panel (TopBar satellite badge opens it).
/opt/agent/cli-pwa/frontend/vite.config.ts base: '/' (was /v3/).
/opt/agent/cli-pwa/frontend/src/lib/api.ts BASE = '/api'.
/opt/agent/cli-pwa/frontend/src/lib/ws.ts WS URL = /ws/sessions/:id.
/opt/agent/cli-pwa/frontend/src/main.tsx Router basename: '/'.
/opt/agent/cli-pwa/frontend/index.html Favicon at /favicon.svg.

Session status machine (live indicator)

Status is driven by WebSocket event types in SessionView.tsx:

Event type Status
assistant / stream_event thinking
result idle
permission_request / tool_use_request awaiting_permission
session_end killed

The "working…" indicator (italic muted text above the input bar, absolutely positioned at bottom: 68px) renders when connected === true AND status is thinking (shows working + animated 1→2→3 dots via pure-CSS @keyframes brian-typing-dots animating content on .brian-typing-dots::after) or awaiting_permission (shows waiting for you...).

Deploy / rebuild

cd /opt/agent/cli-pwa/frontend && npx tsc -b && npx vite build
# Backend auto-serves the new dist. Restart only if backend code changed:
systemctl restart cli-pwa-backend

Caddy reload:

docker exec agent-caddy caddy reload --config /etc/caddy/Caddyfile

Operations

Migration notes (2026-04-19)

Removed from Caddyfile:

# was inside cc.jonahtebaa.com { ... }
handle_path /v3/* {
    reverse_proxy host.docker.internal:8111 { flush_interval -1 }
}

Added:

cli.jonahtebaa.com {
    header { ... security headers, microphone=(self) allowed ... }
    import gate_auth
    import gate_check
    log { output file /data/caddy-cli.log ... }
    reverse_proxy host.docker.internal:8111 { flush_interval -1 }
}

Frontend changes to drop /v3/ prefix: vite base/, api.ts BASE → /api, ws.ts URL → /ws/sessions/..., main.tsx router basename/, index.html favicon → /favicon.svg.

Known limitations