pi-cwd-portal1.1.34
Switch the session working directory in place, with /portal and switch_cwd. (PiDeck integration is an optional local module, not bundled.)
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
pi-cwd-portal
存在目的与所解决问题
pi 把 cwd 绑在会话 runtime 上,既没有原地改 cwd 的 API,也没有换目录的命令。缺这个插件时,跨项目工作只剩两条烂路:开新会话(上下文、技能加载状态全丢),或留在旧 cwd 用绝对路径手工绕——此时 AGENTS.md、技能、设置与工具的默认路径仍指向旧项目,模型按旧项目的规则干活。
本插件原地改写会话文件的 cwd 字段,并以同一路径重建 runtime,让规则文件、技能、设置与路径基准一起搬到新项目。
边界:只换工作目录——不搬会话文件(历史仍在原路径)、不复制任何项目文件、不改任何默认值;PiDeck 界面同步是包外的可选模块,缺失即跳过;同一时刻只允许一次切换。
把会话的工作目录切到另一个项目,而不换会话。
你说「去 Vue3_V2.0 那个项目看看」,理想情况是我在同一个对话里直接过去:读那边的文件、用那边的规则、加载那边的技能。而不是开一个新会话,也不是让你手动切。
这个插件换掉会话的 cwd。此后 bash、read、write 的路径基准,项目规则文件(AGENTS.md),技能与设置全部跟过去。会话文件本身不动——路径不变,PiDeck 的列表和标签页也不会丢。
它做什么
两个入口,一个动作:
- 工具
switch_cwd(path, reason?),我在任务从资料目录转入工程目录时调用 - 命令
/portal <path>,你手动切
切换在本轮回答结束后派发(agent_end 时发一条 /portal),可能延迟到后面某轮生效。实际执行是三步:
- 解析目标目录(展开
~、判等)——只读,不创建;目录不存在时在真正执行切换前才创建 - 改写会话文件头里的
cwd字段(原子写,失败从内存快照回滚),并把这次切换记成一条会话记录 - 用同一个会话文件重新打开会话——runtime 按新的 cwd 重建
进程的 cwd 也跟着切(chdirFollow,默认开),LSP 之类依赖 process.cwd() 的东西一起跟过去。
怎么用
pi install npm:pi-cwd-portal
配置是可选的 ~/.pi/cwd-portal.json:
| 键 | 默认 | 作用 |
|---|---|---|
chdirFollow |
true |
进程 cwd 是否跟随 |
debug |
不设 | 调试日志文件路径,设了才写 |
/portal 不带参数会打印当前目录;带参数直接切。AI 排程的切换由 /portal 无参形式消费。
为什么这样设计
代价必须写在工具描述里。 cwd 是 system 段的一部分,改它就是改 system;system 在整段对话之前,一变就让后面所有前缀缓存作废。本机 60 次切换实测:切换后第一个请求的前缀命中中位数从 283k 掉到 111k,丢 61%。这个代价消不掉,是架构决定的,所以插件把它写进工具描述,让我调用前就知道值不值。
短途别切。 读一个文件用绝对路径;给一条命令换目录用 git -C <path>。
切回当前目录会清掉待派发的切换。 目标等于当前目录时,工具直接返回「已在目标目录」,并清除排程。
失败时你会看到什么
原文来自源码,不加工:
已在目标目录 C:/work/B,无需切换(已清除待派发的切换)。
已排程:本轮结束后派发切换至 C:/work/B(整理资料);生效可能延迟到后续轮次(勿重复排程)。生效后,所有工具、上下文、技能与设置指向新目录。
cwd 切换正在进行中,请稍候再试。
无会话持久化(--no-session),无法切 cwd。
无法读取会话头,取消切换。
会话文件改写失败:<err>
cwd 切换被取消(会话恢复原状)。
cwd 切换被拒绝:会话文件格式版本 4 高于本插件已知的 3。
cwd 已切换:C:/work/A → C:/work/B(整理资料)
失败或取消时,除了界面提示,还会给模型发一条尾部消息说明「仍在原目录」和下一步动作——否则我可能以为切成功了。
边界
- 会话文件不搬家:历史仍记在原来的路径下。
- PiDeck 的界面同步不在这个包里,由本机模块
cwd-portal-local负责(~/.pi/agent/extensions/cwd-portal-local/,不进仓库);两处paths.ts要一起改。 - 目录补全一次最多 200 条,特别宽的目录会被截断。
- 同一时刻只允许一次切换(并发守卫),后来的会被拒绝。
- canon 与项目规则落点跟着 cwd 变:切走后这个会话读不到原目录的
.canon项目知识;工具返回里会先提示原目录有几项(2026-10-20 实测)。 - 会话格式版本未知时拒绝切换:本实现已知
header.version = 3(pi 1.2.0 / 1.3.0 实测)。版本更高时直接拒绝并报错,不猜布局、不写文件——改写 header 是拿宿主内部格式当持久层,赌错的代价是会话损坏。
实测
60 次真实切换(2026-10-18):切换后首个请求前缀命中中位 283k → 111k(−61%);不切的普通请求维持 283k。
2026-10-20 单次全程测量(17 万 token 会话,切换时记录):切换前 cacheRead 177,280 / 单请求 $0.00287;切换后首个请求 cacheRead 9,856、input 169,373 / $0.05207;第二个请求即恢复(cacheRead 178,816 / $0.00299)。所以断层是一次性全量 miss,约 5 美分,不需要重新积累多轮——上面那个「−61%」是首请求瞬时的命中量,不是持续成本。
MIT · Node >= 22.19