How Athena Works
How Athena Works
Athena Flow is a runtime that wraps Claude Code. It does not modify Claude Code's binary or intercept network traffic — it uses Claude Code's official hooks system to observe and influence agent behavior.
The Three-Layer Architecture
┌────────────────────────────────────────────────────────────┐
│ Claude Code │
│ (the agent — reads files, runs bash, writes code) │
└──────────────────────────┬─────────────────────────────────┘
│ fires hooks at each lifecycle point
▼
┌────────────────────────────────────────────────────────────┐
│ athena-hook-forwarder │
│ (thin binary — receives hook stdin, sends NDJSON │
│ over Unix Domain Socket to Athena runtime) │
└──────────────────────────┬─────────────────────────────────┘
│ NDJSON event stream over UDS
▼
┌────────────────────────────────────────────────────────────┐
│ Athena Flow Runtime │
│ ┌──────────────┐ ┌─────────────┐ ┌──────────────────┐ │
│ │ Workflow │ │ Plugins │ │ Isolation Policy │ │
│ │ Engine │ │ System │ │ (controller) │ │
│ └──────────────┘ └─────────────┘ └──────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Session Store (SQLite) │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Terminal UI (React 19 + Ink 6) │ │
│ └──────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────┘
Startup Sequence
When you run athena-flow:
- Config loading — Global config (
~/.config/athena/config.json) and project config (.athena/config.json) are merged with CLI flags - Plugin resolution — Plugin dirs from config +
--pluginflags + workflowplugins[]are loaded. For marketplace refs, the repo is cloned/updated in~/.config/athena/marketplaces/ - Workflow activation — If a workflow is specified, it is loaded from
~/.config/athena/workflows/<n>/workflow.json. Its declared plugins are merged into the plugin set. Its isolation preset may upgrade the session preset (with a warning) - Hook registration — Athena generates a temporary settings file (
athena-hooks-<PID>-<timestamp>.json) that registersathena-hook-forwarderas the handler for all Claude Code hook events. The file is passed to Claude Code via--setting-sourcesand deleted on exit - Socket open — The Unix Domain Socket listener starts at
<projectDir>/.claude/run/ink-<PID>.sock - TUI render — The terminal UI (React 19 + Ink 6) initializes and displays the session header
- Ready — Athena waits for Claude Code to start and send hook events
Hook Registration
Claude Code supports hooks — binaries that Claude Code calls at specific lifecycle points. Athena registers the athena-hook-forwarder binary for all 13+ hook event types. Hook events that require a tool matcher use "*" to receive all tool calls.
Claude Code calls the forwarder synchronously — the agent pauses briefly while the forwarder runs. The forwarder is intentionally minimal: read stdin, write to socket, exit. It completes in single-digit milliseconds.
Event Processing
When an event arrives at the Athena runtime via the socket:
- Parse — The NDJSON envelope is decoded and mapped to a
RuntimeEventwith a canonicalRuntimeEventKind - Store — The event is persisted to SQLite in the current session database
- Policy evaluation — If the event is a
tool.preorpermission.request, the isolation policy (controller) evaluates it and produces aRuntimeDecision. Decisions withsource: 'rule'are auto-applied; decisions requiring user input pause the feed - Feed mapping — The runtime event is transformed into one or more
FeedEventobjects by the feed mapper, then appended to the timeline - Workflow step — If a workflow is active and running a loop, the event is checked against completion and blocked markers
- UI update — The Ink/React tree re-renders with the new feed events
This pipeline runs in Node.js event loop order — each step completes before the next. SQLite writes are synchronous (better-sqlite3), which is fast enough that async adds no benefit.