有些工具,不是从路线图里长出来的。它们通常来自某个很烦的晚上。
Terminal 开着十几个 tab,咖啡已经不顶事了。你记得自己刚才跑过一条命令,里面好像有个 --flag,还可能带了个路径。那条命令当时是有用的,现在你想再看一眼。
我平时会先用那种最朴素的办法,把历史全倒出来再筛一遍。比如想找之前跑过的 Cursor 相关命令,大概就是:
history 1 | grep cursor
这招不是不能用。问题是它很快就会变成另一种麻烦:关键词不准,换一个;大小写不对,再补参数;结果太多,继续肉眼扫。扫着扫着你突然意识到:就算找到了那一行,好像也只找到了那一行。
它长得像当时那条命令,但没人说自己案发时在哪 
Shell history 最让人无语的地方就在这儿。它记了命令,但经常没记现场。
你不知道这条命令是在当前项目跑的,还是隔壁项目跑的;不知道那会儿 Git 分支是什么;不知道最后退出码是多少;更不知道 stdout/stderr 后来去哪了。到最后你不是在查历史,你是在考古。
Stillrun 就是这口气没顺下去的时候写的 
一开始想得很简单:终端能不能别只留一句命令,顺手把现场也记一下?
在哪个目录,哪个 Git 分支,最后有没有跑成,输出去了哪儿。这些东西平时没存在感,真找起来一个都不能少。
把它画出来,大概是这条路。图里的名字都能在 CLI 里找到:
这看起来像一小套系统,其实都在本机。没有账号,没有服务端,也不准备接管你的 shell,只是把几件原本散着的小事收拢起来:命令记录在库里,输出落到日志里,想找的时候能搜,想重跑的时候先预览,想常驻的时候交给 launchd。
现在可以 brew install 了
之前它还更像“我自己机器上能跑”的小工具:clone 仓库,装 Rust,再 cargo install。但感觉这样太折腾了点,所以和之前的 mollow 一样,我也给整成了可用 Homebrew 进行安装。
现在这道门槛低了一点:
brew tap ingeniousfrog/tap
brew install stillrun
懒得先 tap,也可以直接:
brew install ingeniousfrog/tap/stillrun
装完先看一眼版本和帮助:
stillrun --version
stillrun -h
如果只是想看看它会从旧 history 里捞出什么,先别急着写库:
stillrun import-history --shell auto --preview
这事本身不酷,但很重要。一个命令行工具如果第一步就要求对方进入“我要从源码构建”的心态,基本已经筛掉了很多只是想试一下的人。
现在发布链路也规整了一点:打 tag 以后,GitHub Actions 会分别产出 Apple Silicon 和 Intel 的 macOS 包;Homebrew formula 从 release 包里装二进制,同时带上 shell completion。幕后这些东西平时没人想看,但它决定了这个工具到底是“我本机上能跑”,还是“别人也能先跑起来再说”。
Terminal 恢复窗口,但不负责保命
另一个让我动手的原因,是 Mac 的后台任务。
Terminal 有个恢复窗口的功能。听起来很贴心:上次开的窗口,下次尽量摆回来。
但它恢复的是画面,不是任务本身。
窗口还在,命令也像还在。可进程到底活没活着?输出有没有断?端口是不是早就没了?你还是得一个窗口一个窗口翻过去看。
tmux 能救很多场面,我也用。只是有些命令不太值得专门塞进一个 tmux 会话里养着。比如一个本地服务、一个轮询脚本、一个开发时顺手开的辅助进程。你只是希望它在后台跑,有名字,有日志,能停,能重启。
Mac 上正经干这件事,绕不开 launchd。
然后就绕到了 plist。
plist 不是坏东西。它很认真。认真到你只是想让一条命令下楼买包盐,它却问你要不要先填一张海关申报单。
Stillrun 后来加的后台 Job,就是为了少和 plist 正面搏斗几次。你还是用 macOS 自己的 launchd,只是不用每次手写 Label、ProgramArguments、WorkingDirectory、stdout/stderr 路径,也不用隔一阵子重新回忆 launchctl bootstrap 和 bootout。
我想留的,是那会儿的现场
history 最大的问题,不是它不好用。它只是太瘦了。
一条命令能不能再用,经常要看它当时站在哪个坑里。
- cwd 是哪个;
- Git repo 是不是同一个;
- 分支和 commit 对不对;
- 退出码是多少;
- stdout/stderr 有没有东西;
- 这条记录是刚刚用 Stillrun 跑出来的,还是从老 shell history 导进来的。
这些都不高级,但很实用。尤其是你已经连续试错半小时,脑子里只剩“刚才好像有一条能跑”的时候。
Stillrun 的 run 做的事很朴素:跑命令,顺手记录这次 execution。命令、目录、Git 信息、耗时、退出码、输出大小,会进本地 SQLite。搜索用 FTS5,奇怪片段搜不到时再走子串 fallback。
history --details 展开以后,至少能回答几个很普通但很要命的问题:这是哪个目录里的命令?当时在哪个分支?commit 是哪一个?它到底成功了没有?
这几个答案一出来,很多“我记得我跑过”的悬案就没那么悬了。
Replay 要慢一点
重放命令这件事,我一开始就不想做得太豪迈。
命令不是只活在一行文本里。alias、function、TTY、当前 Git 文件树、环境变量,都会影响结果。一个工具如果上来就说“我帮你完整恢复当时现场”,我反而不太敢信。
Stillrun 的 replay 收着点来。
它恢复记录里的 argv、cwd 和非敏感环境变量。它不会自动 checkout Git,也不会假装能复活当年的 shell alias/function。你可以先看:
stillrun replay 1 --preview
它把准备重跑什么、在哪重跑、会恢复多少环境变量先列出来。真要跑,再加 --yes。
这里我宁愿多敲几个字。会改状态的东西,先看一眼,少给自己制造新悬案。
导入旧 history,也先别急着倒进去
Stillrun 也能导入 zsh、bash、fish 的本地历史。
但导入这事太容易热心过头。一个工具第一次见面就说“我帮你把旧东西全搬进来”,听着像亲戚帮你整理房间。动作很快,效果很震撼,主要问题是你自己再也找不到东西了。
所以这里也是先 preview:
它会告诉你扫了几个文件、看了多少条、会导入多少、重复多少、空记录多少。确认没问题,再加 --yes 写进去。
敏感信息也顺手擦一下。常见的 token、password、api_key,以及命令行里像 --token value 这样的模式,落库前会尽量脱敏。
我不想把这事说得太吓人,但命令历史里混进 secret 实在太常见。今天你觉得“反正只有我自己看”,三个月后你就可能把截图贴进 issue、发给朋友,或者写进公众号文章里。
复制粘贴的时候,人类并不总是清醒。
别让一个 Terminal tab 扛着后台任务
我最开始只想少翻几次 history。写着写着发现,记录命令和后台 Job 其实挨得很近。
有些命令只是偶尔跑一次。记下来,能查,能 replay,就够了。
有些命令就不一样。你反复跑它,每次参数差不多,还希望它别随着某个窗口一起没了。那它就不该继续靠 Terminal tab 的命硬程度续命。
Stillrun 里可以这么干:
stillrun run --background --name demo-tick -- \
zsh -lc 'for i in 1 2 3 4 5; do echo tick-$i; sleep 1; done'
stillrun jobs
stillrun status demo-tick
stillrun logs demo-tick
stillrun jobs monitor demo-tick --once
stillrun jobs events demo-tick --limit 10
stillrun stop demo-tick
stillrun jobs delete demo-tick
跑起来以后,我想看的其实就这几样:它在哪、日志在哪、现在活没活着、最近有没有异常。
它会生成对应的 launchd Job。stdout/stderr 有固定日志路径,status 能看运行状态,logs 能看输出,jobs monitor 能采一次 CPU/RSS,jobs events 能看最近发生过什么。launchd 真报错的时候,也别只甩一句失败。至少告诉我 job identity、plist 在哪、可以怎么处理。系统不配合是系统的事,工具别让人猜谜。
先别把它做大
Stillrun 现在只盯 macOS,本地优先。不想写 Web UI,懒得整 TUI,更不想整远程节点,也不负责把命令历史整理成人生建议。
这几个“不做”,对我还挺重要
我希望它像一把放在桌边的小工具,而不是另一个需要开账号、配服务、读三页概念图的平台。烦的时候拿起来,用完放下。
现在我想把这些小地方磨顺:
- 窄终端里,表格别碎成一地;
- 导入和重放,永远先给 preview;
- 人看的输出要清楚,机器读的 JSON 也要稳;
- launchd 报错时,把 plist 路径和恢复命令说清楚。
这些都不适合写在发布会大屏上,但每天用工具时,舒服不舒服基本就差在这儿。
最后,说回那个晚上
Stillrun 的起点真的很小。我就是受够了两件事
:
一是 Mac 上翻历史太费劲。二是 Terminal 恢复窗口经常只是恢复个样子,tmux 又不可能替所有后台任务当保姆,而手写 plist 实在太像给泡面申请施工许可。
于是我写了一个小东西,把命令先记清楚。值得留下来的,再让它规矩地跑在后台。
它不解决宇宙问题,也没法让人第二天融资三千万。但它能解决一个很具体的时刻:你想找回一条命令,不想破案;你想让一个任务继续跑,不想写 plist;你想知道它到底死没死,不想对着 Terminal 窗口沉思。
对我来说,这就够了。人生里要填的表已经很多了。能少写一个 plist,就少写一个。
如果你也有类似的终端烦恼,不妨来 云栈社区 和更多开发者交流。
项目地址:https://github.com/ingeniousfrog/Stillrun