0001 — Founding stack and architecture

Context

DashFloat replaces Octofriend as our CLI AI coding harness: a fast, robust, responsive terminal application that streams LLM responses, executes structured tool calls, and manages coding sessions. The founding spec settled the goal, stack, and shape; this ADR is its durable record — the decisions that outlive the bootstrap task that created this repository (issue #1). All dependency versions were verified on hex.pm on 2026-10-23 (mix hex.info).

Decision

Build DashFloat in Elixir on Erlang/OTP. The concurrency model — processes, GenServers, Tasks, Ports — maps directly onto the harness's concurrent workloads (streaming, tool execution, session management).

Stack

Concern Choice Pin Verified notes
Language / runtime Elixir / Erlang OTP mix.exs requires ~> 1.20.0; dev runs 1.20.4 / OTP 29; CI floats 1.20.x (currently 1.20.4) ex_ratatui supports Elixir 1.17+, OTP 26–29
TUI ex_ratatui ~> 0.17.1 Rustler-backed ratatui bindings; precompiled NIFs for OTP 26–29 (ABI 2.17 loads on OTP 29)
HTTP + SSE req ~> 0.7.5 stable line (0.8 is release-candidate only)
JSON jason ~> 1.4 1.4.5 is the latest stable
Distribution burrito ~> 1.6 single-binary releases; musl precompiled NIFs are a supported payload

Process architecture

Four cooperating processes; the UI process never performs I/O.

  1. UI process (ExRatatui runtime) — owns global UI state (input buffer, scroll positions, session history, execution status) and renders purely. State changes are immutable transformations inside handle_info/2 / handle_event/2.
  2. Agent Manager (GenServer) — coordinates model state, context-window management, tool selection, and tool execution.
  3. Stream Handler (Task) — consumes SSE from the LLM provider, buffers chunks, and sends parsed tokens to the UI process via send/2.
  4. Subprocess Executor (Port/Task) — spawns shell commands and file operations in isolated processes and returns output to the UI without blocking state.

Guideline: all I/O — network, filesystem, shell commands — lives off the UI process, inside dedicated Tasks or GenServers, so the render loop stays fast and non-blocking. Failed subprocesses report back to the chat stream gracefully rather than crashing the BEAM node.

Key subsystems

The TUI is three regions: a header/status bar (model info, context-size indicator, execution state — idle / streaming / executing tool), a scrollable main log view (markdown-formatted model messages, tool calls, shell outputs), and a multi-line input box with history navigation and an execution trigger (Enter / Ctrl+Enter).

The core toolset is fixed and structured (JSON function calls):

File mutation uses explicit, structured search-and-replace blocks — no line-number or best-guess edits. Changes are previewed in the TUI before they are applied whenever user confirmation is required.

Roadmap

Alternatives considered

Consequences