Pandopticon is a web terminal manager for AI coding sessions. Sessions run inside tmux and survive browser closes and server restarts. Connect from any browser tab — your Claude, Gemini, or Codex session is right where you left it.
- Node.js 18+
- tmux —
brew install tmux
-
Install dependencies:
npm install
-
Start the dev servers:
npm run dev
-
Open http://localhost:5173.
- AI session — click + AI next to a group in the sidebar, or + New Session on the welcome screen. Choose an AI (Claude, Gemini, or Codex), a working directory, and a name.
- Plain terminal — click >_ to open a shell without an AI.
- SSH session — enter
user@hostname(oruser@hostname:port) in the SSH Host field. The session runs tmux on the remote machine.
Closing a tab does not kill the session. Sessions reattach automatically after a page refresh or server restart.
Rename a session — double-click the session name in the sidebar.
| Keys | Action |
|---|---|
Alt+T |
New Claude session |
Alt+W |
Close active tab |
Alt+[ / Alt+] |
Cycle tabs |
Alt+1–9 |
Jump to tab |
Use cloud instances to run Claude Code on a disposable EC2 box — useful for long-running tasks, large repos, or keeping your laptop free. Pandopticon launches the VM, installs the AI CLI, clones your repo, and opens a terminal automatically.
Redpanda employees: authenticate via Okta SSO:
aws sso login --profile sandbox-cloud
export AWS_PROFILE=sandbox-cloudAdd the export to your shell profile so it persists. Verify access:
aws sts get-caller-identityRequired IAM permissions: ec2:RunInstances, ec2:TerminateInstances, ec2:StopInstances, ec2:StartInstances, ec2:CreateKeyPair, ec2:DeleteKeyPair, ec2:CreateSecurityGroup, ec2:DeleteSecurityGroup, ec2:AuthorizeSecurityGroupIngress, ec2:CreateTags, ec2:DescribeInstances.
Cost attribution (required): set RP_ATTRIBUTION_TAG before launching any instance:
export RP_ATTRIBUTION_TAG=engineering-core-<your-team>
# e.g. engineering-core-storagePandopticon tags every EC2 resource it creates with redpanda-org=<RP_ATTRIBUTION_TAG>-pandopticon. Without this tag, instances appear unattributed in Cost Explorer.
- Click ☁ Launch at the top of the sidebar.
- Choose a region, instance type, repo URL, and AI CLI.
- Click Launch.
Provisioning takes ~2–3 minutes. The sidebar shows Provisioning… while the setup script runs.
| State | Meaning |
|---|---|
| Provisioning… | EC2 is starting; setup script is running |
| Ready | SSH session is open; AI CLI is running |
| Stopping… / Stopped | Instance stopped to save cost |
| Resuming… | Instance restarting; session reopening |
| Error | Provisioning failed — hover to see details |
- Stop — pause billing by stopping the instance.
- Resume — restart a stopped instance and reopen the session.
- Reconnect — reopen a session without restarting the instance.
- Terminate — destroy the instance and clean up the key pair and security group.
Key pairs and PEM files are stored in ~/.local/share/pandopticon/keys/ and deleted on terminate.
Pandopticon monitors idle sessions and stops instances automatically:
- Idle stop — stops the instance after the configured idle minutes (default: 30) when the AI CLI is idle.
- Auto-terminate — terminates the stopped instance after the configured minutes (default: 240).
A watchdog cron on the VM also stops itself if Pandopticon's SSH heartbeat (sent every 60 s) goes stale for more than 2 hours. The VM stops even if your laptop is offline.
| Command | What it does |
|---|---|
npm run dev |
Start server (port 3000) and client (port 5173) with hot reload |
npm run build |
Compile client to client/dist/, then compile server TypeScript |
npm start |
Run the compiled server, which also serves the built frontend |
Browser ──HTTP/WS──► Express (port 3000)
│
├── REST /api/sessions
├── REST /api/cloud/instances
├── WS /ws/sessions/:id/terminal
├── SessionManager (tmux + node-pty)
└── CloudManager
├── AwsProvider (aws CLI)
├── Heartbeat sender (60 s)
└── Reaper (idle-stop + auto-terminate)
Sessions persist in ~/.local/share/pandopticon/sessions.json. Cloud instance state persists in ~/.local/share/pandopticon/instances.json.