Atuin is a tool and labor of love built by Ellie Huxtable that runs in the background to capture commands you’ve entered. It stores these locally in a SQLite database and provides a great CLI tool to search through that history, provide stats of what commands you frequently run, and optionally syncs this history across devices.
Atuin is one of several cool Rust tools that I’ve found in the past year or so, and is my favorite addition to my terminal workflow in a long time. Other tools that I’ve found and would like to write up soon are: Hyperfine, ripgrep, and Starship.1 I’ve added Atuin to my /uses page with a link back to this post.
Commands are grabbed via preexec and precmd hooks that allow it to get not only the command, but the current directory, hostname, session, duration of the command, and exit code. It stores these in its SQLite database along with a timestamp, so you’re free to introspect that data yourself as well. It also leaves the shell’s history file alone, so unless you disable it yourself you’ll still have the same history experience.
In fact, when setting up Atuin for the first time you’re encouraged to import that history, and depending on your config, things like atuin stats and atuin search may already be pretty useful without needing to use Atuin for a while as it collects commands that you run.
Search
I’ve found it a hugely useful replacement for an awkward search through my ~/.zsh_history file for a poorly remembered command. Atuin’s search, which by default hooks into the same <CTRL>-R that readline-based CLIs provide for backwards history search, presents a colorful and history of commands including some of the additional metadata that Atuin collects: command duration, a relative timestamp for when it was run, and the full command. It features easily toggleable filters for commands run on the current host, in the current session, in the current directory, and globally across all synced devices.
Stats
Atuin’s stats subcommand is fun to have, but also serves as a hint for what aliases I could consider adding.
Here are my current atuin stats as of this writing. I’ve also incorporated atuin stats week into my /now page. It clearly shows that my muscle memory of <CTRL>-Z / fg is strong, and if you squint it’ll also tell you that I’m opening too many files from vim on the CLI instead of from within it. You can also see that I’ve recently switched from the_silver_searcher (ag) to ripgrep (rg) and the latter is climbing the ranks.
[▮▮▮▮▮▮▮▮▮▮] 9607 fg
[▮▮▮▮▮▮▮▮▮ ] 9458 vim
[▮▮▮ ] 3144 ag
[▮▮▮ ] 3095 git status
[▮▮ ] 2248 git diff
[▮ ] 1787 curl
[▮ ] 1571 jq
[▮ ] 1357 rg
[▮ ] 1348 cd
[▮ ] 1322 git log
Total commands: 62849
Unique commands: 26908
Sync
Atuin also provides syncing, and makes assurances that it is end-to-end encrypted, provides for specifying filters as Regular Expressions for commands run as history_filter and for filtering against the current directory before writing commands to history. You can also host your own sync server if you’d like that functionality but don’t want to trust a third-party service to do it.
Configuration
The default configuration is pretty sane, but Atuin allows you to override all sorts of things as well. My personal config makes a few tweaks to the stats section, including adding several common_subcommands that make sense for a Rubyist, adding bundle exec to common prefixes, and setting a few other miscellaneous options that make the tool feel better for my usage.
Wishlist
Atuin recently added “dotfiles syncing”, which allows it to set up aliases and environment variables and sync them across devices as well. My dotfiles already did that, but for fun I went ahead and moved a few things in. I opened a Pull Request that would allow for splitting atuin init into “subsections” that include setting env vars and that include everything else. It’s a super minor performance thing that would allow for setting environment values in ~/.zshenv (or the equivalent in other supported shells) which is read for non-interactive shells, and for setting up the rest of Atuin in ~/.zshrc which is only loaded in interactive sessions.
I’d love to see atuin stats learn more filters. I think it makes sense for it to have (most of?) the same filter-modes as atuin search: global, host, session, directory, and workspace. I’d be interested to see how my stats differ on my work vs person computer, across different projects, etc.
-
I briefly tried out Delta, another Rust tool that acts as a pager for Git and adds things like syntax highlighting and terminal hyperlinks, via an issue on Ripgrep about not having paging built in. I decided that I wasn’t a fan and actually added
diff-highlightfrom Git’s contrib/ directory to get line- and word-wise highlighting. I don’t think I want syntax highlighting in diffs. ↩