How Amplifier learned to see and fix its own terminal UI
amplifier-tui — a Textual-based terminal UI for Amplifier, 284 commits, 282 by Sam Schillace — set out to make Amplifier usable from a rich terminal. The catch: the agent building that terminal could not look at the rendered layout it was supposed to fix.
First, the payoff of doing it right: one engine, everywhere.
Because the session logic was cleanly separated into a shared core, the same engine renders through a Textual terminal app, a FastAPI + WebSocket web app on port 8765, and a PySide6 desktop app.
"Works anywhere" is built, not aspirational. But building the first surface hurt.
The central pain of building the terminal UI: the agent could not see the rendered layout it was supposed to be fixing. app.py alone is 7,131 lines of tightly coupled widgets, actions, and CSS — and no eyes on any of it.
So the first move was to make the invisible screen capturable.
A headless capture pipeline (tools/ux_test.sh) runs the app without a live terminal and exports a Textual SVG of exactly what it looks like — injecting the app's real widget types so the screenshot reflects true rendering, not a simulation.
Now the screen exists as a file. Next: read it precisely.
The design insight, recorded in the manual: Textual's SVG export contains every character with exact position, color, and style — making SVG parsing far superior to OCR. The parser uses only stdlib (xml.etree), so there's zero ML guesswork.
Precise enough to trust — and general enough to lift out.
The generic capture engine was extracted into ramparte/textual-capture, a standalone package the TUI now depends on — providing capture_svg / capture_png / capture plus parse_svg. When the TUI refactored onto it, all 263 tests still passed.
The fix outgrew the project. Now it closes the loop.
Amplifier captures its own screenshot, parses what it sees into structured YAML, spots the layout bug, fixes it, and re-captures. The blind agent from the frame now has eyes on its own work.
One pattern, reusable far beyond a terminal UI.
Once it can see what it makes, an agent can close the build–see–fix loop itself. Here it was a terminal UI rendered to SVG — but the pattern reaches far beyond terminals.
Build it so the maker can look at its own work.
Data as of: Development spanned 2026-02-05 → 2026-04-23 (final local commit c967de0).
Primary sources: ramparte/amplifier-tui (PRIMARY, verified) and ramparte/textual-capture (extracted capture engine).
Commands run:
git rev-list --count HEAD → 284 commits; git log --format='%an' | sort | uniq -c | sort -rn → 282 Sam Schillace, 1 ramparte, 1 Michael J. Jabbourgrep -A4 'project.scripts' pyproject.toml → 3 entry points (amplifier-tui, amplifier-web, amplifier-desktop)ls amplifier_tui/core/commands/*.py | wc -l → 18 files (17 command mixins + __init__.py)grep -in 'websocket\|FastAPI' web/server.py; grep -in '8765' __main__.py → /ws WebSocket, default port 8765git log desktop/ → 383b02f "PySide6 desktop frontend (all 11 phases implemented)"cat tools/ux_test.sh → capture → svg_parser → tui_analyze → YAML pipelinegit show 9b2232d → extraction to textual-capture; "All 263 existing tests still pass"wc -l amplifier_tui/app.py → 7,131 lines; grep -n 'SVG' docs/manual.html → SVG-over-OCR design notePrimary contributor: Sam Schillace (282 of 284 commits, ~99%).
Gaps: textual-capture's local .git HEAD is a bad object, so its commit dates/counts are unverified; its facts are grounded on present files and on amplifier-tui commit 9b2232d. Manual's inline app.py/styles.tcss line figures are stale; current wc -l counts used. The web UI is an MVP.