The k9s for AI Agents: Unpacking Tempo
How a React-driven terminal dashboard uses direct SQLite introspection to orchestrate parallel AI coding sessions.
- Tempo centralizes the management of parallel AI coding agents into a single terminal dashboard.
- The application bypasses official CLI limitations by directly querying the underlying SQLite database to extract real-time session states.
- It utilizes the Ink library and an unmount-remount architecture to use React as a low-level system process dispatcher.
- Strict TypeScript discriminated unions and Vim-inspired navigation ensure terminal ergonomics match modern developer expectations.
The Swarm Bottleneck
We moved from chatting with single AI assistants to dispatching multiple autonomous agents in parallel. One agent refactors, another writes tests, a third scours documentation. The terminal quickly becomes a chaotic bottleneck.
When running multiple instances of tools like opencode, developers lose track of which agent is working, which is stalled awaiting input, and which has finished. Tempo acts as a centralized command center to solve this context-switching penalty.
| Standard Agent CLI | Tempo Dashboard |
|---|---|
| Sequential execution | Parallel execution monitoring |
| Blind to background tasks | Visual status indicators (pending/working) |
| Manual process backgrounding (ctrl+z) | One-keystroke session switching |
| State is hidden behind API | State is extracted via direct DB queries |
Bypassing the API
The standard opencode CLI does not expose real-time granular states in a list view. Tempo bypasses the official CLI entirely. It queries the underlying opencode.db SQLite file directly.
Using complex json_extract calls, Tempo parses internal states in real-time. It knows exactly when a session is working or pending user input. It includes a fallback mechanism that reverts to the standard CLI if the SQLite query fails, ensuring resilience against schema changes.
React as a System Dispatcher
Building a CLI tool with a web framework sounds counterintuitive. Tempo uses the Ink library to render React components in the terminal. This allows the developer to construct complex, stateful system tools using familiar frontend patterns.
The architecture relies on an Unmount-Remount pattern. Tempo entirely unmounts its React tree to hand over raw terminal control to a spawned child process. When the user exits the session, the dashboard successfully remounts.
async function startApp() {
const { waitUntilExit } = render(<App />);
await waitUntilExit();
// Wait for child process to finish, then remount
if (shouldRestart) {
startApp();
}
}
State Machines and Vim Constraints
Developer ergonomics dictate whether a CLI tool survives its first week. Tempo implements native Vim bindings embedded directly within React components. Users navigate with j, k, gg, and G.
It uses TypeScript Discriminated Unions to manage application state. By defining modes like ModeFiltering and ModeConfirmDelete, the developer prevents impossible UI states. You cannot filter and delete simultaneously.