atuin:让 shell 历史跨机同步 + 模糊搜索 + 上下文感知

起因

我有 3 台机器(笔记本 + 两台服务器),每台 bash 历史互相不通。
"那条神秘的 ffmpeg 命令我半年前在哪台机器上跑过…" 永远找不回来。
而且原生 Ctrl-R 只能子串匹配,搜索体验差。

atuin 把 shell 历史存 SQLite + 加密同步 + 替换 Ctrl-R 为模糊搜索 TUI。

安装

# 一行装
bash <(curl --proto '=https' --tlsv1.2 -sSf https://setup.atuin.sh)

# 或包管理器
brew install atuin
cargo install atuin

# 注册到 shell
atuin init bash >> ~/.bashrc
atuin init zsh >> ~/.zshrc
atuin init fish | source >> ~/.config/fish/config.fish

# 重启 shell

第一次跑

Ctrl-R 不再是 bash 原生 reverse-i-search,而是 atuin 的全屏 TUI:

> ffmpeg
2026-05-20 14:32  ffmpeg -i input.mp4 -vcodec libx264 -crf 23 out.mp4
2025-12-01 09:15  ffmpeg -i src.mov -ss 00:00:05 -t 30 clip.mp4
2025-11-10 21:00  ffmpeg -i in.wav -ab 128k out.mp3
↑↓ 选 | Enter 执行 | Tab 编辑后执行 | Ctrl-D 退出

模糊匹配(不需要前缀完整)、按时间最近排序、显示具体执行时间。

同步到云

atuin 提供免费托管:

atuin register -u myuser -e [email protected] -p 'long-password'
# 服务端发邮件确认
atuin login -u myuser -k <密钥>   # 加密 key,重要!
atuin sync

之后每台机器:

atuin login -u myuser -k <密钥>
atuin sync

历史立刻同步过去(端到端加密 —— 服务端只能存 ciphertext)。

密钥(key)丢了等于所有历史丢了——保存到 password manager。

自托管 server

不想用官方 host:

# server 端
docker run -d \
  -e ATUIN_DB_URI=postgres://user:pass@host/db \
  -p 8888:8888 \
  ghcr.io/atuinsh/atuin server start

# 客户端 ~/.config/atuin/config.toml
sync_address = "https://atuin.your-server.com"

配置

~/.config/atuin/config.toml

# 搜索模式:prefix / fulltext / fuzzy(推荐 fuzzy)
search_mode = "fuzzy"

# 启动时显示历史的 filter
filter_mode = "global"        # global | session | host | directory

# 模式:自动按上下文切(按 Tab 切)
filter_mode_shell_up_key_binding = "directory"

# 默认搜索结果数
show_help = true
inline_height = 20

# 不记录某些命令(密码、敏感的)
history_filter = [
    "^secret-cmd",
    "^export.*PASSWORD",
]

# 不记录这些目录
cwd_filter = [
    "/tmp",
]

context-aware 搜索

最强的 feature:按 Tab 切换 filter scope:

  • global:所有机器所有目录
  • host:仅本机
  • session:仅本 shell session
  • directory:仅本目录
> docker  [filter: directory]

~/projects/myapp 目录搜 docker 只显示在这个目录跑过的 docker
命令。这比 bash Ctrl-R 强 10 倍——找上次"在哪个项目里跑的什么命令"
秒级。

时间过滤

atuin search --before '2 days ago' docker
atuin search --after '1 week ago' kubectl

统计

atuin stats
# Total commands: 12847
# Unique commands: 4321
# Top commands:
#   1. ls (1234)
#   2. cd (987)
#   3. git status (654)
#   ...

atuin stats --period 7d   # 最近 7 天

发现自己 80% 时间在 cd 和 ls,提示我多用 z + 文件管理器。

导入老历史

atuin import auto       # 自动检测 bash/zsh/fish/atuin

之前几年的 ~/.bash_history / ~/.zsh_history 全导入 atuin DB。

不想被记录的命令

# 单条命令前面加空格(bash HISTCONTROL=ignorespace 兼容)
 secret-command --token xyz

或者用 atuin 的 history_filter regex。

CLI 用法

atuin history list --limit 50
atuin history list --cwd ~/projects/myapp

atuin search 'docker run'

# 把某条历史拿出来重新跑
atuin search 'ffmpeg' --format '{{ .command }}' --limit 1 | bash

跟 fzf 配合

Ctrl-R 默认是 atuin TUI。如果你更喜欢 fzf:

# atuin 输出 + fzf 渲染
fh() {
  atuin history list --format '{{ .timestamp }} | {{ .command }}' \
    | fzf --tac --no-sort --tiebreak=index \
          --bind 'enter:become(echo {3..})' \
    | xargs -I {} bash -c '{}'
}

但 atuin 自带的 TUI 其实 fzf-like,绝大多数场景不需要替换。

性能

10 万条历史的 atuin DB ~ 30 MB;查询 < 50ms。本地纯 Rust + SQLite,
无网络请求。

效果

  • 3 台机器历史共享,"半年前那条命令" 永远找得回来
  • 搜索体验从 grep-字符串 升到 fuzzy + context-aware
  • 在项目目录 Ctrl-R 自动过滤到本项目历史,省去大量"误中其它项目命令"
  • 跨机迁移 / 重装系统 / 新员工 onboarding 都瞬间继承"老司机经验"

踩过的坑

  1. 加密密钥丢失 = 所有同步历史丢失。注册后立刻 atuin key
    key,存进 password manager 三份(云 + 本地 + 打印)。

  2. 某些 ZSH 主题与 atuin 冲突:oh-my-zsh 的 Ctrl-R 被绑给其它
    插件。bindkey '^R' atuin-search 强制覆盖。

  3. 同步把敏感命令也带走:包含 export PASSWORD=xxx / mysql -p xxx
    的命令也加密同步。提前用 history_filter 过滤。

  4. 服务端不可达时 atuin sync:网络问题导致同步 hang。
    atuin sync --force 或者 kill 后下次再 sync。

  5. 新 shell session 启动慢:atuin init 加了几个 hook。如果发现
    shell 启动 > 100ms,看看是不是 atuin 同步在做(关 auto_sync,手动
    atuin sync)。

精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。