团队统一编辑器模型配置:配置进版本库、密钥不进版本库怎么做

2026-08-07

团队要统一的不是”大家都用哪个模型”,而是一条边界:配置里哪一部分该进版本库、哪一部分必须留在每个人自己机器上。 这条边界一旦画清楚,新人拉下仓库就能跑,密钥泄露的面也收得住;画不清楚,你会同时得到两种病——一种是每个人配得都不一样、出了问题谁也复现不了,另一种是有人把 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_formatweak_model_nameuse_repo_mapcache_controlaccepts_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 是命令脚本而不是数据文件,把上面这行提交进仓库,等于把”怎么接”这件事写成了可执行的说明书。

Zedsettings.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 块下,必填 nameprovidermodel,可选 apiBase(覆盖默认 API 端点)、rolescapabilities(如 tool_useimage_input)、defaultCompletionOptions 等。roles 的取值是 chatautocompleteembedrerankeditapplysummarize,默认是 [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 settingszed: open settingszed: open settings file;另外 disable_ai 设置可以关掉全部 AI 功能,写法是 "disable_ai": true——这一项对”某些仓库不许用 AI”的团队约定有用。

Gemini CLI 给的是另一种解法:settings.json 内支持环境变量插值,写 $VAR_NAME${VAR_NAME},加载时自动解析。这正是”配置进版本库、密钥不进版本库”最直接的形态——文件里写的是变量名,真值在每个人自己的环境里。它的 .env 查找顺序也写明了:当前工作目录 → 逐级父目录(到项目根或 home 为止)→ 用户 home 的 ~/.env。相关项有 GEMINI_API_KEYGEMINI_MODEL。落到实践上就是:.gemini/settings.json 提交,.env.gitignore,仓库里放一份不含真值的样例。

goose 走环境变量与配置文件两条路:GOOSE_PROVIDERGOOSE_MODEL 设默认 provider 与模型,各家密钥用各自变量(文档举例 ANTHROPIC_API_KEYOPENAI_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_urlZed自定义 base URLZed 官方文档(URL 见文末)
available_modelsZed模型数组,每项含 namedisplay_namemax_tokensZed 官方文档
<PROVIDER_NAME>_API_KEYZed密钥环境变量的命名规则不进(变量名可写进文档)Zed 官方文档
.gemini/settings.jsonGemini CLI项目根的项目级设置文件Gemini CLI 官方文档
$VAR_NAME / ${VAR_NAME}Gemini CLIsettings.json 里的环境变量插值写法进(引用的真值不进)Gemini CLI 官方文档
GEMINI_API_KEYGemini CLIGemini API 密钥不进Gemini CLI 官方文档
.aider.model.settings.ymlaider模型设置文件,可放 git 仓库根目录aider 官方文档
.aider.model.metadata.jsonaider给 aider 不认识的模型注册上下文上限与价格aider 官方文档
./.crushrcCrush项目级配置文件(bash 风格,非 JSON)Crush README
--base-urlCrushprovider add 的命令行参数Crush README
apiBaseContinueconfig.yaml 里覆盖默认 API 端点Continue 官方文档
OPENAI_HOST / OPENAI_BASE_PATHgoose自建 / 企业内部 OpenAI 兼容端点的设置视是否含内网信息而定goose 官方文档

注意最后一点也是最容易串台的一点:api_urlapiBaseBase URLOPENAI_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 家。 为什么踩:几家的功能太像了,肉眼看上去 apiBaseapi_url 是”同一个意思”。怎么避:改配置前先打开对应产品的那一页文档确认字段名,跨家复制粘贴时逐字段核对。这一条在本篇看起来啰嗦,实际是新人最高频的报错来源。

坑四:端点带不带 /v1 拍脑袋决定。 为什么踩:各家写法确实不一样——Kilo Code 文档明确说它接受 https://api.provider.com/v1https://api.provider.com/v1/chat/completions 两种形态(后者是为端点结构非标准的服务商与自建网关准备的);Zed 的文档示例是 https://example.com/v1;goose 则把 OPENAI_HOSTOPENAI_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。正文提到的字段名、命令、文件路径与英文原句,均以这些页面当天的内容为准,请读者以官方文档最新版复核。

本篇没有写什么,以及为什么:

  1. 不写任何产品的价格、免费额度、订阅档位、限速数字。 这类数字变动频繁,本次核对也未采集,写出来只会误导人做预算。aider 一节引用的 .aider.model.metadata.json 数值是官方文档的示例值,不是任何真实模型的报价。
  2. 不写完整模型清单。 各家支持哪些模型是滚动变化的,请直接看官方文档或服务商的模型页。
  3. 不写版本号、发布日期与产品之间的关系。 本次只核对了配置层的文档内容。
  4. 不写界面长什么样。 上述来源记录的是配置层事实,没有各家界面的截图与菜单层级,涉及界面的地方请以你实际看到的为准。
  5. 不给各家排座次。 配置形态的差异(文件式、命令式、表单式)是设计取向不同,不构成优劣。
  6. 本篇依据的这几页记录里没有出现的项,不代表该产品没有这项能力——只代表本次核对没有采到,请以官方文档为准。

延伸阅读:同一组里的 编辑器接自定义模型后这笔钱怎么算明明改了配置却没生效;接完之后照 接完自定义模型别急着干活 逐项过一遍,才算真接通。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。