omp packages

pi-switch-profile0.2.1

Switch whole pi configuration profiles with /switch - pi packages, extension, skill, prompt and theme paths, theme, default model, thinking level, default tools - then reload

voorjaar Published 7 days ago MIT ~431 downloads/mo

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.

Did it work for you?

Result

One report per person. A new report replaces your old one.

Reports 0

No reports yet.

Readme

pi-switch-profile

English | 简体中文

一个 pi 扩展,提供 /switch <profile> 命令:一条命令切换整套配置——pi 包、扩展/技能/提示模板/主题路径、主题、默认模型、思考强度、默认工具——然后自动执行 pi 自己的 reload。

用它在一个精简会话和一个全副武装的会话之间来回切换,而不必手动改 settings.json。

特性

  • 一条命令,整体切换。 /switch zen 关闭技能、扩展、提示模板和自定义主题;/switch default 再把它们打开。
  • 白名单,不是排除模式。 配置档只写要保留的东西("skills": ["novel-writer"]),其余全部关掉——不需要写 !extensions/** 这种模式。
  • 不会卸载任何东西。 每个配置档都叠加在一份捕获到的基线(base)快照之上。被禁用的 pi 包会变成 { "source": "...", "autoload": false } 而不是消失,所以重新启用是瞬间的。
  • 不会把自己锁死。 即使是最严格的配置档,也会保留扩展自身所在的包。
  • 可撤销。 切换被替换掉的设置会记在一个单独的单条文件里(~/.pi/agent/pi-switch-undo.json),/switch restore 原样恢复并清掉它。
  • 会话级切换。 revertSession 会在会话开始(默认)或会话结束时把会话换回默认配置,所以一时用的切换不会泄漏到下一个会话。
  • 内置配置档。 首次使用时自动创建 zen(零技能、零扩展)和 default(基线快照的全部内容)。
  • 状态可见。 底栏以 [<配置档名>] 显示当前生效的配置档(括号用主题的 accent 色,名称用 muted,不再是默认白字),/switch 会打印解析后的配置与逐项变更。如果你之后手动改过 settings.json,/switch 与 /switch doctor 会直接指出这一点,而不是假装配置档仍然生效。
  • 自动补全。 输入 /switch 后按 Tab 会列出配置档名称。

安装

安装发布到 npm 的包(会把包声明写入 ~/.pi/agent/settings.json):

pi install npm:pi-switch-profile

或者先临时试用,不做任何安装:

pi -e ./extensions/switch.ts

如果你想直接跑仓库克隆,安装本地目录即可:

pi install ./pi-switch-profile

如果手动修改了 settings.json,之后请执行 /reload。

使用

命令 作用
/switch 显示当前配置档、配置档列表以及当前配置
/switch <profile> 应用某个配置档,然后重新加载扩展、技能、提示模板、主题和设置
/switch list 同 /switch
/switch show <profile> 显示解析后的配置档以及与当前配置的差异,不做任何修改
/switch save <profile> 把当前配置捕获为一个新的配置档
/switch refresh 从 settings.json 重新捕获基线快照(手动安装某个包之后建议执行)
/switch restore 撤销上一次切换(记录在 ~/.pi/agent/pi-switch-undo.json)
/switch install <目标> [--only <配置档>] [--kind <种类>] 装一个包,或把某个资源改成只有指定配置档能加载
/switch revert-session <start|end|off|status> 会话何时回到默认配置(默认 start)
/switch delete <profile> 删除一个配置档
/switch doctor 显示当前会话真实状态:模型、思考等级、激活与已配置的工具,以及设置是否与当前配置档一致
/switch help 列出全部子命令

配置档名称也是命令参数,输入 /switch 后按 Tab 即可补全。

配置档

配置档保存在 ~/.pi/agent/pi-switch-profile.json,项目级的配置档可选放在 .pi/pi-switch-profile.json:

{
  "version": 1,
  "activeProfile": "zen",
  "revertSession": "start",
  "base": {
    "packages": ["npm:pi-lens", "npm:pi-web-access"],
    "theme": "github-dark-default",
    "defaultProvider": "strata",
    "defaultModel": "qwen3.8-flash-next",
    "defaultThinkingLevel": "medium"
  },
  "profiles": {
    "zen": {
      "description": "Zero skills, zero extensions",
      "packages": [],
      "extensions": [],
      "skills": [],
      "prompts": [],
      "themes": [],
      "theme": "system",
      "thinkingLevel": "low",
      "tools": ["read", "bash", "edit", "write"]
    },
    "review": {
      "extends": "zen",
      "description": "Zen plus one review extension",
      "packages": ["pi-simplify"],
      "extensions": ["review", "builtin:mcp"],
      "skills": ["novel-writer"]
    }
  }
}

每个配置档都是叠加在 base 之上的覆盖层,只有显式声明的键才会被改动。

配置档键 写入的设置键 含义
packages packages 保留启用的包来源白名单(子串匹配,例如 pi-lens 能匹配 npm:pi-lens)。base 中其余的包都会被设为 autoload: false。本扩展所在的包始终保留。
disablePackages packages 要禁用的包来源黑名单,其余保持不变。
exclude packages、extensions、skills、prompts、themes 要扔掉的东西,按资源类型分开:{ "extensions": ["review"], "skills": ["archive"] }。单独用就是“除了这些全都开”;跟同类型的白名单一起用就是在这个白名单里再剔掉。exclude.packages 是 disablePackages 的别名。
extensions、skills、prompts、themes 同名设置 白名单:写你想保留的东西,一个词(review、novel-writer)或一个 glob(extensions/review.ts、skills/nov*)。匹配不到任何东西的就关掉,[] 就是“一个都不要”,所以你不需要写排除模式。见资源白名单。
theme theme 主题名称,例如 system、dracula,或自定义主题名;也可以写 light/dark 一对,例如 terminal/terminal-tinted。被选中的主题即使它的提供者被关掉也仍然可用——见主题可用性。
model defaultProvider、defaultModel 写成 provider/modelId,或只写 modelId。reload 之后也会作用到当前会话。
thinkingLevel defaultThinkingLevel 可取 off、minimal、low、medium、high、xhigh、max。同样会作用到当前会话。
tools defaultTools 启动时的工具列表。reload 后该列表也会强制应用到当前会话,因此被移除的工具确实会消失。
extends — 继承另一个配置档;"base" 表示基线快照。

资源白名单

配置档从“空”开始。声明了 extensions 就只保留匹配得上的扩展,而没提到的 skills、prompts、themes 也一律关掉——所以配置档写的是你要什么,而不是要排除什么。

两个配置档是例外,因为它们的意思是“你有的全部”:base,以及没有声明任何资源覆盖项的 default。 这就是 /switch default 仍然会把所有东西打开的原因。

  • 匹配的对象是 pi 会自动发现的资源:~/.pi/agent/extensions|skills|prompts|themes、~/.agents/skills, 以及项目的 .pi/ 对应目录。技能按目录名匹配(novel-writer),文件按名称或路径匹配。
  • pi 自带的内置扩展(mcp、codemode、tool-search、llama.cpp)不在 extensions/** 下面, 所以白名单要直接点名:写 builtin:mcp 就保留,不写就关掉。
  • 包提供的资源跟着 packages 白名单走,因为 pi 是用包自己的过滤器筛它们的。要保留某个包的扩展, 就保留这个包。
  • 写进设置的仍然是普通的 pi 条目(!extensions/** 加上每个匹配项的 +extensions/review.ts), 所以 settings.json 依旧可读可手改,只是这些条目由 /switch 生成。
  • /switch save <名称> 会把当前启用的资源记录成白名单,所以保存下来的配置档能复现当时的状态。
  • 旧版本写的配置档(!pattern、+path、-path 列表)会在加载时迁移:原本被保留的项变成白名单, 只有排除项的列表变成 []。
只排除一个东西

想让某个扩展不在 default 里、只在某个配置档里启用,就给 default 写 exclude——它仍然是“其余全开”, 另一个配置档则列出自己要的东西:

"default": { "exclude": { "extensions": ["review"] } },
"review":  { "packages": ["pi-simplify"], "extensions": ["review", "pi-lens"] }

/switch default 会加载除 review 以外的全部;/switch review 只加载它列出的那些。

主题可用性

theme 和 themes 不是同一个开关,而且只有其中一个真的能把主题关掉。

  • ~/.pi/agent/themes/<名称>.json 里的主题始终可用。pi 的主题加载器会直接读这个目录,/theme 列表也无视 themes 过滤器把它列出来,所以 themes: [] 不会弄坏一个本地主题——它只是把这个资源从自动发现的资源列表里藏起来。
  • system、dark、light 是 pi 自带的主题,任何配置档都关不掉。
  • 包提供的主题(比如 pi-terminal-theme 的 terminal)只在这个包加载时存在。packages 白名单或者 exclude.packages 把包关掉之后,theme 就指向了一个不存在的东西,而 pi 会默默退回系统主题。

所以配置档选中的主题优先级高于会把它关掉的策略。当配置档关掉了提供所选主题的那个包时,这个条目会被保留成 autoload: false 加一条强制包含——这正是 pi 自己从一个被禁用的包里只加载一个资源的做法:

{ "source": "npm:pi-terminal-theme", "autoload": false, "themes": ["+themes/terminal.json"] }

这个包其余的东西仍然是关着的。light/dark 一对会两半都保留。配置档明说的事情优先:exclude: { "themes": ["terminal"] } 是一句明确的“这里不要”,会被尊重而不是被覆盖。谁都提供不了的主题(写错了名字,或者包没装)会由 /switch show、/switch list、/switch doctor 以及切换本身的摘要报告出来。

只装到某个配置档

pi 自己的 pi install 只认一组固定的选项(-l、-a、-na、-h,以及 update 自己那几个),扩展注册的选项会被拒——pi.registerFlag() 只能被正在运行的会话读到。而 pi 本身没有“配置档”这个概念:一个包只存在于 settings.json 里。所以归属的判定只能在这里做:

/switch install npm:pi-simplify --only review          # 装它,并且只让 review 加载
/switch install pi-terminal-theme --only coding,notes  # 给已经装好的包改归属
/switch install skills/novel-writer --only notes       # 给本地技能改归属
/switch install extensions/review.ts                   # 不写 --only:凡是“全开”的配置档都会加载它

<目标> 是一个包来源(npm:…、git:…、http(s):… 或一个路径),或者一个资源名。裸着的名字会拿去跟自动发现的资源匹配(agent 目录、~/.agents/skills、项目的 .pi/):一个都匹配不上就当它是包来源,匹配到多种种类时就必须用 --kind extensions|skills|prompts|themes|packages 说清楚是哪一种。

每个配置档都按它本来的写法改,所以安装不会把一个“全开”的配置档变成白名单档:

  • 基线配置档(base,以及没有资源覆盖项的 default)不在 --only 里时只多一条 exclude;
  • 有白名单的配置档被 --only 点名时白名单多一项,没被点名时从白名单里去掉并且多一条排除;
  • 写成“除了这些全都开”的配置档只是少掉那条排除;
  • 从空开始的配置档得到一个正好是目标的白名单。

包条目会写进 settings.json,缺少的 npm: 或 git: 来源在 reload 后的 resolve 过程中由 pi 装好。/switch restore 能完整撤销一次安装:设置和配置档映射都回到之前,这也是为什么安装的撤销记录里连配置档一起存。

基线、save 与 refresh

base 是每个配置档叠加其上的 settings.json 快照。请在没有配置档生效时捕获它:

  • /switch save my-setup 把当前配置记录成一个可以返回的配置档。配置档名称必须能作为 /switch <name> 输入,因此 base 以及子命令名(list、show、save、delete、refresh、restore、install、revert-session、doctor、help)是保留的。
  • /switch refresh 重新读取 settings.json 并更新 base。当你希望“启用状态”的快照跟随 pi config 的当前结果时执行一次。

切换时写入的是什么

配置档会替换它管理的那些设置项。每个受管理的键优先取配置档的值,配置档没定义时取 base 快照的值;如果两者都没定义,这个键会从 settings.json 中删除。这正是 /switch default 能撤销 /switch zen 的原因:default 什么都没定义,而基线快照里没有 defaultTools,所以 zen 写入的工具列表会被清除,而不是一直留着。/switch restore 同理,它写回的是上一次切换前记录的那份确切设置。

packages 是唯一跟随当前 settings.json(而不是快照)的键:

  • 基线快照之后安装的包会被带过来,所以 /switch default 会启用它,/switch zen 会关掉它。
  • 用 pi remove 移除的包会被丢弃,切换不会把它写回去(否则 pi 在解析 npm: 来源时会重新安装它)。
  • 既没有 packages 也没有 disablePackages 的配置档会启用所有已知的包。packages 是白名单,disablePackages 是黑名单,两者都支持部分匹配,例如 pi-lens 或 npm:pi-lens。
  • 本扩展始终把自己保持在启用状态。如果配置档能把自己关掉,就只能靠手动改 settings.json 才能回来了。

回到默认配置

revertSession 决定会话什么时候回到默认配置:有 default 配置档就用它(所以你自己加了覆盖项的 default 就是回去的地方),否则用 base 快照并启用所有已知的包。

/switch revert-session start   # 每个新会话都从默认配置开始(默认)
/switch revert-session end     # 会话结束时把默认配置写回
/switch revert-session off     # 最后一次切换一直保留
/switch revert-session         # 报告当前是哪一种

默认是 start,因为它能覆盖“会话来不及自己收尾”的情况:如果 pi 被 kill 或者电脑休眠时还挂着某个配置档,下一个会话会把它丢掉。end 适合希望会话一结束文件就立刻正确的人。

  • 开始时的回退只在设置与默认配置不一致时执行。它会写 settings.json、为 /switch restore 记下之前的设置,并在当前会话里重新应用默认配置档的工具、模型和思考等级。如果改动涉及包、扩展、技能、提示词或主题(这些在扩展能行动之前就被 pi 解析完了),它还会接着 reload 会话,所以上一个配置档加载的资源会真的消失。只改主题、模型、思考等级或工具时不需要 reload,就地应用。
  • 结束时的回退只在真正的会话关闭时执行。/reload、/new、/resume、/fork 都不是会话关闭,所以切过去的配置档会一直生效。那时 UI 正在拆掉,所以通知会被存下来,在下一个会话开始时显示。
  • 如果设置本来就已经是默认配置,则什么都不写;基线快照还没建立时也不写,所以没有切换过的会话不会动这个文件。
  • pi 只会写回它自己改过的设置项,所以退出时写入的回退基本保留,只有会话中 pi 自己改过的键会不一样(例如 /model 之后的 defaultModel)。剩下的差异可以用 /switch doctor 查看。

作用范围

/switch 写入的是用户级设置文件(~/.pi/agent/settings.json)。如果项目的 .pi/settings.json 声明了 packages、extensions、skills、prompts 或 themes,项目级的值优先级更高,/switch 会就此提醒你。

开发

npm install                  # 只为下面这几个脚本(tsc);扩展本身不需要依赖
npm test                     # 纯逻辑自检(配置档解析、包策略、设置写入)
npm run test:live            # 实跑冒烟测试:真实 pi 的 RPC 模式,zen、reload 后的工具、save/restore/refresh
npm run check                # 类型检查

selftest.ts 用 node --experimental-strip-types 直接导入 extensions/switch.ts,因此不需要 pi 运行时:扩展只导入 pi 的类型。npm run check 通过 tsconfig.json 的 paths 解析这些类型,它们指向已安装的 pi 版本(~/.pi/agent/install/releases/<version>/node_modules/...)——pi 会把这些包提供给扩展,所以它们列在 peerDependencies,故意不写进 dependencies。

scripts/live-test.mjs 会把本包安装进已备份的 ~/.pi/agent/settings.json,启动真实 pi(RPC 模式),切到 zen,检查文件与 reload 后的会话(注册的命令、激活的工具、被禁用包的工具是否消失),并跑一遍 save/list/delete/refresh/restore,最后把原始设置和原始配置档存储写回。

scripts/verify-installed.mjs 会在不带 -e 的情况下启动一个真实 pi 会话,因此必须由 settings.json 自己提供该扩展。在 pi install npm:pi-switch-profile 之后用它验证:检查 /switch 已注册、/switch list 能列出配置档,以及底栏状态是否以 [<配置档名>] 并带上主题色送达。

许可证

MIT — 见 LICENSE。