services/computer-use-mcp/airi-cli-architecture.md
Define a narrow architecture for a terminal-facing AIRI coding CLI that can
optionally render an animated avatar through chafa, without coupling terminal
presentation to the computer-use-mcp runtime.
This document is a boundary and contract proposal. It is not an implementation plan for a full CLI in this PR.
As of 2026-04-26, the main branch does not expose a stable coding runner event stream. A CLI that renders real progress needs a runner contract first. Starting with terminal animation before that contract exists would produce presentation without reliable runtime state.
The correct dependency order is:
chafa avatar rendering as a display adapter.packages/airi-cli.chafa is optional presentation only.chafa dependency belongs in services/computer-use-mcp core runtime.computer-use-mcp must remain headless-safe and CI-safe.chafa must degrade to plain text rendering.services/computer-use-mcp.packages/airi-cli.packages/airi-cli/src/renderers/text.ts.packages/airi-cli/src/renderers/chafa-avatar.ts.packages/airi-cli/src/adapters/jsonl.ts.Use an append-only event envelope. The first transport should be an in-process callback. JSONL is an adapter over the same envelope.
interface RunnerEventEnvelope<TKind extends string = string, TPayload = unknown> {
runId: string
seq: number
at: string
kind: TKind
payload: TPayload
}
Contract rules:
seq is strictly increasing per runId.at is an ISO timestamp.run_startedpreflight_startedpreflight_completedstep_startedtool_call_startedtool_call_completedassistant_messagestep_timeoutreport_statusrun_finishedrun_crashedrun_started:
interface RunStartedPayload {
workspacePath: string
taskGoal: string
maxSteps: number
stepTimeoutMs: number
}
step_started:
interface StepStartedPayload {
stepIndex: number
maxSteps: number
}
tool_call_started:
interface ToolCallStartedPayload {
toolName: string
argsSummary: string
}
tool_call_completed:
interface ToolCallCompletedPayload {
toolName: string
ok: boolean
status?: string
summary: string
error?: string
}
assistant_message:
interface AssistantMessagePayload {
text: string
}
report_status:
interface ReportStatusPayload {
status: 'completed' | 'failed' | 'blocked'
summary?: string
}
run_finished:
interface RunFinishedPayload {
finalStatus: 'completed' | 'failed' | 'blocked' | 'timeout'
totalSteps: number
error?: string
}
The CLI should have three separable layers.
Input adapters convert transport-specific input into RunnerEventEnvelope
events.
Initial adapters:
The reducer builds deterministic CliViewState from events.
Rules:
Renderer adapters consume CliViewState.
Initial renderers:
chafa avatar rendererThe chafa adapter should:
chafa binary availability at startupInitial CLI flags:
--avatar=chafa|none--no-avatar--events=runner|stdin|jsonl-file--output=pretty|jsonlseq.chafa.packages/airi-clichafa rendererchafachafa dependency is added under services/computer-use-mcp.chafa is not installed.chafa.Layering:
computer-use-mcp runtimechafa dependency in runtime packagespackages/airi-cliRuntime:
Fallback:
chafa does not fail CLI executionScope:
feat(cli): define coding runner event contractfeat(cli): scaffold airi coding cli text rendererfeat(cli): add optional terminal AIRI avatar renderer with chafa