유대선
DalkkakAI

README

프로젝트 자체의 README를 여기 미러링했습니다. repo 상대 링크는 일반 텍스트입니다(repo가 비공개).

DalkkakAI · 딸깍AI

One window for every startup you're running — a native, multi-pane command deck for the solo founder who brings their own AI

A lightweight Tauri + Rust desktop app. Many live terminal panes, across many startups at once, each pane a persistent tmux session — plus a connective layer that turns your git history and your own Claude Code sessions into a cross-startup pulse of real work. It never calls an LLM itself: you bring your own Claude Code / Codex.

🌐 Live site → ddalkkak.daeseon.ai

English · 한국어

Tauri Rust React TypeScript xterm.js platform status license


TL;DR. A native macOS (Apple Silicon) multi-pane terminal workspace built around running several startups at once. Every pane is a live shell backed by a persistent tmux session; every startup is a first-class workspace with its own pane layout and its own granted project folder. On top of that terminal substrate, DalkkakAI builds a connective layer: a 20-second worker turns the git history of the repos you grant into a per-startup change graph, and your own Claude Code sessions are read — through Claude Code hooks and transcripts, never by faking data — into a cross-startup Pulse of effort, momentum and friction (tokens as a measure of effort, never a dollar bill). DalkkakAI does not call any AI itself — you bring your own Claude Code / Codex. Shipped as an unsigned v0.2.0 beta with zero production users; the cloud backend, auth and billing are scaffolds or roadmap. Every bug and decision is captured in a disciplined in-repo system of six-section post-mortems, ADRs, and a dated build log published to a blog.

Table of contents


What is DalkkakAI?

딸깍 (ddalkkak) is the Korean word for the small click of a switch — the sound of a thing just getting done. The mascot is a sloth in a hammock running every dashboard at once, because the AI is doing the clicking.

DalkkakAI is the answer to one concrete, measured pain: its author runs roughly 12 macOS desktops at the same time while building services — about 1–3 startups × ~4 tools (Claude Code, an editor, a browser, a terminal) — and the day is spent in Mission Control, losing context and never knowing at a glance which AI session is working, idle, or stuck (docs/BLUEPRINT.md §2).

So the product is one native window that holds:

  1. Many startups, side by side. A left sidebar lists your startups (workspaces); each one owns its own grid of terminal panes and its own granted project folder. Switch with ⌃1–9. This is the organizing axis of the whole app — N startups in one workspace, not one project at a time (docs/BLUEPRINT.md §1, §4).
  2. Many live shells, in a resizable grid. Each pane is a real PTY backed by a persistent tmux session, so your running claude or codex survives a layout change and an app restart.
  3. A connective layer on top. DalkkakAI watches the repos you explicitly grant and reads your AI sessions, then surfaces — honestly, with provenance — what actually changed across your whole portfolio this week.

The terminal grid is the substrate; the connective layer across startups is the product. The stated north-star is "everything a one-person founder needs to start → build → manage → operate new services — across several startups at once" (docs/BLUEPRINT.md §1, refined 2026-05-30).

The screenshot above is real: six startups in the sidebar (Dalkkak, Mimi, ki-clash, daeseonblog, EnglishGlass, BackendPlatform), four panes running the author's own Claude Code (Opus) and OpenAI Codex sessions — the three Claude Code panes each showing a done status and a ✦ Summarize action. DalkkakAI supplies the workspace around those tools — it does not run them for you.


Why this project

For reviewers in a hurry — the engineering this repo actually demonstrates, each line traceable to a file.

File paths are relative to the repo root: the Rust backend lives under apps/desktop/src-tauri/src/, the React renderer under apps/desktop/src/.


Product walkthrough

FlowWhat happensStatus
Run many startupsA sidebar of workspaces; each has its own pane layout + granted folder. ⌃1–9 switch, ⌃Tab cycle, ⌘⌥↑↓ walk.shipped
Open & arrange panesA react-mosaic grid of live shells. ⌘D split · ⌘⇧D stack · ⌘W close · Reset · ⌘1–9 focus · ⌘[ ⌘] cycle.shipped
Persistent sessionsEach pane is a tmux session (dalkkak-<id>) on a private socket — survives splits and app relaunch; orphans are GC'd on launch.shipped
See what each AI is doingA per-pane status bar driven by Claude Code hook events: thinking / tool-call / blocked / done.shipped
Summarize a session ( / ⌘I)Reads the session transcript and shows token accounting + the latest self-summary card.shipped
Read the conversation (⌘L)Renders the raw scrollback into a clean, scrollable chat log (recent 800 entries), with copy buttons.shipped
Cross-startup Pulse (📊 Graph → Pulse)Six read-time views of effort, momentum, fan-out, explore/produce, friction, shipped-vs-thrash across all startups.shipped
Change graphGrant a folder → your git commits become a per-startup / cross-startup graph (React Flow), within ~20s. No LLM.shipped
Scroll & copy⌘↑ enters tmux scroll mode (no mouse mode); selecting text or clicking a colored token auto-copies.shipped
Shortcuts & language⌘/ opens the shortcut guide; a 🌐 toggle switches the augmentation UI between en / ko.shipped

The multi-startup model & the connective layer

This is the heart of the project — the thing that makes it a solo founder's operating layer rather than "another terminal." Everything here is shipped code with citations; the broader operator vision is flagged honestly in Honest limitations.

A startup is a first-class workspace

A Startup is { id, name, emoji, createdAt, grant? }, persisted under dalkkak.startups.v1. Each startup gets:

(apps/desktop/src/startups.ts, App.tsx, Sidebar.tsx, pathGrant.ts.)

The connective layer — "commits-first" v0

The thesis (docs/BLUEPRINT.md §5.5, docs/CONNECTIVE_LAYER.md) is that the panes and sessions are where work happens and data is born, and a living cross-portfolio graph is what binds them into one operating layer. The shipped v0 is deliberately narrow and honest:

The non-negotiable design rule, in the author's words: "logging and standards must never distort the work" — so the commit→recap transform uses the real subject and real --stat file/line counts and refuses to invent a next-step or an added/edited/deleted tag a --stat can't prove (apps/desktop/src/viz/nodeToRecap.ts).

The cross-startup Pulse

The Pulse (📊 Graph → Pulse) is the clearest expression of the multi-startup thesis. A Rust command (src-tauri/src/pulse.rs, ADR-005) does a read-time, zero-storage rollup over a 14-day window, attributing each session to a startup by longest-path-prefix (ambiguous → the literal unassigned, never a guess), from three real sources — the hook stream, each session's transcript, and the git change-nodes. Six views:

ViewPlain-language question it answers
Effort splitHow much did the AI generate in each startup this week? (output tokens = effort, not a bill)
MomentumHow many of the last 14 days did you move this startup? (a long gap = it's stalling)
Fan-out / scopeInternal steps per question — higher than usual = a big task or a vague ask
Explore vs produceIs the AI mostly reading/searching, or editing/running?
FrictionWhere the flow stalls — times the AI paused waiting on you, plus tool errors
Shipped vs thrashAsks vs commits that day — many asks → 0 commits = churn

Every unit is honest: "output tokens / active days / counts — never a $." On a Max subscription there is no per-token bill, so DalkkakAI never fabricates a dollar figure (apps/desktop/src/viz/PulsePanel.tsx, usagePulse.ts).


The augmentation layer

Around the BYO terminal, a set of React renderers turn raw session output into something legible — on demand, read from the transcript, never by faking live data.

Session summary — real token accounting (output / input / cache; no $) plus the latest self-summary card. Conversation log — raw scrollback rendered as a readable chat, with decisions and code-block copy.

Be precise: the summary cards appear on demand ( / ⌘I), read from the transcript — not as live cards streaming inline as the model types (that wiring exists in code but is deliberately not connected). diff / metric / trend kinds are in the locked vocabulary but have no renderer yet.


Tech stack

LayerChoice
Desktop runtimeTauri 2.x (ai.ddalkkak.desktop)
Local backendRust — portable-pty 0.9, tokio 1.52, tracing + tracing-appender, chrono, dirs, serde · 2,106 LOC / 10 files
RendererReact 19 + TypeScript 5.8 + Vite 7 · 40 files / ~5,274 LOC
Terminalxterm.js 6 + fit / clipboard addons (WebGL addon present but parked — it broke Korean IME)
Pane layoutreact-mosaic-component 6.1.1 (pinned)
Graph / diagrams@xyflow/react (React Flow) 12 · mermaid 11 · framer-motion 12 · react-zoom-pan-pinch
Markdownreact-markdown + remark-gfm
Sessionstmux system daemon — private socket -L dalkkak, one session dalkkak-<pane-id> per pane
IPC19 Tauri commands + 2 event streams (pty-output, session-hook)
The AI (BYO)the user's own Claude Code / OpenAI Codex run inside panes; the on-demand summary shells out to the user's claude -p (claude-haiku-4-5) with API-key env vars stripped to force subscription auth
i18nko / en for the augmentation UI (dependency-free), default en
Monorepo / toolingpnpm 9.12 workspaces · Biome 1.9 · Node ≥ 22
BundleApple-Silicon .app + .dmg (the v0.2.0 download is ~8.9 MB), unsigned

Why Tauri, not Electron or a web app. A browser can't spawn a PTY, and spawning the user's local claude/codex binary is the entire point — a web app is technically incapable of solving the problem (docs/BLUEPRINT.md §6). Tauri gives a small bundle on the system WebKit with a Rust backend that owns the process tree. Why not Swift: it would rule out a future Linux/Windows build for no feature gain.

The internal monorepo also defines @ddalkkak/{advisor, platform-client, skills, viz} — these are named placeholders (a one-line export each), reserved for roadmap layers. Only @ddalkkak/augmentor and @ddalkkak/shared contain real, imported code.


Architecture

                         ┌──────────────── one native window (Tauri) ────────────────┐
                         │                                                            │
  ┌─────────┐   ⌃1–9     │   ┌────────── React renderer (40 files) ──────────┐        │
  │ Startup │ ───────────┼──▶│  Sidebar · Mosaic grid · per-startup layout    │        │
  │ sidebar │            │   │  terminalRegistry (xterm + PTY live OUTSIDE     │        │
  └─────────┘            │   │  React, survives mosaic remounts)              │        │
                         │   └───────────────┬───────────────┬────────────────┘        │
                         │   19 commands ▲    │ pty-output    │ session-hook            │
                         │   ───────────┘     ▼ (event)       ▼ (event)                 │
  Granted repo  ◀── read-only git ──┐   ┌──────────────── Rust backend ───────────────┐ │
  (per startup)                     │   │ pty.rs   spawn /bin/bash → tmux(-L dalkkak)  │ │
        │                           │   │          env hygiene · visible EOF marker    │ │
        ▼  every 20s                └──▶│ capture.rs  git log/show → append-only JSONL  │ │
  GraphStore (.../DalkkakAI/graph/<startup>.jsonl)  │  graph nodes (confirmed)          │ │
        │                               │ hooks.rs  tail session-events.jsonl → status  │ │
        ├──▶ GraphPanel (per-startup / cross-startup)│ summarize.rs  transcript → usage /  │ │
        └──▶ Pulse (read-time 14-day rollup, no $)   │   inline card / readable log; or    │ │
                                                     │   user's own `claude -p` (BYO)      │ │
                                        paths.rs  PathAllowlist — hard-refuse ungranted    │ │
                                        entitlement.rs  trial/paywall gate (local STUB)    │ │
                                        └──────────────────────────────────────────────────┘ │

   Layer-2 logging: Rust `tracing` → ~/Library/Logs/DalkkakAI/runtime.log.<date> (daily)      │
   └──────────────────────────────────────────────────────────────────────────────────────┘

Key decisions (each is an ADR or a documented post-mortem):


Engineering discipline

This is, deliberately, half the point of the project — turning every bug and decision into a reusable asset. All of the following are real files on disk, not aspirations:

The protocol is codified in CLAUDE.md (the agent operating rules for this repo): RULE #6 "Issues are assets — patching and moving on is forbidden," a two-layer logging rule, and a dual-write logging contract with non-negotiable anti-hallucination rules (literal symptom, verified cause, fix names actual files, commit hash after committing). These are house rules written into CLAUDE.md rather than machine-enforced.


Monetization

The business model is ADR-008 (docs/DECISIONS.md, Accepted 2026-06-02): a hard 14-day free trial → paid subscription, no perpetual free tier. Pricing, verified in code (apps/desktop/src/entitlement.ts) and on the landing page:

What is actually wired today (and what isn't): the entitlement gate is real and end-to-end — a Rust get_entitlement command, called once on launch, hard-locks the whole workspace behind a <Paywall> when not entitled. But the entitlement backend is an explicitly-labeled local STUB: a spoofable file-based trial clock plus a DALKKAK_ENTITLEMENT dev override, failing open on error by design. No payment is wired — the checkout button opens the placeholder https://polar.sh/REPLACE_ME; Polar is the intended merchant-of-record and Supabase the intended source-of-truth, both roadmap (src-tauri/src/entitlement.rs, Paywall.tsx).


Security & privacy

DalkkakAI runs your shells and reads your repos, so its reach is constrained deliberately (docs/BLUEPRINT.md §5.5, docs/CONNECTIVE_LAYER.md).

ConcernImplementation
Filesystem reachPer-project path grants only. A native folder picker feeds the path to grant_project_path, which canonicalizes + symlink-resolves it; a single PathAllowlist chokepoint hard-refuses any ungranted path and never falls back to $HOME for capture (paths.rs).
No scary OS permissionsThe model is tuned to what an ordinary user will grant — no blanket Full Disk Access. Our automation only ever touches confirmed project paths (the raw shell you type into is governed by normal OS prompts).
Git reads are read-onlyCapture shells out to git log / git show only — it never writes to your repos.
Provenance, not guessesEvery graph node carries confirmed / inferred / hypothesis; confirmed nodes must carry evidence, and recap cards refuse to invent facts a git --stat can't prove.
No fabricated moneyToken counts are reported as effort; the app never invents a dollar figure for a flat-rate subscription.
Your keys stay yoursDalkkakAI makes no AI calls of its own; the one summary feature runs your claude binary and strips ANTHROPIC_API_KEY to force your own subscription auth.
Logging never logs secretsTwo-layer logging records IDs, counts and lifecycle events — never passwords, tokens, keys or PII (CLAUDE.md).

Run it locally

Requirements: macOS (Apple Silicon), the Rust toolchain, Node ≥ 22, pnpm, and tmux (brew install tmux).

pnpm install
cd apps/desktop && pnpm tauri dev   # opens the native window

Production build / typecheck / lint:

pnpm --filter appsdesktop build      # tsc + vite (frontend) — passes clean (chunk-size warning only)
pnpm --filter appsdesktop typecheck  # tsc --noEmit
pnpm lint                            # biome check .
cd apps/desktop && pnpm tauri build  # produces the .app + .dmg (Apple Silicon)

Or just download it. The v0.2.0 Apple-Silicon .dmg (~8.9 MB) is linked from ddalkkak.daeseon.ai. It's an unsigned beta, so the first launch needs right-click → Open (or xattr -cr).


Honest limitations

Stated plainly — knowing the edges is part of the engineering, and this repo's house rule is to lead with what isn't done.


Project layout

apps/desktop/
  src/                      React renderer (40 files / ~5,274 LOC)
    App.tsx                 mosaic layout · startups · shortcuts · paywall gate
    terminalRegistry.ts     xterm + PTY registry (lives OUTSIDE React)
    TerminalPane.tsx        thin DOM attachment point + status bar
    Sidebar.tsx  startups.ts  pathGrant.ts   multi-startup model + per-startup grants
    GraphPanel.tsx          connective-layer read surface (per/cross-startup)
    entitlement.ts  Paywall.tsx                ADR-008 trial/subscription gate
    sessionStatus.ts  summary*.ts  usagePulse.ts  logModal.ts   augmentation glue
    viz/                    card renderers · PulsePanel · LogPanel · GraphView · OrchestrationView
    i18n/                   ko / en dictionaries (augmentation UI)
  src-tauri/src/            Rust backend (2,106 LOC / 10 files) — 19 commands, 2 events
    pty.rs                  PTY + tmux, env hygiene, visible EOF marker
    capture.rs              20s git→graph-node worker (read-only)
    hooks.rs                tail session-events.jsonl → session-hook events
    summarize.rs            transcript → usage / inline card / readable log; BYO `claude -p`
    pulse.rs                read-time, zero-storage cross-startup rollups
    inline.rs               installs the DalkkakAI-only claude wrapper (<dk-summary>)
    paths.rs                PathAllowlist chokepoint
    entitlement.rs          trial/paywall gate (local STUB)
    lib.rs                  Tauri entry · command registry · two-layer logging
packages/
  augmentor/  shared/       real, used libs (PTY-output parser · graph schema + viz vocab)
  advisor/ platform-client/ skills/ viz/   named placeholders (roadmap)
landing/                    static bilingual landing page (ddalkkak.daeseon.ai) + screenshots + .dmg
docs/                       BLUEPRINT · CONNECTIVE_LAYER · ROADMAP · ISSUES · DECISIONS · MILESTONES · …
content/logs/dalkkak-ai/    40 dated build-log entries (rendered on the blog)
old_repo/                   frozen v1 (Python/FastAPI), read-only reference
CLAUDE.md                   agent operating rules for this repo

DalkkakAI · 딸깍AI — one window for every startup you're running.

Repo: Daeseon-AI-Factory/ddalkkak · Live: ddalkkak.daeseon.ai · Build log: daeseon.ai/projects/dalkkak-ai · 한국어 README · MIT