资讯详情 context-mode 实战:用快照机制将开发者上下文切换成本压缩到秒级
📅 2026/10/8 5:22:25
1. 从一次崩溃的“切上下文”开始context-mode 到底解决什么问题上班第一件事是写早会要说的进度写到一半被拉去线上排查告警处理完回来看着编辑器里打开的十几个标签页想了半天才想起来自己刚才准备干什么。这种经历我相信每个开发者都熟悉。学术界有个很出名的结论被打断之后重新回到原来的工作状态平均需要十五到二十分钟。这里的“回到原来的工作状态”说的就是 context 的恢复。我先说结论context-mode 不是某个框架的特性也不是某个特定软件的功能而是一种把“我正在做什么”这个模糊概念显式化的工程思想。落到开发工具上它表现为一套可以保存、切换、恢复工作上下文的机制。我在自己的日常开发里用这套机制把“切上下文”的成本从十几分钟压缩到了几秒钟这篇文章就是完整的实现记录包括数据结构设计、核心脚本、与 tmux 和 VS Code 的联动以及我踩过的坑。1.1 上下文切换到底贵在哪里我们说的上下文在开发场景里至少包括四层东西。第一层是物理状态当前在哪个目录、哪个 git 分支、跑着哪几条命令、哪些环境变量是被手动 export 的。第二层是心智状态刚才看过的关键代码在哪个文件哪个函数TODO 写到哪一步下一个动作是什么。第三层是工具状态编辑器窗口的布局、打开的标签页、tmux 的分屏。第四层是外部记忆相关的需求文档、接口文档、聊天记录。机器层面的 context switch 只需要纳秒级人的 context switch 却要几分钟甚至更久。为什么因为人无法像 CPU 一样把寄存器压栈保存再弹栈恢复。人只能靠记忆重建而记忆是脆弱且有损的。你瞄了一眼今天的天气可能就忘了刚才正准备改的那个变量名。所以最直接的思路是别靠大脑去记住主动把上下文存成文件。机器恢复状态永远是可靠的只要能设计好数据结构恢复就是确定性操作。这也是 context-mode 和普通“待办清单”最本质的区别清单只记录“要做什么”快照还记录“做这件事时所处的环境是什么”。1.2 我自己需要的 context-mode 是什么在动手之前我列了一个需求清单就三条。一是快保存和恢复都必须在一秒以内完成任何超过三秒的方案我都不会长期用。二是轻不引入重量级依赖不装数据库不额外跑常驻服务。三是可审查所有快照都是人类可读的纯文本我可以随时打开看里面是什么而不是一个黑盒。这三条决定了后续所有技术选型。快意味着保存和恢复不能用虚拟化或者进程迁移这种重型手段而是抽取关键状态。轻意味着用 shell 脚本或者一个小的 CLI 工具就够。可审查意味着采用 JSON 或 YAML 做快照格式存在指定目录下用普通文件保存。我想强调一下为什么不用常见的“系统级恢复”方案。比如 CRIU 可以把整个进程组冻结再恢复这固然强大但太重了而且它恢复的是进程状态不是人的工作状态。真正的痛点不是进程丢了而是知识丢了。所以你需要的不是冷冻内存而是给未来的自己留一张线索丰富的地图。1.3 适合谁来用老实说如果你每天的工作就是坐在一个项目里从早上九点到晚上六点只做同一个功能那 context-mode 对你帮助不大这很正常。它最值钱的场景是任务碎片化严重的情况手头维护三四个仓库、时不时被拉去救火、白天开会晚上写代码、或者同时给多个客户提供技术支持。这种场景下你需要的不是更强大的编辑器而是能秒级复原“上个现场”的工具。我见过很多人为了解决这个问题把希望寄托在更完整的笔记软件上记了满满当当几十页最后还是找不到。问题不在于笔记不够多而在于笔记和工作环境是断开的。context-mode 的价值恰恰是把“环境”和“记忆”拼在一起你回到的不只是一个文件夹而是一个带着提示的完整现场。2. context-mode 的设计先定义“上下文”的数据结构2.1 一个上下文快照里应该包含什么我把一份快照设计成下面这个对象每个字段都有明确用途name快照的名字用于检索和切换。created / updated时间戳方便知道这是什么时候的现场。cwd当时的工作目录。gitBranch当时所在的分支没有 git 环境就留空。env在当前 shell 里手动导出的关键环境变量白名单。files打开的关键文件列表恢复时用编辑器打开。tmuxSession关联的 tmux 会话名。notes自由文本记录“我当时到底在干嘛”比如“正在修 search API 的 offset 越界下一步到 test/query.spec.ts 看失败用例”。tags可选的标签便于按功能或项目归类。为什么要把 env 单独列出来因为 shell 环境变量是很容易被遗忘的上下文。最典型的例子是打包时要用到的目标平台变量、连接某个数据库需要的地址、或者临时加到 PATH 里的工具目录。这些变量不会写进任何配置文件纯靠命令行 export一旦关闭终端就彻底消失下次想不起来时只能去翻命令历史甚至去翻聊天记录非常痛苦。gitBranch 和 files 这两项容易理解但有一个细节值得说说files 存的是相对路径。这样快照就可以在不同机器之间迁移因为仓库结构是一致的。这个决定在后面做跨机器同步时帮了我大忙。2.2 快照格式与存储目录格式我选 JSON理由很简单JSON 不需要额外的解析库、任何语言都能读、人也能直接看懂而且和当前工具的生态完全贴合。如果你不习惯 JSON 的括号换 YAML 也可以只是要多引一个解析器对纯 bash 实现不太友好。存储目录我放在~/.context-mode/下每个快照是一个以 name 命名的 JSON 文件~/.context-mode/ feature-pay-order.json bugfix-search-offset.json support-client-a.json为什么不放到项目目录里因为 ctx 工具本身是全局的它管理的快照属于你的工作状态不属于某一个仓库。放到 HOME 下还有一个好处是方便做备份和同步。我在~/.context-mode/.gitignore里忽略了一条规则所有包含secret字段的快照不被提交后面讲敏感信息处理时会再展开。一个 JSON 快照的完整示例{ name: bugfix-search-offset, created: 2025-06-11T10:24:0008:00, updated: 2025-06-11T10:24:0008:00, cwd: /Users/lin/projects/search-service, gitBranch: fix/offset-overflow, env: { QUERY_DB_URL: postgres://localhost:5432/search_dev, TARGET_ARCH: arm64 }, files: [ src/handlers/search.ts, test/query.spec.ts ], tmuxSession: search-fix, notes: offset 参数在第二页之后溢出可能是 int32 精度问题。下一步看 query.spec.ts 里的边界用例。, tags: [urgent, backend] }这个文件就是整个 context-mode 的“内存”。保存上下文 写这个文件恢复上下文 读这个文件然后执行一系列 shell 命令。2.3 为什么不去保存进程状态可能有读者会想Linux 下用 tmux 已经能保存终端的会话了是不是就够了确实tmux 在很大程度上能解决 shell 状态恢复的问题它内部会保留每个窗口的 cwd、历史和部分环境但它有两个覆盖不到的地方。第一它无法恢复 git 分支也不能主动把编辑器的工作区打开到指定文件。第二tmux 需要你从一开始就养成分会话的习惯对于已经混乱的现场很难事后补一张上下文快照。另一种思路是直接序列化进程状态比如用 CRIU 对进程做 checkpoint 和 restore。这个方案听起来很酷实际上在日常开发中完全不可行因为它要求进程运行在可冻结的状态里涉及网络连接、socket、内核资源的恢复动不动就失败。你可以把 context-mode 理解为“面向人的 checkpoint”它保存的不是原始字节而是语义化的线索。未来要恢复的时候把线索翻译成环境、窗口、文件、分支这些具体动作。3. 动手实现一个可用的 ctx 命令3.1 最小可用版让保存和恢复先跑起来我用 bash 写第一版核心就是两个函数ctx_save和ctx_use。之所以先写 bash 版本是因为它几乎没有依赖任何一台 Linux 或 macOS 机器都能直接运行适合快速验证设计是否合理。# file: ~/.bashrc 或 ~/.zshrc 中追加 export CONTEXT_DIR$HOME/.context-mode ctx_save() { local name$1 [ -z $name ] { echo usage: ctx_save name; return 1; } local dir$(pwd) local branch$(git branch --show-current 2/dev/null || echo ) local ts$(date %Y-%m-%dT%H:%M:%S%z) mkdir -p $CONTEXT_DIR cat $CONTEXT_DIR/$name.json EOF { name: $name, created: $ts, updated: $ts, cwd: $dir, gitBranch: $branch, files: [], env: {}, notes: } EOF echo [ctx] saved $name } ctx_use() { local name$1 local file$CONTEXT_DIR/$name.json [ -f $file ] || { echo [ctx] unknown context: $name; return 1; } local dir$(python3 -c import json,sys;print(json.load(open($file))[cwd])) local branch$(python3 -c import json,sys;print(json.load(open($file))[gitBranch])) cd $dir if [ -n $branch ]; then git checkout $branch; fi echo [ctx] switched to $name }这个版本有几个问题依赖 python3 解析 JSON、notes 和 files 还没有完全用起来。它是我用来验证流程的骨架。第一版跑通之后我发现最重要的其实不是“路径跳转”而是“回忆线索”。每次ctx_use之后我希望能立刻看到 notes 里写的“下一步做什么”。于是我在代码里加了一行echo [ctx] note: $(python3 -c import json,sys;print(json.load(open($file))[notes]))这一行很简单却让整个工具的体感发生了质变。它让未来的你直接看到当时的想法而不是回到现场再花十分钟自己摸索。3.2 进阶版用 Node.js 写一个真正的 CLIbash 版本验证了思路但用 python3 解析 JSON 总是有点隔靴搔痒。我改成 Node.js 单文件脚本。选 Node 不是因为后台必须用 Node纯粹是因为它处理 JSON 是天生的而且child_process.execSync可以直接执行 shell 命令写起来非常顺手。#!/usr/bin/env node // file: ~/bin/ctx const fs require(fs); const os require(os); const path require(path); const { execSync } require(child_process); const CONTEXT_DIR path.join(os.homedir(), .context-mode); function ensureDir() { if (!fs.existsSync(CONTEXT_DIR)) fs.mkdirSync(CONTEXT_DIR, { recursive: true }); } function readContext(name) { const file path.join(CONTEXT_DIR, ${name}.json); if (!fs.existsSync(file)) { console.error([ctx] context not found: ${name}); process.exit(1); } return JSON.parse(fs.readFileSync(file, utf-8)); } function shell(cmd) { return execSync(cmd, { encoding: utf-8 }).trim(); } function save(argv) { const name argv[2]; if (!name) { console.log(usage: ctx save name); return; } const cwd shell(pwd); let branch ; try { branch shell(git branch --show-current); } catch (e) {} const ts new Date().toISOString(); const snapshot { name, created: ts, updated: ts, cwd, gitBranch: branch, env: {}, files: process.argv.slice(4), tmuxSession: process.env.TMUX ? process.env.TMUX.split(,)[1] : , notes: argv[3] || , tags: [] }; ensureDir(); fs.writeFileSync(path.join(CONTEXT_DIR, ${name}.json), JSON.stringify(snapshot, null, 2)); console.log([ctx] saved ${name}); } function restore(argv) { const name argv[2]; const ctx readContext(name); if (ctx.cwd fs.existsSync(ctx.cwd)) { process.chdir(ctx.cwd); } if (ctx.gitBranch) { shell(git checkout ${ctx.gitBranch}); } ctx.files.forEach((f) { shell(code -r ${path.join(ctx.cwd, f)}); }); if (ctx.env) { Object.entries(ctx.env).forEach(([k, v]) { process.env[k] v; }); } console.log([ctx] note: ${ctx.notes}); } const action process.argv[2]; if (action save) save(process.argv); else if (action use || action restore) restore(process.argv); else if (action list) { ensureDir(); fs.readdirSync(CONTEXT_DIR).filter((f) f.endsWith(.json)).forEach((f) console.log(f.replace(.json, ))); } else if (action rm) { const name process.argv[3]; fs.rmSync(path.join(CONTEXT_DIR, ${name}.json), { force: true }); console.log([ctx] deleted ${name}); } else { console.log(usage: ctx save|use|list|rm name); }这里有一个非常关键的坑Node.js 子进程无法修改父进程 shell 的环境变量。你可以用process.env[k] v重置当前进程的环境但这个进程一退出父 shell 的环境并不会改变。所以真正的 env 恢复不能只靠 CLI必须在 shell 层完成。解决办法是让ctx use把环境变量的设置指令打印出来然后在 shell 里 eval。也就是说ctx use在执行时除了做 cd 和 git checkout再把export AB这样的命令打到 stdout在.bashrc里包一层函数ctx() { if [ $1 use ]; then node ~/bin/ctx $ /tmp/ctx_out eval $(node ~/bin/ctx env $2) source /tmp/ctx_out else node ~/bin/ctx $ fi }我最后采用的方案是给 CLI 增加一个子命令ctx env name专门输出环境变量导出语句然后在真正执行恢复的时候先eval $(ctx env $name)再执行目录切换和文件打开。这个细节是整个工具能不能真正恢复“环境现场”的分水岭。如果你跳过这一步你会发现目录切对了、分支切对了但之前临时设置的数据库地址和编译参数全都没了。3.3 联动 tmux 和 VS Code把快照变成现场目录和分支可以简单恢复但“现场感”还很弱。真正让我觉得像回到几分钟前的是下面三个联动。第一是 tmux。在保存时我读取当前 tmux 会话名存入快照。恢复时如果会话已经在运行直接 attach否则新建一个同名会话并 cd 到快照目录。# shell function tmux_restore() { local tmux_name$1 local cwd$2 if tmux has-session -t $tmux_name 2/dev/null; then tmux attach-session -t $tmux_name else tmux new-session -s $tmux_name -c $cwd fi }这个做法的价值在于tmux 会话本身就是当时的现场里面有历史命令、分屏布局、正在跑的服务输出。有了它恢复的不只是路径而是真正的工作环境。第二是 VS Code。我保存快照的时候把当前打开的几个关键文件相对路径存进 files 字段。恢复时调用code -r逐个打开让编辑器迅速回到之前关注的代码位置附近。这里有两个经验一是不要保存所有打开的标签页只保存最近五个以内真正在看的文件否则恢复后反而眼花二是用相对路径保证快照换机器也能用。第三也是最重要的是 notes 字段。我把恢复时打印 notes 这个动作放在所有步骤的最后一行让它在终端里作为最后的醒目输出。这样我每次回到一个旧现场时第一眼看到的是“我当时为什么在这儿”。这比任何自动化操作都更有价值因为它是高速恢复到心智状态的那把钥匙。自动化负责把你带到门口notes 负责推你进门。4. 实战演练真的用 context-mode 切换两个任务4.1 场景设定我挑一个我工作中反复出现的场景来做完整演示。假设你在维护一个电商后端服务手头同时在做一个新功能和一个紧急修复。功能是“支付回调增加幂等校验”分支名feature/payment-idempotent改动文件集中在src/payment/callback.ts紧急修复是“搜索接口分页 offset 溢出”分支名fix/search-offset需要调试的文件是src/search/handler.ts和/tmp/debug.log。你的编辑器里堆着十几个文件一会儿写支付一会儿看搜索脑子已经浆糊。这种情况下我的第一动作不是继续改代码而是先给当前现场存一个快照。4.2 保存给混乱中的自己留一张地图ctx save payment-idempotent 正在改 callback.ts 的幂等键重复判断刚写完 test下一步跑 npm run test:payment code -r src/payment/callback.tssave 命令做两件事把当前所在目录、git 分支、当前关注文件记录到 JSON把 notes 写成自由文本。这里特意要强调写 notes 看起来是额外负担但根据我自己的经验五秒钟的记录能节省半小时的检索时间。如果你实在懒得写至少写一句“做了什么”和“下一步做什么”不需要完整句子。保存之后快照目录里会出现payment-idempotent.json。现在切到紧急修复分支git stash ctx use fix/search-offsetctx use这条命令会执行恢复流程cd 到搜索服务目录、checkout 到fix/search-offset分支、打开记录中的调试文件、最后一屏打印 notes。整个过程不到一秒。对比一下如果用老办法你需要翻 git worktree、查命令历史、找出之前打开的标签页、再回忆自己在干嘛没个五分钟缓不过来。4.3 来回切换把两个现场都保持在指尖修复搜索 bug 的过程持续了四十分钟期间你可能打开了新的标签页、新开了 tmux 窗口、改了三个文件。修完以后你面临的不是“做完”而是“该回支付功能了”。这时候再执行ctx save search-offset 已确认是 int32 溢出把 pageSize 改成 int64 并补了回归测试 ctx use payment-idempotent切回之后你会落在当时支付分支的目录上分支切回去文件被重新打开notes 提示你下一步是跑 npm run test:payment。注意一个细节如果你在支付分支上还没提交的改动在保存时被git stash掉了切回来之后要记得git stash pop。我在 ctx 命令的实现里没有自动做 stash pop原因是不希望工具偷偷改你的 git 状态这种决定权应该留给人。这个场景背后context-mode 真正起作用的原理是什么它把“去网上搜了一圈解决方案之后的茫然”这个状态替换成了“明确的下一步提示”。对自动化的分支切换和文件打开只是锦上添花notes 才是雪中送炭。4.4 一天下来快照就是你的工作日志把 context-mode 当成日常工作流用上两周之后我发现它有一个意外的副作用每个快照都记录了时间戳和 notes这些文件连起来就是一份相当真实的工作日志。传统的工作日志要靠手写写的时候容易美化、容易遗漏。快照不会骗人因为它是操作时留下的真实记录。我后来给 ctx 加了一个很简单的子命令ctx today它把当天的所有快照按时间列出来node ~/bin/ctx list | while read name; do cat $HOME/.context-mode/$name.json done | jq -r select(.created | startswith(2025-06-11)) | [\(.created[11:16])] \(.name): \(.notes)这段脚本简陋但够用。复盘每周工作、写周报、甚至评估自己有多少时间被切碎都有了数据支撑。这是我最初完全没有想到的价值。5. context-mode 的边界、注意事项与常见问题5.1 别把 context-mode 当作万能记忆工具工具再好也不能替代人的思考。我在使用中踩过最深的坑是试图让快照记录一切环境变量、编辑器布局、shell 历史、打开的浏览器标签。结果快照文件越来越复杂恢复逻辑越来越慢而实际上我每天都只会用到其中一小部分。最后我把快照精简成现在这个结构剩下的交给 tmux 和系统的会话恢复去管。想明白了一句话context-mode 的定位是“提示”不是“复刻”。它负责把你带到现场并且告诉你到了现场之后应该干嘛至于现场里面每个角落的灰尘和纸张那不是它该管的。过度设计是这类工具最容易犯的错误。另外一个认知误区是以为保存了快照就可以随意清理现场。实际上快照只是帮你快速切换它不能帮你合并代码、不能替你解决冲突。我有一次在切换前没有看 git status快照倒是顺利保存了结果切回来后发现两个分支的改动纠缠在一起花了额外时间处理。所以我在 ctx save 的实现里加了一个检查如果当前分支有未提交改动保存时会在终端打一行警告提醒你先 stash 或者 commit。这个检查不阻断操作只是提示。5.2 敏感信息与跨机器同步快照里存了 cwd、branch、files 这些无害信息但如果我没管住自己把数据库连接串和 API token 存进 env 字段那这些文件就变成了事故隐患。我在~/.context-mode/.gitignore里加了一条规则所有带secret字段的 JSON 不进入版本库同时在 ctx save 的代码里对所有 env 的值做了过滤跳过包含PASSWORD、TOKEN、SECRET、KEY字眼的变量。这是一个笨办法但比没有强。跨机器同步的问题则更微妙。我在两台电脑上开发同一个仓库快照的 cwd 字段在白天机器是/Users/lin/projects/search-service在晚上机器是/home/lin/dev/search-service。直接同步快照会导致切换时报路径不存在。解决办法有两个维度一是把 cwd 存成相对仓库根目录的形式比如repo:search-service恢复时先根据仓库名解析本机真实路径二是干脆不同步 cwd每台机器各自保存自己的快照靠 git 仓库内容保证代码一致。我目前用的是方案二因为快照与机器绑定更符合直觉。如果你需要方案一的实现可以在 ctx 的代码里加一个resolveRepo函数把快照中的repo:xxx映射到本机目录表。5.3 常见问题速查表下面这张表是我把使用中遇到的典型问题整理出来的结论可以直接当参考手册。问题现象可能原因解决办法ctx use 后目录没变CLI 是子进程cd 影响不了父 shell用 shell 函数包围 ctx把 cd 放在函数体里执行环境变量没有恢复子进程设置的环境变量随进程退出而消失使用ctx env name输出 export 语句用 eval 执行tmux 会话已经存在但内容不对保存快照时会话还活跃恢复时它已被改过恢复前手动 tmux kill-session或用时间戳判断是否值得复用git checkout 失败当前工作区有未提交改动切换被拒绝在 ctx save 时提示 stash恢复时 git checkout 失败不要强制跳过快照里出现敏感信息手动 export 的值被收录进 env过滤 PASSWORD/TOKEN/SECRET 键并用 .gitignore 排除notes 是空的保存时偷懒没写把 notes 字段做成必填选项或者提供一个交互式提示ctx list 输出太多快照没有归档机制加一个ctx archive命令把超过 N 天的快照移入 archive 目录5.4 一个被我砍掉的需求restore 全部环境我尝试过让 ctx use 在一次命令里就把 shell 变量、别名、functions 全都恢复。技术上是可行的通过declare -p把 shell 环境序列化恢复时 eval 回去。但结果非常脆弱因为当前 shell 的很多变量是继承来的强制恢复旧值会破坏新任务需要的设置。最后我把恢复范围限制在三条cwd、gitBranch、env 白名单。这个妥协让工具变得可靠可靠是比强大更稀缺的品质。如果以后真的需要完整的 shell 环境恢复正确做法是在 tmux 里跑内层 shell 加嵌套会话让每次上下文切换对应独立的 shell 生命周期而不是去强行复写当前 shell 的状态。这条思路留给有兴趣的读者自己试。6. 这个思路并不新鲜它在很多地方都有影子6.1 AI 辅助编程里的 context window用过 AI 编程助手的人都会遇到一个现象助手忘了你两轮之前交代的背景回答开始跑偏。这背后的原因就是对上下文的管理策略不对。现在的工具普遍支持把对话分组、把某个文件内容钉在上下文中本质上也是 context-mode 的思路把关键状态显式声明而不是依赖模型的隐式记忆。我在使用这类工具时会把项目背景、构建命令、关键约束写在一个说明文件里每次会话开始就固定加载这相当于给 AI 也做了一颗快照。这个类比非常有价值AI 的注意力是有限的上下文窗口一旦挤满旧信息新任务的效果就会下降。所以好的做法不是无限扩大窗口而是像 ctx 一样为每个任务建一个精简上下文集需要时切换。原理相通工程实现不同。6.2 React 里的 Context API前端同学对 context 再熟悉不过了。React 的 Context API 解决的问题是在组件树深处如何不通过逐层传递 props就让子组件能读取到全局状态。这和 context-mode 的诉求高度相似状态分散在多个层级显式传递成本高于是引入一个共享的上下文存储让组件按需消费。但 React Context 也给了我们一个深刻的教训不要把所有状态都塞进一个全局 context。这和我前面说的“别把快照设计得太重”如出一辙。全局 context 会让组件难以追踪数据来源也会引发大范围重渲染。正确的做法是拆分成小粒度的 context按功能域隔离正如 ctx 快照按任务命名而不是用一个超大快照覆盖所有任务。6.3 Go 的 context.ContextGo 标准库的 context.Context 算得上最严谨的 context 实现之一。它不仅是数据传递更重要的是传递取消信号和超时控制。在一条调用链上上游取消时下游能立刻感知这是分布式系统里防止资源泄漏的关键设计。从 context-mode 的视角来看Go 的 context 把“当前任务的边界”显式化了超时、取消、依赖的 key-value 数据都打包在一个对象里贯穿整个请求生命周期。回到开发工作流这提醒我一个事情好的 context 机制必须包含“退出条件”。ctx 工具里没有自动的超时或取消机制是因为任务的边界由人来定而不是由系统来定。在工具设计上我一直坚持每个快照都要有名字、有 notes、有时间戳这三者构成了任务的边界。我在实际使用中发现的最后一个小技巧是每天开工前用ctx list快速扫一眼有哪些未完成的任务快照挑一个开始每天下班前给当天最后的状态存一个快照。这样一来第二天早上打开电脑直接ctx use就能无缝回到昨天的现场比翻浏览器历史、翻终端历史都快得多。如果你也想在自己的工作流里测试 context-mode我建议就先别写 Node 版本用 bash 的四十行原型跑两周。如果它真的让你感觉到了省下的时间再考虑是不是要加 tmux 联动和跨机器同步。关于这个模式我目前的体会是它改变的不是某个具体的操作效率而是你对“我正在做的事到底包含哪些状态”这个问题的敏感度。一旦开始用显式思维对待上下文你就不会再容忍那种“我好像忘了刚才在做什么”的状态了。