Lab
ccx
Daily driverEvery Claude Code session runs in its own Docker container, per account, so sessions never share credentials.
Sessions
0 needs you Admin + New session-
docs-sitedonepersonaldocsfinished just now
-
api-refactorworkingworkcode8 min
-
payments-spikedoneworkcodefinished 1 h ago
api-refactorcontainer ccx-a1f3live
Renamed 14 handlers across 3 files.
Running the tests, 2 of 3 files done.
working
docs-sitecontainer ccx-7c2elive
Drafted the new landing page copy.
> Publish the docs site now?
1. Yes
2. No, keep it as a draft
waiting for you
> 1
published, session done
0 needs you / 2 done / 1 working
Notices
1 session is waiting for an answer.
A login is about to expire: work account, 3 days left.
Sessions
api-refactordone
docs-siteworking
payments-spikedone
Admin
SessionsShared credentials
NameKeyExpires
registry-token
sk-....7f2ain 41 daysdocs-deploy
sk-....c09din 3 daysAccount logins
personalsigned in, 22 daysRenew
worksigned in, 30 daysRenew
$ claude login
Open this link to sign in:
https://login.example.invalid/device
signed in
How it works
- I start a session. I pick an account, a folder and a mode, docs or code, and the server starts a fresh Docker container for it.
- The container holds one account. Only that account's credentials are mounted, and the folder is mounted as docs or as code, so sessions never share logins.
- The browser shows a live terminal. node-pty runs Claude Code in the container and xterm.js streams it over a websocket.
- Notices tell me when to look. A session that needs an answer or a login about to expire shows on the page, in the menu bar count and as a macOS banner that carries counts only.
- The menu bar app is a small window onto the same page. It signs in with a one-time link, keeps the cookie in memory only, and I reach the server from my phone through Tailscale Serve behind a secret path and an owner check.
Built with
- NodeThe server: it starts containers, restarts itself on file changes and serves the pages.
- DockerOne container per session, with per-account credentials and docs or code mounts.
- xterm.js and node-ptyThe live terminal in the browser, streamed over WebSockets.
- Swift and SwiftUIThe menu bar app: a MenuBarExtra with a WKWebView popover of a compact page.
- TailscaleRemote access with Serve, behind a secret path prefix and an owner check.
Decisions
- One container per session, per account. It costs more start-up time than sharing one box, but a session can only see its own account and its own mounts, so credentials never leak across.
- Notices carry counts, never content. The banner says how many sessions need me, not what they say, so nothing from a session lands on a lock screen.
- The menu bar app retries sign-in until the page loads. It once got stuck forever when it launched before the dashboard at login, and showed a blank popover until I quit it. Now it keeps trying quietly and recovers on its own.