Skip to main content
Welcome. This site supports keyboard navigation and screen readers. Press ? at any time for keyboard shortcuts. Press [ to focus the sidebar, ] to focus the content. High-contrast themes are available via the toolbar.
serard@dev00:~/cv

From 1270 Lines to State Machines: Rebuilding a Developer CLI

We had 28 state machines in the frontend. The developer CLI had zero.

This site's browser code uses pure, testable state machines for everything: SPA navigation, scroll spy, theme switching, copy feedback, sidebar resizing. Factory functions. Callback injection. Guard clauses. No global state. 28 of them in src/lib/, each under 100 lines, each independently testable.

Meanwhile, the developer workflow tool — the CLI that builds, tests, serves, audits, commits, and deploys the site — was a single 1270-line file with 6 mutable globals, nested wizard state tracked through booleans, and zero unit tests.

Same developer. Same project. Two completely different architectures.

This series tells the story of bringing the frontend's state machine pattern to the CLI — and what happened when we did.

The Journey

Impact

Metric Before After
Entry point 1270 lines 30 lines
Mutable globals 6 0
Files 1 24 source + 15 test
Max file size 1270 lines < 150 lines
Unit tests 0 81
Test duration untestable 600ms
Processes spawned in tests N/A 0
--help 60 hand-written lines Auto-generated at every level

The same developer who architected the frontend's 28 state machines applied the exact same pattern to rebuild the CLI tooling. No framework switch. No new library. Just the same TypeScript pattern, in a different domain.