diff --git a/CLAUDE.md b/CLAUDE.md index 1190168..8f61b8a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -62,7 +62,7 @@ docker exec stdout → tokio task → emit("terminal-output-{sessionId}") → li - **`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 +- **`components/settings/`** — Settings panels for API keys, Docker, AWS, Web Terminal ### Backend Structure (`app/src-tauri/src/`) @@ -72,7 +72,11 @@ docker exec stdout → tokio task → emit("terminal-output-{sessionId}") → li - `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`, `Backend`, `BedrockConfig`, `OllamaConfig`, `OpenAiCompatibleConfig`, `ContainerInfo`, `AppSettings`). These define the IPC contract with the frontend. +- **`web_terminal/`** — Remote terminal access via axum HTTP+WebSocket server: + - `server.rs` — Axum server lifecycle (start/stop), serves embedded HTML and handles WS upgrades + - `ws_handler.rs` — Per-connection WebSocket handler with JSON protocol, session management, cleanup on disconnect + - `terminal.html` — Self-contained xterm.js web UI embedded via `include_str!()` +- **`models/`** — Serde structs (`Project`, `Backend`, `BedrockConfig`, `OllamaConfig`, `OpenAiCompatibleConfig`, `ContainerInfo`, `AppSettings`, `WebTerminalSettings`). 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/`) diff --git a/HOW-TO-USE.md b/HOW-TO-USE.md index b91d20e..e33ca2e 100644 --- a/HOW-TO-USE.md +++ b/HOW-TO-USE.md @@ -16,6 +16,7 @@ Triple-C (Claude-Code-Container) is a desktop application that runs Claude Code - [Ollama Configuration](#ollama-configuration) - [OpenAI Compatible Configuration](#openai-compatible-configuration) - [Settings](#settings) +- [Web Terminal (Remote Access)](#web-terminal-remote-access) - [Terminal Features](#terminal-features) - [Scheduled Tasks (Inside the Container)](#scheduled-tasks-inside-the-container) - [What's Inside the Container](#whats-inside-the-container) @@ -480,6 +481,17 @@ Instructions applied to **all** projects. Written to `~/.claude/CLAUDE.md` in ev Environment variables applied to **all** project containers. Per-project variables with the same key take precedence. +### Web Terminal + +Enable remote access to your project terminals from any device on the local network (tablets, phones, other computers). + +- **Toggle** — Click ON/OFF to start or stop the web terminal server. +- **URL** — When running, shows the full URL including the access token. Click **Copy URL** to copy it to your clipboard, then open it in a browser on your tablet or phone. +- **Token** — An access token is auto-generated on first enable. Click **Copy** to copy the token, or **Regenerate** to create a new one (this disconnects existing web sessions). +- **Port** — Defaults to 7681. Configurable in `settings.json` if needed. + +The web terminal server auto-starts on app launch if it was previously enabled, and stops when the app closes. + ### Updates - **Current Version** — The installed version of Triple-C. @@ -490,6 +502,43 @@ When an update is available, a pulsing **Update** button appears in the top bar. --- +## Web Terminal (Remote Access) + +The web terminal lets you access your running project terminals from a tablet, phone, or any other device on the local network — no app installation required, just a web browser. + +### Setup + +1. Go to **Settings** in the sidebar. +2. Find the **Web Terminal** section and click the toggle to **ON**. +3. A URL appears (e.g., `http://192.168.1.100:7681?token=...`). Click **Copy URL**. +4. Open the URL in a browser on your tablet or other device. + +### Using the Web Terminal + +The web terminal UI mirrors the desktop app's terminal experience: + +- **Project picker** — Select a running project from the dropdown at the top. +- **Claude / Bash buttons** — Open a new Claude Code or bash session for the selected project. +- **Tab bar** — Switch between multiple open sessions. Click the **x** on a tab to close it. +- **Input bar** — A text input at the bottom optimized for mobile/tablet keyboards. Characters are sent immediately without waiting for autocomplete. Helper buttons for **Enter**, **Tab**, and **^C** (Ctrl+C) are provided for keys that are awkward on virtual keyboards. +- **Scroll to bottom** — A floating arrow button appears when you scroll up, letting you jump back to the latest output. + +### Security + +- Access requires a token in the URL query string. Without the correct token, connections are rejected. +- The token is auto-generated (32 bytes, base64url-encoded) and can be regenerated at any time from Settings. +- The server only listens on port 7681 (configurable) — make sure this port is not exposed to the public internet. +- All sessions opened from a browser tab are automatically cleaned up when the tab is closed or the WebSocket disconnects. + +### Tips + +- **Bookmark the URL** on your tablet for quick access. +- The web terminal works best in landscape orientation on tablets. +- If the connection drops (e.g., Wi-Fi interruption), the web terminal auto-reconnects after 2 seconds. +- Regenerating the token invalidates all existing browser sessions — you'll need to update bookmarks with the new URL. + +--- + ## Terminal Features ### Multiple Sessions diff --git a/README.md b/README.md index fadf97b..5d6c445 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,18 @@ Triple-C supports [Model Context Protocol (MCP)](https://modelcontextprotocol.io Optional per-project integration with [Flight Control](https://github.com/msieurthenardier/mission-control) — an AI-first development methodology. When enabled, the repo is cloned into the container, skills are installed, and workflow instructions are injected into CLAUDE.md. +### Web Terminal (Remote Access) + +Triple-C includes an optional web terminal server for accessing project terminals from tablets, phones, or other devices on the local network. When enabled in Settings, an axum HTTP+WebSocket server starts inside the Tauri process, serving a standalone xterm.js-based terminal UI. + +- **URL**: `http://:7681?token=...` (port configurable) +- **Authentication**: Token-based (auto-generated, copyable from Settings) +- **Protocol**: JSON over WebSocket with base64-encoded terminal data +- **Features**: Project picker, multiple tabs (Claude + bash sessions), mobile-optimized input bar, scroll-to-bottom button +- **Session cleanup**: All terminal sessions are closed when the browser disconnects + +The web terminal shares the existing `ExecSessionManager` via `Arc`-wrapped stores — same Docker exec sessions, different transport (WebSocket instead of Tauri IPC events). + ### Docker Socket Path The socket path is OS-aware: @@ -108,7 +120,8 @@ Users can override this in Settings via the global `docker_socket_path` option. | `app/src/components/projects/ContainerProgressModal.tsx` | Real-time container operation progress | | `app/src/components/mcp/McpPanel.tsx` | MCP server library (global configuration) | | `app/src/components/mcp/McpServerCard.tsx` | Individual MCP server configuration card | -| `app/src/components/settings/SettingsPanel.tsx` | Docker, AWS, timezone, and global settings | +| `app/src/components/settings/SettingsPanel.tsx` | Docker, AWS, timezone, web terminal, and global settings | +| `app/src/components/settings/WebTerminalSettings.tsx` | Web terminal toggle, URL, token management | | `app/src/components/terminal/TerminalView.tsx` | xterm.js terminal with WebGL, URL detection, OSC 52 clipboard, image paste | | `app/src/components/terminal/TerminalTabs.tsx` | Tab bar for multiple terminal sessions (claude + bash) | | `app/src/hooks/useTerminal.ts` | Terminal session management (claude and bash modes) | @@ -124,7 +137,11 @@ Users can override this in Settings via the global `docker_socket_path` option. | `app/src-tauri/src/commands/mcp_commands.rs` | MCP server CRUD Tauri commands | | `app/src-tauri/src/models/project.rs` | Project struct (backend, Docker access, MCP servers, Mission Control) | | `app/src-tauri/src/models/mcp_server.rs` | MCP server struct (transport, Docker image, env vars) | -| `app/src-tauri/src/models/app_settings.rs` | Global settings (image source, Docker socket, AWS, microphone) | +| `app/src-tauri/src/models/app_settings.rs` | Global settings (image source, Docker socket, AWS, web terminal) | +| `app/src-tauri/src/web_terminal/server.rs` | Axum HTTP+WS server for remote terminal access | +| `app/src-tauri/src/web_terminal/ws_handler.rs` | WebSocket connection handler and session management | +| `app/src-tauri/src/web_terminal/terminal.html` | Embedded web UI (xterm.js, project picker, tabs) | +| `app/src-tauri/src/commands/web_terminal_commands.rs` | Web terminal start/stop/status Tauri commands | | `app/src-tauri/src/storage/mcp_store.rs` | MCP server persistence (JSON with atomic writes) | | `container/Dockerfile` | Ubuntu 24.04 sandbox image with Claude Code + dev tools + clipboard/audio shims | | `container/entrypoint.sh` | UID/GID remap, SSH setup, Docker group config, MCP injection, Mission Control setup | diff --git a/TECHNICAL.md b/TECHNICAL.md index a1cca8b..f7a8ab2 100644 --- a/TECHNICAL.md +++ b/TECHNICAL.md @@ -100,9 +100,13 @@ Tauri uses a Rust backend paired with a web-based frontend rendered by the OS-na │ │ Project Management │◄─┤ ProjectsStore │ │ │ │ Settings UI │ │ bollard Docker Client │ │ │ │ │ │ keyring Credential Mgr │ │ -│ └───────────┬───────────┘ └────────────┬─────────────┘ │ +│ └───────────┬───────────┘ │ Web Terminal Server │ │ +│ │ └────────────┬─────────────┘ │ │ │ Tauri IPC (invoke/emit) │ │ │ └───────────┬───────────────┘ │ +│ ▲ │ +│ axum HTTP+WS│(port 7681) │ +│ │ │ └──────────────────────────┼───────────────────────────────┘ │ Docker Socket ▼ @@ -129,6 +133,8 @@ The application uses two IPC mechanisms between the React frontend and Rust back **Request/Response** (`invoke()`): Used for discrete operations — starting containers, saving settings, listing projects. The frontend calls `invoke("command_name", { args })` and awaits a typed result. +**WebSocket Streaming** (Web Terminal): Used for remote terminal access from browsers on the local network. An axum HTTP+WebSocket server runs inside the Tauri process, sharing the same `ExecSessionManager` via `Arc`-wrapped stores. The WebSocket uses a JSON protocol with base64-encoded terminal data. Each browser connection can open multiple terminal sessions; all sessions are cleaned up when the WebSocket disconnects. + **Event Streaming** (`emit()`/`listen()`): Used for continuous data — terminal I/O. When a terminal session is opened, the Rust backend spawns two tokio tasks: 1. **Output reader** — Reads from the Docker exec stdout stream and emits `terminal-output-{sessionId}` events to the frontend. 2. **Input writer** — Listens on an `mpsc::unbounded_channel` for data sent from the frontend via `invoke("terminal_input")` and writes it to the Docker exec stdin. @@ -263,7 +269,7 @@ triple-c/ │ ├── projects/ # ProjectCard, ProjectList, AddProjectDialog, │ │ # FileManagerModal, ContainerProgressModal, modals │ ├── settings/ # SettingsPanel, DockerSettings, AwsSettings, - │ │ # UpdateDialog + │ │ # WebTerminalSettings, UpdateDialog │ └── terminal/ # TerminalView (xterm.js), TerminalTabs, UrlToast │ └── src-tauri/ # Rust backend @@ -282,7 +288,13 @@ triple-c/ │ ├── project_commands.rs # Start/stop/rebuild containers │ ├── settings_commands.rs # Settings CRUD │ ├── terminal_commands.rs # Terminal I/O, resize - │ └── update_commands.rs # App update checking + │ ├── update_commands.rs # App update checking + │ └── web_terminal_commands.rs # Web terminal start/stop/status + ├── web_terminal/ # Remote terminal access + │ ├── mod.rs # Module root + │ ├── server.rs # Axum HTTP+WS server lifecycle + │ ├── ws_handler.rs # WebSocket connection handler + │ └── terminal.html # Embedded xterm.js web UI ├── docker/ # Docker API layer │ ├── client.rs # bollard singleton connection │ ├── container.rs # Create, start, stop, remove, fingerprinting @@ -323,6 +335,11 @@ triple-c/ | `tar` | 0.4 | In-memory tar archives for Docker build context | | `dirs` | 6.x | Cross-platform app data directory paths | | `serde` / `serde_json` | 1.x | Serialization for IPC and persistence | +| `axum` | 0.8 | HTTP+WebSocket server for web terminal | +| `tower-http` | 0.6 | CORS middleware for web terminal | +| `base64` | 0.22 | Terminal data encoding over WebSocket | +| `rand` | 0.9 | Access token generation | +| `local-ip-address` | 0.6 | LAN IP detection for web terminal URL | ### JavaScript (Frontend)