适用场景
你有两台以上的开发机:公司台式机、家里的笔记本、一台远端构建机。编码智能体(如各类在终端里运行的 CLI 智能体)都在这些机器的 shell 里启动,提示词、跑过的命令、进过的目录散落在各自机器的历史里。换一台机器后,第一件事往往是花十分钟翻旧终端,回忆"上次改到哪个分支、最后一条提示词怎么写的"。
这套方案用 Atuin 把这些终端活动端到端加密地汇总成一条跨机器时间线,再用一个统一的线程标签把属于同一个任务的智能体会话串起来。换机后一条命令就能把这条线捞回来,接着往下跑。
> 说明:Atuin 围绕会话与线程的组织能力(官方文档中的 Threads 相关特性)在不同版本中命名和参数可能不同,涉及具体子命令时以官方文档当前版本为准。本文给出的线程标签法不依赖特定版本,任何版本都能用。
环境与前置条件
- 操作系统:Linux(x86_64 / arm64)或 macOS。Windows 建议在 WSL 里操作,并且所有机器都尽量统一到同一类 shell 环境,减少命令格式差异。
- Shell:zsh、bash 或 fish 之一,必须是交互式 shell(非交互脚本不记录)。
- 安装方式:系统包管理器(如 Homebrew)、发行版仓库,或有 Rust 工具链时用
cargo install atuin。版本以官方文档当前版本为准,各机器尽量保持同一大版本,避免同步格式不兼容。 - 同步服务:可以使用官方托管的同步服务,也可以自建(自建需要一个 PostgreSQL 实例)。多机器方案里同步端点是核心,端点不通这台机器就是孤岛。
- 磁盘:本地历史库是 SQLite,通常几十到几百 MB,预留 1 GB 空间足够宽裕。
- 密钥:Atuin 采用端到端加密,加密密钥只存在于你的机器上。密钥丢失,云端历史无法解密,务必离线备份。
- 时间同步:所有机器开启 NTP。时间线是按时间戳合并的,某台机器慢几分钟,合并出来的顺序就会错乱。
- 智能体:任意在终端中运行的 CLI 智能体都可以,方案不绑定具体产品。
分步骤部署
步骤 1:在每台机器上安装 Atuin
按官方文档给出的安装方式操作,常见有两种:
```bash
方式一:包管理器(macOS 示例)
brew install atuin
方式二:已有 Rust 工具链
cargo install atuin
```
安装完成后确认二进制可用:
```bash
atuin --version
```
能打印出版本号即成功。这一步只是装二进制,还没有接入 shell,此时按上箭头仍然是旧的历史行为。
步骤 2:把 Atuin 接入 shell
编辑对应 shell 的启动文件,把初始化语句放到文件末尾(放前面容易被其他历史插件覆盖):
```bash
zsh
echo 'eval "$(atuin init zsh)"' >> ~/.zshrc
bash
echo 'eval "$(atuin init bash)"' >> ~/.bashrc
fish
echo 'atuin init fish | source' >> ~/.config/fish/config.fish
```
然后重开一个终端,或执行 source ~/.zshrc。成功的标志是:随便敲一两条命令,按上箭头或 Ctrl-R 出现 Atuin 的搜索界面,而不是 shell 原生历史。至此,本机已经在记录了,但还没有同步。
步骤 3:注册账号,或在已有账号上登录
在第一台机器上注册:
```bash
atuin register -u <用户名> -e <邮箱> -p <密码>
```
在其余每台机器上登录同一个账号:
```bash
atuin login -u <用户名> -p <密码>
```
成功后执行 atuin status,会显示已登录用户、本地记录条数和最后同步时间。注册只需一次,之后所有机器都是登录。
步骤 4:备份并统一加密密钥(关键一步)
```bash
atuin key
```
它会打印一串密钥。把这串密钥用密码管理器或离线方式保存下来,并确认每台机器打印出来的完全一致。不一致会导致同步下来的历史无法解密,表现是列表里出现乱码或空白。
如果某台机器的密钥不一致,用带密钥的方式重新登录一次即可覆盖:
```bash
atuin login -u <用户名> -p <密码> -k <上一步保存的密钥>
```
多机方案里这一步最容易出问题,建议在第一台机器上先把密钥存好,再去做其他机器的登录。
步骤 5:写入配置文件
配置文件在 ~/.config/atuin/config.toml,写入以下内容。字段名以官方文档当前版本为准:
```toml
自动同步:开启后按下面的间隔后台同步
auto_sync = true
sync_frequency = "5m"
使用官方服务时保持注释;自建时改成自己的地址
sync_address = "https://<你的同步服务地址>"
搜索与过滤模式
search_mode = "fuzzy"
filter_mode = "global"
不把明显带密钥的命令写进历史
secrets_filter = true
history_filter = [
"^export .*KEY=",
"^export .*TOKEN=",
"^export .*SECRET=",
]
```
filter_mode 可选 global / host / session / directory:host 只看本机,directory 只看当前目录,global 看全部机器。跨机器时间线主要用 global。
步骤 6:导入本机已有的历史
新装 Atuin 后,本机原有的 shell 历史可以一次性灌进去:
```bash
atuin import auto
```
成功时会输出导入的条数,比如类似 Imported N history items 的提示。条数大于 0 说明历史已经进了 Atuin 的库,可以参与后续同步。
步骤 7:触发首次同步
```bash
atuin sync
```
成功时输出同步完成的信息,没有报错即可。随后用 atuin status 看看记录条数和最后同步时间是否更新。注意:同步是双向的,本地没有的会拉下来,云端没有的会推上去。
步骤 8:在其他机器上重复步骤 1、2、4、5、6、7
每台机器都走一遍安装、接入 shell、登录、写配置、导入、同步。全部完成后,任意一台机器执行:
```bash
atuin stats
```
能看到来自不同主机的记录时,多机时间线就接通了。也可以在搜索界面里看每条记录右侧标注的主机名,确认不是只来自本机。
步骤 9:给智能体会话打线程标签
Atuin 记录的是命令本身,包括启动智能体的命令和后面跟着的提示词。所以"线程"可以用一个统一前缀来实现:给同属一个任务的所有智能体调用加上同一个标签。
在每台机器的 rc 文件末尾加一个小函数:
```bash
~/.zshrc 或 ~/.bashrc
thread() { THREAD="$1" "${@:2}"; }
```
之后启动智能体时这样写:
```bash
thread proj-alpha <你的智能体命令> "把 orders 接口的分页改成游标式"
thread proj-alpha <你的智能体命令> "补上分页的边界测试"
```
这几条命令会被完整记录下来,proj-alpha 这个字符串也在记录里。换个任务就换标签:thread proj-beta ...。标签尽量短、唯一、可读,比如用"项目-模块"的形式。
步骤 10:换机续跑
在新机器上先同步,再按标签捞回整条线程:
```bash
atuin sync
atuin search "proj-alpha"
```
也可以打开交互式搜索界面,用同样的关键词过滤:
```bash
atuin search -i
```
结果会按时间排序、跨主机混排。找到最后一条,把里面的提示词和目录复制出来,在新机器上接着往下跑;如果代码还没同步过来,先 git pull 再继续。这样上下文就不是靠脑子记,而是靠一条可以随时查回来的时间线。
验证部署是否成功
按顺序跑下面几条,都能对上就说明部署成立:
```bash
1. 二进制与 shell 集成
atuin --version # 打印版本号
在终端按 Ctrl-R # 出现 Atuin 搜索界面而非原生历史
2. 登录状态
atuin status # 显示用户名、记录条数、最后同步时间
3. 密钥一致性(每台机器都执行,输出必须完全相同)
atuin key
4. 跨主机记录
atuin search "proj-alpha" # 结果里出现来自不同主机的同名标签命令
5. 记录量与来源
atuin stats # 能看到命令总量与分布
atuin history list # 列出近期记录,含时间与主机信息
```
最直接的验证方式是做一次真实往返:在 A 机器执行 thread verify-check echo hello-atuin,然后在 B 机器执行 atuin sync && atuin search "verify-check",能搜到这条命令即闭环成功。
常见报错与解决
报错 1:atuin: command not found,或装好后按上箭头仍是旧历史
→ 原因:二进制不在 PATH 中,或 eval "$(atuin init ...)" 没写进当前 shell 的 rc 文件、写在了会被其他插件覆盖的位置。
→ 解决:
```bash
which atuin # 确认能找到二进制
tail -n 5 ~/.zshrc # 确认 init 语句在文件末尾
echo 'eval "$(atuin init zsh)"' >> ~/.zshrc
source ~/.zshrc
```
报错 2:同步后历史列表出现乱码、空白,或提示解密失败
→ 原因:这台机器用的加密密钥与其他机器不一致,通常是重复注册了新账号或登录时没带密钥。
→ 解决:
```bash
atuin key # 与第一台机器输出的密钥对比
atuin logout
atuin login -u <用户名> -p <密码> -k <正确的密钥>
atuin sync
```
如果本地已经存了错误密钥加密过的记录,先备份再重建本地库:
```bash
mv ~/.local/share/atuin ~/.local/share/atuin.bak
atuin login -u <用户名> -p <密码> -k <正确的密钥>
atuin sync
```
报错 3:atuin sync 报连接失败或超时(如 error sending request for url)
→ 原因:网络不通、公司网络需要代理,或配置文件里的 sync_address 指向了错误的地址。
→ 解决:
```bash
先确认端点可达
curl -sS -o /dev/null -w '%{http_code}\n' <你的同步服务地址>
检查配置里的地址是否写错
grep -n sync_address ~/.config/atuin/config.toml
需要代理时导出环境变量后重试
export HTTPS_PROXY=<代理地址>
atuin sync
```
报错 4:命令没有被记录,或出现重复条目
→ 原因:多个历史工具同时接管 shell(例如另外的历史插件、fzf 集成),或 history_filter 的正则把命令过滤掉了,或 rc 文件里 init 语句被重复添加。
→ 解决:
```bash
grep -n "atuin init" ~/.zshrc # 只应出现一次,多了就删掉多余的
grep -n "history_filter" -A5 ~/.config/atuin/config.toml
临时关掉过滤规则验证是否为过滤导致
把 history_filter 改为 [] 后重开终端再试
```
后续维护
备份:只有两样东西不能丢——加密密钥和本地数据库。建议定期打包(注意包里含密钥,要放在加密介质上):
```bash
tar czf atuin-backup-$(date +%F).tar.gz \
~/.config/atuin \
~/.local/share/atuin
```
升级:用当初安装时的同一个包管理器升级,不要在不同机器上混用安装方式。跨大版本升级前先做上面的备份,升级后立刻跑一次 atuin sync 和 atuin status,确认没有数据结构迁移失败或同步异常。具体升级注意事项以官方文档当前版本为准。
日志与排查:需要看细节时打开调试日志重跑一次同步:
```bash
RUST_LOG=debug atuin sync
```
日常排查先看 atuin status 的最后同步时间——如果某台机器的时间长时间不更新,说明它的后台同步已经断了,优先检查网络和登录状态。
监控:多机场景下最简单的健康检查是每周在任意一台机器上执行一次 atuin stats 和 atuin search "<常用线程标签>",看记录量是否还在增长、最近的会话是否还能搜到。记录量突然停滞通常意味着某台机器掉线。
控制体量:历史库是标准 SQLite,长期使用后体积会增长。优先用配置里的 history_filter 和 secrets_filter 控制写入,而不是事后删除。确需清理时,先备份数据库文件,再做任何改动;直接操作库文件的命令不要在没有备份的情况下执行。
线程标签规范:标签是这套方案里唯一需要人工维护的部分。建议固定一套命名规则(如 项目名-模块名),并且只在实际动手改代码的智能体会话上加标签,不要把一次性的查看命令也打上标签,否则时间线会被噪声稀释。
