/user/kayd @ devops :~$ cat atuin.md

Atuin Cheatsheet: Better Shell History Search Atuin Cheatsheet: Better Shell History Search

QR Code linking to: Atuin Cheatsheet: Better Shell History Search
Karandeep Singh
Karandeep Singh
• 9 minutes

Summary

Atuin turns your shell history into a searchable database. What it is in plain words, the install, the search keys, filter and search modes, encrypted sync across machines, and the gotchas — every command checked against Atuin 18.19.0.

Every terminal user has done this: you ran the right command last Tuesday, on a different machine, in a different directory, and now you are pressing the up arrow forty times hoping to recognise it. Ctrl-R helps a little, but it only matches from the start of what you type and shows you one result at a time.

Atuin fixes that. It replaces your shell history with a small database, then gives Ctrl-R a real search screen — fuzzy matching, multiple results at once, and filters like “only commands I ran in this folder”. Optionally it syncs that history between your machines, encrypted so the server cannot read it.

Everything below was checked against Atuin 18.19.0 on Linux. If you live in a terminal all day, pair this with my tmux cheatsheet.

What it actually does, in plain words

Your shell normally keeps history in a plain text file — one command per line, and that is all it knows. Atuin keeps a SQLite database instead, and records extra facts about every command:

Atuin remembersWhy you care
The command itselfSame as before
Which directory you ran it in“What did I run in this repo?”
Whether it worked (exit code)Skip the commands that failed
How long it tookSpot the slow ones
Which machine and sessionSeparate work laptop from server
When you ran it“Sometime last week” becomes searchable

That extra context is the whole point. A text file cannot answer “show me the commands I ran in this folder that actually succeeded” — a database can.

plain english
SQLite is just a database that lives in a single file. There is no server to run and nothing to configure — Atuin creates the file at ~/.local/share/atuin/history.db and that is it. If you ever want out, your history is sitting right there in a standard format.

Install

# The official one-liner
curl --proto '=https' --tlsv1.2 -LsSf https://setup.atuin.sh | sh

Or through a package manager you already trust:

brew install atuin              # macOS / Linuxbrew
cargo install atuin --locked    # if you have Rust
paru -S atuin                   # Arch

Then wire it into your shell. This is the step people forget — installing the binary alone does nothing to Ctrl-R:

echo 'eval "$(atuin init bash)"' >> ~/.bashrc     # bash (also needs ble.sh or bash-preexec)
echo 'eval "$(atuin init zsh)"'  >> ~/.zshrc      # zsh
echo 'atuin init fish | source'  >> ~/.config/fish/config.fish

Atuin supports bash, zsh, fish, nushell, xonsh and PowerShell.

Bring your existing history across — this reads your old history file and imports it, so you do not start from an empty screen:

atuin import auto     # detects your current shell
atuin import bash     # or name it explicitly
atuin import zsh
atuin import fish

atuin import also understands nu, xonsh, powershell, replxx, resh, and the SQLite-backed variants zsh-hist-db, nu-hist-db and xonsh-sqlite.

your old history is safe
Importing copies from your existing history file into Atuin’s database. It does not delete or rewrite ~/.bash_history. If you decide Atuin is not for you, remove the eval line from your shell config and everything is exactly as it was.

The search screen

Press Ctrl-R (or the up arrow) and you get a full search UI instead of a one-line prompt.

KeyWhat it does
Ctrl-ROpen search — press again to cycle the filter mode
Up arrowAlso opens search (rebindable)
EnterRun the selected command
TabPut it on your prompt to edit before running
Alt-1Alt-9Jump straight to result 1–9
Esc / Ctrl-CCancel

Tab is the one to remember. Most of the time you want last week’s command nearly verbatim — one flag different — and Tab hands it to you for editing rather than firing it off immediately.

If you would rather keep your normal keys, turn the bindings off individually:

atuin init bash --disable-ctrl-r      # leave Ctrl-R alone
atuin init bash --disable-up-arrow    # leave the up arrow alone
atuin init bash --disable-ai          # leave "?" alone

Filter modes — the killer feature

Pressing Ctrl-R again while the search screen is open cycles through what you are searching:

Filter modeSearches
globalEverything, every machine (the default)
hostOnly this machine
sessionOnly this terminal session
directoryOnly commands run in this folder
workspaceThe current git repo

directory is the one that changes how you work. Land in a project you have not touched in six months, hit Ctrl-R twice, and you are looking at exactly the commands you last ran there — the right make target, the right docker compose invocation, the right deploy script.

Set your usual default in the config, or override it per command:

atuin search --filter-mode directory deploy
atuin search --filter-mode host kubectl

Search modes

How your typing is matched:

Search modeBehaviour
fuzzyLetters in order, gaps allowed — the default
prefixMust start with what you typed
fulltextMatch anywhere in the command
daemon-fuzzyFuzzy, served by the background daemon

Fuzzy is why this feels fast. Typing kgp finds kubectl get pods — the letters just have to appear in order, not next to each other:

atuin search --search-mode fuzzy "kgp"
2026-08-11 22:29:53	kubectl logs -f deploy/api	0s
2026-08-11 22:29:53	kubectl get pods -n prod	0s

Note that kubectl logs -f deploy/api matches too — it also contains k…g…p in order. Fuzzy is generous on purpose; you narrow it by typing another letter or two.

Searching from the command line

The search screen is interactive, but atuin search works in scripts too:

atuin search kubectl                       # plain text search
atuin search --limit 5 docker              # cap the results
atuin search --cwd /srv/app terraform      # only in this directory
atuin search --exclude-cwd /tmp deploy     # skip a directory
atuin search --exit 0 make                 # only commands that succeeded
atuin search --exclude-exit 0 make         # only commands that FAILED
atuin search --after "1 day ago" aws       # time-boxed
atuin search --before "2026-08-01" psql
atuin search -i                            # open the interactive UI

--exclude-exit 0 deserves a mention: it shows you only the commands that failed, which is a surprisingly good way to reconstruct what went wrong during an incident.

the gotcha that trips everyone

Run atuin search in a script or CI job and you may get:

Error: Failed to find $ATUIN_SESSION in the environment.
Check that you have correctly set up your shell.

Nothing is broken. Atuin’s shell init exports ATUIN_SESSION in every interactive shell, and non-interactive contexts never run it. Set one yourself:

export ATUIN_SESSION=$(atuin uuid)
atuin search kubectl

That is precisely what the atuin uuid subcommand exists for.

Stats

atuin stats                        # since the beginning
atuin stats last week
atuin stats --count 20             # top 20 instead of top 10
atuin stats --ngram-size 2         # count two-word commands together

--ngram-size 2 is the useful one: it counts git commit and git push separately instead of lumping everything under git.

Total commands:   10
Unique commands:  10

Sync between machines

Sync is optional. Atuin is perfectly good as a local-only tool, and if you never run register nothing leaves your machine.

On your first machine:

atuin register -u <username> -e <email>   # create an account
atuin sync                                # push history up
atuin key                                 # PRINT YOUR ENCRYPTION KEY — save it

On every other machine:

atuin login -u <username>                 # it will ask for the key from above
atuin sync
atuin status                              # check it worked
atuin sync -f          # force a full sync
atuin logout
atuin account delete   # remove the account entirely
do not lose the key

Your history is encrypted on your machine before upload, so the server stores something it cannot read. That is good for privacy and unforgiving about key loss: without the key from atuin key, a new machine cannot decrypt the history it downloads, and nobody can recover it for you — the server genuinely does not have it.

Save it in your password manager the moment you register, not later.

Prefer not to trust anyone else’s server? Point Atuin at your own by setting sync_address in the config — the server is open source and self-hostable.

Config worth changing

Lives at ~/.config/atuin/config.toml. Print the fully commented default with atuin default-config.

search_mode = "fuzzy"                 # prefix | fulltext | fuzzy | daemon-fuzzy
filter_mode = "global"                # global | host | session | directory | workspace
style = "compact"                     # "compact" or "full"
inline_height = 40                    # 0 = full screen; small number = inline
show_preview = true                   # show the full command in a preview pane
enter_accept = true                   # Enter runs it; false = Enter only selects
keymap_mode = "emacs"                 # or "vim-normal" / "vim-insert"
auto_sync = true
sync_frequency = "5m"
sync_address = "https://api.atuin.sh" # change for a self-hosted server
workspaces = false                    # treat git repos as workspaces
secrets_filter = true                 # do not record things that look like secrets
update_check = true

Three worth a second look:

  • secrets_filter = true — on by default, and it tries to keep API keys and tokens out of the database. Leave it on.
  • inline_height — a full-screen takeover on every Ctrl-R annoys some people. Set something like 20 and the search appears inline instead.
  • enter_accept — set to false if you want Enter to put the command on your prompt rather than run it straight away. Safer if you tend to hit Enter reflexively.

To stop recording specific commands entirely, use the filters:

history_filter = ["^secret-cmd", "^curl .*token"]   # by command pattern
cwd_filter = ["^/very/secret/directory"]            # by directory

When something is wrong

atuin doctor      # checks for common setup problems
atuin info        # where the config and database live
atuin --version

atuin doctor first, always. It catches the usual suspects — shell integration not loaded, a missing bash-preexec on bash, a stale daemon.

Beyond history

Recent versions carry more than search. Worth knowing they exist:

atuin dotfiles    # sync aliases and env vars alongside history
atuin scripts     # save and run parameterised scripts
atuin kv          # small key-value store, synced
atuin wrapped     # a year-in-review of your terminal
atuin daemon      # background daemon (experimental)
atuin mcp         # expose history search to AI tools over MCP

That last one may interest you if you have been building with the Model Context Protocolatuin mcp runs a stdio MCP server so an assistant can search your shell history as a tool.

0

Is it worth it?

If you use one machine and rarely repeat commands, plain Ctrl-R is fine and this is overkill.

It earns its place when you have more than one machine, or when your commands are long enough that retyping them is a real cost — kubectl invocations with four flags, docker run lines with six mounts, aws commands with ARNs in them. Directory filtering alone saves the “what was the command for this project again?” round trip, several times a day.

Start local. Skip register entirely, run it for a week, and only set up sync once you have caught yourself wishing your laptop knew what you typed on the server.

1

References

Question

How many times a day do you press the up arrow more than five times in a row?

Similar Articles

More from devops

tmux Cheatsheet

Quick-reference tmux cheatsheet: sessions, windows, panes, copy mode, synchronize-panes, .tmux.conf …

Jenkins Cheatsheet

Jenkins cheatsheet with declarative pipeline syntax, credentials, parameters, parallel stages, …

Bash Basics Cheatsheet

Quick-reference Bash basics cheatsheet: variables, parameter expansion, conditionals, loops, arrays, …

Knowledge Quiz

Test your general knowledge with this quick quiz!

A set of multiple-choice questions to test your knowledge.

Take as much time as you need.

Your score will be shown at the end.