团队统一编辑器模型配置:配置进版本库、密钥不进版本库怎么做
团队要统一的不是”大家都用哪个模型”,而是一条边界:配置里哪一部分该进版本库、哪一部分必须留在每个人自己机器上。 这条边界一旦画清楚,新人拉下仓库就能跑,密钥泄露的面也收得住;画不清楚,你会同时得到两种病——一种是每个人配得都不一样、出了问题谁也复现不了,另一种是有人把 API key 提交进了 git 历史。
这篇只讲”配置怎么共享、密钥怎么隔离”这一件事,依据是各家官方文档在 2026-08-07 当天的记载。站内另外三篇管的是别的层面:团队规则文件冲突怎么收敛 讲的是 AI 读的那套项目规则文本怎么避免互相打架,AI 在团队里怎么落地 讲的是流程和推进节奏,AI 工具的团队治理 讲的是权限、审计和采购口径。本篇比它们低一层,专门啃”模型接入配置”这一小块文件。
一、先把两件事分开:接入方式和模型能力
很多人配不明白,是因为把两件事混成一件。
接入方式,说的是你的编辑器怎么把请求发出去:端点地址填什么、密钥从哪读、模型 ID 写成什么字符串。这一层的绝大部分内容是”团队里每个人应该一模一样”的,所以它天然属于版本库。
模型能力,说的是那个模型本身能干什么:能不能调工具、上下文窗口多大、能不能吃图。这一层里有一部分需要你在客户端手工声明——因为客户端不一定认识你接的那个模型。
顺带把几个词说明白,后面会反复用:
- OpenAI 兼容端点:指一个 HTTP 服务,它的请求和响应格式跟 OpenAI 那套 chat completions 接口一样,所以任何支持这套格式的客户端都能接上去。它跟”服务在哪家公司”没关系。
- 原生工具调用(native tool calling / function calling):模型按结构化格式返回”我要调用哪个工具、参数是什么”,客户端据此去执行。有些客户端把这当硬门槛——Roo Code 官方文档的原话是 “Roo Code uses native tool calling exclusively. This is the only supported tool protocol — there is no XML-based fallback.”(这是该产品官方文档的说法,不是本文的判断),文档还建议先查服务商文档确认所选模型是否支持工具调用。
- 上下文窗口:一次请求里模型最多能吃进多少 token(模型处理文本的最小计价与计数单位)。
- 嵌入与重排(embed / rerank):把文本转成向量以便检索叫嵌入,把检索回来的一批结果再排一次序叫重排。它们是检索链路上的角色,跟”聊天”是不同用途。
- keychain:操作系统提供的凭据保管服务,密码由系统加密保管,程序按需取用,不落在明文配置文件里。
- 环境变量插值:配置文件里不写真值,只写一个变量名占位,程序加载时把当前环境里同名变量的值替换进去。
二、配置进版本库:各家把”可共享的那部分”放在哪
真正决定这件事能不能做的,是工具有没有”项目级配置文件”这个概念——也就是一个躺在仓库里、被自动读到的文件。
Gemini CLI 把位置和优先级都写进了文档。截至 2026-08-07 官方文档,它的 settings.json 有四处位置:系统默认 /etc/gemini-cli/system-defaults.json(Linux)、用户级 ~/.gemini/settings.json、项目级”项目根的 .gemini/settings.json”、系统覆盖 /etc/gemini-cli/settings.json(Linux)。文档给出的优先级链是从低到高:硬编码默认 → system defaults 文件 → user settings → project settings → system settings → 环境变量 → 命令行参数。这条链的含义很实际:项目级文件能盖住个人偏好,而环境变量和命令行参数又能盖住项目级文件——正好是”团队定基线、个人临时改”想要的形状。文档还说明设置按类别组织成顶层对象(general、ui、tools、model、context 等),每个设置要放进对应类别里;跟模型相关的项有 model.name(默认模型)和 security.auth.selectedType。
aider 的 .aider.model.settings.yml 可以放四处,文档说是按顺序加载、后加载的优先:home 目录、git 仓库根目录、启动 aider 的当前目录、--model-settings-file <filename> 指定的自定义路径。第二项就是团队共享的落点——文件放在仓库根,跟着 git 走。另外,对 aider 不认识的模型,用 .aider.model.metadata.json 注册上下文上限与价格,官方文档的示例是这样的(下列数值是文档示例值,不是任何真实模型的报价):
{
"provider/model-name": {
"max_tokens": 4096,
"max_input_tokens": 32000,
"max_output_tokens": 4096,
"litellm_provider": "provider",
"mode": "chat"
}
}
文档里还有 extra_params,可以把任意参数透传给 litellm.completion(),包括 extra_headers;特殊模型名 aider/extra_params 能让设置对所有模型全局生效。文档提到的其他设置项名有 edit_format、weak_model_name、use_repo_map、cache_control、accepts_settings。
Crush 的配置文件是 crushrc,README 说明它是 bash 风格加 Crush 内建命令,不是 JSON。文档列出的两处是 ./.crushrc(项目级)和 ~/.config/crush/crushrc(全局,Unix 类系统),项目级列在前面。加自定义 provider 走命令,README 的示例是:
provider add deepseek --type openai-compat \
--base-url "https://api.deepseek.com/v1"
README 同时写明自定义 provider 必须是 OpenAI 兼容或 Anthropic 兼容 API。因为 crushrc 是命令脚本而不是数据文件,把上面这行提交进仓库,等于把”怎么接”这件事写成了可执行的说明书。
Zed 用 settings.json,官方文档给的结构是这样(已裁剪):
{
"language_models": {
"openai_compatible": {
"my-provider": {
"api_url": "https://example.com/v1",
"available_models": [
{
"name": "my-model",
"display_name": "My Model",
"max_tokens": 128000
}
]
}
}
}
}
其中 api_url 是自定义 base URL,available_models 是模型数组,每项含 name(模型标识)、display_name(界面显示名)、max_tokens(上下文窗口上限);另有 capabilities 对象控制能力开关(tools、images、parallel_tool_calls 等)。这一整块都是可共享的纯配置。
Continue 的配置文件是 config.yaml,模型配置在 models 块下,必填 name、provider、model,可选 apiBase(覆盖默认 API 端点)、roles、capabilities(如 tool_use、image_input)、defaultCompletionOptions 等。roles 的取值是 chat、autocomplete、embed、rerank、edit、apply、summarize,默认是 [chat, edit, apply, summarize]——如果你想让某个模型专门承担嵌入或重排,就得显式写出来。
三、密钥不进版本库:各家给的机制不一样
这一层是本篇的重点,因为各家给的机制形态差别不小,而且它常常被”能跑起来就行”的心态盖过去。
Zed 把话说死了。官方文档原话是 “Do not put API keys in settings.json.”,凭据走两条路:provider 设置界面,或者环境变量,命名规则是 <PROVIDER_NAME>_API_KEY——provider 名为 my-provider 时对应 MY_PROVIDER_API_KEY。配置页另有一句原话:“Provider keys saved through Zed are stored in the system keychain, not in settings.json.”。这套设计对团队非常友好:settings.json 里只有端点和模型清单,可以放心提交;密钥要么在系统 keychain,要么在每个人自己的 shell 环境里。相关命令文档也列了:agent: open settings、zed: open settings、zed: open settings file;另外 disable_ai 设置可以关掉全部 AI 功能,写法是 "disable_ai": true——这一项对”某些仓库不许用 AI”的团队约定有用。
Gemini CLI 给的是另一种解法:settings.json 内支持环境变量插值,写 $VAR_NAME 或 ${VAR_NAME},加载时自动解析。这正是”配置进版本库、密钥不进版本库”最直接的形态——文件里写的是变量名,真值在每个人自己的环境里。它的 .env 查找顺序也写明了:当前工作目录 → 逐级父目录(到项目根或 home 为止)→ 用户 home 的 ~/.env。相关项有 GEMINI_API_KEY 和 GEMINI_MODEL。落到实践上就是:.gemini/settings.json 提交,.env 进 .gitignore,仓库里放一份不含真值的样例。
goose 走环境变量与配置文件两条路:GOOSE_PROVIDER、GOOSE_MODEL 设默认 provider 与模型,各家密钥用各自变量(文档举例 ANTHROPIC_API_KEY、OPENAI_API_KEY),配置持久化在 config.yaml。接自建或企业内部的 OpenAI 兼容端点时,设 OPENAI_HOST,可选 OPENAI_BASE_PATH。文档自述支持 40+ 个 LLM provider,并称 “works best with Claude 4 models”,理由是这些模型的工具调用能力——这是官方文档的说法,本文不替它背书。CLI 侧的配置流程是跑 goose configure → 选 Configure Providers → 从列表选 provider → 填 API key 与附加参数 → 选模型。
aider 的四层加载顺序里,“后加载的优先”意味着仓库根的文件会被”启动目录的文件”和 --model-settings-file 指定的文件覆盖,个人想临时换设置不必改仓库里的东西。
Cline、Roo Code、Kilo Code 这三家在文档里是以图形界面表单的形式描述的(Cline 与 Roo Code 的三个主参数是 Base URL、API Key、Model;Kilo Code 建 provider 的字段包括 Provider ID、Display name、Provider API、Base URL、API key、Models、Headers)。表单意味着配置不天然是一个能提交的文件——团队想统一,得靠写进 onboarding 文档、让每个人照着填。本次核对的这几页文档里没有写明它们的配置导出机制,这不等于产品没有,请以官方文档为准。
四、字段对照表:哪一项该进仓库
下表的字段名逐字取自各家官方文档(核对日期 2026-08-07),“进不进版本库”一列是本文给的团队实践建议,不是各家文档的规定。
| 配置项 | 所属工具 | 它是什么 | 进不进版本库 | 出处 |
|---|---|---|---|---|
api_url | Zed | 自定义 base URL | 进 | Zed 官方文档(URL 见文末) |
available_models | Zed | 模型数组,每项含 name、display_name、max_tokens | 进 | Zed 官方文档 |
<PROVIDER_NAME>_API_KEY | Zed | 密钥环境变量的命名规则 | 不进(变量名可写进文档) | Zed 官方文档 |
.gemini/settings.json | Gemini CLI | 项目根的项目级设置文件 | 进 | Gemini CLI 官方文档 |
$VAR_NAME / ${VAR_NAME} | Gemini CLI | settings.json 里的环境变量插值写法 | 进(引用的真值不进) | Gemini CLI 官方文档 |
GEMINI_API_KEY | Gemini CLI | Gemini API 密钥 | 不进 | Gemini CLI 官方文档 |
.aider.model.settings.yml | aider | 模型设置文件,可放 git 仓库根目录 | 进 | aider 官方文档 |
.aider.model.metadata.json | aider | 给 aider 不认识的模型注册上下文上限与价格 | 进 | aider 官方文档 |
./.crushrc | Crush | 项目级配置文件(bash 风格,非 JSON) | 进 | Crush README |
--base-url | Crush | provider add 的命令行参数 | 进 | Crush README |
apiBase | Continue | config.yaml 里覆盖默认 API 端点 | 进 | Continue 官方文档 |
OPENAI_HOST / OPENAI_BASE_PATH | goose | 自建 / 企业内部 OpenAI 兼容端点的设置 | 视是否含内网信息而定 | goose 官方文档 |
注意最后一点也是最容易串台的一点:api_url、apiBase、Base URL、OPENAI_HOST、--base-url 不是同一个东西,它们分属不同产品,名字和填法都不能互相搬。你在某一家的文档里学到的填法,只对那一家成立。
五、边界与代价:这套做法放弃了什么
把配置沉进仓库不是免费的,下面这些代价要提前认。
它不管密钥的生命周期。 上面所有机制解决的只是”密钥不落进 git”,至于密钥怎么发、多久轮换一次、离职了怎么回收,这些是另一套系统的事,配置文件里看不出来。这块可以看 API 密钥的安全管理。
它不管”配置正确”这件事。 仓库里的文件只是一份声明,端点通不通、模型 ID 存不存在、密钥有没有过期,都要到真正发请求时才知道。配置文件的正确性不等于链路的可用性。
统一配置会跟”个人自由”打架。 有人想临时换个模型试试,有人的网络环境需要走不同端点。所以优先级链很重要——Gemini CLI 的环境变量与命令行参数排在项目级设置之上、aider 的”后加载的优先”,都给个人留了覆盖口子。如果一个工具没有这样的覆盖层,强推统一配置就会变成天天有人改仓库文件又忘了改回来。
它对图形界面表单型的工具作用有限。 配置不落在文件上,就没法用 git 管,只能靠文档和检查表。这不是缺陷,是配置形态不同带来的必然差异。
它不解决模型能力问题。 你把配置发给全组,不代表那个模型能干活——比如上面提到的原生工具调用要求,模型不支持就是不支持,配置写得再整齐也没用。
它跟版本无关。 各家的字段随时可能变,本篇记录的是 2026-08-07 官方文档的情况,你团队真要落地时请以官方文档最新版为准。
六、避坑清单:为什么会踩,怎么避
坑一:把密钥写进了会被提交的那个文件。
为什么踩:很多工具的配置文件既能放端点又能放密钥,随手一写就过去了,本地跑得好好的。怎么避:Zed 文档已经把这句写成禁令了(“Do not put API keys in settings.json.”),照做即可;Gemini CLI 用 $VAR_NAME 插值把真值挪到环境里。另外在 CI 里加一道扫描,把带 key 特征的字符串挡在合并之前——这是通用工程手段,不是某家产品的功能。
坑二:以为把 .env 加进 .gitignore 就万事大吉。
为什么踩:.gitignore 只挡未跟踪的新文件,已经提交过的文件继续被跟踪;而且 git 历史里的旧提交不会因为你现在删掉文件就消失。怎么避:密钥一旦进过仓库,第一动作是去服务商侧吊销重发,而不是改历史。
坑三:把 A 家的字段名抄到 B 家。
为什么踩:几家的功能太像了,肉眼看上去 apiBase 和 api_url 是”同一个意思”。怎么避:改配置前先打开对应产品的那一页文档确认字段名,跨家复制粘贴时逐字段核对。这一条在本篇看起来啰嗦,实际是新人最高频的报错来源。
坑四:端点带不带 /v1 拍脑袋决定。
为什么踩:各家写法确实不一样——Kilo Code 文档明确说它接受 https://api.provider.com/v1 和 https://api.provider.com/v1/chat/completions 两种形态(后者是为端点结构非标准的服务商与自建网关准备的);Zed 的文档示例是 https://example.com/v1;goose 则把 OPENAI_HOST 和 OPENAI_BASE_PATH 拆成两段。怎么避:以你要接的那个服务商文档给的地址为准,再对照客户端文档看它期望的形态,不要从别家的例子里推。
坑五:上下文窗口这类要手填的项,团队里各填各的。
为什么踩:客户端不认识你自建或新接的模型时,这些数值需要人来声明——Zed 在 available_models 里写 max_tokens,aider 在 .aider.model.metadata.json 里写 max_input_tokens / max_output_tokens,Cline 文档里这一项写作 Context Window size、Roo Code 文档里写作 Context Window(两家措辞不同,别互相套用)。官方文档并未逐条说明客户端内部拿这些值做什么,实际行为以官方文档为准;但从工程上讲,一个人填 32000、另一个人填 128000,两人遇到的行为就可能不一致,事后很难对齐。怎么避:把这些数值当成团队约定的一部分写进仓库里的配置文件,谁要改就走一次代码评审。
坑六:忘了工具调用是硬门槛。
为什么踩:接上了、能聊天,就以为配好了,直到 agent 流程跑起来才发现工具调不动。怎么避:接入前先按官方文档确认所选模型支持工具调用;Continue 有 capabilities.tool_use、Zed 的 capabilities 含 tools 与 parallel_tool_calls,这类开关也要一并核对。更细的接入步骤见 编辑器接自定义 API 的通用做法。
坑七:把”最大输出”设得过小。 这属于 OpenAI 兼容协议层的通用机制推理,不是哪家产品文档的记载:最大输出 token 设小了,长回答会被截断;窗口值填得超过服务端真实上限,请求可能被服务端拒绝。遇到”回答莫名断掉”先回头看这两个数,比排查客户端划算。
数据来源与核对日期
以下 URL 均取自各产品官方文档/仓库,核对日期 2026-08-07。正文提到的字段名、命令、文件路径与英文原句,均以这些页面当天的内容为准,请读者以官方文档最新版复核。
- Zed:https://zed.dev/docs/ai/use-api-access、https://zed.dev/docs/ai/configuration
- Gemini CLI:https://google-gemini.github.io/gemini-cli/docs/get-started/configuration.html
- aider:https://aider.chat/docs/config/adv-model-settings.html
- Crush:https://raw.githubusercontent.com/charmbracelet/crush/main/README.md
- Continue:https://docs.continue.dev/reference
- goose:https://goose-docs.ai/docs/getting-started/providers/
- Cline:https://docs.cline.bot/provider-config/openai-compatible
- Roo Code:https://roocodeinc.github.io/Roo-Code/providers/openai-compatible
- Kilo Code:https://kilo.ai/docs/providers/openai-compatible
本篇没有写什么,以及为什么:
- 不写任何产品的价格、免费额度、订阅档位、限速数字。 这类数字变动频繁,本次核对也未采集,写出来只会误导人做预算。aider 一节引用的
.aider.model.metadata.json数值是官方文档的示例值,不是任何真实模型的报价。 - 不写完整模型清单。 各家支持哪些模型是滚动变化的,请直接看官方文档或服务商的模型页。
- 不写版本号、发布日期与产品之间的关系。 本次只核对了配置层的文档内容。
- 不写界面长什么样。 上述来源记录的是配置层事实,没有各家界面的截图与菜单层级,涉及界面的地方请以你实际看到的为准。
- 不给各家排座次。 配置形态的差异(文件式、命令式、表单式)是设计取向不同,不构成优劣。
- 本篇依据的这几页记录里没有出现的项,不代表该产品没有这项能力——只代表本次核对没有采到,请以官方文档为准。
延伸阅读:同一组里的 编辑器接自定义模型后这笔钱怎么算、明明改了配置却没生效;接完之后照 接完自定义模型别急着干活 逐项过一遍,才算真接通。