The Nightly Build.
Expert Tools

Atuin makes your shell history answer questions bash can't

Every command lands in a local SQLite file with its directory, exit code, and duration, and the encryption that syncs it covers less than the word suggests.

Bash history is a list of strings

Bash writes each command you run to .bash_history, one line per command, and that line is all it keeps. The file holds the text you typed and nothing about the run: not the directory you were in, not whether the command succeeded, not how long it took. Atuin replaces that file with a SQLite database and records the surrounding context beside every command.1 The command text is still there. So are the working directory, the exit code, the duration, the session, and the hostname, each a column the schema names.2

With Atuin, that history stops being a flat log and becomes a table you can query.

Asking Atuin which commands failed here

A build broke in this directory last week and you want the command that failed. In bash your history is text, so the most you can do is grep for a fragment you remember and read past every success to find the failure. The exit code was never written down, so the plain question, which commands failed, is one the file cannot answer at all.

Atuin wrote the exit code and the directory into their own columns, so the same question is a filter.2

shell sessionSHELL
# bash: history is plain text, with no exit code and no directory
history | grep make

# atuin: the same commands, now filtered by how and where they ran
atuin search --exclude-exit 0 --cwd .
Fig. 1 · The bash query can only match text; the Atuin query filters on context bash never recorded.3

Read the second command the way you would trace any tool: by what each part does. --exclude-exit 0 drops every command that exited cleanly. --cwd . restricts the search to the directory you are standing in. What remains is the commands that failed here, newest first.3 The directory and the exit code did the work, and neither is in .bash_history, which is why the same request against bash returns a pile of text you still have to read by hand.

The filter reaches only what the shell hook captured. A command you ran before installing Atuin, or in a shell where the hook is not loaded, is not in the table, and the search will not invent it. The database answers for what it saw and says nothing about the rest. Atuin records more than the two fields this query uses, including the shell, a timestamp, and, more recently, an author field that marks whether a human or an AI agent ran the command.4

The hook runs on every command

Recording that context has a price, and the price is paid on every prompt. To capture a command, Atuin installs a shell hook: a preexec step runs before the command and records its text, time, and directory, and a precmd step runs after it and records the exit code and duration.5 That hook fires every time you press enter. It is written in Rust and does little, but it is real work on the path you hit most, and it is the cost you cannot opt out of while still using the tool. The database is the other standing cost. It grows with your history, and it sits on disk unencrypted.

Atuin also ships a background daemon, and it is easy to assume that is part of the deal. It is not. The daemon is opt-in: its enabled setting defaults to false and it does not autostart.6 Sync, when you turn it on, runs in the shell process on a default cadence of five minutes, not through a resident service.6 So the footprint you are actually adopting is the hook and the SQLite file, and nothing that keeps running when your shell is closed.

One default costs more than compute. Atuin rebinds both Ctrl-R and the up arrow to a full-screen search interface.7 Ctrl-R for search is what you would expect. Rebinding the up arrow is the surprise: the key you have pressed for years to recall the previous line now opens a search UI instead. Atuin ships --disable-up-arrow to put the old behavior back, and a tool that includes an escape hatch for its own default is telling you the default divides its users.7

A release every week or two, since 2021

A tool that sits on every prompt is only worth adopting if it will still be maintained next year. Atuin has shipped stable releases roughly every one to two weeks, with 18.19.0 on 3 August 2026 the latest at the time of writing and a beta line already open past it.8 It is MIT-licensed, written in Rust, and has been developed since 2021, first by Ellie Huxtable and now under the atuinsh organization.9 For software you wire into your shell startup, an active cadence and a license that lets you fork if that ever stops are the two facts that decide the question, and both hold.

What "end-to-end encrypted" actually covers

Sync is optional, and off until you register an account. When you do turn it on, the README says your history is fully end-to-end encrypted, and the maintainer writes that she could not read your data even if she wanted to.1 That is true of your command text. Two facts from the source qualify the promise, and both cut the same way.

The first is on your own machine. The client stores its database unencrypted and encrypts only before sending to the server. The history.rs comment says so in as many words.4 Anything that can read your home directory can read your entire command history, and that history is richer than .bash_history ever was. A digital-forensics write-up takes exactly this database as its subject, independent confirmation that the exposure is real.10

The second is on the wire. Encryption protects the payload, not the envelope. Each synced record carries its id, a per-host index, the host id, a tag, a version, and a timestamp in the clear, because the server uses those to order records and drop duplicates.11 The server cannot read your commands. It can see how many you run, on which host, and when.

What sync's encryption covers, and what each layer still exposes.411
Layer State What is exposed
Local database plaintext Your full command history to anything that can read your home directory.
Sync payload encrypted Nothing. The command text is unreadable to the server.
Sync envelope plaintext Host id, per-host record counts, and timestamps: how much you run and when.

The encryption is sound where it does apply. Each record gets its own random 32-byte key, and that key is wrapped under a master key generated on your machine and never sent over the wire.12 And if the metadata a hosted server sees is what bothers you, point the sync address at a server you run, and the trust question moves in-house.13

When the swap pays off

The decision comes down to whether you ask questions of your history. If you want to know which commands failed, or what you ran in a given directory, Atuin answers in a filter where bash cannot answer at all. The hook and the database are a fair price for that. If you only ever tap the up arrow for the last few commands, the trade is worse. You install a hook, carry a growing plaintext database, and relearn a key you have used for years, all for a search UI you did not need.

On sync, the honest reading of the source is narrower than the marketing word. Your command text stays private in transit and at the server, whether you use the hosted server or your own. What the encryption does not do is protect the copy on your own disk. Run sync if the search across machines is worth it to you, run it self-hosted if the envelope metadata is not, and either way treat the local database, not the sync server, as the file worth protecting.411

Verdict

For an engineer who queries their shell history, Atuin earns the shell hook and the SQLite file. The encryption keeps your commands private when they sync but leaves the local database in plaintext, so the thing to guard is the copy on your own machine.4

Sources

  1. atuinsh/atuin · README
  2. atuinsh/atuin · create_history.sql migration
  3. Atuin Docs · atuin search reference
  4. atuinsh/atuin · history.rs
  5. Atuin Docs · Shell integration
  6. atuinsh/atuin · settings.rs
  7. Atuin Docs · Key binding
  8. atuinsh/atuin · Releases
  9. atuinsh/atuin · LICENSE
  10. SANS ISC · Linux Shell Forensic: Let's Dive Into Atuin! (Xavier Mertens)
  11. atuinsh/atuin · record.rs
  12. atuinsh/atuin · paseto_v4.rs
  13. Atuin Docs · Sync guide