diff --git a/README.md b/README.md
index 94fbe2f..a0584e3 100644
--- a/README.md
+++ b/README.md
@@ -77,6 +77,29 @@ timeout_secs = 5
See [Plugin Development](docs/plugin-development.md) for the full protocol.
+## Architecture
+
+Clean Architecture (Domain → Application → Infrastructure → Main):
+
+```
+domain — pure value types (ResultId, ResultTitle, Score, LaunchAction, SearchResult),
+ port traits (Plugin, AppLauncher), shared constants
+kernel — application use case: Kernel orchestrator (fan-out search, sort, truncate)
+config — TOML config loading with typed errors (ConfigError)
+ui-core — framework-agnostic UI state machine (LauncherState, Action, Effect)
+ui — iced 0.14 rendering adapter
+ui-egui — egui rendering adapter (optional)
+os-bridge — UnixAppLauncher (process spawning, terminal detection, clipboard)
+plugin-host — ExternalPlugin (JSON stdin/stdout protocol with typed PluginError)
+plugins/
+ plugin-apps — XDG .desktop search, frecency ranking, nucleo fuzzy matching, bincode cache
+ plugin-calc — evalexpr math evaluator (supports sqrt, sin, cos, ln, pi, e, etc.)
+ plugin-cmd — shell command runner (> prefix, launches in terminal)
+ plugin-files — filesystem browser (/ and ~/ paths)
+ plugin-url — URL detection (external binary, tests the external plugin protocol)
+k-launcher — entry point: DI wiring, logging, signal handling
+```
+
## Docs
- [Installation](docs/install.md)
diff --git a/architecture.mmd b/architecture.mmd
new file mode 100644
index 0000000..f60f8cc
--- /dev/null
+++ b/architecture.mmd
@@ -0,0 +1,81 @@
+---
+title: k-launcher — Clean Architecture
+---
+graph TB
+ subgraph Main["Main (Composition Root)"]
+ BIN["k-launcher
DI wiring, logging,
signal handling, --version"]
+ BIN_EGUI["k-launcher-egui
Optional egui binary"]
+ end
+
+ subgraph Application["Application Layer"]
+ KERNEL["kernel
Kernel orchestrator
Fan-out search, sort by score,
truncate to max_results,
catch_unwind per plugin"]
+ end
+
+ subgraph Domain["Domain Layer (0 external deps)"]
+ direction TB
+ subgraph Types["Value Types"]
+ VT_ID["ResultId(String)"]
+ VT_TITLE["ResultTitle(String)"]
+ VT_SCORE["Score(u32)"]
+ VT_ACTION["LaunchAction
SpawnProcess, SpawnInTerminal,
OpenPath, CopyToClipboard"]
+ VT_RESULT["SearchResult
id, title, description,
icon, score, action"]
+ end
+ subgraph Ports["Port Traits"]
+ P_PLUGIN["Plugin
name, search, on_selected,
shutdown"]
+ P_LAUNCHER["AppLauncher
execute(LaunchAction)"]
+ end
+ CONSTANTS["constants
APP_NAME, APP_TITLE,
CONFIG_FILENAME, LOG_*,
FRECENCY_SNAPSHOT_FILENAME"]
+ end
+
+ subgraph Infrastructure["Infrastructure Layer"]
+ direction TB
+ subgraph UI["UI"]
+ UI_CORE["ui-core
LauncherState, Action, Effect
Framework-agnostic state machine"]
+ UI_ICED["ui (iced)
style, view, update
Rendering adapter"]
+ UI_EGUI["ui-egui
style, input, render
Rendering adapter"]
+ end
+ subgraph Plugins["Plugins (implement Plugin trait)"]
+ PL_APPS["plugin-apps
XDG .desktop search
Frecency, nucleo fuzzy,
bincode cache"]
+ PL_CALC["plugin-calc
evalexpr math
sqrt, sin, cos, ln, pi, e"]
+ PL_CMD["plugin-cmd
Shell commands
> prefix → terminal"]
+ PL_FILES["plugin-files
Filesystem browser
/ and ~/ paths"]
+ PL_URL["plugin-url
URL detection
External binary (JSON protocol)"]
+ end
+ subgraph Platform["Platform"]
+ OS_BRIDGE["os-bridge
UnixAppLauncher
shell, terminal, spawn"]
+ PLUGIN_HOST["plugin-host
ExternalPlugin
JSON stdin/stdout protocol"]
+ CONFIG["config
TOML loading
ConfigError, try_load"]
+ end
+ end
+
+ %% Dependency arrows
+ BIN -->|"wires"| Application
+ BIN -->|"wires"| Infrastructure
+ BIN_EGUI -->|"wires"| Application
+ BIN_EGUI -->|"wires"| Infrastructure
+
+ Application -->|"depends on"| Domain
+
+ UI_ICED -->|"delegates to"| UI_CORE
+ UI_EGUI -->|"delegates to"| UI_CORE
+ UI_CORE -->|"uses"| KERNEL
+
+ Plugins -.->|"implements"| P_PLUGIN
+ OS_BRIDGE -.->|"implements"| P_LAUNCHER
+ PLUGIN_HOST -.->|"implements"| P_PLUGIN
+
+ KERNEL -->|"fan-out"| P_PLUGIN
+
+ %% Key data flows
+ UI_CORE ===|"Action → Effect"| KERNEL
+ PL_APPS ===|"frecency log"| CONSTANTS
+
+ classDef domain fill:#1a1a2e,stroke:#e94560,color:#fff
+ classDef app fill:#16213e,stroke:#0f3460,color:#fff
+ classDef infra fill:#0f3460,stroke:#533483,color:#fff
+ classDef binary fill:#533483,stroke:#e94560,color:#fff
+
+ class Domain domain
+ class Application app
+ class Infrastructure infra
+ class Main binary