Files
Triple-C/CLAUDE.md
Josh Knapp 4b56610ff5 Add CLAUDE.md and HOW-TO-USE.md documentation
CLAUDE.md provides guidance for Claude Code instances working in this
repo (build commands, architecture overview, key conventions).

HOW-TO-USE.md is a user-facing guide covering prerequisites, setup,
all application features, and troubleshooting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:59:53 -08:00

116 lines
5.6 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
Triple-C (Claude-Code-Container) is a Tauri v2 desktop application that sandboxes Claude Code inside Docker containers. It has two main parts: a React/TypeScript frontend, a Rust backend, and a Docker container image definition.
## Build & Development Commands
All frontend/tauri commands run from the `app/` directory:
```bash
cd app
npm ci # Install dependencies (required first time)
npx tauri dev # Launch app in dev mode with hot reload (Vite on port 1420)
npx tauri build # Production build (outputs to src-tauri/target/release/bundle/)
npm run build # Frontend-only build (tsc + vite)
npm run test # Run Vitest once
npm run test:watch # Run Vitest in watch mode
```
Rust backend is compiled automatically by `tauri dev`/`tauri build`. To check Rust independently:
```bash
cd app/src-tauri
cargo check # Type-check without full build
cargo build # Build Rust backend only
```
Container image:
```bash
docker build -t triple-c-sandbox ./container
```
### Linux Build Dependencies (Ubuntu/Debian)
```bash
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev libsoup-3.0-dev patchelf libssl-dev pkg-config build-essential
```
## Architecture
### Two-Process Model (Tauri IPC)
- **React frontend** (`app/src/`) renders UI in the OS webview
- **Rust backend** (`app/src-tauri/src/`) handles Docker API, credential storage, and terminal I/O
- Communication uses two patterns:
- `invoke()` — request/response for discrete operations (CRUD, start/stop containers)
- `emit()`/`listen()` — event streaming for continuous data (terminal I/O)
### Terminal I/O Flow
```
User keystroke → xterm.js onData() → invoke("terminal_input") → mpsc channel → docker exec stdin
docker exec stdout → tokio task → emit("terminal-output-{sessionId}") → listen() → xterm.js write()
```
### Frontend Structure (`app/src/`)
- **`store/appState.ts`** — Single Zustand store for all app state (projects, sessions, UI)
- **`hooks/`** — All Tauri IPC calls are encapsulated in hooks (`useTerminal`, `useProjects`, `useDocker`, `useSettings`)
- **`lib/tauri-commands.ts`** — Typed `invoke()` wrappers; TypeScript types in `lib/types.ts` must match Rust models
- **`components/terminal/TerminalView.tsx`** — xterm.js integration with WebGL rendering, URL detection for OAuth flow
- **`components/layout/`** — TopBar (tabs + status), Sidebar (project list), StatusBar
- **`components/projects/`** — ProjectCard, ProjectList, AddProjectDialog
- **`components/settings/`** — Settings panels for API keys, Docker, AWS
### Backend Structure (`app/src-tauri/src/`)
- **`commands/`** — Tauri command handlers (docker, project, settings, terminal). These are the IPC entry points called by `invoke()`.
- **`docker/`** — Docker API layer using bollard:
- `client.rs` — Singleton Docker connection via `OnceLock`
- `container.rs` — Container lifecycle (create, start, stop, remove, inspect)
- `exec.rs` — PTY exec sessions with bidirectional stdin/stdout streaming
- `image.rs` — Image build/pull with progress streaming
- **`models/`** — Serde structs (`Project`, `AuthMode`, `BedrockConfig`, `ContainerInfo`, `AppSettings`). These define the IPC contract with the frontend.
- **`storage/`** — Persistence: `projects_store.rs` (JSON file with atomic writes), `secure.rs` (OS keychain via `keyring` crate), `settings_store.rs`
### Container (`container/`)
- **`Dockerfile`** — Ubuntu 24.04 base with Claude Code, Node.js 22, Python 3.12, Rust, Docker CLI, git, gh, AWS CLI v2, ripgrep, pnpm, uv, ruff pre-installed
- **`entrypoint.sh`** — UID/GID remapping to match host user, SSH key setup, git config, docker socket permissions, then `sleep infinity`
- **`triple-c-scheduler`** — Bash-based scheduled task system for recurring Claude Code invocations
### Container Lifecycle
Containers use a **stop/start** model (not create/destroy). Installed packages persist across stops. The `.claude` config dir uses a named Docker volume (`triple-c-claude-config-{projectId}`) so OAuth tokens survive even container resets.
### Authentication
Per-project, independently configured:
- **Anthropic (OAuth)** — `claude login` in terminal, token persists in config volume
- **AWS Bedrock** — Static keys, profile, or bearer token injected as env vars
## Styling
- **Tailwind CSS v4** with the Vite plugin (`@tailwindcss/vite`). No separate tailwind config file.
- All colors use CSS custom properties in `index.css` `:root` (e.g., `--bg-primary`, `--text-secondary`, `--accent`)
- `color-scheme: dark` is set on `:root` for native dark-mode controls
- **Do not** add a global `* { padding: 0 }` reset — Tailwind v4 uses CSS `@layer`, and unlayered CSS overrides all layered utilities
## Key Conventions
- Frontend types in `lib/types.ts` must stay in sync with Rust structs in `models/`
- Tauri commands are registered in `lib.rs` via `.invoke_handler(tauri::generate_handler![...])`
- Tauri v2 permissions are declared in `capabilities/default.json` — new IPC commands need permission grants there
- The `projects.json` file uses atomic writes (write to `.tmp`, then `rename()`). Corrupted files are backed up to `.bak`.
- Cross-platform paths: Docker socket is `/var/run/docker.sock` on Linux/macOS, `//./pipe/docker_engine` on Windows
## Testing
Frontend tests use Vitest with jsdom environment and React Testing Library. Setup file at `src/test/setup.ts`. Run a single test file:
```bash
cd app
npx vitest run src/path/to/test.test.ts
```