Installation
Klaudii installs on your Mac in about 30 seconds. One command does everything: checks dependencies, installs system tools, sets up a background service, and opens your dashboard.
curl -fsSL https://klaudii.com/setup.sh | bash
The installer will:
- Verify Node.js 18+ is installed
- Install
tmuxandttydvia Homebrew (if not present) - Clone Klaudii to
~/.klaudii - Create
config.jsonwith your home directory paths - Register a
launchdagent that auto-starts on login - Compile the menu bar app (optional, requires Xcode CLI tools)
- Open the dashboard at http://localhost:9876
cd ~/.klaudii && git pull && launchctl kickstart -k gui/$(id -u)/com.klaudii
Quick Start
After installation, open localhost:9876 in your browser. Here's how to get your first workspace running:
Create a workspace
Click + New Session in the top right. Search for a GitHub repo (requires gh CLI authenticated), enter a branch name, and click Start.
Klaudii will clone the repo (if needed), create a git worktree for your branch, and start Claude Code in it.
Watch it work
The workspace card shows real-time status: running/stopped badge, CPU, memory, uptime, and git status. Click Terminal to open a live web terminal and see Claude's output.
Manage your sessions
Use Stop, Restart, Continue (resume last session), or History (pick a past session to resume). Click Open to jump to the conversation on claude.ai.
Requirements
| Dependency | Version | Notes |
|---|---|---|
| macOS | 12+ | Monterey or later |
| Node.js | 18+ | nodejs.org |
| Homebrew | any | brew.sh (installs tmux and ttyd) |
| Claude Code CLI | latest | npm i -g @anthropic-ai/claude-code |
| GitHub CLI | any | brew install gh && gh auth login |
| Xcode CLI Tools | any | Optional, for menu bar app. xcode-select --install |
Workspaces
A workspace is a project + branch combination. Each workspace gets its own isolated git worktree and tmux session. This means multiple Claude instances can work on different branches of the same repo simultaneously without any conflicts.
Naming convention
Workspaces follow the pattern {repo}--{branch}. For example, my-app--feature-auth lives at ~/repos/my-app--feature-auth.
Creating a workspace
Click + New Session, pick a GitHub repo, enter a branch name. If you leave the branch name empty, Klaudii generates claude-{timestamp}.
Behind the scenes:
- If the repo isn't cloned locally, Klaudii clones it via SSH
- Creates a git worktree:
git worktree add ~/repos/{repo}--{branch} {branch} - Registers the workspace in
config.json - Starts Claude Code in a new tmux session
Removing a workspace
Click the Remove button on a stopped workspace. Klaudii checks git status first:
- If the worktree is clean (no uncommitted changes, no unpushed commits), it removes immediately
- If it has uncommitted work, you'll see a warning and must confirm twice
Sessions
Every Claude Code conversation has a unique session ID. Klaudii tracks these IDs and lets you resume any past session.
Session actions
| Action | What it does |
|---|---|
| New | Start a fresh Claude session in the workspace |
| Continue | Resume the most recent session with --continue |
| History | Show up to 20 past sessions; click any to resume with --resume {id} |
| Stop | Gracefully terminate the tmux session and ttyd process |
| Restart | Stop then start with --continue to preserve context |
| Open | Navigate to the session's claude.ai/code URL |
| Terminal | Open a live web terminal (ttyd) in the dashboard |
Session tracking
Klaudii maintains its own sessions.json mapping workspace names to session IDs. This is necessary because Claude's built-in history.jsonl maps by project path, which breaks for git worktrees (all worktrees of the same repo would share one history).
Permission Modes
Each workspace has an independent permission mode that controls how much autonomy Claude gets. Toggle between modes on the workspace card (only when the session is stopped).
| Mode | Behavior | Use case |
|---|---|---|
| Yolo | Claude auto-approves everything (--dangerously-skip-permissions) |
Personal projects, sandboxed environments, maximum speed |
| Ask | Claude prompts in the terminal for each action | Sensitive work, client projects, learning what Claude does |
| Strict | Read-only tools only (Read, Glob, Grep, WebSearch, WebFetch) |
Code analysis, auditing, research tasks |
Web Terminal
Every running session has a web terminal powered by ttyd. Click Terminal on any running workspace to open a full-screen terminal overlay in the dashboard.
How it works
When a session starts, Klaudii spawns a ttyd process that attaches to the workspace's tmux session:
ttyd -p {port} -W tmux -S {socket} attach -t {session-name}
Ports are allocated sequentially starting from ttydBasePort (default 9877). The terminal iframe is destroyed and recreated each time you open it to avoid stale session artifacts.
Compatibility
The web terminal works in all modern browsers including iOS Safari. Full keyboard input is supported, so you can interact with Claude's prompts, approve actions in Ask mode, or run commands directly in the tmux session.
Git Integration
Every workspace card shows real-time git status:
- clean or N changed — uncommitted file count
- M unpushed — commits not yet pushed to origin
- Click the git status area to see a detailed modal with per-file status (Modified, Added, Deleted, Untracked)
Worktree management
Klaudii uses git worktree to give each branch a completely isolated working directory. This means:
- No stashing, no context switching, no conflicts between branches
- Multiple Claude instances can work on the same repo simultaneously
- Each worktree has its own
node_modules, build output, etc.
Cleanup
When you remove a workspace, Klaudii runs git worktree remove to clean up the worktree directory. If the worktree has uncommitted changes, you'll be warned before deletion.
GitHub Integration
The + New Session modal lists your GitHub repositories (via gh CLI). Each repo shows whether it's already cloned locally.
Setup
Make sure the GitHub CLI is authenticated:
brew install gh
gh auth login
Klaudii uses SSH URLs to clone, so ensure your SSH keys are configured for GitHub.
Direct links
Workspace cards link directly to the GitHub repo and branch view. Click the repo name to open it on GitHub; click the branch to see that branch's code.
Resource Monitoring
The dashboard shows real-time CPU, memory, and uptime for every Claude process. Stats are aggregated across the entire process tree — if a Claude session spawns a dev server, database, or build watcher, their resource usage is included.
Free Range Claudes
Any Claude instances running outside Klaudii (started manually in Terminal, VS Code, etc.) appear in a separate "Free Range Claudes" section. Each shows:
- PID and working directory
- CPU and memory (aggregated with child processes)
- Launching app (Terminal, iTerm2, VS Code, etc.)
- Inline kill button with two-step confirmation
Health detection
Every 10 seconds, Klaudii polls the process tree and detects if a Claude process crashed, hung, or exited. Crashed sessions show as "exited" with Restart/Clean up options.
Kloud Konnect Overview
Kloud Konnect lets you access your local Klaudii dashboard from anywhere — your phone, a different computer, a coffee shop — without port forwarding, VPN, or Tailscale.
How it works
- Your local Klaudii server connects to the relay at
konnect.klaudii.comvia WebSocket - You sign in with Google on any device and pick your server
- Every API request from your browser is encrypted with AES-256-GCM before it leaves the device
- The relay forwards the encrypted blob to your server, which decrypts it with the shared Connection Key
- The relay never sees the plaintext
Pairing Setup
Pairing connects your local Klaudii to the cloud relay. It only needs to be done once.
Start pairing
On your local dashboard (localhost:9876), click the Kloud Konnect button in the header. Click Start Pairing.
Get the pairing code
Go to konnect.klaudii.com, sign in with Google, and click Add Server. You'll get a 6-character pairing code.
Enter the code
Enter the pairing code on your local dashboard. Klaudii exchanges Ed25519 public keys with the relay, establishing trust.
Scan the QR code
After pairing, your local dashboard shows a QR code containing the 256-bit Connection Key. On konnect.klaudii.com, scan it with your camera. The key is stored in your browser's localStorage and never touches the relay.
Security Model
Encryption
- AES-256-GCM — every API request/response encrypted end-to-end
- HKDF — session keys derived from the Connection Key
- Ed25519 — server authenticates itself via signature challenge
What the relay sees
| Data | Visible to relay? |
|---|---|
| Your Google email/name | Yes (for login) |
| Server name and online status | Yes |
| Request timing and size | Yes (traffic analysis) |
| Dashboard content | No (encrypted) |
| Workspace names, code, git status | No (encrypted) |
| Connection Key | No (never transmitted) |
Wrong key detection
If the browser has a stale Connection Key (e.g., you re-paired), AES-GCM authentication will fail. The server detects this and sends an unencrypted wrong_key signal, prompting the browser to clear the stale key and redirect to the pairing page.
Self-Hosting the Relay
The relay is a standard Node.js + Express + SQLite app in konnect/server/. You can deploy it anywhere that supports persistent WebSocket connections.
Deploy to Fly.io
# From the repo root
fly launch --name my-klaudii-relay
fly volumes create klaudii_data --size 1 --region sjc
fly secrets set GOOGLE_CLIENT_ID=xxx GOOGLE_CLIENT_SECRET=xxx SESSION_SECRET=$(openssl rand -hex 32)
fly deploy
Environment variables
| Variable | Required | Description |
|---|---|---|
GOOGLE_CLIENT_ID | Yes | Google OAuth 2.0 client ID |
GOOGLE_CLIENT_SECRET | Yes | Google OAuth 2.0 client secret |
SESSION_SECRET | Yes | Random string for session cookies |
GOOGLE_REDIRECT_URI | No | Defaults to https://{host}/auth/google/callback |
DB_PATH | No | SQLite path. Defaults to ./relay.db |
Then update your local Klaudii's config.json to point at your relay:
{
"cloud": {
"relayUrl": "wss://my-klaudii-relay.fly.dev/ws"
}
}
Chrome Extension Installation
- Download
klaudii-extension.zipfrom releases - Unzip to a permanent location (e.g.,
~/klaudii-extension/) - Open
chrome://extensions - Enable Developer mode (top right toggle)
- Click Load unpacked and select the unzipped folder
- Click the Klaudii icon in your toolbar to open the side panel
The extension defaults to connecting to http://localhost:9876. Change this in the extension's Settings if your Klaudii runs on a different host/port.
Extension Features
Side panel
All your workspace cards in a compact side panel. Shows running/stopped status, git branch, resource stats, and action buttons (Open, Terminal, Stop, Continue, History).
Auto-rename conversations
When you click Open on a workspace, the extension navigates to the claude.ai conversation and renames it to {repo} ({branch}) format. This makes your browser tabs readable when you have multiple sessions open.
Smart behavior: if you've already given the conversation a custom name, the extension won't overwrite it.
Tab switching
Two modes (configurable in Settings):
- In-place: navigates the current tab to the session URL
- Tab switch: if a tab for that session already exists, switches to it; otherwise opens a new tab
Extension Settings
Right-click the Klaudii extension icon and select Options, or click the gear icon in the side panel.
| Setting | Default | Description |
|---|---|---|
| Klaudii URL | http://localhost:9876 | The URL of your Klaudii server |
| Tab behavior | In-place | How clicking Open handles tabs |
Configuration
Klaudii's configuration lives in config.json at the install root (typically ~/.klaudii/config.json). It's created by the installer and gitignored.
{
"port": 9876,
"ttydBasePort": 9877,
"reposDir": "/Users/you/repos",
"tmuxSocket": "/Users/you/.claude/klaudii-tmux.sock",
"projects": [
{
"name": "my-app",
"path": "/Users/you/repos/my-app",
"permissionMode": "yolo"
},
{
"name": "my-app--feature-x",
"path": "/Users/you/repos/my-app--feature-x",
"permissionMode": "ask"
}
],
"cloud": {
"relayUrl": "wss://konnect.klaudii.com/ws",
"serverId": "...",
"connectionKey": "..."
}
}
| Field | Description |
|---|---|
port | Dashboard HTTP port (default 9876) |
ttydBasePort | Starting port for ttyd instances (default 9877) |
reposDir | Base directory where repos are cloned and worktrees created |
tmuxSocket | Absolute path to the tmux socket. Must be absolute for launchd compatibility |
projects | Array of registered workspaces |
cloud | Kloud Konnect settings (populated by pairing flow) |
tmuxSocket path must be an absolute path (e.g., /Users/you/.claude/klaudii-tmux.sock). Relative paths or ~ expansion will break under launchd because the background service sees a different working directory and HOME than your shell.
Architecture
Klaudii is a lightweight Node.js server that orchestrates existing Unix tools. No Docker, no Kubernetes, no cloud dependency.
Browser (localhost:9876)
| REST API
Express server (server.js)
|-- lib/tmux.js -------> tmux (session management, dedicated socket)
|-- lib/ttyd.js -------> ttyd (web terminal, one per session)
|-- lib/processes.js --> ps (process discovery + resource stats)
|-- lib/claude.js -----> ~/.claude/history.jsonl (session history)
|-- lib/session-tracker.js -> sessions.json (worktree mapping)
|-- lib/git.js --------> git (clone, worktree, status)
|-- lib/github.js -----> gh CLI (repo listing)
|-- lib/projects.js ---> config.json (workspace registry)
|-- konnect/client/ ---> Kloud Konnect WebSocket tunnel
'-- public/ -----------> Dashboard UI
Key design decisions
- Dedicated tmux socket: Klaudii uses its own socket at
tmuxSocketto avoid colliding with your personal tmux sessions - Process tree aggregation: Resource stats walk the full descendant tree, not just the Claude process
- Vanilla frontend: No build step, no framework. HTML + CSS + JS served directly by Express
- Worktree-based isolation: Each branch gets its own directory, preventing conflicts between parallel sessions
Troubleshooting
Dashboard won't load
- Check if the server is running:
launchctl list | grep klaudii - Check logs:
cat /tmp/klaudii.logandcat /tmp/klaudii-error.log - Restart:
launchctl kickstart -k gui/$(id -u)/com.klaudii
Sessions show as "exited" immediately
- Make sure Claude Code CLI is installed:
which claude - Check if tmux is available at the configured socket:
tmux -S ~/.claude/klaudii-tmux.sock ls - Look for errors in the tmux session:
tmux -S ~/.claude/klaudii-tmux.sock attach -t {session}
Kloud Konnect shows "disconnected"
- Check that
config.jsonhas acloudsection withrelayUrl,serverId, andconnectionKey - Try re-pairing: click Kloud Konnect > Unpair, then re-pair
- Check relay health:
curl https://konnect.klaudii.com/api/relay/health
QR code won't scan
- Ensure the QR code has a white background (hard refresh if it looks invisible on dark theme)
- Try the manual key entry option below the QR code as a fallback
- The QR encodes
klaudii://{serverId}/{key}— the camera app should recognize it
tmux socket mismatch
- The most common cause of "can't find sessions" is the tmux socket path differing between your shell and the launchd agent
- Verify
config.jsonhas an absolutetmuxSocketpath (no~, no relative paths) - Check both environments see the same socket:
ls -la $(cat ~/.klaudii/config.json | python3 -c "import sys,json; print(json.load(sys.stdin)['tmuxSocket'])")