Intercept clipboard paste events containing images in the terminal,
upload them into the Docker container via bollard's tar upload API,
and inject the resulting file path into terminal stdin so Claude Code
can reference the image.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace fragile line-by-line reassembly heuristic with a simpler
approach: flatten the buffer by converting blank lines to spaces
(URL terminators) and stripping remaining newlines (PTY wraps),
then match URLs with a single regex on the flat string.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The PTY may deliver a long URL across multiple chunks with enough delay
that the debounce fires between them, emitting a truncated URL. Fixed by:
1. Stripping trailing empty strings from split (artifact of trailing \n)
2. Deferring emission when the URL reaches the end of the buffer — a
confirmation timer (500ms) waits for more data before emitting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PTY hard-wraps long URLs (e.g. OAuth) with \r\n at column width, breaking
xterm.js link detection. This adds a UrlDetector that reassembles wrapped
URLs from the output stream and shows a non-intrusive floating toast with
an "Open" button. Auto-dismisses after 30s, no terminal layout impact.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduces a cron-based scheduler that lets Claude set up recurring and
one-time tasks inside containers. Tasks run as separate Claude Code agents
and persist across container recreation via the named volume.
New files:
- container/triple-c-scheduler: CLI for add/remove/enable/disable/list/logs/run/notifications
- container/triple-c-task-runner: cron wrapper with flock, logging, notifications, auto-cleanup
Key changes:
- Dockerfile: add cron package and COPY both scripts
- entrypoint.sh: timezone setup, cron daemon, crontab restore, env saving
- container.rs: init=true for zombie reaping, TZ env, scheduler instructions, timezone recreation check
- image.rs: embed scheduler scripts in build context
- app_settings.rs + types.ts: timezone field
- settings_commands.rs: detect_host_timezone via iana-time-zone crate
- SettingsPanel.tsx: timezone input with auto-detection
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add per-project port mapping configuration (host:container port pairs with
TCP/UDP protocol) stored in project config and applied as Docker port
bindings at container creation. Port changes trigger automatic container
recreation via fingerprint detection.
- Create PortMappingsModal UI component following the same pattern as
EnvVarsModal, integrated into ProjectCard config panel.
- Inject port mapping details into CLAUDE_INSTRUCTIONS so Claude inside the
container knows which ports are available for testing services.
- Update default global instructions for new installs to encourage use of
subagents for long-running and parallel tasks.
- Replace app icons with new v2 sun logo design for better visibility at
small sizes (taskbar/dock).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
API key auth only provides short-lived session tokens (8hrs or until
session restart) with no refresh mechanism, unlike OAuth which persists
via .credentials.json. Remove the non-functional API key settings UI
and all supporting code (frontend state, Tauri commands, keyring
storage, container env var injection, and fingerprint-based recreation
checks) to avoid user confusion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the three auth modes (Login, API Key, Bedrock) with two
(Anthropic, Bedrock). The Anthropic mode uses OAuth via `claude login`
inside the terminal, which generates and stores its own API key in the
persistent config volume. The separate API Key mode is removed because
Claude Code now requires interactive approval of externally-provided
keys, making the injected ANTHROPIC_API_KEY approach unreliable.
Old projects stored as "login" or "api_key" are automatically migrated
to "anthropic" via serde aliases.
Also fix the Windows taskbar icon showing as a black square by loading
icon.png instead of icon.ico for the runtime window icon.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The container was only recreated when the auth mode changed, not when
the API key value itself changed. This meant saving a new key required
a manual container rebuild. Now we store a hash of the API key as a
Docker label and compare it on start, so a key change automatically
recreates the container (preserving the claude config volume).
Also adds a note to the global AWS settings UI that changes require a
container rebuild.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix Windows taskbar icon by loading icon.ico instead of icon.png (ICO contains
multiple sizes native to Windows taskbar/title bar/alt-tab)
- Add "Container must be stopped to change settings" warning banner in config panel
- Move per-project Environment Variables and Claude Instructions into modal dialogs
for more editing space, with buttons in the config panel to open them
- Move global Claude Instructions into a modal in Settings panel
- Add default global Claude instruction recommending git initialization
- Add global environment variables support (full stack: Rust model, TS types,
container creation with merge logic where project overrides global for same key,
fingerprinting for recreation checks, and Settings UI with modal)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous approach used Builder::default_window_icon() which doesn't
exist in Tauri 2.10. Instead, set the icon via window.set_icon() in the
setup hook, and enable the "image-png" feature flag so Image::from_bytes
can decode the PNG icon at runtime.
Also change bundle identifier from "com.triple-c.app" to
"com.triple-c.desktop" to avoid conflicting with the .app bundle
extension on macOS.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The sidebar config panel content was overflowing its container width,
causing project names and directory paths to be clipped. Added min-w-0
and overflow-hidden to flex containers, and restructured folder path
config rows to stack vertically instead of cramming into one line.
The Windows taskbar was showing a black square because no default window
icon was set at runtime. Added default_window_icon() call in the Tauri
builder using the app's icon.png.
Also adds vitest test infrastructure with tests verifying both fixes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace placeholder icons with the Triple-C branded logo at all required
Tauri sizes. Remove the host_path display from sidebar folder listings to
prevent text overflow. Remove the URL accumulator that injected clickable
login URL text into the terminal — the native WebLinksAddon still handles
URLs when the window is wide enough. Add explicit logging on container
removal confirming named volumes are preserved.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Only the active terminal holds a WebGL rendering context now. When
switching tabs the outgoing terminal disposes its WebGL addon (freeing
the GPU context) and the incoming terminal creates a fresh one. This
avoids exhausting the browser's limited WebGL context pool (~8-16) which
caused expensive context loss/restoration lag when switching.
Also skip ResizeObserver callbacks for hidden terminals (zero dimensions)
to avoid unnecessary fit/resize work on inactive tabs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Feature 1 - Update Detection: Query Gitea releases API on startup (3s
delay) and every 24h, compare patch versions by platform, show pulsing
"Update" button in TopBar with dialog for release notes/downloads.
Settings: auto-check toggle, manual check, dismiss per-version.
Feature 2 - Multi-Folder Projects: Replace single `path` with
`paths: Vec<ProjectPath>` (host_path + mount_name). Each folder mounts
to `/workspace/{mount_name}`. Auto-migrate old single-path JSON on load.
Container recreation via paths-fingerprint label. AddProjectDialog and
ProjectCard support add/remove/edit of multiple folders.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix Windows CI build to use npm ci instead of deleting lockfile and
running npm install, ensuring reproducible cross-platform builds
- Remove duplicate uv/ruff root installations from Dockerfile (only
need the claude user installations)
- Make AWS CLI install architecture-aware using uname -m for arm64
compatibility
- Remove unused SiblingContainers component (dead code)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Debounce project config saves: use local state + save-on-blur instead
of firing IPC requests on every keystroke in text inputs
- Add Zustand selectors to all store consumers to prevent full-store
re-renders on any state change
- Fix initialization race: chain checkImage after checkDocker resolves
- Fix DockerSettings setTimeout race: await checkImage after save
- Add console.error logging to all 11 empty catch blocks in ProjectCard
- Add keyboard support to AddProjectDialog: Escape to close,
click-outside-to-close, form submit on Enter, auto-focus
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix broken URL accumulator by using TextDecoder instead of raw
Uint8Array concatenation that produced numeric strings
- Fix event listener memory leak by using aborted flag pattern to
ensure cleanup runs even if listen() promises haven't resolved
- Throttle ResizeObserver with requestAnimationFrame to prevent
hammering the backend during window resize
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Support per-project environment variables injected into containers,
plus global and per-project Claude Code instructions written to
~/.claude/CLAUDE.md inside the container on start. Reserved env var
prefixes are blocked, and changes trigger automatic container recreation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove global * { padding: 0 } reset that was overriding all Tailwind
padding classes (unlayered CSS beats Tailwind v4 @layer utilities)
- Add color-scheme: dark to fix native form controls (select dropdowns)
rendering with white backgrounds
- Make sidebar responsive (25% width, min 224px, max 320px)
- Increase internal padding on TopBar, Sidebar, ProjectList, StatusBar
- Add flex-shrink-0 to TopBar status indicators to prevent clipping
- Allow project action buttons to wrap on narrow sidebars
- Increase terminal view padding for breathing room
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Support pulling images from registry (default: repo.anhonesthost.net/cybercovellc/triple-c/triple-c-sandbox:latest),
local builds, or custom images via a new settings UI. Add global AWS configuration
(config path auto-detect, profile picker, region) that serves as defaults overridable
per-project for Bedrock auth.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduces a third auth mode alongside Login and API Key, allowing
projects to authenticate Claude Code via AWS Bedrock. Includes support
for static credentials, profile-based, and bearer-token auth methods
with full UI controls. Also adds a URL accumulator to the terminal to
reassemble long OAuth URLs split across hard newlines, and installs
the AWS CLI v2 in the container image.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tauri v2 desktop app (React/TypeScript + Rust) for managing
containerized Claude Code environments. Includes Gitea Actions
workflow for building and pushing the sandbox container image,
and a BUILDING.md guide for manual app builds on Linux and Windows.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>