先说结论:很多人以为“context-mode”只是某种编辑器里的专注模式开关,但实际上,它值得被理解为一整套上下文管理思路。我过去大半年一直在折腾这件事——把终端会话、编辑器状态、项目分支、任务清单统一到同一个框架下管理,并把这套工作流命名为 context-mode。它的核心目标不是让你“不分心”,而是让你在频繁切换任务时,把丢失的上下文成本压到最低。
如果你经常同时处理两三个项目、经常在“改完需求”和“回头写方案”之间反复横跳、经常打开终端后愣在那不知道刚才在查什么,那这篇文章就是写给你看的。下文会从原理讲起,再给出一套可以直接照抄的终端与编辑器配置,最后聊聊我在落地过程中踩过的坑。
1. 先搞清楚 context-mode 解决的是什么问题
1.1 一天 20 次切换,真正丢的时间是什么
我做过一个很粗糙的统计:某一周里,我每天要切换项目或任务的次数大约在 18 到 25 次之间。每次切换后,光是想起来“刚才做到哪一步”往往需要两三分钟,再加上重新打开对应文件、恢复终端目录、找到上次调试的日志位置,单次切换的成本很容易超过五分钟。
这不是个例。大多数开发者的日常工作里,真正的瓶颈不是打字速度,而是“从一件事跳回另一件事”时的状态重建成本。context-mode 想解决的就是这个成本。它把上下文拆解成几个可以显式保存和恢复的对象——终端会话、编辑器窗口布局、当前分支、待办事项、甚至环境变量——然后让这些对象跟着项目走。
1.2 context-mode 与“专注模式”“沉浸模式”的差异
市面上已经有很多“专注模式”“禅模式”产品,它们通常做的是同一件事:把干扰源隐藏起来,让你停留在当前任务里。比如编辑器的 Zen Mode、手机的免打扰、番茄钟工具。
context-mode 的思路不太一样。它不假设你会一直待在一个任务里,而是假设你必然会被打断、必然要切换。与其对抗切换,不如把每次切换变成“桌面切换”式操作:一键离开当前上下文,一键回到另一个上下文,回到哪台“桌面”,哪台桌面上的东西都还是你离开时的模样。
用一句话概括差异:专注模式是“锁死状态”,context-mode 是“可暂停、可恢复的状态镜像”。
1.3 哪些人值得花时间搭这套东西
不是所有人都需要 context-mode。判断标准很简单:
- 你每天是否至少切换三个以上不同的代码仓库或工作目录?
- 你是否经常出现“吃完午饭后忘了上午在改哪个 bug”?
- 你是否同时维护着多个终端窗口,却经常找不到对应项目的窗口?
三个问题里中了两个,就值得搭。如果只是固定时间只做一个项目,那确实没必要引入额外工具链。别为了折腾而折腾,这是我自己的教训一。
2. 把上下文当成显式资源:核心原理拆解
2.1 隐式上下文与显式上下文的差异
人脑默认会把上下文存储在“环境线索”里——桌面上的窗口位置、终端里的目录、编辑器里的打开标签页。这属于隐式上下文。
隐式上下文的问题是:它依赖非常脆弱的视觉线索。一旦窗口被关闭、机器重启、或者你把全部终端最小化,这些线索就没了。而 context-mode 要做的事,是把隐式上下文转化为显式状态:用一个会话文件记住窗口布局,用一个环境变量记住当前项目根目录,用一个 git 分支名记住当前工作阶段。
显式上下文的最大好处是“可被工具管理”。它不再只是你脑子里的模糊记忆,而是文件、变量、进程,可以被备份、同步、脚本化。
2.2 上下文生命周期:从开机到改需求
我习惯把上下文分成四个层级,从小到大分别是:
- 分支层:当前在哪个分支上做事,对应需求或修复的目标。
- 项目层:当前在哪个仓库、哪个目录结构下工作。
- 会话层:终端开在哪个目录、编辑器打开了哪些文件、有没有正在跑的预览或测试进程。
- 意图层:这一轮任务接下来三十分钟要做什么。
context-mode 的落地重点在前三层。意图层虽然也重要,但它通常适合放到笔记或任务管理工具里,而不是塞进终端配置。别把上下文状态模型搞得过重,否则维护状态本身的成本会超过它省下的时间。
2.3 判断上下文的三个指标
当你搭建自己的 context-mode 时,可以用三个指标来评判方案是否合格:
- 恢复速度:从命令执行到完整恢复工作现场,应该不超过十秒。
- 可见性:当前处于哪个上下文,应该在一秒钟之内从终端提示符或编辑器状态栏看出来。
- 无感性:切换上下文时,不应该需要手动去逐个打开文件、逐个切换目录。
只要有一项不达标,说明这套体系还停留在“手动登记”阶段,没有真正形成模式。
2.4 用一个厨房里的例子解释
把 context-mode 类比成厨房备餐:隐式上下文是你随手把葱姜蒜放在灶台边上,做一半被叫走,回来发现保洁已经把灶台擦干净了,葱姜蒜也没了。显式上下文则是把配料分别装进贴了标签的小碗,放回冰箱,回来以后按标签拿出来就能接着做。
代码仓库也一样。你上个星期在改支付模块时,终端可能停在src/payment目录下,编辑器开着三四个相关文件,测试命令跑在某个终端标签页里。如果这些东西散落在界面各处,一场重启就能让你彻底失忆。context-mode 就是那套贴了标签的保鲜盒。
3. 终端为先:在 shell 里搭一套 context-mode 骨架
3.1 tmux 作为上下文容器
我选 tmux 作为终端部分的地基。原因不是因为它新潮,而是因为它天然符合“会话即上下文”的模型。tmux 的 session 可以单独命名、后台运行、随时重新附着,这正好匹配项目的粒度:一个项目一个 session。
常用命令其实就这几条:
tmux new-session -s projectA # 新建项目会话 tmux a -t projectA # 重新附着到会话 tmux list-sessions # 查看所有活跃上下文 tmux kill-session -t projectA # 结束上下文我通常会为每个项目分配一个 session,里面再开三个窗口:一个跑 git 和日常命令,一个跑测试或构建,一个留给临时操作。这样切项目时不是切窗口,而是整个 session 级别地切换,目录、历史、环境全都在。
提示:别忘了在 tmux 配置里打开鼠标模式和滚动回退,否则你在会话里翻历史输出会非常痛苦。配置写在
~/.tmux.conf里即可。
3.2 绕开 CD 的目录跳转
进入项目上下文的第一步是到达项目根目录。裸用cd配合一长串路径很低效,我用的是zoxide。
z init zsh z payment # 直接跳到最常匹配的 payment 相关目录zoxide会记录你的目录访问频率和时长,之后输入模糊关键字就能直达目标目录。这个工具的厉害之处在于它是“频率加权”的,你越常去的地方排得越靠前,不需要手动维护快捷方式。
3.3 让提示符直接显示上下文状态
恢复速度快不够,还要让“当前在哪”一目了然。我的 zsh 提示符右侧会显示三样信息:当前目录名、当前 git 分支、当前 tmux 会话名。
实现不复杂,核心是几个变量:
# 右侧提示符 RPROMPT='%F{cyan}${PWD##*/} %F{green}$(git_current_branch 2>/dev/null) %F{magenta}$(tmux display-message -p "#S" 2>/dev/null)%f'效果上,任何时候瞟一眼右下角,就知道自己身处哪个 session、在哪个目录、改哪个分支。这直接满足“可见性”指标。
3.4 写一个 mkproject 脚本来启动上下文
为了让新建项目上下文变成一条命令,我写了个小脚本,放在~/bin/mkproject:
#!/usr/bin/env bash # 用法: mkproject <项目名> [绝对路径] set -e name="$1" path="$2" if [ -z "$path" ]; then path="$HOME/work/$name" fi if [ ! -d "$path" ];then mkdir -p "$path" fi if ! tmux has-session -t "$name" 2>/dev/null; then tmux new-session -d -s "$name" -c "$path" tmux send-keys -t "$name" "z $name" Enter tmux send-keys -t "$name" "git status" Enter tmux new-window -t "$name" -c "$path" fi tmux switch-client -t "$name"这个脚本做的事可以拆成四步:
- 检查或创建目录。
- 如果 tmux 里没有对应 session,就新建一个,并自动切到目标目录。
- 顺手跑一次
git status,让你立刻知道工作区状态。 - 再开一个备用窗口,然后把你切进这个 session。
我并不需要把脚本写得特别复杂。它省掉的是重复的“新建窗口、打 cd、敲 git status”三连操作,每天省下的时间不多,但心智负担少很多。
3.5 离开上下文时如何挂起
进入上下文解决了,离开上下文同样重要。我给自己定了一条规矩:要切走之前,必须保证当前窗口能明确反映“做到哪了”。
具体做法是,在切走前用git status或git stash list留下痕迹,或者在 tmux 窗口标题里写上关键信息。因为 tmux 窗口可以随时重命名:
tmux rename-window "feature/hook-debug"窗口标题变成了一个临时的“任务标签”。回来时不用回忆,看一眼窗口列表就明白当时在搞什么。
4. 编辑器一侧的 context-mode:状态保存与工作区配置
4.1 编辑器工作区作为上下文单元
终端搞定后,编辑器是另一半。VSCode 的 workspace 文件是一个被低估的上下文管理工具。每个项目一个.code-workspace,里面可以指定根目录、默认文件夹、甚至启动时自动打开的文件组。
一个典型的payment.code-workspace长这样:
{ "folders": [ { "path": "/home/me/work/payment" }, { "path": "/home/me/work/shared-lib" } ], "settings": { "files.exclude": { "**/node_modules": true } }, "launch": { "configurations": [], "compounds": [] } }好处是一次打开一个 workspace,等于打开整组项目上下文,而不是逐个文件夹窗口乱摆。切项目时用命令直接开对应 workspace,浏览器标签页那种“开了一百个标签找不到东西”的情况就少了。
4.2 用别名快速打开对应工作区
光有 workspace 文件还不够,得能快速调用。我在 zsh 里加了两行别名:
alias cdp="code ~/workspaces/payment.code-workspace" alias cdpay="code ~/workspaces/payment.code-workspace && z payment"第二个别名比较实际:先打开 VSCode 工作区,同时把终端切到对应目录。一条命令,两个上下文步进到位。
如果你更习惯 NeoVim,思路一样,不过用的是 session 文件。可以记住两个命令:
:mksession ~/sessions/payment.vim:保存当前窗口布局、打开的文件、部分选项。nvim -S ~/sessions/payment.vim:恢复会话。
配合 autosession 插件,甚至可以做到进入目录时自动恢复上次编辑状态。但插件自动恢复有个副作用:有些临时文件也会跟着回来,容易让会话越积越乱。我个人的做法是手动保存 session,而不是全自动。
4.3 不要忽略编辑器的小状态
除了文件布局,还有个常被忽略的上下文项:剪贴板历史、搜索历史、最近的调试配置。
这些通常不需要刻意管理,因为它们本身有记录。不过要注意调试配置的隔离。如果你同时调试两个项目,VSCode 的launch.json混在同一个全局列表里,就很容易选错启动项。
解决办法是让launch.json跟着 workspace 走,并且每个 workspace 只保留当前项目相关的调试配置。这算是个细节,但确实能省下不少“怎么又启动不了”的排查时间。
4.4 编辑器侧的最大风险点
编辑器 context-mode 的最大风险是“把上下文存得太多”。我一开始恨不得把所有窗口布局都存下来,结果恢复出来的 session 里有一堆已经不需要的文件,反而增加了认知负担。
做了减法之后,我只保存两类状态:当前需求相关的文件组、以及当前正在使用的测试配置。其余一律不保存。记住,context-mode 的目的是让你更快进入状态,而不是让你回到一个“看起来什么都没变”的旧桌面。
5. 反干扰与防丢上下文:笔记、任务和冷却机制
5.1 用外部笔记让大脑卸载上下文
再好的工具,也不能替你把“意图层”记下来。我过去总是自信地认为“这个 bug 的排查思路我记得住”,结果三次里有两次在隔天就忘干净。
后来养成的习惯是:在每次切换任务前,用最短的形式写一条“移到笔记”。格式极简,三行以内:
[payment] 修复回调验签失败 - 现象:某些请求 code 返回 null - 怀疑:回调里的加密串解码逻辑 - 下一步:在 decode 处打日志这条笔记不要写成文档,就当作是给未来的自己留的一份便签。它最大的价值不是在写的时候,而是在你第二天回来时,用它把丢失的上下文快速重新载入大脑。我试过用各种花哨的笔记软件,最终发现纯文本文件加目录结构最好用——因为它没有任何使用成本。
5.2 让任务追踪绑定到上下文
如果你用看板或者任务管理工具,建议给每个上下文一个固定的前缀标签,比如[payment]、[infra]。这样所有的待办事项可以按上下文过滤,一天结束时,只需要看某一个前缀下面堆积了什么,就能快速判断哪个项目陷入了泥潭。
我在终端的做法是维护一个todos/目录,每个项目一个文件,配合简单的 grep 就能拉出全局待办视角:
grep -r "TODO" ~/todos --include="*.md" | less不需要什么重量级看板系统。对于个人开发者或小团队,轻量文件往往比协作平台更适合做个人上下文管理。
5.3 给上下文加冷却时间
context-mode 不只是切换工具,也隐含着自我保护机制。我给自己定了一个规则:同一个上下文内的重度决策,如果卡了半小时没有进展,必须主动把上下文挂起,去干点别的。
这不是玄学,而是换了一批缓存数据再回来。长时间卡在同一个问题上,你会不断重复读取同一个错误信息,陷入“重新分析同一段代码”的循环。把上下文挂起后,哪怕是倒杯水、看两页别的东西,再回来时往往能发现之前漏掉的线索。
工具上的配合是:tmux 里保留当时的窗口不要杀掉,但把它放到后台,不给它视觉焦点。这样回来时所有现场还在,但你已经完成了“大脑的缓存刷新”。
5.4 如何测量 context-mode 是否有效
搭完之后,应该用数据验证效果,而不是凭感觉。最简单的方法是每周五下午统计三件事:
- 每天从“打开电脑”到“进入第一个实质任务”,花了多久。
- 切换任务后,恢复到“能继续动手”平均要多久。
- 下班前,有没有超过两个上下文处于“不知道做到哪”的状态。
第一项和第二项的目标是下降,第三项的目标是归零。只要这三个指标没变好,就说明你的 context-mode 配置可能只是花架子——需要精简,而不是继续加东西。
6. 落地过程中踩过的坑和我的最终配置
6.1 三个最值得记下的坑
第一个坑是过度自动化。最初我试过在 shell 的chpwd钩子里自动加载项目专属的环境变量、自动启动对应服务、自动打开编辑器。听着很省事,但实际上每次cd都要等一两秒,进度条转完才落到提示符,而且中途会在你不想启动服务时也启动服务。后来我只保留了两个自动动作:进入目录时自动读取项目根标记、提示符自动切换上下文显示。其余全部改成手动触发。
第二个坑是 session 数量失控。tmux 的 session 开起来很容易,但如果不定期清理,最后会积累十几个僵尸 session。我加了条清理策略:每个周末把上周没有打开过的 session 全部 kill 掉,然后把目录里对应的入口脚本重新生成一遍。上下文本身变成一种“可重建”的状态,就不必担心误删。
第三个坑是同步问题。如果你有台工作电脑和一台笔记本,session 文件、workspace 文件、todos 目录最好纳入版本管理或同步盘。我自己就把~/workspaces和~/todos放进了一个 git 仓库,换设备以后只需git clone加mkproject两条命令就能恢复大部分工作环境。
6.2 当前最终配置一览
整个过程下来,我实际留下来用到今天的工具极少:
- tmux:管会话层。
- zoxide:管目录跳跃。
- zsh 右侧提示符:管可见性。
- 一个
mkproject脚本:管新建上下文入口。 - VSCode workspace 文件:管编辑器布局。
- 纯文本 todo 目录:管意图层。
没有使用任何重量级平台。这些组件彼此独立,任何一个坏了都可用最朴素的命令顶上。越是依赖少,这套体系越稳固。
6.3 如果只推荐三个起步动作
如果你还不想全套搬走,我建议先做三件小事:
- 把所有常工作目录写进
zoxide,练到敲“项目名”就能跳过去。 - 给每个项目建一个 tmux session,坚持用 session 名区分项目而不是开一堆乱窗口。
- 开始切换前写一条三行的文本便签。
这三件事加起来不超过半小时,但已经开始把“用脑子记状态”转成“用工具存状态”。等这个习惯固化下来,再慢慢补 workspace 和自动脚本也不迟。
我在实际使用里最大的体会是:context-mode 不是一个可以一次性安装完成的软件包,它更接近于一种持续维护的工作习惯。工具的复杂度要跟你的项目数量匹配,项目少的时候,多一个快捷方式都是负担。保持最小够用,遇到新的切换痛点再加一块补丁,这才是它最合理的演化路径。