Skip to content
Story

Why I Built Suvadu

By Madhubalan Appachi7 min read

It started with a production incident at 2 AM. I remembered running a specific kubectl command three days earlier that fixed the exact same problem. I knew the command existed somewhere in my history. I pressed Ctrl+R, typed fragments, scrolled through hundreds of irrelevant matches, and eventually gave up. I retraced my steps manually, wasting 40 minutes on something I had already solved.

That night, I decided standard shell history had to go.

The Problem with Shell History

Your shell's built-in history is, fundamentally, a plain text file. It hasn't meaningfully changed since the 1970s. Every command you type gets appended to ~/.zsh_history (or ~/.bash_history), one line at a time, with almost no metadata.

Think about what that means:

  • No context. You can see that you ran docker compose up -d, but not which directory you were in, whether it succeeded, or how long it took.
  • No filtering. You can't search for "all failed commands from last week" or "commands I ran in the payments repo."
  • No indexing. Every search is a linear scan through a flat file. With 50,000 commands, that starts to lag.
  • No deduplication. Run git status ten thousand times? You'll see it ten thousand times in your history.
  • No source tracking. Was that command typed by you, executed by your IDE, or run by an AI assistant? History doesn't know, and it doesn't care.

I had been working around these limitations for years with various hacks: shell aliases to grep history, custom scripts to deduplicate, even a messy Python wrapper. None of it felt right.

What I Wanted

I sketched out what an ideal shell history system would look like:

  1. Database-backed. Every command stored in a proper database with metadata: working directory, exit code, duration, timestamps with millisecond precision.
  2. Instant search. Indexed queries that return in under 10ms, even with hundreds of thousands of entries.
  3. Zero overhead. Recording a command should add less than 2ms of latency. Shell responsiveness is non-negotiable.
  4. Fully local. No cloud sync, no accounts, no telemetry. My command history is deeply personal and often contains sensitive information.
  5. Executor tracking. In an age of AI coding assistants and IDE terminals, I wanted to know who ran each command, not just what was run.

Why Rust

The performance requirement alone ruled out scripting languages. Every millisecond matters in a shell hook that fires on every single command. Rust gave me native speed, memory safety, and the ability to statically link SQLite directly into the binary. One binary, no dependencies, no runtime.

SQLite with WAL (Write-Ahead Logging) mode turned out to be the perfect storage engine. It gives you concurrent reads while writes happen, and with synchronous=NORMAL, each insert takes roughly 1ms. The entire database is a single file that lives at ~/Library/Application Support/suvadu/history.db on macOS.

Building the Hooks

The trickiest part was making the Zsh integration invisible. Suvadu hooks into two Zsh lifecycle events:

  • preexec fires just before a command executes. We capture the command string and record the start time using Zsh's native $EPOCHREALTIME — pure shell arithmetic, no subprocesses.
  • precmd fires just before the next prompt appears. We grab the exit code from $?, compute duration, detect the executor, and fire off suv add with all the metadata.

The executor detection was the feature I was most excited about. By inspecting environment variables at capture time, Suvadu can tell whether a command was run by a human in a terminal, by Claude Code, by Cursor, by a CI pipeline, or by a dozen other tools. This turns your history from a flat log into a rich audit trail of everything happening in your development environment.

What Suvadu Does Today

What started as a weekend project to fix my own history workflow has grown into a full-featured CLI with 14+ commands:

  • Interactive TUI search with filters for date range, tags, exit codes, executors, and working directory. Sub-10ms query time.
  • Arrow key navigation that works like built-in history but powered by frecency ranking (frequency x recency).
  • Session tagging to organize commands by project or workspace.
  • Bookmarks and notes for commands you want to remember with context.
  • Stats dashboard with heatmaps, hourly distribution charts, and top commands analysis.
  • Alias suggestions that analyze your history and recommend shell aliases for frequently typed long commands.
  • Import/export in JSONL and CSV formats, plus direct import from ~/.zsh_history.
  • Native Claude Code integration via PostToolUse hooks.

The Name

Suvadu (pronounced "soo-va-doo") means "trace" or "footprint" in Tamil. Every command you run leaves a trace. Suvadu makes sure you never lose it.

Your history is the story of your work. It deserves better than a text file.

If you're tired of losing commands, try Suvadu. It installs in 30 seconds, runs 100% locally, and makes your shell history actually useful.

Share this article

PostShare
👣Try Suvadu

Total recall for your terminal. Database-backed shell history with AI agent tracking, built in Rust.

Install now →
👣

Madhubalan Appachi

Building developer tools at Appachi Tech. Creator of Suvadu and Kaval.

Related Posts