atuinに乗り換えて半年。シェル履歴がSQLiteになって生活が変わった話
水曜の深夜、本番のVPSで「3週間前にやったあのワンライナー、なんだっけ」を5分間思い出せなかった。history | grepを打っても出てこない。~/.bash_historyがどうやら途中で潰れていたらしい。あの瞬間に、atuinを入れた。
あれから半年経った。Ctrl+Rの体験はもう戻れない。
この記事は、atuinを毎日3台のマシン(Mac / Raspberry Pi 5 / VPS)で使い込んだ自分が、本当に効いた使い方とハマったポイントだけを書く。公式READMEの和訳ではなく、現場で気付いたものを中心に。
atuin とは何か(普通のhistoryと何が違うのか)
atuinは Ellie Huxtable 氏が Rust で書いた、シェル履歴の置き換えツールだ。bash / zsh / fish / nushell に対応している。
普通のシェル履歴と決定的に違うのは、保存先がプレーンテキストではなくSQLiteな点。これが効く。
- コマンドだけでなく、実行ディレクトリ・終了コード・所要時間・ホスト名も一緒に記録される
- 重複は自動でマージ、古い履歴も上限なしで残せる
- セッション単位の履歴ロストが起きない(zshで複数ターミナル開いてた時のあれ、もう発生しない)
- サーバー連携でE2E暗号化済みの履歴を別マシンと同期できる
「ふーん、grep でええやん」と思った人。半年前の自分もそう思っていた。一週間使うと、たぶん戻れなくなる。
インストールと最低限のセットアップ
ワンライナーで入る。Mac でも Linux でも Raspberry Pi (arm64) でも同じ。
curl --proto '=https' --tlsv1.2 -LsSf https://setup.atuin.sh | sh
Homebrew 派ならbrew install atuinでも入る。cargo install atuinもある。Rust ツールチェーンがあるなら速い。
その後シェルへの組み込み。zshの場合は.zshrcに1行。
eval "$(atuin init zsh)"
bash の場合は~/.bashrcに同じ要領で書く。bash-preexec.shを読み込む形になるが、インストーラが面倒見てくれる。
ここまでで Ctrl+R が atuin の検索画面に変わる。早速触ってみると、見た目からして違う。実行時刻・ディレクトリ・終了コードがその場で見える。
既存のhistoryを取り込む
これを忘れがち。新規インストール直後はatuinの履歴ゼロなので、まず吸い上げる。
atuin import auto
これでbashなら.bash_history、zshなら.zsh_historyを読み込んでSQLiteに突っ込んでくれる。10年分の.zsh_history(自分の場合、約42,000行)も数秒で食べてくれた。タイムスタンプも保持される、これは正直うれしい。
Ctrl+Rで生活が変わる5つの操作
キーバインドは色々あるが、毎日使うのは結局この5つだけだった。
1. ファジー検索 + フィルタモード切替
Ctrl+R を押した検索画面で、Ctrl+Rをもう一度押すと検索モードが切り替わる。Global / Host / Session / Directory の4段階。
- Global: 全マシン全期間の履歴(同期している場合)
- Host: 今のマシンだけ
- Session: 今開いているターミナルセッションだけ
- Directory: 今いるディレクトリで実行した履歴だけ ← 個人的に最強
「このプロジェクトでよくやってる作業をもう一度」というケースで、Directory モードが圧倒的に効く。同じnpm runでも、案件ごとに異なるサブコマンドを使い分けている人は刺さるはず。
2. 終了コードでフィルタ
失敗したコマンドだけを除外できる。検索フィールドの先頭でTabを押してフィルタを開き、Exit code: 0 onlyに切り替えると、過去にちゃんと通ったコマンドだけが出てくる。
これが効く場面はいくつかあって、たとえば「ffmpegのオプションが正しかった時のフルコマンドを出したい」みたいな状況。タイポ含む失敗履歴に埋もれず、正解だけ呼び出せる。
3. 直前のコマンドを別マシンに飛ばす(Workspace固有)
これはちょっと裏技。同期サーバーを使っていると、Mac で打ったコマンドが数秒で Raspberry Pi 5 のCtrl+Rで出てくる。
自分の場合、Mac でローカルに作って動作確認したシェルスクリプトのワンライナーを、SSH先のRaspberry Piに「再入力なしで」貼れる。Raspberry Pi 5 のホームサーバー運用をしていると、こういう細かい摩擦の積み重ねが地味に効いてくる。
4. 統計を見る
「自分が一番打ってるコマンドって何だっけ」を可視化できる。
atuin stats
自分の場合、トップはgit status(月3,200回)、次がls、3位がcd、4位がvim、5位がpythonだった。git statusの数字を見たとき、さすがに何か対策を取るべきと思って、lazygitに乗り換えたのはこの直後だ。
5. 履歴の削除
うっかりexport AWS_SECRET=...を打ってしまった時。atuin searchで該当コマンドを見つけ、Ctrl+Dで削除できる。SQLiteから物理的に消える。これはhistory -dより使いやすい。
セルフホスト同期サーバー(プライバシーを担保しつつ複数マシン運用)
atuinの真価は、履歴をE2E暗号化して同期できるところにある。公式が無料の同期サーバーを提供しているが、自分は自前のVPSで立てている。理由は単純で、自分のシェル履歴は他人(運営含む)に渡したくないからだ。
セルフホストはDocker一発で立つ。
version: "3"
services:
atuin:
image: ghcr.io/atuinsh/atuin:latest
command: server start
volumes:
- "./config:/config"
ports:
- 8888:8888
environment:
ATUIN_HOST: "0.0.0.0"
ATUIN_OPEN_REGISTRATION: "false"
ATUIN_DB_URI: postgres://user:pass@postgres/atuin
postgres:
image: postgres:14
restart: unless-stopped
volumes:
- "./database:/var/lib/postgresql/data/"
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: atuin
あとはCaddyのリバースプロキシでHTTPS化して終わり。クライアント側は~/.config/atuin/config.tomlに同期先を書くだけ。
sync_address = "https://atuin.example.com"
登録はatuin register -u USER -e EMAIL、ログインはatuin login -u USER -p PASS -k KEY。keyは復元用の暗号化キーで、これをなくすと既存の暗号化履歴は二度と復号できない。これは絶対にパスワードマネージャに入れておくべき値だ。自分は1度ロストしかけて、汗をかいた。
ちなみにVPSはお名前.comの高性能VPS
のいちばん安いプランで動かしている。atuinサーバー自体は数十MBのメモリしか食わないので、月数百円のプランで十分間に合う。
半年使って気付いた地味なハマりどころ
べた褒めばかりじゃ嘘になるので、ハマったポイントも正直に書く。
- SSH先で履歴が分離される問題: 当然と言えば当然だが、SSHした先のマシンにもatuinが入っていないと、ローカルの履歴と統合されない。サーバー全部に入れるか、Hostフィルタを使い分けるかの二択。自分はTailscaleで繋いだホスト群には全部入れている。
- 同期競合は基本起きないが、巨大履歴の初回同期は遅い: 4万行の初回pushが約2分かかった。Wi-Fiが弱い環境ではコーヒーを淹れる時間。
- シェルの起動が体感数十ms遅くなる: 計測すると約30-50ms。チューニングしたい人は
atuin init zsh --disable-up-arrow等のフラグで無駄な機能を切ると軽くなる。 - 自動補完(atuin shellと別)との衝突:
fzfのCtrl+Rと被ると、どちらかしか使えない。自分はfzfのCtrl+Rを一旦無効にしてatuinに統一した。fzfは別キー(Alt+R)で残してある。
あ、もう一つ。atuin initを入れた状態で別のシェル設定を弄ると、稀にプロンプトが二重に描画される。これはpreexec hookの登録順問題で、初期化の位置を一番下にすると直る。
誰におすすめか、誰にいらないか
正直に言うと、シングルマシンで完結している人にはあまり刺さらない。HISTSIZE=999999とHISTFILESIZE=999999で十分という人もいる。それは正しい判断だ。
逆に、以下のどれかに当てはまる人にはたぶん刺さる。
- 複数マシン(ノートPC + デスクトップ + サーバー)で同じシェル作業をしている
- 過去の履歴を「いつ・どこのディレクトリで・成功したか」で絞り込みたい
- シェル履歴ファイルを過去に1度でもロストしたことがある
- 普段から
history | grepを多用していて、地味にストレスを感じている
自分は最後の3つ全部に当てはまった。たぶん、エンジニアの大半はそうだと思う。
導入リスクは低い、戻りも数秒で済む
atuinは Ctrl+R を奪うだけで、bash や zsh の設定そのものは壊さない。.bashrcからeval "$(atuin init bash)"を消せば、即座に元の Ctrl+R に戻る。SQLiteのファイルは~/.local/share/atuin/history.dbに残るので、後で気が向いたら再開できる。
合わなければやめればいい。インストールが2分、削除が30秒。これくらいの軽さなら、試さない理由がない。
普段のターミナル環境を底上げするツール群は、まとめてDevToolsコレクションでも紹介している。気になる人はあわせて見てほしい。
半年前、本番VPSの深夜デバッグであのワンライナーを思い出せなかった自分は、もう存在しない。Ctrl+R を打って、ディレクトリで絞り込んで、終了コード0でフィルタする、それだけのことなのに、毎日の摩擦が減る。
その差は、たぶん想像より大きい。