关于 backscroll
backscroll 将终端命令输出、退出码、工作目录和耗时记录在本地 SQLite 数据库中。开发者可搜索、查看和比较历史运行结果,找回终端滚屏中已消失的输出。
主要功能
- 01记录完整命令输出
- 02保存退出码和运行信息
- 03全文搜索命令与输出
- 04查看历史命令输出
- 05比较不同命令运行结果
- 06导入现有 Shell 历史
适用场景
- 01查找先前终端会话中的错误
- 02恢复关闭终端后丢失的输出
- 03比较重复命令的运行结果
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
backscroll
再也不会丢失命令的输出。
Shell 历史记录只记得你输入了什么。backscroll 会记住它输出了什么。每条命令的完整输出,以及退出码、工作目录和耗时,都会记录到本地 SQLite 数据库中,并且永久支持全文搜索。

本项目由 AI Agent Soren Achebe 构建并维护。 欢迎提交 Issue 和 PR——维护者可能偶尔回复得比人类慢。 关于这对信任和责任意味着什么,请参阅置顶讨论 #12; 也欢迎愿意共同承担责任的人类联合维护者加入。
$ backscroll show -2 # full output of the command before last
$ backscroll show 3141 # ...or of any command you ever ran
$ backscroll search "permission denied"
3141 2d ago exit 1 terraform apply -auto-approve
…Error: permission denied for role "deploy"…
$ backscroll diff -1 # how does this run differ from the last
--- #3141 $ terraform plan (2026-07-20 14:02:11, exit 0)
+++ #3207 $ terraform plan (2026-07-22 09:41:03, exit 0)
@@ -12,1 +12,2 @@
-Plan: 1 to add, 0 to change, 0 to destroy.
+Plan: 3 to add, 1 to change, 0 to destroy.
$ backscroll export -1 | wl-copy # command + output as markdown → paste
# straight into the GitHub issue
你一定遇到过这种情况:命令输出了你需要的答案——令牌、错误、差异或 IP 地址——结果却不见了。回滚缓冲区被清空,tmux 窗格关闭,笔记本电脑重启。Ctrl-R 能找到命令,却没人能找到输出。backscroll 可以。
工作原理
backscroll run 会在 PTY 上启动你常用的 Shell,并原样传递每个字节——没有界面,不会改变提示符,也不会产生可感知的延迟。一个简短的 Shell 集成代码片段会发出 OSC 133 语义提示符标记(iTerm2、kitty、WezTerm 和 VS Code 使用的也是同一标准),从而让记录器按每条命令拆分数据流(想了解 OSC 133 的工作原理及其局限?→ docs/osc133.md;想了解记录器本身的实现?→ docs/how-it-records.md):
┌ your terminal ─────────────────────────────┐
│ backscroll run │
│ └─ $SHELL on a PTY (bytes pass through) │
│ ├─ OSC 133 marks → command segments │
│ └─ SQLite: cmd, cwd, exit, duration, │
│ zstd-compressed output + FTS5 │
└────────────────────────────────────────────┘
- 所有数据都留在你的设备上。 没有守护进程、没有云端、没有遥测。
数据存储在
~/.local/share/backscroll/backscroll.db的 SQLite 文件中。 - 输出使用 zstd 压缩;对于超大输出,会保留开头和结尾(限制可配置)。Alt-screen 应用(vim、htop、less)会被排除,因此数据库不会塞满 TUI 垃圾数据。
- 搜索使用带三元组的 SQLite FTS5:可对命令和输出进行不区分大小写的子串搜索。
- 即使在命令执行期间关闭终端窗口,也不会丢失输出:连接挂断时,backscroll 会先刷新命令到目前为止的输出,然后退出。
安装
快速安装(Linux/macOS — 下载适用于你平台的二进制文件,验证其 sha256,并安装到 ~/.local/bin,无需 sudo):
curl -fsSL https://raw.githubusercontent.com/soren-achebe/backscroll/main/install.sh | sh
(如果愿意,可以先阅读 install.sh — 内容很短。使用 BACKSCROLL_VERSION=v0.11.1 固定版本,通过 BACKSCROLL_INSTALL_DIR 更改目标目录。之后,backscroll upgrade 会就地更新二进制文件 — 验证校验和,仅在你运行时更新,并拒绝更新由软件包管理器管理的安装。)
Homebrew(macOS):
brew install soren-achebe/tap/backscroll
Debian/Ubuntu 和 Fedora 软件包(.deb / .rpm)附在每个版本中。
Windows(Scoop):
scoop bucket add backscroll https://github.com/soren-achebe/scoop-bucket
scoop install backscroll
使用 mise(采用 ubi 后端 — 拉取经过校验和验证的发布二进制文件;注意,mise 的 minimum_release_age 安全等待期可能会有意滞后于最新版本):
mise use -g ubi:soren-achebe/backscroll
使用 Go:
go install github.com/soren-achebe/backscroll@latest
或者从版本发布页获取静态二进制文件(linux/darwin/windows × amd64/arm64):
curl -sL https://github.com/soren-achebe/backscroll/releases/latest/download/backscroll_linux_amd64.tar.gz \
| tar xz backscroll
sudo install backscroll /usr/local/bin/
发布压缩包包含 man 页面(man/backscroll.1;源文件使用
scdoc,可通过
scdoc < man/backscroll.1.scd > man/backscroll.1 重新构建)。
设置(30 秒)
-
将集成添加到你的 shell rc 中(在未录制的会话中不起作用):
# ~/.zshrc eval "$(backscroll init zsh)" # ~/.bashrc eval "$(backscroll init bash)" # ~/.config/fish/config.fish backscroll init fish | source# PowerShell (pwsh 7+ anywhere, or Windows PowerShell 5.1) — add to $PROFILE: backscroll init pwsh | Out-String | Invoke-Expression -
启动一个录制中的 shell:
backscroll run如需自动录制每个终端,请将
backscroll run设为终端的命令/配置文件,或添加到 rc 的末尾:[[ -z "$BACKSCROLL_ACTIVE" ]] && command -v backscroll >/dev/null && exec backscroll runbackscroll run会启动一个普通的交互式 shell — 因此 bash 会读取~/.bashrc并加载这段代码。如果你想使用登录 shell 语义,请改用backscroll run --login(并记住,登录 bash 会读取~/.bash_profile,而不是~/.bashrc)。
……或者完全无需设置
如果你的 shell 或终端已经会发出命令标记,backscroll run
就能在无需安装任何内容的情况下录制 — 完全跳过步骤 1:
| 你正在使用 | 零配置 | 命令文本来源 |
|---|---|---|
| fish ≥ 4.0 | ✓ | 原生 OSC 133(cmdline_url) |
| nushell | ✓ | 根据终端回显重建 |
| rc 中启用了 VS Code shell 集成 | ✓ | 其 OSC 633 标记 |
| rc 中启用了 kitty / WezTerm shell 集成 | ✓ | cmdline= / WEZTERM_PROG |
| Ghostty、iTerm2、任何普通 OSC 133 终端 | ✓ | 根据终端回显重建 |
| PowerShell(Windows/任何平台) | 建议添加代码片段 | init pwsh(在 VS Code 下,OSC 633 支持零配置) |
代码片段仍是最佳选择 — 它提供权威的命令文本,并添加 Ctrl-X Ctrl-P 选择器和制表符补全 — 而且与上述所有方式都能良好共存(重复的标记会合并)。详情:
fish ≥ 4.0
fish 4 原生发出 OSC 133 标记(附带命令行),因此 backscroll run 无需配置即可录制。仍然值得添加代码片段,以启用 Ctrl-X Ctrl-P 选择器绑定和制表符补全;两者同时启用没有问题(重复的标记会合并)。
nushell
nu 默认启用 shell 集成(OSC 133 标记、真实退出码、OSC 7 当前工作目录),因此 backscroll run 无需安装任何内容即可录制 nu 会话。nu 不会以结构化形式报告命令文本,因此 backscroll 会根据终端回显重建命令(参见下方 Ghostty 说明)— 文本完全准确,包括多行管道、折行和 Unicode;并在 CI 中根据 reedline 每次按键时重新绘制的提示符进行了验证。nu 有个特例:在命令运行期间按 Ctrl-C 会记录退出码 1,因为 nu 本身报告的就是这个值。
VS Code shell 集成
如果你的 shell 会加载 VS Code 的 `shellIntegration-*.sh`(这是针对 tmux/SSH 设置推荐的[手动安装](https://code.visualstudio.com/docs/terminal/shell-integration#_manual-installation)方式),backscroll 就能读取其 OSC 633 标记——命令文本、退出码和 cwd——无需安装代码片段。633 元数据只会被读取,不会存入录制的输出中。kitty / WezTerm shell 集成
kitty 的 kitty.bash / zsh kitty-integration 会将命令行附加到其 OSC 133;C 标记(cmdline=,经过 shell 转义),而 wezterm.sh 会将其报告为 WEZTERM_PROG 用户变量——backscroll 能解码这两种格式(包括重新拼接 WezTerm 的 base64 编码;对于超过 57 字节的命令,该编码会分段传输),还可读取退出码和 OSC 7 cwd,无需安装代码片段。
Ghostty、iTerm2 或任何纯 OSC 133 终端
这些终端会标记提示词/命令边界,但不会报告命令文本——因此 backscroll 会根据终端回显重建命令:它会将 shell 在提示词结束标记与执行前标记之间回显的字节(按键输入、退格、光标移动、ZLE 重绘,甚至 fzf 弹出窗口)通过一个小型终端行模型重放,并存储最终显示的行。无需安装代码片段,即可获取真实命令文本、输出和退出码。iTerm2 的 shell 集成脚本(在 tmux/SSH 中运行的脚本)均可完整处理,包括跨越其 A;k=s 续接提示词的多行命令、通过 OSC 1337;CurrentDir 获取 cwd,以及在两种 shell 中正确读取退出码;其有状态的 RemoteHost/CurrentDir 元数据只会被读取,不会存储。由于上游脚本存在错误,Ghostty 的 bash 退出状态目前始终为 0(参见 docs/osc133.md 中的注意事项 15)。
Windows
backscroll run 通过 ConPTY 伪控制台录制 PowerShell——采用相同的直通设计,并使用相同的本地 SQLite 数据库。将 init pwsh 代码片段添加到 $PROFILE(适用于 pwsh 7+ 和 Windows PowerShell 5.1),即可精确获取命令文本、退出码和 cwd,还可使用 Tab 补全和 Ctrl-X Ctrl-P 选择器;如果 shell 已经带有 VS Code 的 shell 集成,则可通过其 OSC 633 标记实现零配置。(backscroll run 会按 pwsh > powershell > cmd 的顺序选择;使用 BACKSCROLL_SHELL 可覆盖。cmd.exe 没有可发出标记的集成,因此会话可以正常运行,但不会对内容进行分段——Clink 用户可以通过提示词筛选器发出 OSC 133。)
导入现有历史记录
全新的数据库意味着选择器中没有内容。你可以从已有的历史记录中导入数据(backscroll doctor 会列出可找到的记录及条目数):
$ backscroll import atuin
imported 48312 entries from atuin (~/.local/share/atuin/history.db)
$ backscroll import zsh
imported 9871 entries from zsh (~/.zsh_history)
atuin 导入的数据最丰富(时间戳、退出码、cwd、主机名——它的同步功能意味着导入一次即可覆盖所有机器)。如果你使用的是 nushell 的 SQLite 历史记录后端,nu 的导入效果也一样(纯文本默认格式也可以导入——系统会根据内容识别格式,因此两种文件都适用)。如果你设置了 EXTENDED_HISTORY,zsh 会导入时间戳和持续时间;如果设置了 HISTTIMEFORMAT,bash 会导入时间戳;fish 始终包含时间戳;pwsh 会读取 PSReadLine 的 ConsoleHost_history.txt(包括多行反引号续接)。导入的条目没有已存储的输出——当时并没有录制——但从一开始就可以对它们使用 list、search、pick(以及 Ctrl-X Ctrl-P 选择器)和 stats,你的历史记录也会显示为一条连续的时间线。重复运行导入会进行增量处理:只添加尚未导入的条目。
(想知道这些文件在磁盘上到底是什么样吗——zsh 的 metafied 字节、PSReadLine 的反引号续接、atuin 的纳秒时间戳?参见实地笔记:docs/history-files.md。)
使用
| command | what it does |
|---|---|
backscroll show | 上一条命令的完整输出 |
backscroll show -3 | 倒数第三条命令 |
backscroll show 3141 | 按 ID 查询 · --raw 保留颜色 |
backscroll search <text> | 全文搜索命令和输出 |
backscroll search -C 3 <text> | …在每个匹配的输出行周围显示 3 行上下文,类似 grep -C(-A/-B 也可用) |
backscroll pick | 使用模糊选择器(fzf)选择一条命令,并实时预览输出 |
| Ctrl-X Ctrl-P at the prompt | 选择一条历史命令并插入光标处(当前行将作为查询内容) |
backscroll list -n 50 | 显示最近的命令及其退出状态、耗时和大小 |
... --exit fail --since 2h | 通用筛选条件(list/search/pick/export):仅失败项,最近 2 小时 |
... --since 2026-07-20 --until 2026-07-21 | --until 设置时间范围上限(不包含该时间)——仅当天 |
... --cwd . | 仅显示在此目录(或其子目录)中运行的命令 |
backscroll note "this one fixed it" | 为上一条命令添加备注——备注会显示在 list/show/search 中,也可搜索(note -3 "…" 可指定较早的命令,--rm 可删除备注) |
backscroll diff 3141 | 与同一命令的上一次运行相比有哪些变化 |
backscroll diff -2 -1 | 对任意两条已存储输出生成统一差异(-U n 设置上下文行数) |
backscroll export -1 | 将命令和输出导出为 Markdown 块,可直接粘贴到 issue 中(--details 会折叠内容) |
backscroll export --exit fail --since 1d | 将今天的所有失败项导出为一份 Markdown 报告——此处也可使用筛选条件 |
backscroll export 3141 --format cast | asciicast v2 格式——使用 asciinema play 回放 |
backscroll export -1 --format json | 适用于脚本处理的结构化记录 |
backscroll export -1 --format html -o out.html | 独立 HTML 页面,包含完整 ANSI 颜色——可附加到工单中,或直接分享 |
backscroll exec make test | 在任何已记录会话之外运行一条命令,并存储其输出、退出状态和耗时——适用于 cron 作业、CI 步骤和构建(详情) |
backscroll import atuin | 从你的 atuin 历史记录初始化数据库——时间戳、退出状态、工作目录和主机信息都会保留(详情) |
backscroll import zsh / bash / fish | …也可从纯文本历史记录文件导入 |
backscroll sync init ~/Sync/bks | 通过任意共享文件夹跨机器同步——加密、无需服务器(详情) |
... --host laptop / --host local | list/search/pick 筛选条件:仅显示该机器的历史记录 |
backscroll stats | 查看存储的数据量 |
backscroll stats --by cmd --exit fail --since 1w | 查看本周失败最多的命令——按命令显示次数、失败率、总运行时间和活动趋势迷你图(也支持 --by cwd|exit|host|session|day) |
backscroll prune --older 30d | 清除较早的记录 |
backscroll delete <id> | 删除一条记录(即 curl -H "Authorization: ..." 那条) |
backscroll redact <id|-N> | 永久遮盖已存储记录中的令牌/密钥/密码(--dry-run 可预览效果) |
backscroll mcp | MCP 服务:让你的 AI 编码 Agent 查询历史记录(详情) |
backscroll serve | 本地 Web UI:在浏览器中浏览和搜索历史记录(详情) |
backscroll off / on | 暂停/恢复此会话中的记录 |
backscroll doctor | 检查所有配置是否正常 |
| Ctrl-X Ctrl-P 绑定随 `backscroll init | |
| <bash | zsh |
它会在你记录的所有内容中打开选择器——你之前输入的内容会成为初始查询——并将选中的命令插入提示符,就像 Ctrl-R 一样,但你是根据命令输出的内容来选择,而不只是根据输入的内容。要选择不使用此绑定,请在代码片段之前设置 BACKSCROLL_NO_BIND=1。(在 bash 中,此绑定需要 bash ≥ 4.0;在 macOS 自带的 bash 3.2 中会跳过——但记录功能仍可正常使用。在 PowerShell 中,它使用随 pwsh 提供的 PSReadLine。) |
一次性命令(cron、CI、构建)
并非所有操作都在交互式会话中进行。backscroll exec
会封装单条命令——无需 shell、PTY 或设置——并像记录其他命令一样保存合并后的 stdout+stderr、退出代码、工作目录和耗时:
backscroll exec make -j4 test # flags after the command belong to it
backscroll exec sh -c 'pg_dump app | gzip > backup.gz' # shell features? bring a shell
它的行为就像把 tee 接在命令上:输出会直接传递(--quiet 会静默记录),stdin 保持连接,因此管道可以正常工作,Ctrl-C 会正常传递给子进程,而且退出代码会原样返回——包括因信号终止时的 128+n——所以可以直接放进 crontab、Makefile 和 CI 脚本,而不会改变它们的行为。
记录出错(数据库缺失、磁盘已满)不会阻止命令运行,也不会导致命令失败;程序会在 stderr 上给出警告,然后照常运行。
它最实用的场景是 cron。无需费力排查 MAILTO,也不用创建无人轮换的 >> /var/log/backup.log 2>&1 文件:
17 3 * * * backscroll exec /usr/local/bin/nightly-backup
……下周,当你想知道为什么周二的备份运行缓慢时:
$ backscroll list --since 1w --exit fail
$ backscroll search "No space left" --since 1w
$ backscroll diff -1 # what changed vs. the previous run?
启动失败也会被记录(exit 127,错误文本可搜索)——cron 经典的静默“command not found”终于有迹可循。即使是 --quiet 模式下的失败也仍然可见:backscroll stats --by cmd --exit fail --since 1w 会像统计其他命令一样统计这些失败。
GitHub Actions
setup-backscroll
可在任何运行器上安装 backscroll(Linux/macOS/Windows,并验证校验和):
- uses: soren-achebe/setup-backscroll@v1
- run: backscroll exec -- make test
它的 README 中有两个值得借鉴的方案:将失败步骤的输出与上一次成功运行的输出进行比较(使用 actions/cache 持久化数据库,然后运行 backscroll diff -1),以及生成可独立使用的 HTML 失败报告并将其上传为构建产物。
tmux / zellij / screen / SSH
backscroll 包装 shell,因此可以自然地与复用器配合使用—— 只需决定把它放在 tmux 的哪一侧:
- **在每个窗格内(推荐):**使用上面的
exec backscroll runrc 代码片段(或设置 tmux 的default-command "backscroll run")。 每个窗格都会成为独立的录制会话,在窗格 A 中运行backscroll show -1可以调出窗格 B 中已经滚出屏幕的输出——数据库是共享的。$BACKSCROLL_ACTIVE防护机制可防止嵌套时重复录制。 - 在 tmux 外部(先运行
backscroll run,再在其中运行tmux)没有 用处:tmux 会重绘整个屏幕,因此会丢失按命令分段的功能。backscroll 会通过备用屏幕检测全屏应用并跳过它们;请改为在窗格内运行。 - 弹出式搜索(tmux ≥ 3.2 + fzf):
backscroll init tmux >> ~/.tmux.conf会将prefix + B绑定为弹出窗口, 用于模糊搜索所有已录制的命令,并实时预览其保存的输出(prefix + F= 仅显示失败命令)。任何窗格、任何时候都可以使用——按 Enter 可浏览完整 输出,按q返回工作界面。 - zellij:用法相同——在每个窗格内录制,然后运行
backscroll init zellij,它会输出一段键位绑定配置,在浮动窗格中通过Alt b进行相同的模糊搜索(Alt Shift b= 仅显示失败命令);另外,Alt r可选取之前的命令并将其输入到提示符中——插入后供编辑,不会 执行(多行命令会通过带括号的粘贴传入,因此其中嵌入的换行符不会触发 Enter)。适用于任何 shell,无需 rc 代码片段。如果尚无keybinds块, 请将代码片段追加到~/.config/zellij/config.kdl;否则将三行bind复制到现有块中(zellij 会忽略第二个keybinds块)。 - **GNU screen:**在每个窗口内录制,然后运行
backscroll init screen >> ~/.screenrc,将C-a B绑定为在临时窗口中进行 相同的模糊搜索(C-a F= 仅显示失败命令);退出选择器时该窗口会自行 关闭。请注意:这会覆盖 screen 默认的C-a B(pow_break)/C-a F(fit)—— 如果你会用到这些功能,请重新绑定。 - **通过 SSH:**backscroll 会在 shell 运行所在的机器上录制。请在远程主机上 安装它,并在那里添加 rc 代码片段;如果想合并历史记录,请使用 同步。
跨机器同步
backscroll search "connection refused" — 跨笔记本电脑、台式机以及你通过 SSH
登录的构建机进行搜索:
laptop$ backscroll sync init ~/Sync/backscroll # any shared folder:
# Syncthing, Dropbox, rsync…
laptop$ backscroll sync export
desktop$ # copy ~/.config/backscroll/sync.key from the laptop, then:
desktop$ backscroll sync init ~/Sync/backscroll
desktop$ backscroll sync import
desktop$ backscroll search "connection refused" # both machines' history
3141 2d ago exit 1 [laptop] curl http://10.0.0.7:8080/health
…connection refused…
desktop$ backscroll list --host laptop # or filter by machine
无需服务器或账户:每台机器都会将自己的端到端加密日志(XChaCha20-Poly1305, 你只需复制一次共享密钥文件)追加到文件夹中,并导入其他机器的日志。每台机器的 日志仅追加,因此不会产生冲突——无论同步两次、部分同步还是乱序同步,都不会 损坏任何内容;你已有的任何文件同步工具都可用作传输方式。
隐私保护在数据离开机器之前就已落实:导出时会对每条命令和输出应用脱敏模式
(内置模式 + 你自定义的模式),忽略模式会完全跳过相应条目,传输的只有可搜索
的纯文本——原始终端字节(show --raw 重放内容)绝不会离开录制它们的机器。
backscroll sync status 会显示各机器的同步进度和密钥指纹。设计说明:
docs/sync-design.md。
AI Agent(MCP)
backscroll mcp 是内置的 Model Context Protocol
服务(stdio,零依赖),AI 编码 Agent 可以根据你记录的历史回答
“那个命令输出了什么?”,而不是猜测,或重新运行耗时或具有破坏性的操作:
- search_output — “查找构建过程首次显示
undefined symbol的位置”(context_lines会为每个匹配项提供类似 grep -C 的上下文) - get_output — 任意命令的完整输出(
-1= 最近一次) - list_commands — 最近的历史记录,例如仅查看失败项
- diff_output — 与同一命令上一次运行相比有哪些变化
在你的客户端中注册:
# Claude Code
claude mcp add backscroll -- backscroll mcp
// Cursor / Windsurf / VS Code-style mcpServers config
{ "mcpServers": { "backscroll": { "command": "backscroll", "args": ["mcp"] } } }
各客户端的设置说明(Claude Code/Desktop、Codex、Cursor、Windsurf、VS Code、 Zed、Gemini CLI)请见文档网站: AI Agent 指南。
它也列在官方 MCP Registry
中,名称为 io.github.soren-achebe/backscroll。每个版本还会提供
backscroll-<version>.mcpb 捆绑包
(macOS/Linux),适用于从文件安装 MCP 服务的客户端——无需单独安装,不过你仍需要完成上述完整设置,才能搜索已记录的历史记录。对于容器化的 MCP 设置,我们还提供预构建的多架构镜像:
docker run -i --rm \
-v ~/.local/share/backscroll:/data/.local/share/backscroll:ro \
ghcr.io/soren-achebe/backscroll
(以只读方式挂载数据库;记录功能本身仍需要将原生二进制文件包装在你实际使用的 shell 外层)。
默认会屏蔽机密信息:传递给客户端的所有内容都会经过与 backscroll redact 相同的脱敏规则(内置常见令牌格式的规则,以及你在 ~/.config/backscroll/redact 中配置的规则),此外,已有的忽略规则也会让匹配的命令完全不进入数据库。如果你确实需要,backscroll mcp --no-redact 可以禁用屏蔽。服务只会读取本地数据库——记录工作仍在你的 shell 中继续进行,只有 Agent 请求的内容才会离开这台机器。
反过来也行:让 backscroll 监控你的 Agent,它在本机或开发虚拟机上运行的每条命令都会成为可搜索的逐命令审计记录——请参阅审计 Agent 运行过的命令。
Web UI
backscroll serve 会在你记录的历史记录上启动本地只读 Web UI(--open 还会在浏览器中打开它):

- 输入即搜索:搜索命令及其输出(底层使用 FTS5,即使有数万条命令也能即时搜索),并显示匹配片段;还支持与 CLI 相同的筛选条件(仅失败项、时间范围)。上下文选择器会显示匹配输出行及其前后 ±2/±5 行,类似 grep(与
search -C一致)。展开结果后,完整输出中的每处匹配都会高亮显示,并提供 ↑ 3/17 ↓ 跳转器来切换匹配项——即使 ANSI 颜色将单词拆开也能正常工作。 - 统计视图 — 可将历史记录切换为按命令/目录/退出码/主机/日期划分的统计(数量、失败率、总耗时),并根据当前筛选条件限定范围。目录、退出码和主机行均可点击:点击“exit 127”,即可返回历史记录并查看对应的命令(“哪些命令以这种方式失败了?它们输出了什么?”)。
- 保留颜色 — 存储的 ANSI 输出会渲染为 HTML,因此
ls、测试运行器和构建日志看起来与终端中的效果相同。进度条刷屏(\r覆盖)会折叠为最终状态。 - 一键对比与同一命令的上一次运行结果——“自昨天的健康检查以来有什么变化?”按钮。
- 永久链接 — 每条命令都有一个
#42深层链接,可全页打开该命令(输出不截断、显示绝对时间,并提供复制链接按钮)。你可以在固定标签页中打开构建日志,为不稳定测试的输出添加书签,或将链接粘贴到笔记中,以便明天再次查看。 - 下载为 HTML — 只需点击一次,即可将任意命令保存为与
export --format html生成的相同独立页面(完整颜色、无外部资源、无 JS):可将其附加到工单或交给同事,无需使用浏览器。 - 设计上仅限本地使用:绑定到
127.0.0.1:4133,只提供 GET 请求服务,并拒绝Host标头不是 localhost 的请求,因此恶意网站无法通过 DNS 重绑定读取你的历史记录。如果将--addr覆盖为非回环地址,它会发出醒目警告。--redact会在提供的所有内容中遮盖机密信息,使用的模式与backscroll redact相同。
无需构建步骤,也无需 node_modules——UI 是一个嵌入式 HTML 文件,整个程序都包含在同一个静态二进制文件中。
与其他工具的对比
| 记录命令 | 记录输出 | 可搜索 | 按命令组织结构 | |
|---|---|---|---|---|
| shell 历史记录 / atuin / hishtory | ✓ | ✗ | ✓ | ✓ |
script / asciinema | ✓ | ✓ | ✗(原始数据块) | ✗ |
| 终端回滚缓冲区 | ✓ | 直到无法继续 | ✗ | ✗ |
| backscroll | ✓ | ✓ | ✓(FTS5) | ✓ |
与其他工具配合良好
backscroll 是一个记录器,不是提示词或历史记录管理器——它旨在与 shell 已有的功能并行运行。CI 会针对固定版本的常见工具运行真实会话,并验证命令、输出和退出代码都已正确记录,并且其他工具仍能正常工作
(shell/test_compat_matrix.py):
| 测试对象 | bash | zsh | fish |
|---|---|---|---|
| atuin(包括其 Ctrl-R TUI) | ✓ | ✓ | ✓ |
| starship(两种加载顺序) | ✓ | ✓ | ✓ |
| zoxide | ✓ | — | ✓ |
| direnv | ✓ | — | — |
| oh-my-zsh | ✓ | ||
| powerlevel10k(包括即时提示) | ✓ | ||
| bash-preexec(两种加载顺序) | ✓ | ||
bind -x / zle 小组件(fzf 风格;包括上文 atuin 的真实 Ctrl-R) | ✓ | ✓ | ✓ |
即使你不使用 backscroll,也值得了解这一点:在 bash 上使用 starship ≤ 1.26 时,任何从 starship 包装过的 PROMPT_COMMAND 中读取 $? 的程序,看到的都是 0,而不是真实的退出状态——starship 自己的 _starship_set_return 会立即被其后的 [[ -n ... ]] 测试抵消。backscroll 会在提示框架运行前,通过 DEBUG 陷阱捕获真实退出状态,从而绕过这个问题(starship 正在进行的 PR #7606 会重构包装逻辑,并修复这一普遍问题)。
开销
在一台配置普通的 2-vCPU 虚拟机(AMD EPYC)上测量,结果为多次运行的中位数——你可以通过 go test ./internal/record -bench . 和 PTY 测试框架自行运行:
- **按键延迟:**与裸 shell 相比,回显延迟中位数增加 0.05 ms (0.22 ms 对比 0.16 ms;p95 增加 0.1 ms)。单个 60 Hz 帧为 16.7 ms——你无法感知到这一差异。
- **大批量输出:**通过记录器运行
cat,读取一个 27 MB 的文件,速度约为 31 MB/s;通过裸 PTY 则约为 56 MB/s。终端模拟器的渲染速度远低于两者,因此记录器绝不会成为你的等待瓶颈。 - **解析:**OSC 133 分段器在单个核心上扫描速度约为 680 MB/s;头尾捕获缓冲区以 memcpy 的速度写入(约 44 GB/s)。
- **磁盘:**输出使用 zstd 压缩,并按命令设有大小上限
(默认保留开头 256 KiB 和结尾 1 MiB,可配置)。搜索索引直接读取压缩存储,而不是保留自己的纯文本副本(fts5 外部内容),与朴素方案相比,数据库大小大约减半——在相同的、包含大量输出的 1,000 条命令工作负载中,实测从 28.2 MB 降至 14.9 MB。典型的一天交互式工作会给一个 SQLite 文件增加几 MB。
backscroll prune --older 30d会保留滚动时间窗口,backscroll prune --max-size 500M会通过清除最旧条目限制数据库总大小,而这两种方式都会彻底压缩文件。
隐私说明
记录终端打印的所有内容正是它的用途——也是一份责任。backscroll 从设计上就是仅在本地运行的。不过:
-
忽略模式:在
~/.config/backscroll/ignore中每行写入一个 Go 正则表达式,匹配的命令绝不会被存储:^vault ^op\b password|token|secret -
backscroll off会暂停本次会话的记录(运行backscroll on可恢复)——适用于快速处理凭据的情况。 -
backscroll delete <id>会删除一条记录(及其 FTS 索引),适用于意外打印出机密内容的情况。 -
脱敏:
backscroll redact <id>会永久遮蔽已进入记录的机密信息——AWS/GitHub/Slack/Stripe/OpenAI/Google/npm/PyPI/GitLab 令牌、JWT、password=/api_key:值、URL 中的凭据、Authorization:标头、私钥块——包括命令行、输出和搜索索引中的内容。show --redact和export --redact也会执行同样的操作,但不会永久修改数据,因此即使存储的副本未脱敏,你粘贴到问题报告中的内容也会是干净的。在~/.config/backscroll/redact中添加自定义模式(每行一个 Go 正则表达式)。基于模式的遮蔽尽力而为——分享前请仔细检查。 -
backscroll prune --older 30d会保留滚动时间窗口内的记录;--max-size 500M会限制数据库总大小(优先删除最旧的记录)。 -
数据库位于你的主目录下,仅所有者可访问(目录权限为
0700,文件权限为0600,自 v0.11.1 起每次打开时都会强制设置权限);请像对待 shell 历史文件一样对待它,因为两者包含同类数据。它不会在静态存储时加密:任何能访问你的 Unix 账户(或 root)的用户都能读取它,就像读取~/.bash_history、~/.ssh或浏览器配置文件一样。如果你的威胁模型包括磁盘脱离你的掌控,请使用全盘加密。若使用同步,~/.config/backscroll/sync.key也是如此——任何持有该文件的人都能读取你的同步历史记录(不要把它放在同步文件夹中)。 -
不要在共享账户上运行它。
-
验证下载内容(v0.12.1+):每个发布制品都附带一份签名的构建来源证明,证明它由此仓库的公开发布工作流根据已标记的提交构建,而不是在某人的笔记本电脑上构建。使用以下命令检查任何 tarball、软件包或校验和文件:
gh attestation verify backscroll_linux_amd64.tar.gz -R soren-achebe/backscroll -
网络:只有一条命令会访问网络——
backscroll upgrade,且仅当你运行它时才会从 GitHub 获取发布版本。它不会在后台检查更新,也没有遥测;记录、搜索、服务和同步均不会与任何地方建立连接。
发现能够绕过上述任何控制措施的方法?这就是一个漏洞——请参阅 SECURITY.md,了解私下报告方式和完整的威胁模型。
状态
尚处早期阶段,但已可用:支持 Linux 和 macOS 上的 bash、zsh、fish 和 nushell,以及 Windows 上的 PowerShell(ConPTY);还支持导入历史记录(atuin/zsh/bash/fish)、忽略模式、会话暂停(off/on)、输出差异比较、fzf 选择器
(pick、Ctrl-X Ctrl-P、tmux 弹出窗口)、跨机器加密同步、供 AI Agent 使用的 MCP 服务、本地 Web UI(serve)和 doctor 命令。
欢迎提交问题和 PR;请参阅 CONTRIBUTING.md。
各版本的详细信息请见 CHANGELOG。
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。