Skip to content
My GitHub My Twitter My LinkedIn

Synchronized Shell History with Atuin

I'm a firm believer in remote development environments; folks who know me can vouch for that. At work, we relied on Gitpod before graduating to self-hosted Coder, and let me tell you, it's a game-changer! I'd love to share more about this upcoming posts. That said, there's one caveat to keep in mind though.

Argh, my shell history is gone.

Remote development environments are ephemeral by design. At the close of the day, your workspace gets torn down, and along with it, your shell history. Sure, you could store your history on an external volume, but how about a centralized vault for all your shell history? This is where Atuin enters the stage.

Atuin - A Magical Shell History

Atuin by Ellie Huxtable is an open source tool that transforms your ordinary shell history into a searchable and durable vault. The baseline is that it replaces your existing history with a SQLite database, tracks your commands in that local database by augmenting it with supplementary context details (like exit codes, command duration, etc.). Besides this core functionality, here's what you can expect feature-wise:

  • ⌨: Rebinds your beloved ctrl + r and cursor up keys to a full screen history view (TUI). Keyboard binding is configurable though.
  • 🗄: SQLite as the storage backend for persisting all your history items (incl. exit code, cwd, hostname, command duration, etc.).
  • 🔍: Powerful search capabilities (due to SQLite as the storage backend). Questions like: "Show me the pnpm run build, I performed yesterday after 3pm which failed with an exit code of 1." can be answered in a snap.
  • 📈: Statistics like "How many times do I execute ls -l?" with a following: "Yikes, I have to change my file system navigation behavior."
  • ⛅🔒: End-to-end encrypted cloud synchronisation (also self-hostable).

Installation

Ready to give Atuin a spin? We'll begin by installing Atuin on your local machine, explore its features, and then progress to the cloud until we arrive at the self-hosted Cloud installation. Are you ready? Let's dive in!

Important: Although, Atuin supports bash, I encountered problems, especially when it comes to syncing the history to my self-hosted instance. zsh works flawlessly though.

The installation is pretty straight-forward, because Atuin provides an installation script. After reading the script, you can install it (as an unprivileged user) via:

bash <(curl https://raw.githubusercontent.com/ellie/atuin/main/install.sh)

Once you've installed Atuin, don't forget to restart your shell. And that's it! Every command you run thereafter will get recorded in your local database. Put it to the test with an echo "Atuin rockz!" command and hit ctrl + r. Behold, the echo command will show up in Atuin's TUI.

Importing your existing history

Now, since Atuin will capture and store your performed commands from this moment onwards, you may be sitting on a considerable history file. But don't worry; importing this file into your Atuin database is a breeze. By executing atuin import <shell-type>, you can retire your old HISTFILE for good. It has served its purpose, and now Atuin is here to take things up a level.

Once you've been utilizing Atuin for an extended duration, your local database would be brimming with history items. This immersion provides ample opportunity to run complex and advanced queries using Atuin's search feature.

Prepare to take a deep dive into Atuin's search capabilities. In this section, we'll explore each option in detail, with accompanying example queries. Keep in mind that you can combine these options to construct more intricate searches, as we'll demonstrate. I'll demonstrate you each option one-by-one and you can go fancy by combining them afterwards, deal?

#
# All commands which start with the string "pnpm run build".
#
atuin search "^pnpm run build"

#
# All commands in a particular (current) working directory.
#
atuin search --cwd /home/akoenig/projects`

#
# All commands **NOT** in a particular (current) working directory.
#
atuin search --exclude-cwd /home/akoenig/projects/website

#
# All commands with a particular exit code.
#
atuin search --exit 0

#
# All commands WITHOUT a particular exit code.
#
atuin search --exclude-exit 127

#
# All commands before a specific date.
#
atuin search --before 2023-06-01

#
# All commands after a specific date.
#
atuin search --after 2023-05-20

#
# Limit the entries to return at most.
#
atuin search --after 2023-05-20 --limit 4

#
# Limit the first 10 occurences of "pnpm install" and skip (offset) the first one.
#
atuin search "^pnpm install$" --offset 1 --limit 10

👁 View Options

The following options can be used in conjuntion and they change the output formatting.

  • -i, --interactive: Displays the TUI, you're already familiar with when you type ctrl + r.
  • --human: Displays human-readable formatting for time.
  • cmd-only: Displays only the command and not the other context information.
  • -r, --reverse: Displays the oldest entry first.

🚨 Destructive Options

The search results can also be used to delete the found entries:

  • --delete: Appending this option leads to the case that the found items will be removed from the history. The results won't be printed before deletion, so if you want to use it, make sure to perform a search query without the option before.
  • delete-it-all: Well, this will delete all your entries from the history.

Cloud Sync

Having your shell history securely stored in a local SQL database is undoubtedly fantastic. But how can we sync this history across different machines? With Atuin, it's a no-brainer! As I previously mentioned, Atuin has a robust cloud sync mechanism in place. I understand you may have reservations about syncing sensitive information to an uncontrolled server. But fear not, because Atuin uses end-to-end encryption (E2EE) to encrypt all your history entries before syncing them to the cloud. No history entry will leave your machine in an unencrypted way. They will be encrypted locally and then synced to the cloud.

Ellie Huxtable runs an instance of the Atuin server, which you can use for free. If you do, please make sure to sponsor her.

Registering an account

For syncing your history to the cloud start by registering an account with Atuin, using atuin register command and following the prompts. During registration, be sure to select a strong password that you can store securely in a password manager, such as Bitwarden.

atuin register

Please enter username: andre
Please enter email: hi@andrekoenig.de
Please enter password: ***************************

Now that you have an account, you can sync your history across different machines easily. Simply execute atuin sync to move your history to the cloud.

But wait, do you have to sync it manually every time? Good news — the default sync interval is 1h. However, you can alter this default by changing the sync_frequency attribute in ~/.config/atuin/config.toml. For instance, I configured my sync interval to 10m, given my tendency to work in ephemeral development workspaces. While you can set a shorter interval, keep in mind the sync server's load and, preferably, sponsor the project, as well.

✨ Bonus Tip: I highly recommend to maintain your ~/.config/atuin/config.toml in your dotfiles repository.

Shared History Time!

Wow, what a journey! Let's do a quick recap of what we've accomplished so far:

  1. Installed Atuin locally, imported our old shell history, and played with the search functionality.
  2. Synced our (encrypted) history to the cloud.

Now, what's next, you ask? Syncing our history to another machine, of course! Allow us to present a scenario:

  • Our existing, configured machine is called daisy.
  • Our second machine is called luke.

We want luke to access the cloud, so that both machines have synced shell histories.

First, install Atuin on luke, following the same steps as the ones on daisy. Then, execute atuin login, and enter your username when prompted. You'll land on the query Please enter encryption key [blank to use existing key file]. What's that?

The encryption key is used to encrypt your history entries before syncing them to the cloud. What's the actual value of it? I've never entered such a key. That's true. The key was generated after registering your user on daisy. So, head over to daisy and execute atuin key. This is the encryption key you'll use on luke. The final step is to input the password you defined while registering your account on the cloud sync server.

That's it! luke is now connected to the cloud server, and you can manually perform atuin sync to retrieve the full synced history. Try a ctrl + r on luke, and voilà! The same history that daisy holds now appears on luke.

Conclusion

I have been using Atuin for several weeks now, and I absolutely love it. It has significantly made my life easier, and tracking my command history's growth is quite entertaining. Though we use our own cloud sync server at Open Formation (only accessible when connected to our company Tailnet), I recommend using Atuin's team-operated sync server.

If anybody is interested, I could write a follow-up post on how to deploy the Atuin server on own infrastructure though. Just let me know via an async message, or reach out to me on Twitter.

✨ Bonus Tip: Check out atuin stats. What's your most frequently used command? Mine is nb (which is another excellent software, but this is for another post).

Take care and happy shell history hording!