SPB Git

Repository Public

README.md 10.9 KB 161 lines markdown

1# Claude Remote — MacLustr Command Center23A private, single-administrator web application that exposes the **real Claude Code CLI**, running inside4tmux on a Mac Studio of the MacLustr cluster, to any browser. Nothing is simulated: the browser terminal is5an xterm.js view attached to a tmux session in which `claude` (or a login shell) runs.67Production instance: `https://claude.spboucher.ai` → node M5M36 (deployed 2026-11-10).89The same code base also deploys as **Codex Remote** (OpenAI Codex CLI) — a second independent instance10selected by `CR_AGENT=codex` (own port, database, data dir, tmux socket; planned at11`https://codex.spboucher.ai`, not deployed yet). Differences, verified CLI facts and limitations:12[docs/codex-profile.md](docs/codex-profile.md); deployment: "Codex Remote instance" in13[docs/deployment.md](docs/deployment.md).1415This README is a summary. Every statement about behaviour is backed by the source; anything that is not16implemented or not verified is listed under [Limitations](#limitations--not-verified) and in the17"Limitations / not verified" section of each document.1819## Architecture2021```22 browser (desktop / phone)23    │  HTTPS + WSS24    ▼25 Caddy on the public gateway (BHS64) ── TLS termination, reverse proxy26    │  WireGuard tunnel (the node dials out; no inbound port on the LAN)27    ▼28 M5M36 ─ apps/server   Fastify, port 862029    │      auth (password + passkey/TOTP), REST + WebSocket API /api/v1,30    │      static web app (apps/web/out), PostgreSQL 17 (loopback), audit, notifications31    │32    │  unix socket (0600, dir 0700) + bearer token — HTTP and WebSocket33    ▼34         apps/runtime  no TCP listener; the only process that spawns anything35    │      tmux sessions, node-pty attach, durable tasks, file/git operations,36    │      Claude Code introspection, host metrics, hook endpoint37    ▼38         tmux server (socket `-L claude-remote`)39           cr-<uuid>   one per terminal session: `claude …` or a login shell40           crt-<uuid>  one per background task (local, or `ssh <allow-listed node>`)41```4243Details: [docs/architecture.md](docs/architecture.md), [docs/network-architecture.md](docs/network-architecture.md),44binding engineering contract: [docs/CONTRACT.md](docs/CONTRACT.md).4546## Repository layout4748| Path | Content |49|---|---|50| `packages/shared` | `@cr/shared`: zod schemas and types — state machines, browser DTOs, WebSocket wire formats, runtime IPC types |51| `apps/runtime` | Runtime daemon (Fastify on a unix socket): tmux, PTY attach, scrollback mirror, tasks, hooks, fs/git, skills, MCP, metrics. `bin/cr-hook` is the Claude Code hook relay |52| `apps/server` | Browser-facing server: authentication, API, WebSocket proxy, static files, migrations (`migrations/*.sql`) |53| `apps/web` | Next.js App Router **static export** (xterm.js, Monaco, React Query). `dev/mock-server.mjs` is a mock API used only by the Playwright suite; `e2e/`, `e2e-real/` |54| `deploy/` | `make-manifest.py` (mld manifest generator), `backup.sh`, `restore.sh` |55| `scripts/` | `dev-up.sh`, `dev-down.sh` (local run), `ci.sh` (local CI gate) |56| `docs/` | Documentation set (index below) |57| `.env.example` | Every configuration variable, without secrets |5859## Quick start (local development, macOS)6061Requirements: Node ≥ 24, pnpm, tmux, a local PostgreSQL with `psql`/`createdb` on `PATH`, and the `claude`62CLI on `PATH` if you want Claude sessions (shell sessions work without it).6364```bash65pnpm install66pnpm --filter @cr/web build      # optional: without it dev-up serves the API only67scripts/dev-up.sh                # builds shared/runtime/server, creates + migrates claude_remote_dev,68                                 # starts both processes on http://localhost:862069cat /tmp/cr-dev-data/setup-token # one-time token for the first-run page (/setup/)70scripts/dev-down.sh              # stops both and kills ONLY the dev tmux server (claude-remote-dev)71```7273`dev-up.sh` uses `/tmp/cr-dev-data` (data), `/tmp/cr-dev-workspace` (workspace root), database74`claude_remote_dev` and its own tmux socket. It never sets `CR_INSTALL_CLAUDE_HOOKS`, so your75`~/.claude/settings.json` is not modified and sessions do not report `WAITING_FOR_INPUT` in this mode.7677## Tests7879| Command | What runs |80|---|---|81| `scripts/ci.sh` | build shared → typecheck all → runtime tests → server tests → web unit tests → full build |82| `scripts/ci.sh --e2e` | the above + Playwright (`apps/web/e2e`, against the dev mock server) |83| `pnpm --filter @cr/runtime test` | runtime suite (real tmux, real `claude` binary, never sends a prompt) |84| `pnpm --filter @cr/server test` | server suite (one temporary Postgres database per file; `integration/real-runtime.test.ts` starts the real runtime) |85| `pnpm --filter @cr/web test` | web unit tests |86| `pnpm --filter @cr/web exec playwright test -c playwright.real.config.ts` | 2 flows against a real backend started with `scripts/dev-up.sh` (web export built with `NEXT_PUBLIC_E2E=1`) |8788Last recorded results (laptop, 2026-11-10): runtime 209 passed · server 175 passed (17 against the real89runtime) · web unit 12 passed · Playwright 19 passed against the mock (15 Chromium desktop, 4 WebKit90iPhone 15 emulation) and 2 passed against the real backend · `scripts/ci.sh` green.9192## Deployment summary9394Deployed with the cluster orchestrator `mld` from the gateway (M1M32), pinned to M5M36:9596- PM2 processes `claude-remote-runtime`, `claude-remote-server` (port 8620), `claude-remote-backup` (nightly, 03:35);97- PostgreSQL 17 on loopback (role and database `claude_remote`);98- code in `~/apps/claude-remote` (git clone; **the node directory is the source of truth**), data in99  `~/claude-remote-data` (0700), workspace root `~/workspace`;100- public route `https://claude.spboucher.ai` → Caddy (BHS64) → WireGuard → M5M36:8620.101102Updating is done on the node (edit, build, migrate, restart, commit, push): see [docs/deployment.md](docs/deployment.md).103104## Status of the 17 deliverables105106Detail, files, tests and limitations per item: [docs/deliverables-status.md](docs/deliverables-status.md).107108| # | Deliverable | Status |109|---:|---|---|110| 1 | Working production web application | Deployed and verified (health, auth refusals, headers); no administrator created yet |111| 2 | Real Claude Code PTY runtime | Implemented; real `claude` 2.1.322 rendered in tmux on the node; Claude not yet authenticated |112| 3 | Secure private authentication | Implemented and tested; passkeys verified with a software authenticator only |113| 4 | Persistent terminal sessions | Implemented and tested for every failure mode except a real host reboot (simulated by killing the tmux server) |114| 5 | Polished desktop interface | Implemented; 15 Playwright tests (Chromium, mock API) + 2 against the real backend |115| 6 | Tested mobile interface | Implemented; tested in WebKit iPhone 15 **emulation** only |116| 7 | Project management | Implemented; `create`/`existing` tested end to end, `clone` not tested against the real git server from the app |117| 8 | File browsing and editing | Implemented and tested end to end |118| 9 | Skills and MCP management | Implemented; listings tested against the real CLI, mutations tested with mocks/fakes only; registry install returns 501 |119| 10 | Authorized MacLustr integration | Implemented (agentd telemetry, allow-listed SSH tasks); in-app remote tasks tested with a fake `ssh` only |120| 11 | Background task management | Implemented and tested end to end (local tasks) |121| 12 | Real observability | Implemented (system status, host metrics, audit trail, cluster view); no external alerting |122| 13 | Deployment configuration | Done (mld manifest generator, PM2, tunnel route, git adoption) |123| 14 | Backup and recovery procedures | Nightly encrypted backup + restore drill succeeded; backups are not yet copied off the node |124| 15 | Security documentation | Written ([docs/security.md](docs/security.md)) |125| 16 | Automated tests | 396 unit/integration tests + 21 Playwright tests, local gate `scripts/ci.sh`; no hosted CI |126| 17 | Demonstrated laptop-independence test | **Not yet demonstrated** — pending the owner (laptop off, phone on cellular) |127128## Documentation index129130| Document | Subject |131|---|---|132| [docs/architecture.md](docs/architecture.md) | Processes, data flows, state machines, storage |133| [docs/security.md](docs/security.md) | Threat model, implemented controls mapped to tests, residual risks |134| [docs/authentication.md](docs/authentication.md) | First-run setup, login flows, sessions, throttling |135| [docs/terminal-runtime.md](docs/terminal-runtime.md) | tmux sessions, attach, scrollback mirror, hooks, backpressure |136| [docs/codex-profile.md](docs/codex-profile.md) | Agent profiles; what differs for Codex Remote; verified Codex CLI facts |137| [docs/session-persistence.md](docs/session-persistence.md) | Exact guarantees per failure |138| [docs/cluster-integration.md](docs/cluster-integration.md) | agentd telemetry, remote tasks, git server, local models |139| [docs/mobile-experience.md](docs/mobile-experience.md) | Phone layout, key toolbar, gestures, PWA shell |140| [docs/deployment.md](docs/deployment.md) | mld manifest, PM2, environment, first run, remote-first updates |141| [docs/operations-runbook.md](docs/operations-runbook.md) | Routine checks and procedures |142| [docs/troubleshooting.md](docs/troubleshooting.md) | Symptoms → causes → actions |143| [docs/backup-recovery.md](docs/backup-recovery.md) | Backup content, restore, disaster recovery |144| [docs/api.md](docs/api.md) | API conventions; reference is `/api/v1/openapi.json` |145| [docs/implementation-log.md](docs/implementation-log.md) | Chronological build log |146| [docs/deliverables-status.md](docs/deliverables-status.md) | The 17 deliverables in detail |147| [docs/CONTRACT.md](docs/CONTRACT.md) · [infrastructure-inventory](docs/infrastructure-inventory.md) · [node-selection](docs/node-selection.md) · [network-architecture](docs/network-architecture.md) · [deployment-plan](docs/deployment-plan.md) · [migration](docs/migration.md) | Earlier design documents (kept as written) |148149## Limitations / not verified150151- Not verified on a real iPhone (Safari or installed PWA); emulation only.152- The laptop-independence test has not been run.153- Passkey login has not been exercised in a real browser.154- `WAITING_FOR_INPUT` has not been observed from a real (paid) Claude conversation; the hook relay itself is tested end to end with the real hook script.155- Web Push is not implemented (in-app notifications only). Skills-registry install is not implemented (501).156- There is no dedicated LaTeX / Jupyter / research feature; a PDF file preview exists in the editor, nothing more. TeX is not installed on the node.157- No local model endpoint exists on the cluster; the Local Models panel is empty by design.158- The application runs under the cluster operator's macOS account, not a dedicated OS identity (see [docs/security.md](docs/security.md)).159- Single host: if M5M36 is down the service is down. Backups currently stay on M5M36.160- No hosted CI; `scripts/ci.sh` is run by hand. The root `lint` script references ESLint, which is not configured in this repository.161
Files main
Menu

Theme