Initial commit: Triple-C app, container, and CI

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>
This commit is contained in:
2026-02-27 04:29:51 +00:00
commit 97a0745ead
65 changed files with 17202 additions and 0 deletions

2
app/src/lib/constants.ts Normal file
View File

@@ -0,0 +1,2 @@
export const APP_NAME = "Triple-C";
export const IMAGE_NAME = "triple-c:latest";

View File

@@ -0,0 +1,42 @@
import { invoke } from "@tauri-apps/api/core";
import type { Project, ContainerInfo, SiblingContainer } from "./types";
// Docker
export const checkDocker = () => invoke<boolean>("check_docker");
export const checkImageExists = () => invoke<boolean>("check_image_exists");
export const buildImage = () => invoke<void>("build_image");
export const getContainerInfo = (projectId: string) =>
invoke<ContainerInfo | null>("get_container_info", { projectId });
export const listSiblingContainers = () =>
invoke<SiblingContainer[]>("list_sibling_containers");
// Projects
export const listProjects = () => invoke<Project[]>("list_projects");
export const addProject = (name: string, path: string) =>
invoke<Project>("add_project", { name, path });
export const removeProject = (projectId: string) =>
invoke<void>("remove_project", { projectId });
export const updateProject = (project: Project) =>
invoke<Project>("update_project", { project });
export const startProjectContainer = (projectId: string) =>
invoke<Project>("start_project_container", { projectId });
export const stopProjectContainer = (projectId: string) =>
invoke<void>("stop_project_container", { projectId });
export const rebuildProjectContainer = (projectId: string) =>
invoke<Project>("rebuild_project_container", { projectId });
// Settings
export const setApiKey = (key: string) =>
invoke<void>("set_api_key", { key });
export const hasApiKey = () => invoke<boolean>("has_api_key");
export const deleteApiKey = () => invoke<void>("delete_api_key");
// Terminal
export const openTerminalSession = (projectId: string, sessionId: string) =>
invoke<void>("open_terminal_session", { projectId, sessionId });
export const terminalInput = (sessionId: string, data: number[]) =>
invoke<void>("terminal_input", { sessionId, data });
export const terminalResize = (sessionId: string, cols: number, rows: number) =>
invoke<void>("terminal_resize", { sessionId, cols, rows });
export const closeTerminalSession = (sessionId: string) =>
invoke<void>("close_terminal_session", { sessionId });

45
app/src/lib/types.ts Normal file
View File

@@ -0,0 +1,45 @@
export interface Project {
id: string;
name: string;
path: string;
container_id: string | null;
status: ProjectStatus;
auth_mode: AuthMode;
allow_docker_access: boolean;
ssh_key_path: string | null;
git_token: string | null;
git_user_name: string | null;
git_user_email: string | null;
created_at: string;
updated_at: string;
}
export type ProjectStatus =
| "stopped"
| "starting"
| "running"
| "stopping"
| "error";
export type AuthMode = "login" | "api_key";
export interface ContainerInfo {
container_id: string;
project_id: string;
status: string;
image: string;
}
export interface SiblingContainer {
id: string;
names: string[] | null;
image: string;
state: string;
status: string;
}
export interface TerminalSession {
id: string;
projectId: string;
projectName: string;
}