Pomodoro, Todos, Tasks, Habits, Calendar, Clock, and a real Terminal anchored as connectable nodes on one infinite whiteboard.
Documentation · Architecture · ADRs · Visual System · Challenges Journal
Most productivity stacks are several apps that don't share state. A focus session relates to a task; a habit feeds a goal; a calendar blocks both. The separation is an artifact of how the apps were built, not how the work flows.
KRNL0 puts every primitive on one canvas as a node, and lets them communicate. Drop a task on the calendar — the entire chain auto-positions back-to-back. Wire a Pomodoro to a habit — finishing the timer ticks the streak. Type claude in the embedded terminal — the AI operates the same krnl CLI you do.
One file (board.json) is the only persisted state. Every view derives from it.
| Category | Tools you use today | KRNL0 node |
|---|---|---|
| Infinite canvas | Miro, FigJam, tldraw | The canvas itself |
| Pomodoro timers | Pomofocus, Forest, Be Focused | pomo mother |
| Todo lists | Things, Todoist, Apple Reminders | todo mother |
| Tasks & projects | Notion, Linear (light) | todo.task DAG |
| Habit trackers | Streaks, Habitica, Loop | habit mother |
| Calendars | Notion Calendar, Cron, Fantastical | calendar mother |
| Time analytics | RescueTime, Toggl, Clockify | Heatmaps + corner timers |
| Terminal | Warp, iTerm, Hyper | term mother (real PTY) |
| AI assistant | ChatGPT tab, Claude.ai | claude natively in term |
Every productivity primitive is a node with typed events and typed commands. They share one source of truth and communicate through edges stored as data in board.json.
| Node | Kind | What it does |
|---|---|---|
| Pomodoro | pomo |
Vapor-pill timer with draining liquid, session pips, configurable session/break, blinking colon. Linkable to an active task — the task accumulates seconds in the corner. |
| Todos | todo |
Tagged task list. Items spawn todo.task children, which form chains via task.next edges. Filterable by calendar day selection. |
| Habits | habit |
Week / Month / Year (GitHub-style 53×7 heatmap) views. Color-coded streaks. Schedulable daily / weekly / weekdays. |
| Calendar | calendar |
Week / Month / Year views. Hour grid with now-line. Drop-to-schedule for tasks and habits. Habit dots and Pomodoro completion heatmap layer on top. |
| Terminal | term |
Real PTY (node-pty + WebGL xterm.js). Hosts claude, git, npm, the krnl CLI — anything. |
| Node | Kind | What it does |
|---|---|---|
| Clock | clock |
Day-anchored 12-hour wall-clock dial. Concentric rings for parallel branches. Independent day cursor. |
| Tasks | todo.task |
Free-floating cards. Form a DAG: Add subtask, Add next task, Add parallel task. Click body → load into Pomo. |
| Sessions, days | pomo.session, habit.day |
History records spawned by mothers when sessions complete or days are toggled. |
| Notes, images | text, image |
Free child nodes for context, reference material, screenshots. |
Drop one task on the calendar — the entire task.next chain auto-positions back-to-back. Only the dropped task stores scheduledFor; every successor's position is derived at read time by the selectSchedule selector.
| Time | Task | Source |
|---|---|---|
| 14:00 | Outline chapter 3 (50 min) | Anchor — you dropped this here |
| 14:50 | Draft section 3.1 (25 min) | Derived |
| 15:15 | Draft section 3.2 (25 min) | Derived |
| 15:40 | Review notes (parallel A, 30 min) | Derived |
| 15:40 | Cite-check (parallel B, 45 min) | Derived (shared start) |
| 16:25 | Stretch + tea (15 min) | Derived |
Edit any duration upstream — every downstream block re-positions instantly. Pin a second anchor mid-chain and both fixpoints coexist. No write fan-out, no de-normalisation.
Specs: ADR 0003 — Cascade scheduling · ADR 0005 — Multi-anchor cascade
Drag a habit from the Habit mother onto a calendar cell. A chooser appears at the drop point with 2 options — Daily, Weekly. Click a wedge to confirm; click the dead zone or press Escape to cancel.
The chooser is a reusable primitive (useRadialChooser), portaled to document.body with z-index: 2147483000. Future drag interactions — edge-type pickers, Pomo preset assignment — will reuse the same hook.
The Terminal mother is a real PTY. Type claude and the full Claude Code agent runs on the canvas, reading claude/CLAUDE.md and claude/skills/*.md for context.
$ claude "plan a thesis afternoon — three deep blocks plus one break"
► Reading claude/CLAUDE.md and skills/plan-session.md
► krnl task add "Outline chapter 3" --duration 50
► krnl task add "Draft section 3.1" --duration 25 --next-of <id1>
► krnl task add "Draft section 3.2" --duration 25 --next-of <id2>
► krnl task add "Stretch + tea" --duration 15 --next-of <id3>
► krnl task schedule <id1> 2026-05-20T14:00
✓ Cascade scheduled. Pomo armed.There is no backdoor. Claude uses the same krnl CLI a power user types. It reads board.json for context, dispatches commands, the file watcher fires, the canvas re-renders.
Spec: Decision 3 — How Claude drives the app · TerminalNode requirements
flowchart TB
subgraph SSOT["board.json — the only persisted state"]
N["Nodes<br/>pomo · todo · task · habit · calendar · clock · term"]
E["Edges<br/>typed event → command mappings"]
A["Anchors<br/>scheduledFor on dropped tasks only"]
end
subgraph Selectors["Pure derived selectors (memoised, no state)"]
SS["selectSchedule"]
ST["selectTimeline"]
CW["chainWalker"]
end
subgraph Views["Views — re-render automatically"]
CAL["Calendar Week / Month / Year"]
CLK["Clock day-anchored dial"]
TODO["TodoNode filtered by day"]
TASK["TaskNodes with corner timers"]
end
SSOT --> Selectors --> Views
SYS["krnl CLI"] -.writes.-> SSOT
AI["Claude Code"] -.runs.-> SYS
UI["Canvas UI"] -.dispatches.-> SYS
style SSOT fill:#0e0d0b,stroke:#c9f158,color:#c9f158
style Selectors fill:#0e0d0b,stroke:#4ea8b0,color:#4ea8b0
style Views fill:#0e0d0b,stroke:#c8553d,color:#c8553d
style SYS fill:#0e0d0b,stroke:#fff,color:#fff
style AI fill:#0e0d0b,stroke:#6b4ea8,color:#6b4ea8
style UI fill:#0e0d0b,stroke:#fff,color:#fff
Persist intent, derive presentation. A running Pomodoro stores startedAt — the countdown is computed every render. A scheduled task stores scheduledFor once — every successor in its chain is derived. Close the app, reopen — every view shows the right state.
board.json has a strict round-trip contract: load → save → byte-identical (modulo savedAt), tested on every CI run.
Specs: Node specification · Design patterns map
flowchart LR
subgraph L1["Input surfaces"]
UI["Canvas UI"]
CLI["Terminal + krnl CLI"]
AI["Claude Code subprocess"]
VOICE["Voice (Whisper → Brain → Piper)"]
end
subgraph L2["Action surface"]
SYS["krnl CLI / SysFacade"]
DISP["commandDispatch<br/>typed commands"]
EDGE["Edge dispatcher<br/>event → command"]
end
subgraph L3["State"]
BOARD["board.json<br/>singleton"]
ASSETS["assets/<br/>image bytes"]
NOTES["notes/<br/>markdown sidecars"]
end
subgraph L4["Render"]
STORE["Zustand store"]
SEL["Pure selectors"]
RF["React Flow canvas"]
end
UI --> SYS
CLI --> SYS
AI --> SYS
VOICE --> SYS
SYS --> DISP --> BOARD
BOARD --> EDGE --> DISP
BOARD -.file watcher.-> STORE --> SEL --> RF
style L1 fill:#181612,stroke:#3d362b,color:#f0ebdd
style L2 fill:#181612,stroke:#c9f158,color:#c9f158
style L3 fill:#181612,stroke:#c8553d,color:#c8553d
style L4 fill:#181612,stroke:#4ea8b0,color:#4ea8b0
One mutation path. krnl is the only writer of board.json. The UI dispatches through it; the AI runs it; the edge dispatcher fires it. No component bypasses the facade.
Six unbreakable rules for every node — state is JSON-serializable, render is pure, commands mutate state, events are typed strings, no cross-node imports, no privileged access. Mothers play by the same rules as children — anchored and cannot delete are kernel properties, not node-level overrides.
Specs: Three-layer overview · Decisions log (250+ lines, 25+ decisions)
Every GUI action has a CLI equivalent. Every read command supports --json. Every ID argument accepts an 8-character prefix or a unique name.
krnl info --json # mother ids + node counts
krnl board show --json # full board state
krnl task add "Outline chapter 3" --duration 50 --tag deep
krnl task add "Draft section 3.1" --duration 25 --next-of <id>
krnl task schedule <id> 2026-05-20T14:00 # cascade fires
krnl task pomo <id> # load into Pomo, start
krnl habit add "Morning meditation"
krnl habit done "Morning meditation"
krnl habit color "Morning meditation" cyan
krnl edge add --from "<pomoId>:onComplete" --to "<habitId>:markDone"
krnl edge list
krnl calendar setView month
krnl pomo start --label "deep work" --minutes 50Internally, krnl is the user binary; sys is the corresponding facade module. The two are interchangeable in command shape — sys is what older docs reference.
Aesthetic direction: Anthropic warmth × cyberpunk ASCII — the native theme is called cyber. Warm paper tones at rest; acid green, rust, and cyan as high-signal accents.
| Token | Hex | Meaning | Used for |
|---|---|---|---|
--acid |
#c9f158 |
Active focus | Running Pomo ring, listening orb, terminal cursor |
--cyan |
#4ea8b0 |
Todo kinship | Todo + Task selection rings, animated task-flow edges |
--rust |
#c8553d |
Danger / stop | Pomodoro timer, RESET, delete, error states |
--spine |
#5e7d1d |
Mother identity | Anchored mother slot tags, fixed-corner brackets |
--plum |
#6b4ea8 |
Reserved accent | Radial-chooser stroke, "thinking" orb state |
--acid is invariant across light and dark — it's a signal, not a shade. The Terminal node is always dark regardless of host theme.
| cyber (default) | noir (data-vibe="noir") |
|
|---|---|---|
| Vibe | Warm paper × acid neon | High-contrast monochrome |
| Accent | #c9f158 lime |
#fafaf6 near-white |
| Node radius | 10px | 0px sharp corners |
| Letter-spacing | 0.04em | 0.18em uppercase |
| Effects | Acid glow, edge pulses | None — geometry only |
The docs/ folder is held to professional spec standards. Every architectural decision is recorded as an ADR with binding contract code. Every node has Functional Requirements + Use Cases + Gherkin scenarios. Every hard bug solved is journaled in plain language. Treat this repo as a reference for how to document a serious solo build.
| Folder | Contents |
|---|---|
docs/01-concept/ |
Vision, framing, motivation |
docs/02-prd/ |
PRD v0.6.0 — locked specification |
docs/03-architecture/ |
Three-layer overview, design patterns map, 25+ decisions log, styling philosophy |
docs/03-adr/ |
Five binding ADRs: Calendar, Radial Chooser, Cascade, Clock day-anchor, Multi-anchor |
docs/04-visual-system/ |
Design tokens, color contract, typography, density modes |
docs/05-node-system/ |
Node contract — state, config, events, commands, six rules |
docs/06-requirements/ |
Per-node specs with Functional Requirements, Use Cases, Gherkin scenarios |
docs/07-roadmap/ |
10-week build roadmap, references |
docs/08-history/HISTORY.md |
Every merge logged with PRs, files changed, summary |
docs/Challenges.md |
Plain-language journal — Symptom → Wrong Guesses → Real Cause → Fix → Lesson |
Every ADR follows the same structure: Context, Decision, Contract (with file paths and binding code shapes), Consequences, Alternatives Rejected, recommended slice ordering. Open ADR 0003 for a representative example.
Requires Node 20+ and npm 10+.
git clone https://github.com/theMindDeveloper/krnl0
cd krnl0
npm install # runs electron-rebuild for node-pty automatically
npm run dev # opens the canvas
npm test # vitest — Gherkin-shaped scenarios per node
npm run typecheck # strict TypeScript, zero `any`| Provider | Install | Purpose | |
|---|---|---|---|
| Brain (default) | Claude Code | npm i -g @anthropic-ai/claude-code |
Uses your subscription via claude -p subprocess |
| Brain (fallback) | Anthropic API | Bring your own key | Pay-per-token via HTTPS |
| Brain (offline) | Ollama | ollama.com |
Fully local LLM |
| STT | Whisper.cpp | ggerganov/whisper.cpp |
Local speech-to-text |
| TTS | Piper | rhasspy/piper |
Local text-to-speech |
Functional Source License v1.1, with an Apache 2.0 future grant.
| ✅ | Use, fork, modify, self-host, contribute |
| ✅ | Build plugins and themes |
| ❌ | Sell as a competing commercial product |
| 🕒 | Each release becomes Apache 2.0 two years after publication |

