Atuin Review: The Shell History Tool That Actually Earned a Slot in My Dotfiles Dev Tools

Atuin Review: The Shell History Tool That Actually Earned a Slot in My Dotfiles

by Joule P. Kraft · May 22, 2026

I am extremely skeptical of dev tools that ask to live between me and my shell. Most of them last a week. Half of them break something I cared about. The bar for “okay this gets to stay in my dotfiles” is high, and very few things clear it.

Atuin cleared it about six months ago and I’ve been running it daily since. This is the review.

What Atuin Is

Atuin replaces your shell’s history. That’s the whole pitch. Instead of ~/.zsh_history (or ~/.bash_history) being an append-only text file, Atuin stores every command in a local SQLite database, then gives you a fast fuzzy search UI bound to Ctrl-R.

Underneath that one-line description, it does a few things that matter:

  • Records context with each command — exit code, duration, working directory, hostname, session id. So you can search “all the commands I ran in this repo last week that exited with non-zero status.”
  • Survives across sessions and terminals. If you ran a command in tmux pane 4 yesterday, you can find it from a fresh terminal today. The old HISTFILE flow of “history is per-shell-session” goes away.
  • Optionally syncs end-to-end-encrypted history across machines. Self-hostable. Or use the free hosted service. Or don’t sync at all.
  • Doesn’t replace your shell. It hooks into zsh/bash/fish via a small init snippet. Your $SHELL is still your shell. If you uninstall Atuin tomorrow, your ~/.zsh_history is still there.

That last point is what got me to try it. I’ve been burned by tools that take over a workflow and then become impossible to remove. Atuin is opinionated about its database but it doesn’t touch your shell’s native history file. You can A/B it.

Installation

On macOS:

brew install atuin

On Linux, there’s a one-liner installer at atuin.sh or you can use your package manager. Then add one line to your shell rc:

# zsh
eval "$(atuin init zsh)"

# bash
eval "$(atuin init bash)"

# fish
atuin init fish | source

Then either let it import from your existing history, or run:

atuin import auto

That’s it. Open a new shell. Hit Ctrl-R. The new UI is now there.

What Replaces Ctrl-R

The default Atuin UI is a full-screen fuzzy search with a list of past commands, their exit codes, when they ran, and how long they took. You type, the list filters in real time, you arrow up/down, you hit enter, the command lands on your prompt.

The exit-code coloring is the small detail I didn’t expect to care about. Failed commands are red. Successful ones are green. Most of the time when I’m Ctrl-R-ing, what I want is “the version of this command that worked last time.” Atuin makes that visually obvious.

You can also filter by directory or session:

  • Ctrl-R then Tab cycles search scope (global / session / directory).
  • Searching with the cwd filter on is the killer feature. “What was that complicated docker compose invocation I ran in this repo two weeks ago?” — type docker, scope to directory, done.

The other thing the UI surfaces is command duration. After a few weeks of using Atuin I had a much better sense of which of my regular commands were actually slow. A surprising number of “I think this is slow” commands were not. A surprising number of “I think this is fast” commands took 8 seconds. This is genuinely useful information that I never had visibility into before.

What Sold Me

Three things, in order of how often they save me time.

1. Cross-Session History That Just Works

I run a lot of tmux. I also reboot. Native zsh history with setopt SHARE_HISTORY mostly works, but every now and then it does something weird — a session’s commands get lost, or two sessions interleave their writes and you get half-commands. Atuin’s “every command goes to SQLite immediately, every session reads from the same SQLite” model has been bulletproof for me. I have never lost a command since I started using it.

This one I underestimated. About half my Ctrl-R queries are some variation of “the thing I ran here before.” With native history, I had to remember enough of the command to disambiguate it from the same command run elsewhere. With Atuin, I just scope to cwd and the noise is gone.

This is especially nice in monorepos. If I have a npm test -- --watch <some-package> invocation I used last Tuesday in packages/foo/, I can stand in that directory and pull it up instantly.

3. Stats

Run atuin stats and you get a summary of your most-run commands, your longest-running commands, and your most common typos. This is just fun, but it’s also occasionally useful. Mine consistently shows that I run git status an embarrassing number of times per day. Make of that what you will.

The Sync Story

Atuin can sync your shell history across machines, end-to-end encrypted. There’s a free hosted service (api.atuin.sh), and the server is open source if you want to self-host.

I do not use sync.

Not because anything is wrong with it — the encryption story is solid, the team has been thoughtful about it, and people I trust use it without issue. I just don’t want my shell history leaving my machines. My laptop and my homelab and my server all have separate, machine-local Atuin databases. That has been fine. If you do want sync, the setup is one command and a registration.

If you self-host, the server is a small Rust binary backed by Postgres. Reasonable to run alongside other home-server services.

The Couple of Things That Annoy Me

A short list, in fairness:

  • First-paint latency on a huge history. I imported about 80,000 commands when I first installed Atuin. The initial UI render was visibly slow for the first few weeks. A atuin search index rebuild fixed it, but it wasn’t obvious that was the fix.
  • Multi-line commands display awkwardly. If you have a multi-line shell snippet in history (a heredoc, a multi-line for loop), Atuin shows it on one line in the search UI. Selecting it works fine, but the preview is cramped.
  • fzf users will want to disable fzf’s Ctrl-R integration. Otherwise they’ll fight. This is documented but I missed it the first time and was confused for ten minutes.
  • The default keybinding for “execute immediately” vs “edit at prompt” surprised me. Enter executes; Tab puts it on the prompt for editing. I want the reverse half the time. There’s a config option for it, but the default tripped me up.

None of these are dealbreakers. The first is one-time. The rest are documented.

My Config

For reference, the relevant chunks of my ~/.config/atuin/config.toml:

# Filter scopes I use
filter_mode_shell_up_key_binding = "session"
search_mode = "fuzzy"

# UI
style = "compact"
inline_height = 20

# Don't sync — local only
auto_sync = false

# Don't record commands prefixed with a space (lets me run a "secret" command)
history_filter = [
  "^secret-",
]

And in my zshrc, after the Atuin init:

# Bind Up-Arrow to atuin's session-scoped search (not global)
# This keeps the "up arrow walks history of *this* session" behavior I'm used to
bindkey '^[[A' atuin-up-search

That last bit is the one I’d recommend if you’re trying it for the first time. The Atuin default rebinds up-arrow to a global fuzzy search, which is a much bigger behavioral change than most people want. Session-scoped up-arrow gives you “shell history as you’ve always known it” for up-arrow, and a much better Ctrl-R on top.

Should You Install It?

If you live in a terminal and use Ctrl-R more than a handful of times a day, yes. It is the rare dev tool that earns its slot and then keeps earning it. The install is reversible. Your existing history file is untouched. The worst case is you uninstall it in a week and you’re back exactly where you started.

If you Ctrl-R once a week and you’re happy with your current flow, skip it. It’s a workflow upgrade for shell-heavy people. It’s not a revelation for people who barely use shell history.

For me, it’s the most consistent quality-of-life improvement I’ve made to my shell environment since switching to a justfile-based workflow. And unlike most dotfile changes, I don’t even think about it anymore. It’s just how my shell works now.