raise:原子化 AI agent 配置档案切换
一个用 Go 写的 CLI,用单条命令通过原子符号链接在 17 个 AI 编程工具间热替换配置档案,同时保留凭证--因为在四个客户项目间来回切换时手工编辑十七份配置文件不是纪律问题,是工具问题。
名字是个谐音梗。Raise,Rice-aise—怎么读都行,反正是那个解决了一个配置漂移问题的工具,而那个问题在我承认它是问题之前,已经悄悄地让我每周越来越慢了好几个月。
为什么它存在
我做咨询。这意味着不同的客户、不同的代码库、不同的上下文窗口,以及—关键是—不同的 agent 配置。Claude Code 给我基础设施客户的系统提示需要知道他们的 Terraform 布局、命名规范、PR 流程。给某个产品初创公司的看起来完全不同。Gemini CLI 有单独的配置格式,Codex 有另一个,OpenCode 又另一个,Pi 还有一个。
有一次我数了数:我在为四个活跃客户合同的十七个 AI 编程工具管理定制化配置文件,不是档案,是平铺的文件。在客户之间切换上下文之前我得手动编辑它们,这意味着我经常忘记更新某个工具,带着错误的系统提示开始一个会话,产出在我实际所处的上下文里微妙地不对的东西。
「更自律一点」这个纪律修复方案不会复利增长,我需要工具修复。
它是怎么工作的
raise 是一个 Go 单体二进制文件。它读取一个命名档案的目录,每个档案是一个目录树,镜像你想管理的工具的配置位置。当你运行 raise use <profile> 时,它同时在每个配置工具位置执行原子符号链接替换。
原子是关键词。这个问题的老方案—「写一个复制文件的 shell 脚本」—有一个失败窗口。如果脚本中途报错,你就处于某些工具用新配置某些用旧配置的混合状态,比任何一个干净状态都糟糕。raise 用符号链接而不是复制,每个位置用一个 rename(2) 系统调用原子地替换符号链接目标,这是 POSIX 文件系统上能做到的最原子的了。
凭证保留是花心思最多的部分。API key、auth token 和会话凭证和系统提示、工具设置住在同一个配置目录里,你不想让它们随档案一起替换—它们是每台机器的,不是每个项目合同的。raise 有每个工具的凭证清单,标识哪些配置键或文件节是凭证相关的,并把它们排除在替换之外。档案存储带占位符的模板,替换层在写入之前从本地凭证存储里填入。
支持十七个工具需要审计十七套不同的配置约定。有些工具用 ~/.config/<tool>/config.json,有些用 ~/.toolrc,有些有目录,有些有单文件,有些两者都有而且各有不同含义。raise 里的工具注册表为每个工具编码这些—配置住在哪里、格式是什么、哪些字段是凭证。添加一个新工具是注册表里三处添加和一个测试 fixture。
有意思的地方
让我意外的:最难支持的工具不是那个晦涩的,而是 Claude Code—它有一个分层配置层级—全局设置、项目设置、本地覆盖—以及关于哪层胜出的有意义语义。替换掉项目层的档案切换会破坏那些有项目特定设置提交进 repo 的仓库。raise 必须了解层级语义,只碰它应该碰的层。
另一个意外是我对最初构建这个工具感受到的强烈阻力。开发者工具里有一种「我应该更自律」的强大吸引力。那种本能是错的。自律是为了真正需要判断的事情;配置文件管理不是。如果你每周手动做某件事超过两次,而它不再教你任何新东西,你应该把它自动化。没有例外。
名字来自一次关于提示工程里「提高地板」这个概念的对话。一个对上下文来说错误的档案会主动降低地板。raise 把它保持在它应该在的地方。
我会改什么
凭证清单目前是手动维护的。我想要一个首次运行向导,检查你现有的配置文件,识别凭证形状的值(API key 模式、token 格式、bearer 字符串),并自动提出一个清单。信息在那里,只需要一次读取和一些启发式方法。
我也想要一个 raise diff <profile-a> <profile-b> 命令。现在你要自己目视比较档案目录。一个把系统提示变更和工具设置变更分开高亮的结构化 diff,会让档案审计快得多,尤其是当你几周没碰某个客户合同、不记得自己到底配置了什么的时候。
档案格式目前是基于目录的,这很灵活但不可移植。我一直在考虑单文件档案格式—类似一个 TOML bundle,可以通过 git repo 或 gist 分享—这样你就能把 agent 配置和你的实际项目并排版本控制。这是让这个东西真正成为多人协作工具的自然下一步。