Josh Knapp 090aad6bc6
All checks were successful
Build App / build-macos (push) Successful in 2m43s
Build App / build-windows (push) Successful in 4m31s
Build App / build-linux (push) Successful in 4m41s
Build App / sync-to-github (push) Successful in 9s
Fix project rename, remove confirmation, and auth mode change bugs
- Add double-click-to-rename on project names in the sidebar
- Replace window.confirm() with inline React confirmation for project
  removal (confirm dialog didn't block in Tauri webview)
- Add serde(default) to skip_serializing fields in Rust models so
  deserialization doesn't fail when frontend omits secret fields

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 17:39:34 -08:00
2026-02-27 09:40:19 -08:00
2026-02-27 07:00:48 -08:00
2026-03-02 10:07:16 -08:00

Triple-C (Claude-Code-Container)

Triple-C is a cross-platform desktop application that sandboxes Claude Code inside Docker containers. When running with --dangerously-skip-permissions, Claude only has access to the files and projects you explicitly provide to it.

Architecture

  • Frontend: React 19 + TypeScript + Tailwind CSS v4 + Zustand state management
  • Backend: Rust (Tauri v2 framework)
  • Terminal: xterm.js with WebGL rendering
  • Docker API: bollard (pure Rust Docker client)

Layout Structure

┌─────────────────────────────────────────────────────┐
│  TopBar (terminal tabs + Docker/Image status)       │
├────────────┬────────────────────────────────────────┤
│  Sidebar   │  Main Content (terminal views)         │
│  (25% w,   │                                        │
│  responsive│                                        │
│  min/max)  │                                        │
├────────────┴────────────────────────────────────────┤
│  StatusBar (project/terminal counts)                │
└─────────────────────────────────────────────────────┘

Container Lifecycle

  1. Create: New container created with bind mounts, env vars, and labels
  2. Start: Container started, entrypoint remaps UID/GID, sets up SSH, configures Docker group
  3. Terminal: docker exec launches Claude Code with a PTY
  4. Stop: Container halted (filesystem persists in named volume)
  5. Restart: Existing container restarted; recreated if settings changed (e.g., Docker access toggled)
  6. Reset: Container removed and recreated from scratch (named volume preserved)

Mounts

Target in Container Source Type Notes
/workspace Project directory Bind Read-write
/home/claude/.claude triple-c-claude-config-{projectId} Named Volume Persists across container recreation
/tmp/.host-ssh SSH key directory Bind Read-only; entrypoint copies to ~/.ssh
/home/claude/.aws AWS config directory Bind Read-only; for Bedrock auth
/var/run/docker.sock Host Docker socket Bind Only if "Allow container spawning" is ON

Authentication Modes

Each project can independently use one of:

  • Anthropic (OAuth): User runs claude login inside the terminal on first use. Token persisted in the config volume across restarts and resets.
  • AWS Bedrock: Per-project AWS credentials (static keys, profile, or bearer token).

Container Spawning (Sibling Containers)

When "Allow container spawning" is enabled per-project, the host Docker socket is bind-mounted into the container. This allows Claude Code to create sibling containers (not nested Docker-in-Docker) that are visible to the host. The entrypoint detects the socket's GID and adds the claude user to the matching group.

If the Docker access setting is toggled after a container already exists, the container is automatically recreated on next start to apply the mount change. The named config volume (keyed by project ID) is preserved across recreation.

Docker Socket Path

The socket path is OS-aware:

  • Linux/macOS: /var/run/docker.sock
  • Windows: //./pipe/docker_engine

Users can override this in Settings via the global docker_socket_path option.

Key Files

File Purpose
app/src/App.tsx Root layout (TopBar + Sidebar + Main + StatusBar)
app/src/index.css Global CSS variables, dark theme, color-scheme: dark
app/src/components/layout/TopBar.tsx Terminal tabs + Docker/Image status indicators
app/src/components/layout/Sidebar.tsx Responsive sidebar (25% width, min 224px, max 320px)
app/src/components/layout/StatusBar.tsx Running project/terminal counts
app/src/components/projects/ProjectCard.tsx Project config, auth mode, action buttons
app/src/components/projects/ProjectList.tsx Project list in sidebar
app/src/components/settings/SettingsPanel.tsx API key, Docker, AWS settings
app/src/components/terminal/TerminalView.tsx xterm.js terminal with WebGL, URL detection
app/src/components/terminal/TerminalTabs.tsx Tab bar for multiple terminal sessions
app/src-tauri/src/docker/container.rs Container creation, mounts, env vars, inspection
app/src-tauri/src/docker/exec.rs PTY exec sessions for terminal interaction
app/src-tauri/src/docker/image.rs Image building/pulling
app/src-tauri/src/commands/project_commands.rs Start/stop/rebuild Tauri command handlers
app/src-tauri/src/models/project.rs Project struct (auth mode, Docker access, etc.)
app/src-tauri/src/models/app_settings.rs Global settings (image source, Docker socket, AWS)
container/Dockerfile Ubuntu 24.04 sandbox image with Claude Code + dev tools
container/entrypoint.sh UID/GID remap, SSH setup, Docker group config

CSS / Styling Notes

  • Uses Tailwind CSS v4 with the Vite plugin (@tailwindcss/vite)
  • All colors use CSS custom properties defined in index.css :root
  • color-scheme: dark is set on :root so native form controls (select dropdowns, scrollbars) render in dark mode
  • Do not add a global * { padding: 0 } reset — Tailwind v4 uses CSS @layer, and unlayered CSS overrides all layered utilities. Tailwind's built-in Preflight handles resets.

Container Image

Base: Ubuntu 24.04

Pre-installed tools: Claude Code, Node.js 22 LTS + pnpm, Python 3.12 + uv + ruff, Rust (stable), Docker CLI, git + gh, AWS CLI v2, ripgrep, openssh-client, build-essential

Default user: claude (UID/GID 1000, remapped by entrypoint to match host)

Description
No description provided
Readme MIT 1.6 MiB
2026-03-06 16:43:28 +00:00
Languages
TypeScript 50%
Rust 39.3%
Shell 8.3%
Dockerfile 1.8%
CSS 0.3%
Other 0.2%