Compare commits
2 Commits
v0.2.23-ma
...
v0.2.25-ma
| Author | SHA1 | Date | |
|---|---|---|---|
| 57a7cee544 | |||
| 6369f7e0a8 |
@@ -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/terminal/TerminalView.tsx`** — xterm.js integration with WebGL rendering, URL detection for OAuth flow
|
||||||
- **`components/layout/`** — TopBar (tabs + status), Sidebar (project list), StatusBar
|
- **`components/layout/`** — TopBar (tabs + status), Sidebar (project list), StatusBar
|
||||||
- **`components/projects/`** — ProjectCard, ProjectList, AddProjectDialog
|
- **`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/`)
|
### 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)
|
- `container.rs` — Container lifecycle (create, start, stop, remove, inspect)
|
||||||
- `exec.rs` — PTY exec sessions with bidirectional stdin/stdout streaming
|
- `exec.rs` — PTY exec sessions with bidirectional stdin/stdout streaming
|
||||||
- `image.rs` — Image build/pull with progress 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`
|
- **`storage/`** — Persistence: `projects_store.rs` (JSON file with atomic writes), `secure.rs` (OS keychain via `keyring` crate), `settings_store.rs`
|
||||||
|
|
||||||
### Container (`container/`)
|
### Container (`container/`)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ Triple-C (Claude-Code-Container) is a desktop application that runs Claude Code
|
|||||||
- [Ollama Configuration](#ollama-configuration)
|
- [Ollama Configuration](#ollama-configuration)
|
||||||
- [OpenAI Compatible Configuration](#openai-compatible-configuration)
|
- [OpenAI Compatible Configuration](#openai-compatible-configuration)
|
||||||
- [Settings](#settings)
|
- [Settings](#settings)
|
||||||
|
- [Web Terminal (Remote Access)](#web-terminal-remote-access)
|
||||||
- [Terminal Features](#terminal-features)
|
- [Terminal Features](#terminal-features)
|
||||||
- [Scheduled Tasks (Inside the Container)](#scheduled-tasks-inside-the-container)
|
- [Scheduled Tasks (Inside the Container)](#scheduled-tasks-inside-the-container)
|
||||||
- [What's Inside the Container](#whats-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.
|
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
|
### Updates
|
||||||
|
|
||||||
- **Current Version** — The installed version of Triple-C.
|
- **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
|
## Terminal Features
|
||||||
|
|
||||||
### Multiple Sessions
|
### Multiple Sessions
|
||||||
|
|||||||
21
README.md
21
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.
|
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://<LAN_IP>: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
|
### Docker Socket Path
|
||||||
|
|
||||||
The socket path is OS-aware:
|
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/projects/ContainerProgressModal.tsx` | Real-time container operation progress |
|
||||||
| `app/src/components/mcp/McpPanel.tsx` | MCP server library (global configuration) |
|
| `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/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/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/components/terminal/TerminalTabs.tsx` | Tab bar for multiple terminal sessions (claude + bash) |
|
||||||
| `app/src/hooks/useTerminal.ts` | Terminal session management (claude and bash modes) |
|
| `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/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/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/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) |
|
| `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/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 |
|
| `container/entrypoint.sh` | UID/GID remap, SSH setup, Docker group config, MCP injection, Mission Control setup |
|
||||||
|
|||||||
23
TECHNICAL.md
23
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 │ │
|
│ │ Project Management │◄─┤ ProjectsStore │ │
|
||||||
│ │ Settings UI │ │ bollard Docker Client │ │
|
│ │ Settings UI │ │ bollard Docker Client │ │
|
||||||
│ │ │ │ keyring Credential Mgr │ │
|
│ │ │ │ keyring Credential Mgr │ │
|
||||||
│ └───────────┬───────────┘ └────────────┬─────────────┘ │
|
│ └───────────┬───────────┘ │ Web Terminal Server │ │
|
||||||
|
│ │ └────────────┬─────────────┘ │
|
||||||
│ │ Tauri IPC (invoke/emit) │ │
|
│ │ Tauri IPC (invoke/emit) │ │
|
||||||
│ └───────────┬───────────────┘ │
|
│ └───────────┬───────────────┘ │
|
||||||
|
│ ▲ │
|
||||||
|
│ axum HTTP+WS│(port 7681) │
|
||||||
|
│ │ │
|
||||||
└──────────────────────────┼───────────────────────────────┘
|
└──────────────────────────┼───────────────────────────────┘
|
||||||
│ Docker Socket
|
│ 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.
|
**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:
|
**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.
|
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.
|
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,
|
│ ├── projects/ # ProjectCard, ProjectList, AddProjectDialog,
|
||||||
│ │ # FileManagerModal, ContainerProgressModal, modals
|
│ │ # FileManagerModal, ContainerProgressModal, modals
|
||||||
│ ├── settings/ # SettingsPanel, DockerSettings, AwsSettings,
|
│ ├── settings/ # SettingsPanel, DockerSettings, AwsSettings,
|
||||||
│ │ # UpdateDialog
|
│ │ # WebTerminalSettings, UpdateDialog
|
||||||
│ └── terminal/ # TerminalView (xterm.js), TerminalTabs, UrlToast
|
│ └── terminal/ # TerminalView (xterm.js), TerminalTabs, UrlToast
|
||||||
│
|
│
|
||||||
└── src-tauri/ # Rust backend
|
└── src-tauri/ # Rust backend
|
||||||
@@ -282,7 +288,13 @@ triple-c/
|
|||||||
│ ├── project_commands.rs # Start/stop/rebuild containers
|
│ ├── project_commands.rs # Start/stop/rebuild containers
|
||||||
│ ├── settings_commands.rs # Settings CRUD
|
│ ├── settings_commands.rs # Settings CRUD
|
||||||
│ ├── terminal_commands.rs # Terminal I/O, resize
|
│ ├── 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
|
├── docker/ # Docker API layer
|
||||||
│ ├── client.rs # bollard singleton connection
|
│ ├── client.rs # bollard singleton connection
|
||||||
│ ├── container.rs # Create, start, stop, remove, fingerprinting
|
│ ├── container.rs # Create, start, stop, remove, fingerprinting
|
||||||
@@ -323,6 +335,11 @@ triple-c/
|
|||||||
| `tar` | 0.4 | In-memory tar archives for Docker build context |
|
| `tar` | 0.4 | In-memory tar archives for Docker build context |
|
||||||
| `dirs` | 6.x | Cross-platform app data directory paths |
|
| `dirs` | 6.x | Cross-platform app data directory paths |
|
||||||
| `serde` / `serde_json` | 1.x | Serialization for IPC and persistence |
|
| `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)
|
### JavaScript (Frontend)
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
height: 100dvh; /* dynamic viewport height — shrinks when mobile keyboard opens */
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -46,6 +47,9 @@
|
|||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
min-height: 42px;
|
min-height: 42px;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topbar-title {
|
.topbar-title {
|
||||||
@@ -101,6 +105,9 @@
|
|||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
min-height: 32px;
|
min-height: 32px;
|
||||||
|
position: sticky;
|
||||||
|
top: 42px; /* below .topbar min-height */
|
||||||
|
z-index: 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab {
|
.tab {
|
||||||
|
|||||||
Reference in New Issue
Block a user