TRENDSHIFT · 2026.06.15

desktop-cc-gui (ccgui) 딥다이브
— 터미널 AI 코딩 CLI를 데스크톱 앱으로 감싼 멀티엔진 클라이언트의 설계

ccguiClaude Code · Codex CLI · Gemini · OpenCode 같은 터미널용 AI 코딩 도구를 데스크톱 GUI로 감싸, 검은 콘솔 대신 친근한 화면에서 AI와 대화하며 코드를 쓰고·고치고·커밋하게 해 주는 오픈소스 데스크톱 클라이언트다. AI가 어떤 파일을 건드렸는지, 어떤 명령을 실행했는지, 비용이 얼마인지를 실시간 카드로 한눈에 보여 준다. Tauri 2 + React 19 + TypeScript + Rust로 만들어져 macOS·Windows·Linux에서 돌아가며, 모든 데이터는 사용자 컴퓨터에만 남는다. (저장소: zhukunpenglinyutong/desktop-cc-gui · 패키지명 ccgui v0.5.9 · Tauri 데스크톱 · CodexMonitor에서 파생)

이 문서는 "CLI 도구를 GUI로 감싸는 데스크톱 앱의 아키텍처에서 무엇을 배울 수 있는가"에 초점을 둔 해설이다. README를 베끼지 않고 package.json·Cargo.toml·Rust 엔진 소스까지 분석했다.
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 시스템 / 환경 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

이 레포가 무엇을 하는 물건인가.

핵심 메시지

"터미널에서 한 줄씩 쳐야 했던 AI 코딩 CLI를,
VS Code 같은 데스크톱 앱 안으로 통째로 옮긴 것."

Claude Code는 본래 터미널에서 claude를 실행해 텍스트로 대화하는 도구다. 강력하지만, 검은 화면에서 스크롤하며 "AI가 방금 어떤 파일을 고쳤지?", "이번 답에 토큰을 얼마나 썼지?"를 추적하기는 불편하다. ccgui는 이 CLI를 백그라운드에서 대신 실행하고, 그 출력 스트림을 파싱해 파일 편집·셸 명령·읽기 동작을 시각적 카드로 그려 준다.

핵심은 "또 하나의 챗봇"이 아니라는 점이다. ccgui는 여러 CLI 엔진을 추상화한 어댑터 계층(engine)을 두고, Claude Code·Codex·Gemini·OpenCode를 같은 UI로 다룬다. 즉 "AI 코딩 CLI들을 위한 통합 IDE 셸"이다.

ccgui데스크톱 AI 코딩 클라이언트다. 프로젝트 폴더를 열고 채팅으로 작업을 지시하면, 내부의 Rust 백엔드가 적절한 CLI(claude -p 등)를 자식 프로세스로 띄우고 stream-json 형식의 출력을 실시간 파싱해 화면에 흘려 보낸다. 파일 트리·내장 터미널·Git 패널·전역 검색은 물론, 프로젝트 맵(지식 그래프)·프로젝트 메모리·컨텍스트 원장(ledger)·사용량 통계·칸반·인텐트 캔버스까지 갖춘 풀 IDE급 데스크톱 앱이다. CodexMonitor라는 작은 프로젝트에서 출발해 멀티엔진 클라이언트로 성장했다.

용어
CLI 래퍼 (CLI wrapper)
이미 존재하는 명령줄 프로그램(CLI)을 직접 다시 구현하지 않고, 자식 프로세스로 실행한 뒤 그 입력/출력을 가로채 GUI나 다른 인터페이스를 입히는 방식. ccgui는 Claude Code를 재구현하지 않고 그대로 실행하므로, CLI가 업데이트되면 그 기능을 거의 공짜로 따라간다.
용어
stream-json
Claude Code CLI가 지원하는 출력 형식. 답변을 한 번에 주지 않고 줄 단위 JSON 이벤트(NDJSON)로 흘려 보낸다("텍스트 조각이 왔다", "도구를 호출했다", "토큰을 N개 썼다" 등). ccgui 백엔드는 이 스트림을 파싱해 실시간 카드로 변환한다. CLI를 GUI로 감싸는 핵심 통로다.

2왜 주목받는가

트렌딩 이유 · Claude Code 단독·웹 챗봇 대비 장점.

AI 코딩 CLI(Claude Code·Codex 등)는 강력하지만 터미널 UX의 한계가 있다. 긴 출력은 스크롤로 사라지고, 어떤 파일이 바뀌었는지·비용이 얼마인지 추적이 어렵고, 여러 세션·여러 엔진을 오가기가 번거롭다. ccgui가 빠르게 스타를 모으는 이유는 이 "터미널에서 진짜 불편한 부분"을 데스크톱 앱으로 정면 돌파했기 때문이다. 첫째 하나의 앱에서 여러 엔진을 전환·혼합, 둘째 모든 동작이 시각적 카드로 투명하게, 셋째 세션·비용·컨텍스트의 영속화, 넷째 프로젝트 맵·메모리 같은 "프로젝트 지능"이다.

비교 항목Claude Code 단독 (터미널)웹 챗봇 (ChatGPT 등)ccgui
실행 위치로컬 터미널브라우저(원격)로컬 데스크톱 앱(데이터 로컬)
엔진Claude 고정해당 서비스 고정Claude·Codex·Gemini·OpenCode 전환·혼합
동작 가시성텍스트 스크롤코드 블록 복붙파일편집·셸·읽기를 실시간 카드로
세션종료 시 추적 어려움웹 히스토리재시작해도 복원·재개(로컬 SQLite)
비용/토큰직접 계산불투명토큰·비용·캐시율 리포트 + 월 예산 상한
주변 도구외부 터미널·에디터없음파일트리·터미널·Git·검색·칸반 내장
기존 방식의 한계
"터미널 단독"의 함정 — 가시성·영속성·멀티엔진의 부재

터미널에서 AI 코딩 CLI를 돌리면, AI가 수십 개 파일을 고쳐도 결과가 텍스트 로그로 흘러가 무엇이 바뀌었는지 한눈에 안 보인다. 세션을 닫으면 맥락이 날아가기 쉽고, 비용은 직접 머릿속으로 더해야 한다. 게다가 엔진마다 명령어·옵션·출력 포맷이 달라 여러 도구를 오가려면 그때마다 새로 배워야 한다.

ccgui의 해결
"엔진을 어댑터로 추상화 + 스트림을 카드로 시각화"

ccgui는 각 CLI를 engine 어댑터(claude.rs·codex_adapter.rs·gemini.rs·opencode.rs)로 감싸 하나의 통일된 인터페이스로 노출한다. CLI를 자식 프로세스로 띄우고 stream-json 출력을 파싱해 프론트엔드 카드 이벤트로 변환한다. 세션·사용량은 로컬 SQLite에 영속화하고, 프로젝트 맵·메모리로 코드베이스 이해까지 더한다. "여러 CLI를 위한 단일 IDE 셸"이 설계 철학이다.

3기술 스택 전체 지도

백엔드(Rust/Tauri)·프론트엔드(React)·인프라 각각.

용어
Tauri
데스크톱 앱을 만드는 프레임워크. UI는 OS에 내장된 웹뷰(WebView)로 렌더링하고(HTML/JS), 무거운 로직은 Rust 백엔드가 처리한다. Electron과 달리 Chromium을 통째로 번들하지 않아 앱 용량이 작고 메모리가 가볍다. 프론트엔드는 invoke()로 Rust 함수(command)를 호출하고, Rust는 emit()으로 이벤트를 프론트로 흘려 보낸다.

① 백엔드 — Rust + Tauri 2 (src-tauri/)

ccgui의 진짜 엔진은 Rust다. CLI 프로세스 관리, 파일·Git·터미널·SQLite 접근, 코드 분석 등 OS와 부딪치는 모든 일을 Rust가 맡고, 프론트엔드는 #[tauri::command]로 노출된 함수를 호출한다(소스 전반에 44개 파일에 걸쳐 명령이 흩어져 있다).

요소역할
Tauri 2 (protocol-asset, macos-private-api)데스크톱 셸·IPC·창 관리·자동 업데이트.
tokio비동기 런타임. 자식 프로세스(process)·파일·네트워크·타이머를 async로.
portable-pty내장 터미널의 핵심. 진짜 의사 터미널(PTY)을 띄워 셸을 구동(terminal.rs).
git2 (libgit2)Git 패널 — 스테이징·커밋·브랜치·워크트리·diff·히스토리.
rusqlite (bundled)로컬 SQLite — 세션·노트카드·메모리·사용량을 영속화.
reqwest (rustls)HTTP 클라이언트 — 프로바이더 호출·업데이트 체크·스트리밍.
axum (ws)내부 웹 서비스·원격 백엔드 브리지(WebSocket 포함).
ignore / regex코드 인텔리전스(code_intel.rs)·프로젝트 맵 — 파일 워킹·심볼 추출.
whisper-rs + cpal (비-윈도우)음성 받아쓰기(dictation) — 로컬 음성→텍스트.
lettre / imap / mailparse메일 기능(SMTP 송신·IMAP 수신·파싱).
objc2-* (macOS) / windows-sys (Win)OS별 네이티브 통합(투명창·메뉴·외형 등).

② 프론트엔드 — React 19 + TypeScript (src/)

UI는 60개 이상의 기능(feature) 폴더로 모듈화돼 있다(git·terminal·project-map·kanban·context-ledger 등). 화면 자체는 웹 기술이지만, @tauri-apps/apiinvoke로 Rust 명령을 호출하고 이벤트를 구독한다.

요소역할
React 19 + TypeScript 5.8UI 컴포넌트·상태. 타입 정의가 방대(src/types.ts 약 55KB).
Tailwind CSS 4 + radix-ui + antd 6스타일·디자인 시스템·컴포넌트(VS Code풍 15+ 테마).
@xterm/xterm브라우저 안의 진짜 터미널 화면(백엔드 PTY와 연결).
@uiw/react-codemirror + CodeMirror 6 언어팩코드 편집/미리보기(JS·Python·Rust·HTML·YAML 등 다국어 하이라이트).
@excalidraw/excalidraw인텐트 캔버스 — 코드 짜기 전 손그림 기획.
mermaid · react-markdown + remark/rehypeAI 답변의 다이어그램·마크다운·수식(KaTeX) 렌더링.
@tanstack/react-virtual긴 메시지/세션 목록 가상 스크롤(성능).
framer-motion · @hello-pangea/dnd애니메이션·드래그앤드롭(칸반 카드 등).
i18next + react-i18next영어/중국어 이중 언어 UI.
dompurify · pdfjs-dist · mammoth · xlsxHTML 정화·PDF/Word/Excel 첨부 미리보기.

③ 인프라 · 빌드 · 품질 게이트

요소역할
Vite 7프론트엔드 번들러/개발 서버. vite build 후 Tauri가 패키징.
npm 강제preinstall 스크립트로 pnpm/yarn 차단 — 모두 동일한 의존성 버전을 쓰게.
크로스 플랫폼 빌드build-platform.mjs — mac(arm64/x64/universal)·win-x64·linux(x64/arm64) 산출.
doctor / doctor:strict빌드 전 환경·런타임 계약·브랜딩 검증(tauri:build가 먼저 호출).
check:* 게이트 다수"런타임 계약"·번들 청킹·라지파일·이벤트 스키마 등 수십 개 자동 검사 스크립트.
Vitest + Testing Library + jsdom프론트 테스트. Rust 쪽은 cargo test(계약 테스트 다수).
자동 업데이트tauri-plugin-updater — 인앱 업데이트.
Nix (flake.nix)재현 가능한 개발 환경(선택).
용어
런타임 계약 (runtime contract)
코드의 특정 구조/규칙을 빌드 시점에 스크립트로 강제 검증하는 것(check:app-shell:runtime-contract 등). 예: "이 이벤트는 반드시 이 스키마를 따라야 한다", "이 거대 파일은 분할돼야 한다". 사람의 리뷰만 믿지 않고 규약을 코드로 못 박는 대형 프로젝트의 품질 관리 기법이다.

4아키텍처 심화 분석

웹뷰(React) ↔ IPC ↔ Rust ↔ CLI 자식 프로세스, 그리고 멀티엔진 어댑터.

ccgui의 심장은 "프론트엔드(웹뷰)와 백엔드(Rust)가 IPC로 대화하고, 백엔드가 CLI를 자식 프로세스로 띄워 그 스트림을 다시 프론트로 중계"하는 흐름이다. 전체 구조를 그림으로 보면 다음과 같다.

┌──────────────────────────────────────────────────────────────┐ │ 데스크톱 창 (Tauri WebView) │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ 프론트엔드 : React 19 + TypeScript (src/) │ │ │ │ 채팅 · 파일트리 · Git패널 · 터미널(xterm) · 칸반 ... │ │ │ │ 60+ feature 모듈 / CodeMirror / Excalidraw / mermaid │ │ │ └───────────▲───────────────────────────────┬──────────────┘ │ │ │ emit(event) (이벤트 수신) │ invoke(cmd) │ │ ───────────┼───── Tauri IPC 경계 ───────────┼─────────────── │ │ │ ▼ │ │ ┌───────────┴─────────────────────────────────────────────┐ │ │ │ 백엔드 : Rust + Tauri 2 (src-tauri/) │ │ │ │ command_registry → #[tauri::command] 핸들러들 │ │ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ │ │ engine/ : 멀티엔진 어댑터 계층 │ │ │ │ │ │ EngineType = Claude | Codex | Gemini | OpenCode │ │ │ │ │ │ manager(EngineManager) → 엔진 선택/라우팅 │ │ │ │ │ └──────┬──────────┬──────────┬──────────┬────────────┘ │ │ │ │ storage git2 portable rusqlite code_intel │ │ │ │ (SQLite) (Git) _pty(PTY) (세션DB) project_map │ │ │ └─────────┼──────────┼─────────────────────────────────────┘ │ └────────────┼──────────┼────────────────────────────────────────┘ │ spawn │ spawn (셸) ▼ ▼ ┌──────────────────┐ ┌─────────────┐ │ claude (CLI) │ │ 사용자 셸 │ │ claude -p \ │ │ (bash/zsh/ │ │ --input-format │ │ pwsh ...) │ │ stream-json \ │ └─────────────┘ │ --output-format │ │ stream-json \ │ stdout: 줄단위 JSON 이벤트(NDJSON) │ --verbose │ ──────────────────────────────► └──────────────────┘ 파싱 → 도메인 이벤트 → emit → 카드

핵심 설계 패턴 ① — 멀티엔진 어댑터 (Adapter Pattern)

가장 중요한 추상화는 src-tauri/src/engine/다. 서로 다른 CLI(Claude·Codex·Gemini·OpenCode)는 명령어 인자도, 출력 포맷도 다르다. ccgui는 이를 공통 EngineType 열거형 + 엔진별 어댑터 모듈로 통일한다. 프론트엔드는 "어떤 엔진인지"를 신경 쓰지 않고 같은 명령을 호출하면, EngineManager가 알맞은 어댑터로 라우팅한다.

// src-tauri/src/engine/mod.rs  (발췌·요약)
pub enum EngineType {
    Claude,    // "Claude Code"  — 기본값
    Codex,     // "Codex"
    Gemini,    // "Gemini"
    OpenCode,  // "OpenCode"
}
// 각 엔진은 별도 어댑터 파일로:
//   claude.rs / codex_adapter.rs / gemini.rs / opencode.rs
// 기본 엔진은 Claude Code (impl Default for EngineType)

이 패턴 덕에 새 엔진 추가 = 새 어댑터 파일 작성이고, UI와 나머지 백엔드는 거의 손대지 않는다. capability_matrix.rs 같은 보조 모듈로 "이 엔진이 어떤 기능을 지원하는가"를 표로 관리해, UI가 엔진에 맞춰 버튼을 켜고 끈다.

핵심 설계 패턴 ② — CLI를 stream-json으로 구동 (Process + Stream)

Claude 어댑터(claude.rs, 약 87KB)는 CLI를 단순히 "텍스트로 실행"하지 않는다. 입력도 출력도 stream-json으로 묶어, 프롬프트 텍스트를 셸이 해석할 위험을 없애고 출력을 구조화된 이벤트로 받는다.

// src-tauri/src/engine/claude.rs  (인자 구성 발췌)
cmd.arg("-p");                       // print(비대화) 모드
cmd.arg("--input-format");  cmd.arg("stream-json");  // 입력도 JSON
cmd.arg("--output-format"); cmd.arg("stream-json");  // 출력도 JSON
cmd.arg("--verbose");                 // 더 많은 이벤트
// 실제 프롬프트 본문은 인자가 아니라 stdin(stream-json)으로 주입
// → 셸 래퍼가 프롬프트를 절대 파싱하지 않는다(안전)
비유

CLI를 인자로 실행하는 것은 식당에서 주문을 큰 소리로 외치는 것과 같다 — 옆 테이블(셸)이 잘못 알아들을 수 있다. ccgui는 대신 주문서를 손으로 적어 주방에 직접 건네고(stdin), 주방은 요리를 한 접시씩 컨베이어(stream-json)로 내보낸다. 손님은 접시가 나올 때마다 바로바로 받아 본다(실시간 카드).

백엔드는 이 NDJSON 줄들을 파싱해 도메인 이벤트(텍스트 델타·도구 호출·토큰 사용량 등)로 정규화한 뒤 emit으로 프론트에 보낸다. 그래서 화면에 "파일 편집 카드", "셸 명령 카드", "비용 표시"가 실시간으로 뜬다. 시작 시 일정 시간 내 유효한 스트림 이벤트가 안 오면 타임아웃 진단을 띄우는 등, 실패 경로까지 촘촘히 다뤄져 있다.

핵심 설계 패턴 ③ — 로컬 영속성 + 프로젝트 지능

ccgui는 클라우드 없이 모든 상태를 로컬에 둔다. storage.rs·rusqlite로 세션·노트카드·메모리·사용량을 SQLite에 저장하고, session_management*.rs(여러 파일로 분할)가 세션 카탈로그·폴더·아카이브·되감기(rewind)/포크를 담당한다. 여기에 프로젝트 맵(project_map*.rs — 파일 관계·API 계약·모듈 의존성 그래프)과 프로젝트 메모리(project_memory/), 코드 인텔리전스(code_intel.rs — 심볼·정의 탐색)를 더해 "AI가 이 코드베이스를 안다"는 느낌을 만든다.

용어
컨텍스트 원장 (Context Ledger)
AI에게 보낸 답변마다 어떤 컨텍스트 소스(파일·메모리·규칙 등)가 얼마나 들어갔는지를 회계 장부처럼 기록·표시하는 기능. 토큰은 곧 비용이므로, 무엇이 컨텍스트를 잡아먹는지 보이게 만들어 사용자가 비용을 통제하도록 돕는다. 컨텍스트 예산(cost budget) 게이트와 짝을 이룬다.

5디렉토리 구조 해부

"프론트(src) ↔ 백엔드(src-tauri) ↔ 규칙/스펙 문서"의 3층.

desktop-cc-gui/ ├─ src/ 프론트엔드 (React 19 + TS) │ ├─ app-shell.tsx 메인 앱 셸(약 72KB) — 전체 레이아웃 골격 │ ├─ router.tsx / main.tsx 라우팅·진입점 │ ├─ types.ts 방대한 공유 타입(약 55KB) │ ├─ features/ 60+ 기능 모듈(아래) │ │ ├─ engine/ codex/ opencode/ 엔진별 UI │ │ ├─ git/ git-history/ terminal/ files/ │ │ ├─ project-map/ project-memory/ context-ledger/ │ │ ├─ kanban/ plan/ tasks/ intent-canvas/ │ │ ├─ skills/ commands/ composer/ search/ │ │ └─ theme/ settings/ update/ ... │ ├─ services/ 프론트 서비스(invoke 래퍼 등) │ ├─ i18n/ 영어/중국어 번역 │ └─ styles/ Tailwind·테마 CSS │ ├─ src-tauri/ 백엔드 (Rust + Tauri 2) │ ├─ src/ │ │ ├─ lib.rs 앱 부팅·플러그인·invoke_handler 등록 │ │ ├─ command_registry.rs 모든 #[tauri::command] 집결 │ │ ├─ engine/ ★ 멀티엔진 어댑터 계층 │ │ │ ├─ mod.rs / manager.rs EngineType·라우팅 │ │ │ ├─ claude.rs (~87KB) Claude Code 구동 │ │ │ ├─ codex_adapter.rs / gemini.rs / opencode.rs │ │ │ ├─ events.rs 스트림→도메인 이벤트 │ │ │ └─ claude_history*.rs 히스토리·되감기·포크 │ │ ├─ session_management*.rs 세션 카탈로그(여러 파일 분할) │ │ ├─ terminal.rs portable-pty 내장 터미널 │ │ ├─ git/ git_utils.rs git2 기반 Git 패널 │ │ ├─ storage.rs local_usage.rs SQLite 영속·사용량 │ │ ├─ code_intel.rs project_map*.rs 코드 분석·지식그래프 │ │ ├─ project_memory/ note_cards.rs 메모리·노트 │ │ ├─ dictation/ computer_use/ browser_agent/ email/ │ │ └─ menu.rs window.rs state.rs ... │ ├─ Cargo.toml Rust 의존성 │ ├─ capabilities/ Tauri 권한(capability) 설정 │ └─ tauri.conf.json (+ .windows/.linux) 앱 설정·번들 │ ├─ scripts/ 빌드·doctor·각종 check:* 게이트 ├─ docs/ openspec/ .trellis/ AGENTS.md 아키텍처·규칙·스펙 ├─ vendor/ 로컬 벤더 의존성(xmlchars 등) ├─ package.json 프론트 의존성·수십 개 npm 스크립트 ├─ flake.nix Nix 개발환경 └─ icon.png CHANGELOG.md(252KB!) README(.md / .zh-CN.md)

주목할 점: 같은 관심사를 여러 파일로 잘게 쪼갠다. 예를 들어 세션 관리는 session_management.rs(108KB) 한 덩어리가 아니라 _types·_catalog_projection·_folder_counts·각종 _tests로 분리돼 있다. check:large-files 게이트가 거대 파일을 감시하기 때문이다. 또 .trellis/·openspec/·AGENTS.md처럼 "AI 에이전트가 이 레포에서 일할 때의 규칙"을 문서로 명시한 점이 특징이다(이 앱 자체가 AI 코딩 도구로 개발됨).

6학습 포인트 (기술별)

이 레포를 뜯어보며 배울 수 있는 것 + 실습 아이디어.

① Tauri 2 — "웹 UI + Rust 백엔드" 데스크톱 앱

배울 것: invoke(프론트→Rust)와 emit(Rust→프론트)으로 양방향 통신하는 법, #[tauri::command]로 함수를 노출하는 법, capabilities/로 권한을 좁히는 법, 플랫폼별 설정(tauri.windows.conf.json)과 자동 업데이트.

실습 아이디어: 작은 Tauri 앱을 만들어 버튼을 누르면 Rust가 시스템 정보를 모아 emit으로 흘려 보내 화면에 실시간 표시해 보기.

② CLI를 자식 프로세스로 구동하고 스트림 파싱

배울 것: tokio::process로 외부 프로그램을 띄우고, stdout을 줄 단위(NDJSON)로 읽어 구조화 이벤트로 바꾸는 패턴. 인자 대신 stdin으로 데이터를 넣어 셸 인젝션을 피하는 보안 감각. 시작 타임아웃·조기 종료 같은 실패 경로 처리.

실습 아이디어: claude -p --output-format stream-json --verbose "안녕"을 직접 터미널에서 실행해, 어떤 JSON 이벤트들이 줄줄이 나오는지 관찰하기(ccgui가 무엇을 파싱하는지 체감).

③ 어댑터 패턴으로 이종 도구 통일하기

배울 것: 공통 인터페이스(EngineType + 매니저)를 두고 도구별 차이를 어댑터로 격리하는 설계. "능력 행렬(capability matrix)"로 기능 차이를 데이터화해 UI를 조건부로 그리는 기법.

실습 아이디어: 두 개의 가짜 CLI(서로 다른 출력 포맷)를 공통 인터페이스로 감싸는 미니 어댑터 계층을 직접 설계해 보기.

④ 로컬 우선(local-first) 영속성 — SQLite

배울 것: 클라우드 없이 rusqlite로 세션·메모리·사용량을 저장하고, 앱 재시작 후에도 복원하는 설계. 되감기(rewind)·포크처럼 "대화의 시간여행"을 데이터 모델로 표현하는 법.

실습 아이디어: 채팅 기록을 SQLite에 저장하고, 특정 메시지로 되감아 그 이후를 새 분기로 만드는 미니 데이터 모델 설계.

⑤ 대형 프론트엔드의 모듈화 + 품질 게이트

배울 것: 기능별 폴더(feature-based) 구조, 거대 파일 분할, 그리고 check:*처럼 규약을 빌드 시 강제하는 스크립트로 코드 품질을 자동 관리하는 문화. 가상 스크롤(react-virtual)로 긴 목록 성능 잡기.

실습 아이디어: 본인 React 프로젝트에 "특정 파일이 N줄을 넘으면 CI 실패" 스크립트를 붙여 라지파일 게이트를 흉내 내 보기.

7시스템 / 환경 요구사항

그냥 쓰는 경우와, 직접 빌드하는 경우.

그냥 설치해 쓰기

Releases 페이지에서 OS별 설치 파일을 받는다. 설치 후 설정에서 AI 엔진(예: Claude Code API 키나 로컬 CLI)을 구성하고 프로젝트 폴더를 추가하면 끝.

플랫폼설치 파일
macOS (Apple Silicon)aarch64.dmg
macOS (Intel)x64.dmg
Windows.exe / .msi (WebView2 필요 — Win11 기본 탑재)
Linux.AppImage (webkit2gtk 필요)

직접 빌드/기여하기

도구버전용도
Node.js20 이상프론트엔드 구동(반드시 npm, pnpm/yarn 차단)
Ruststable(rustup)백엔드 컴파일
CMake최신일부 의존성 빌드
# 빌드 3단계
git clone https://github.com/zhukunpenglinyutong/desktop-cc-gui.git
cd desktop-cc-gui
npm install            # pnpm/yarn 쓰면 preinstall이 막음
npm run tauri:dev      # doctor:strict 검증 후 개발 실행
npm run tauri:build    # 배포용 빌드
주의
실제로 코드를 짜려면 별도의 AI 엔진과 비용이 필요

ccgui는 "껍데기(클라이언트)"다. 실제 AI 코딩은 내부에서 호출하는 Claude Code·Codex 등 CLI/구독·API 키가 있어야 작동하며, 토큰 사용량만큼 과금된다. ccgui의 사용량/예산 기능은 바로 이 비용을 관리하기 위한 것이다. 또 macOS는 Xcode CLT, Windows는 C++ Build Tools 등 OS별 Tauri 사전 요구사항이 있다.

8직접 해볼 수 있는 실습 과제

난이도별 — 손으로 만지며 구조를 체득한다.

실습 1 · 난이도 ★☆☆

stream-json 출력 직접 관찰하기

Claude Code CLI가 설치돼 있다면 터미널에서 claude -p --output-format stream-json --verbose "hello"를 실행한다. 줄줄이 나오는 JSON 이벤트의 종류(텍스트 델타·도구 호출·usage 등)를 적어 보고, "ccgui가 이것을 어떤 카드로 바꿀까"를 추론해 본다.

실습 2 · 난이도 ★☆☆

레포를 클론하고 엔진 어댑터 읽기

src-tauri/src/engine/mod.rs에서 EngineType을 찾고, 각 엔진의 어댑터 파일 4개(claude.rs·codex_adapter.rs·gemini.rs·opencode.rs)의 첫머리 주석을 비교한다. "공통점 vs 엔진별 차이"를 한 표로 정리해 본다.

실습 3 · 난이도 ★★☆

미니 Tauri 앱: CLI 출력 실시간 표시

새 Tauri 앱을 만들어, 버튼을 누르면 Rust가 tokio::process로 간단한 명령(예: ping)을 띄우고 stdout을 줄 단위로 emit한다. 프론트는 이벤트를 받아 화면에 흘려 보낸다. ccgui의 핵심 흐름(spawn→stream→emit→render)을 축소판으로 재현하는 것.

실습 4 · 난이도 ★★★

나만의 "엔진" 어댑터 추가 상상하기

가상의 다섯 번째 엔진(예: 로컬 LLM CLI)을 추가한다고 가정하고, 어떤 파일을 새로 만들고 어디(mod.rs·manager.rs·capability_matrix.rs·UI feature)를 고쳐야 하는지 변경 목록을 작성한다. 어댑터 패턴이 변경을 어떻게 국소화하는지 체감한다.

실습 5 · 난이도 ★★★

품질 게이트 한 개 흉내 내기

scripts/check:large-files나 런타임 계약 스크립트를 읽고, 본인 프로젝트에 "이 디렉토리의 파일은 N줄을 넘으면 안 됨"을 검사하는 Node 스크립트를 작성해 npm run check:*로 붙인다. "규약을 코드로 못 박기"를 실제로 해 본다.

9관련 기술 심화 학습 로드맵

"데스크톱 AI 코딩 클라이언트"를 이해/제작하기 위한 주차별 길.

주차주제학습 내용
1주차Tauri 기초Tauri 2 시작·창·invoke/emit IPC·권한(capability). Electron과의 차이.
2주차Rust 비동기 + 프로세스tokio 런타임·process로 자식 프로세스 spawn·stdout 스트림 읽기·채널.
3주차스트림 프로토콜NDJSON/stream-json 파싱, 이벤트 정규화, 백프레셔·타임아웃·에러 경로.
4주차어댑터/플러그인 설계이종 도구 통일(어댑터 패턴), capability matrix, 매니저로 라우팅.
5주차로컬 영속성SQLite(rusqlite) 스키마·마이그레이션·세션/메모리 모델·rewind/fork.
6주차대형 React 프론트feature 모듈화·가상 스크롤·CodeMirror/xterm 통합·i18n·테마.
7주차코드 인텔리전스파일 워킹(ignore)·정규식 심볼 추출·의존성 그래프(프로젝트 맵).
8주차릴리스 엔지니어링크로스 플랫폼 빌드·자동 업데이트·doctor/품질 게이트·CI.

10핵심 키워드 사전

이 문서에서 반복된 용어를 한 번에.

키워드
ccgui이 앱의 패키지명(desktop-cc-gui). 데스크톱 AI 코딩 클라이언트.
Tauri 2웹뷰 UI + Rust 백엔드로 가벼운 데스크톱 앱을 만드는 프레임워크.
IPC프로세스 간 통신. 여기선 프론트(invoke)↔Rust(emit) 사이의 다리.
#[tauri::command]프론트엔드가 호출할 수 있게 노출한 Rust 함수.
stream-jsonCLI가 줄 단위 JSON 이벤트로 입출력하는 형식(NDJSON). GUI화의 통로.
EngineTypeClaude·Codex·Gemini·OpenCode를 통일한 열거형(어댑터 패턴의 중심).
어댑터 패턴이종 도구의 차이를 어댑터로 격리하고 공통 인터페이스로 노출하는 설계.
PTY의사 터미널. portable-pty로 앱 안에 진짜 셸을 띄움.
local-first클라우드 없이 모든 데이터를 로컬(SQLite)에 두는 철학.
프로젝트 맵AI가 코드베이스를 스캔해 만든 파일/API/모듈 관계의 지식 그래프.
컨텍스트 원장각 답변에 어떤 컨텍스트가 얼마나 들어갔는지 회계 장부처럼 기록.
런타임 계약코드 규약을 빌드 시 스크립트(check:*)로 강제 검증.
rewind / fork대화를 과거 시점으로 되감거나 그 지점에서 새 분기를 만드는 기능.

11참고 링크

원본과 더 깊이 파기 위한 자료.