跳转到内容

配置与认证

Chord 将行为配置与凭据配置分开管理。

  • ~/.config/chord/config.yaml:provider、模型、权限、扩展能力等行为配置
  • ~/.config/chord/auth.yaml:API key 或 OAuth 凭据
  • .chord/config.yaml:项目级覆盖配置
  • ~/.config/chord/agents/ / .chord/agents/:角色配置

无需从头到尾阅读本页:

优先级从低到高:

  1. 内置默认
  2. 全局配置
  3. 项目配置
  4. Agent 级配置

兼顾用户习惯、项目差异和不同 Agent 的能力特化。

项目配置 .chord/config.yaml 会先按“无内置默认值注入”的方式加载,再覆盖到已加载的全局配置上。运行时命令把当前工作目录视为项目根,因此项目层配置读取的是启动 cwd 下的 ./.chord/config.yaml,不会自动向父目录继续查找。因此:

  • 项目里没写的字段会保持真正的未设置状态,不会意外遮蔽全局默认值;
  • 项目配置写坏了会直接作为启动错误暴露,而不是被静默忽略;
  • paths.*maintenance.*(以及 model_templatesdiagnostics)这类仅全局生效的字段,即使写进项目配置也会被忽略;
  • 大多数标量值和对象值会按同一路径直接覆盖全局值;
  • model_pools 按 pool 名称合并:项目里同名 pool 会覆盖全局定义;
  • mcp 按 server 名称合并:项目里的同名 server 会完整替换全局定义,不会逐字段继承旧的连接、凭据或工具权限;
  • 追加型扩展点会保留全局条目并附加项目条目:当前包括 skills.pathshooks.* 下各触发点的 hook 列表,它们是 append,不是 replace。

首次在交互式终端里运行 chordconfig.yaml 缺失时,Chord 会启动一次性的初始化向导。它会写入最小可用的 config.yaml,必要时再写入 auth.yaml,如果已有匹配的 auth.yaml 凭据则尽量直接复用,并在结束时展示真实解析后的路径。stdin 被重定向本身不等于非交互;只要还能打开控制 TTY,向导仍会使用该 TTY。只有没有控制 TTY 时,它才会直接退出,不会等待输入。

providers:
modelscope:
type: chat-completions
api_url: https://api-inference.modelscope.cn/v1/chat/completions
models:
Qwen/Qwen3.5-397B-A17B:
limit:
context: 262144
input: 262144
output: 65536
modalities:
input: [text, image]

BigModel Chat Completions(Coding Plan)

Section titled “BigModel Chat Completions(Coding Plan)”

Chord 的 api_url 是完整请求 URL。BigModel Coding Plan 的 OpenAI-compatible endpoint 需要在 Coding Plan base 后追加 /chat/completions

providers:
bigmodel:
type: chat-completions
api_url: https://open.bigmodel.cn/api/coding/paas/v4/chat/completions
models:
glm-5.2:
limit:
context: 1000000
output: 128000
reasoning:
effort: max
compat:
request_overrides:
rename_body_fields:
max_completion_tokens: max_tokens
body:
thinking:
type: enabled
clear_thinking: false
reasoning_continuity:
mode: openai_visible

各 provider / 模型的可复制片段(GPT-5.4/5.5/5.6、Claude、Gemini、GLM、DeepSeek/OpenAI-compatible)见模型配置速查

providers:
openai:
type: responses
api_url: https://api.openai.com/v1/responses
models:
gpt-5.6:
limit:
context: 400000
input: 272000
output: 128000
reasoning:
effort: medium
summary: auto
variants:
low:
reasoning:
effort: low
high:
reasoning:
effort: high
xhigh:
reasoning:
effort: xhigh
max:
reasoning:
effort: max
modalities:
input: [text, image]
model_pools:
default:
- openai/gpt-5.6@high

还需要在 ~/.config/chord/auth.yaml 中为这个 provider 配置 API key:

openai:
- "$OPENAI_API_KEY"
  • 如需固定模型 ID,把配置中的两处 gpt-5.6 同时替换为 gpt-5.6-solgpt-5.6-terragpt-5.6-luna
  • 保守默认值为 400000 / 272000 / 128000,与 Codex 配额一致,也适合许多 基于 Codex 的 Responses 中转。如果账号或网关明确支持完整的 1.05M OpenAI API 窗口,把 context 改成 1050000 并删除 input;Chord 会在预留实际 请求输出后推导可用输入预算。此时超过 272K 是计价阈值,不是输入上限。
  • API 支持的 reasoning effort 为 nonelowmediumhighxhighmax;可用 openai/gpt-5.6@max 这样的 ref 选择已配置 variant。
  • Responses 在启用 reasoning 时默认使用 reasoning.summary: auto;如需明确关闭,请配置为 none。Chord 当前尚未暴露 GPT-5.6 的 reasoning.mode: pro
  • preset: codex provider 也可以使用 max;是否接受该 effort 由具体模型 / 后端决定。

模型限制和 reasoning 取值已根据当前 Codex 模型目录及 OpenAI 的 GPT-5.6 配置指南核对。 中转的实际配额可能更小,应以上游公布的模型目录为准。

按这个顺序理解模型限制:

  1. limit.context 是总窗口。对大多数模型,只要“输入 + 请求输出”放得进这个数字即可。
  2. limit.input 只在 provider 还单独列出输入上限时才需要。部分 GPT 模型属于这种情况;如果省略,Chord 会从 limit.context 中预留有效请求输出后,推导可用输入预算。
  3. limit.output 是模型的最大输出能力。Chord 默认 max_output_tokens64000,因此在按可用上下文继续收缩前,实际请求上限为 min(64000, limit.output)。如需不同的全局上限,请显式设置 max_output_tokens。若某模型实际输出能力低于 64000 且未配置 limit.output,在服务端校验 max_tokens 的后端会直接拒绝这类请求——请为该模型声明 limit.output,或调低全局 max_output_tokens

当前 GPT-5.6 Codex 配额为 400K 总窗口、272K 输入上限和 128K 输出上限, 因此默认应显式配置这三个字段。

Responses 和 Chat Completions 服务商的 parallel_tool_calls 默认都是 true。只有后端或工作流要求串行工具调用时,才在服务商、模型或变体上设为 false。部分网关要求特定客户端标识时,还可以配置服务商级 user_agent

Provider 的认证头会与 type 分开推断;如果某个兼容 endpoint 要求不同的凭据 header,也可以用 auth_scheme 手动覆盖:

  • type: messages → 默认 auth_scheme: anthropic-api-key(发送 x-api-key
  • type: responses → 默认 auth_scheme: bearer(发送 Authorization: Bearer
  • type: chat-completions → 默认 auth_scheme: bearer
  • preset: azure → 默认 auth_scheme: api-key(发送 api-key

支持的 auth_scheme 取值有:

  • anthropic-api-key
  • bearer
  • api-key

只有当 endpoint 的认证要求和 Chord 默认传输策略不一致时,才需要显式覆盖。例如,有些 /messages 兼容接口虽然走 Anthropic 风格的请求体,却要求 Authorization: Bearer,而不是 x-api-key。这时保留原有 type,只设置 auth_scheme: bearer 即可。

对于 Anthropic 受限开放的 1M 上下文能力,Chord 只会在模型声明至少 1M token 窗口时启用:优先读取 limit.input,否则读取 limit.context。窗口较小的模型不会收到相应 beta header。超过 200K token 时,服务商可能采用不同的权限要求和计价方式。

store 控制 Responses 后端是否在服务端保留请求和响应。除 preset: azure 外,默认值都是 false。只有后端明确要求服务端留存、且你接受相应数据保留影响时才启用。不要为 preset: codex 开启;官方 Codex OAuth 端点会拒绝 store: true

Codex OAuth 使用与 Responses 兼容 API 示例不同的独立模型限制;provider preset 和认证方式也不同。

providers:
codex:
preset: codex
type: responses
models:
gpt-5.5:
limit:
context: 400000
input: 272000
output: 128000
gpt-5.4:
limit:
context: 1050000
input: 950000
output: 128000
gpt-5.6-sol:
limit:
context: 400000
input: 272000
output: 128000

GPT-5.4 使用 1050000 / 950000 / 128000;GPT-5.5 使用 400000 / 272000 / 128000;GPT-5.6 Sol、Terra、Luna 使用 400000 / 272000 / 128000(依次为 context / input / output)。完整示例见 模型配置速查

preset: codex 可使用 auth.yaml 中的 OpenAI / ChatGPT OAuth 凭据。OAuth 条目通常是 mapping:

codex:
- refresh: rfr_...
access: eyJ...
expires: 1774009702606
account_id: acc_... # 可选;workspace/account 账号才一定有
account_user_id: u_...__acc_... # 可选;缺失时后台解析/补齐
email: user@example.com # 可选

account_id 不是所有 ChatGPT 账号都有。个人 Plus/Pro 账号的 access token 可能只包含 user_id,不包含 chatgpt_account_id;这类账号现在仍会作为普通 OAuth access token 使用,请求时不会发送 ChatGPT-Account-ID header。依赖 workspace/account id 的增强能力(例如 Codex usage / rate limit polling)会跳过这些账号,直到后台解析或配置中提供了 account id。

为支持大量账号池,Chord 启动时不会同步解析每个 OAuth JWT,也不会因为某个 access token 缺 account_id 阻塞 provider 初始化。启动路径只读取 auth.yaml 中已经显式写出的 metadata;缺失的 account_user_idaccount_idemailexpires 会在 provider 建立后后台解析并尽量回填。若手动转换 Codex / sub2api / 其他登录结果,建议保留能拿到的 account_idaccount_user_idemail,但它们不是启动必填项。

Azure OpenAI Responses endpoint 使用 preset: azure。这个 preset 必须显式配置:Chord 不会根据 endpoint URL 自动识别 Azure。它会设置 type: responses、默认 store: true、把该 endpoint 视作 official API 处理 400、禁用 Codex WebSocket/OAuth 行为,把凭据作为 Azure 要求的 api-key 请求头发送,而不是 Authorization: Bearer,并省略 OpenAI-Betaoriginator 等 Codex 兼容 header。

Azure v1 Responses endpoint 可以直接使用 /openai/v1/responses;只有需要固定或启用特定版本(例如 preview)时,才在 api_url 中添加 api-version

providers:
azure:
preset: azure
api_url: https://YOUR-RESOURCE.openai.azure.com/openai/v1/responses
models:
gpt-5.5:
limit:
context: 400000
input: 272000
output: 128000

Azure API key 写在 auth.yaml 的同名 provider 下:

azure:
- $AZURE_OPENAI_API_KEY
providers:
gemini:
api_url: https://generativelanguage.googleapis.com/v1beta/models
models:
gemini-3.5-flash:
limit:
context: 1048576
output: 65536
modalities:
input: [text, image, pdf]

Gemini 的 api_url 应设为 /models 基础路径。Chord 根据 URL path 的 /models 后缀自动识别为 type: generate-content,可省略 type。不要在 URL 中包含模型名或 :streamGenerateContent?alt=sse,Chord 会自动追加 /{model}:streamGenerateContent?alt=ssemodels 下的 key(如 gemini-3.5-flash)即为发送给 Gemini 的模型 ID。

Gemini 的 thinking 参数与其他 provider 一样统一放在 thinking 下(不使用 gemini_thinking 之类的专有键):

  • thinking.budgetgenerationConfig.thinkingConfig.thinkingBudget
    • Gemini:✅ 使用
    • Anthropic:⚠️ 仅在 thinking.type: enabled 时用于预算模式
    • OpenAI:❌ 忽略
  • thinking.include_thoughtsgenerationConfig.thinkingConfig.includeThoughts
    • Gemini:✅ 使用
    • Anthropic / OpenAI:❌ 忽略
  • thinking.levelgenerationConfig.thinkingConfig.thinkingLevelminimal|low|medium|high,Gemini 3+;并非所有模型都支持 minimal
    • Gemini 3+:✅ 使用
    • Gemini 2.x / Anthropic / OpenAI:❌ 忽略

示例:

providers:
gemini:
api_url: https://generativelanguage.googleapis.com/v1beta/models
models:
gemini-2.5-flash:
limit:
context: 1048576
output: 65536
modalities:
input: [text, image, pdf]
thinking:
budget: -1
include_thoughts: true
gemini-3-pro:
limit:
context: 1048576
output: 65536
modalities:
input: [text, image, pdf]
thinking:
budget: -1
level: high

省略 type 时,Chord 按以下规则自动推断:

  • preset: codexresponses
  • preset: azureresponses
  • api_url 的 path 以 /responses 结尾 → responses
  • api_url 的 path 以 /chat/completions 结尾 → chat-completions
  • api_url 的 path 以 /messages 结尾 → messages
  • api_url 的 path 以 /models 结尾 → generate-content

不匹配以上规则时,需显式设置 type

如果你的模型会输出英文 thinking / reasoning,而你希望在界面中附加中文译文,可启用 thinking_translation

model_pools:
translation:
- openai/gpt-5.4-mini
thinking_translation:
target_language: zh-Hans
model_pool: translation
max_chars: 1000

要点:

  • 只翻译 thinking / reasoning,不翻译 assistant 正文。译文附加在对应 thinking 卡片下方,使用中性的 Translated · <target_language> 分隔标题,保留 Markdown / 代码高亮,不会写回模型上下文。
  • target_languagemodel_pool 都是必填,缺失任一项时该能力不会启用。model_pool 必须指向一个顶层 model_pools 条目,建议单独配置低成本翻译池。该池可包含多个 provider/model[@variant] ref;翻译会按顺序执行单轮 fallback:候选失败(含网络/5xx/超时)、返回为空、明显截断或不是目标语言时,都会切到下一个候选。
  • max_chars(默认 1000)限制送去翻译的 thinking 预览长度,只翻译开头 max_chars 个字符,超出部分不会出现在翻译卡片中。追求更低延迟/成本可设为 500,希望译文更完整可调大。
  • 某个 thinking block 临时失败只会跳过该 block,不会阻塞后续 thinking 翻译,也不会影响主回答。provider 底层传输超时(默认一分钟级别)仍然生效,卡住的模型 / key 可以失败切换,同时模型池仍有机会完整运行。
  • 译文持久化到会话目录的 thinking_translations.json,恢复同一 session 时直接复用。同一个 thinking block 最多翻译一次:之后修改 thinking_translation.target_language 也不会重新翻译已存在的块。

更完整的字段说明见下文配置参考。

auth.yaml 的 key 名需与 config.yaml 中的 provider 名称对应:

首次向导可以帮你创建这个文件。它既支持字面 API key,也支持 $ENV_VAR 占位符。

anthropic:
- "$ANTHROPIC_API_KEY"
openai:
- "$OPENAI_API_KEY"

可配置多个 key 作为轮换或备用。

对于 preset: codex 的 OAuth provider,Chord 会把高频变化的运行时状态(额度快照、重置时间、最近 warm-up 时间、共享 OAuth 状态缓存)写入 auth.state.json,而不是继续频繁改写 auth.yaml

这样拆分是有意为之:

  • auth.yaml 仍是用户可编辑的凭据与稳定 OAuth 字段来源,例如 refreshaccessexpiresaccount_idemail;Chord 重写文件时会省略空 OAuth 字段,OAuth status 不属于 auth.yaml
  • auth.state.json 是机器维护的共享运行时状态。普通条目在每个 provider 下直接以 account_user_id 为 key;quota / reset 更新,以及 expireddeactivatedinvalidated 这类账号状态,不会在用户可能同时编辑 auth.yaml 时频繁改写该文件。尚不知道账号的 refresh-only 凭据可临时使用 refresh_sha256:<digest> state 条目,直到首次成功 refresh 后回填 account_user_idchord auth state clean 会移除没有对应 auth.yaml OAuth 凭据的孤儿状态,以及无法识别的旧 state key 格式。

对带 access 的 OAuth 凭据来说,access token 必须能解析出 account 与 user/account-user claim。如果 auth.yaml 已有 account_id,token 中的账号 ID 必须一致;否则该 access token 会被视为账号不匹配而拒绝。Chord 也支持只包含 refresh、没有 access 的 OAuth 条目,并会在首次使用时刷新;成功刷新后会解析 account_id 并把运行时状态切换到 account_user_id key。如果在账号未知前 refresh 发生不可恢复失败,Chord 会在 refresh_sha256:<digest> 下记录无效状态,之后由用户执行 chord auth state clean 清理该不可用凭据。既没有 access 也没有 refresh 的 OAuth 条目不可用。

expires 是 access token 的 Unix 毫秒过期时间。如果 access 是带 exp claim 的 JWT,Chord 会优先使用该值作为更准确的过期元数据,并可将得到的过期时间缓存到 auth.state.json,但不会在 state 文件里保存 access token。缺失或本地已过期的 expires 不会单独把 OAuth slot 标记为 expired 或不健康。Chord 仍会先尝试已有的 access token,只有在认证失败后,才会在可恢复时刷新凭据,或者在无法恢复时标记为 expired。

典型的 auth.state.json 内容如下:

{
"openai": {
"user-1__acc-1": {
"account_user_id": "user-1__acc-1",
"account_id": "acc-1",
"email": "user@example.com",
"expires": 1774009702606,
"status": "expired",
"updated_at": 1774009702606,
"last_warmup_at": 1774009702606,
"codex_primary_used_pct": 12.5,
"codex_primary_window_minutes": 60,
"codex_primary_reset_at": 1774013302000,
"codex_secondary_used_pct": 40,
"codex_secondary_window_minutes": 10080,
"codex_secondary_reset_at": 1774600000000
}
}
}

status 字段只在 auth.state.json 中权威生效。当 access token 已不可用且凭据无法刷新时,Chord 会写入 expired(包括 refresh token 缺失、无效、过期或已被复用),服务端报告账号停用 / 封禁时写入 deactivated,账号需要重新认证时写入 invalidated。任意非空状态都会让该 OAuth slot 不再被选择,直到清理或替换凭据。

这些 Codex 缓存字段是跨重启保留的调度与展示提示,不是硬封禁:

  • 会帮助启动后 / 首次选号时优先选择更可能仍有额度的账号;
  • 会让切 key 时先显示上次缓存的额度快照,再等待新 warm-up 覆盖;
  • 不会仅凭字段本身就让账号绝对不可选;
  • 真正的硬封禁仍来自已确认的请求失败和运行时 cooldown 状态。

auth.yaml 的标量 API key 值支持环境变量展开:

anthropic:
- "$ANTHROPIC_API_KEY"
openai:
- "${OPENAI_API_KEY}"

标量字符串以 $ 开头时触发展开。未设置的环境变量会展开为空字符串并被过滤,除非 YAML 值本身就是字面空字符串。该展开仅适用于 auth.yaml 凭据,config.yaml 的字段不会自动展开。

确实需要空 API key 时,请显式写字面空字符串:

local-provider:
- ""

不要依赖未设置的环境变量来表示空 key——未设置的 $ENV_VAR 会被视为缺失凭据而过滤掉。

Chord 支持多个 API key / OAuth 账号时的两层选择策略:key_rotation 决定何时重新选 key,key_order 决定在候选 key 中如何选择。

  • key_rotation: on_failure(默认):尽量固定使用当前 key,只有失败、冷却或不可用时才切换。
  • key_rotation: per_request:每次请求前都重新选择 key,适合多个独立 key 做负载均衡。
  • key_order: sequential(默认的非 Codex 行为):按可用 key 的稳定顺序选择,通常接近“最久未使用优先”。
  • key_order: random:在可用 key 中随机挑选。
  • key_order: smart:仅 Codex provider 支持。会优先健康、额度更充足、reset 更近的 OAuth 账号。

key_rotation 只轮换 credential / API key,不会轮换模型;模型选择仍由 model pool 的 sticky cursor 和 fallback 逻辑控制。

在 loop 模式下,Chord 仍尊重用户显式配置的 key_rotation / key_order。如果希望 Codex 长任务保持 transport / cache 连续性,建议保留默认 key_rotation: on_failure;如果希望多账号分摊额度,则可显式启用 per_request

当前仅配置了 preset: codex 的 provider 支持 OAuth。

对 Codex provider,建议只写 preset: codex 和模型配置,不要手动覆盖 api_urltoken_urlclient_idtypestoreresponses_websocketsupported_service_tiers 等由 preset 管理的字段。Codex preset 会自动选择官方 OAuth transport、Responses endpoint、WebSocket / cache 默认值、额度轮询、smart key 排序和 service-tier 能力。它不定义另一套 HTTP 请求体,也不会强制伪装成 Codex User-Agent;非 Codex 的 type: responses provider 也使用上面那套 Responses 请求形态,所有 provider 默认仍发送 User-Agent: chord/<version>。需要显式 tier 矩阵时使用 supported_service_tiers

Codex OAuth 账号的选择由 Provider key 选择 中的 key_rotation / key_order 控制。Codex 默认使用 key_order: smart,会结合额度快照、soft cooldown 和 reset 时间选择更合适的账号。

smart 会在可选 Codex OAuth 账号之间优先:

  • 缓存快照中没有任何受跟踪窗口达到 100% 使用率的账号;100% 窗口只会被放到最后尝试,不会仅凭快照硬封禁;
  • 短窗口(例如 5h primary window)仍有剩余额度的账号,并优先选择 primary reset 更近的账号,以免快过期额度被浪费;
  • 然后考虑长窗口(例如 1w secondary window)仍有剩余额度的账号,同样优先选择 secondary reset 更近的账号;
  • 可比较窗口的 reset 时间相同时,再选择剩余额度更高的账号;
  • 如果没有更优信息,仍会回退尝试未知或缓存较旧的账号。

当 Codex client 变为活跃状态后,Chord 还可能在后台探测其他 OAuth slot,以刷新缓存的 headroom 快照。这个 warm-up 是 best-effort、低并发的,会在活跃 client 被替换时取消,并且只刷新缓存额度状态;usage probe 的认证失败不会把 OAuth 凭据标记为不可用。

warm-up 本身也会参考共享状态优先级:

  • 从未在共享状态里 warm-up 过的账号优先;
  • 缓存较旧的账号优先于最近刚刷新的账号;
  • warm-up 或轮询拿到更新后的快照后,会写回 auth.state.json,其他进程会在下次读取选 key 或额度状态时按需吸收这些更新。
Terminal window
# 自动选择已配置的 codex provider
chord auth
# 显式指定 provider
chord auth codex
# 无桌面环境 / SSH
chord auth codex --device-code

Chord 通过命名模型池选择当前使用的模型。每个池条目建议写成完整的 provider/model[@variant],这样 provider endpoint、认证、协议以及 variant tuning 都是明确的。

模型池在 config.yaml(全局或项目级)中定义;agent 配置可以引用池名来限制可用池,但不允许在 agent 中内联定义池。

# ~/.config/chord/config.yaml 或 .chord/config.yaml
model_pools:
thinking:
- anthropic/claude-opus-5
- openai/gpt-5.5
non-thinking:
- anthropic/claude-sonnet-4

项目级 .chord/config.yamlmodel_pools 会合并到全局配置中(同名覆盖)。

Agent 可以不设置 model_pools。省略时,该 agent 可使用合并后的 config.yaml 顶层 model_pools 中的所有池,并按池名的字母顺序排序。只有在需要限制该 agent 可用池,或自定义 fallback 顺序时,才需要设置 model_pools: [...]

# ~/.config/chord/agents/builder.yaml 或 .chord/agents/builder.yaml
name: builder
mode: main
model_pools: [thinking, non-thinking]
.chord/agents/reviewer.yaml
name: reviewer
mode: subagent
model_pools: [thinking]

未显式选择池时,Chord 会回退到该 agent 的第一个可用池:如果配置了 model_pools: [...],使用列表中的第一个;否则使用按字母顺序排序后的第一个顶层池。

运行时通过 /models 切换当前视图对象的池(按项目持久化,重启后仍生效):main 视图作用于当前主角色,SubAgent 视图作用于该 agent。切换池会更新后续 LLM 调用的整条 fallback 链;即使当前选中的 provider/model 同时存在于两个池中,也会按新池的顺序重新构建(已发起的 in-flight 请求仍使用其开始时快照到的 client)。也可通过 /models --agent <name> <pool> 直接设置指定 agent 的池。SubAgent 默认使用第一个可用池;想恢复默认时切回该池即可。

Chord 没有 model_templates 配置字段,但可以在该顶层容器中使用 YAML anchor 和 merge key。Chord 会忽略容器本身,只读取 providers 下展开后的 模型配置。

本页只介绍协议和字段语义。当前模型限制、价格以及 GPT / Claude / Gemini / GLM / DeepSeek 的完整可复制配置见模型配置速查

model_templates:
chat-thinking: &chat-thinking
limit:
context: 200000
output: 64000
reasoning:
effort: high
compat:
# DeepSeek 与 GLM Chat API 使用 max_tokens,而不是 OpenAI reasoning
# 模型默认使用的 max_completion_tokens。
request_overrides:
rename_body_fields:
max_completion_tokens: max_tokens
body:
thinking:
type: enabled
# 回放原生 reasoning_content,并把其他 wire family 的可移植可见
# reasoning 映射为 reasoning_content,同时不注入请求字段。
reasoning_continuity:
mode: openai_visible
responses-thinking: &responses-thinking
limit:
context: 200000
output: 64000
reasoning:
effort: high
summary: auto
messages-thinking: &messages-thinking
limit:
context: 200000
output: 64000
thinking:
type: adaptive
effort: high
compat:
# 除非兼容接口自己的文档明确要求,否则不要发送 Anthropic beta header。
request_overrides:
headers:
anthropic-beta: null
providers:
chat:
type: chat-completions
api_url: https://example.com/v1/chat/completions
models:
chat-model: *chat-thinking
responses:
type: responses
api_url: https://example.com/v1/responses
models:
responses-model: *responses-thinking
messages:
type: messages
api_url: https://example.com/v1/messages
models:
messages-model: *messages-thinking

模型字段语义:

  • limit.context:provider 公布的总请求窗口。如果省略该字段且同时配置了 正数的 limit.inputlimit.output,Chord 会按 input + output 推导; 显式配置的 context 始终优先。
  • limit.input:provider 单独公布的输入上限。省略时,Chord 按 limit.context 减去有效请求输出推导 prompt 预算。当两者都配置且公布的 上限不满足加和关系(input + output 超过 context)时,Chord 会把 prompt 预算收敛到 limit.context 减去有效请求输出,因为 provider 实际按总窗口 限制单次请求。
  • limit.output:模型输出能力上限。实际请求还受全局 max_output_tokens 和总窗口剩余空间限制。
  • reasoning.effort:推理深度或预算。Chord 规范化空格和大小写后,将 provider 支持的值透传给上游。
    • Chat Completions 发送顶层 reasoning_effort
    • Responses 发送 reasoning.effort 和可选的 reasoning.summary
  • reasoning.summary:Responses 推理摘要请求。Chord 支持 autoconcisedetailednone;启用 reasoning 时,省略该字段会默认使用 auto,以便跨 provider 回放时保留可移植的摘要文本;配置 none 可明确退出。
  • thinking:Messages 兼容的扩展思考配置。type: adaptive 可与 thinking.effort 组合,Chord 会将 effort 发送为 output_config.effort
  • text.verbosity:可选的 OpenAI 兼容可见文本详细程度提示。
  • variants:命名模型参数覆盖,可用 provider/model@high 选择。
  • cost:可选的每百万 token 美元成本估算,可包含输入 / 输出、缓存价格、 service tier 倍数和长上下文价格阶梯。
  • modalities.input:支持的输入类型:textimagepdf
  • supported_service_tiers:支持的非 standard tier,例如 fastslow; 价格倍数需要在 cost 中单独配置。

兼容字段:

  • compat.request_overrides.body:递归合并任意 JSON 到最终协议请求中。 值为 null 时删除对应字段。
  • compat.request_overrides.rename_body_fields:重命名最终请求字段,同时保留 Chord 动态计算的值,例如 max_completion_tokens: max_tokens
  • compat.request_overrides.headers:设置任意请求 header。值为 null 时 删除 Chord 默认 header,例如兼容 Messages endpoint 使用 anthropic-beta: null
  • compat.reasoning_continuity.mode
    • none:不回放 provider 专属的可见 reasoning。
    • openai_visible:在 Chat Completions 工具循环中原样回放 assistant 的 reasoning_content,并把其他 wire family 的可移植可见 reasoning 转成 reasoning_content。它不注入请求字段;字段差异由 request_overrides.body 配置。首次尝试时,Chord 仍会把 chat 原生 reasoning 乐观回放给任何 Chat Completions 目标(包括跨 provider), 因此 Kimi K2.6/K2.7→K3 这类官方支持的同 provider 升级和同模型跨 provider fallback 都能保留连续性。目标拒绝该请求后,Chord 会对该 target 降级,但在严格级别之前仍尽量保留结构化工具事实。
    • anthropic_unsigned:仅用于已验证的 Messages 兼容模型,例如返回无 Claude signature 的可见 thinking 的 DeepSeek/GLM endpoint。无签名 thinking 首次只对同 provider/model 原生回放;对兼容 target,其他 wire family 的可移植可见 reasoning 会转成无签名 thinking block, 而不会注入 assistant 正文。
    • Responses、Claude 签名 Messages 和 Gemini 其余情况使用协议原生连续性 机制。Chord 只在 wire 和 provenance 允许时回放加密/签名 opaque 状态; 跨不兼容协议时,只有存在结构化目标载体(openai_visibleanthropic_unsigned)的可见 reasoning 才会被转换;否则直接丢弃。 Chord 不会伪造 opaque 状态,也不会把 reasoning 注入普通 assistant 正文。已完成工具事实会尽量转换为目标协议的结构化表示,只有目标拒绝 该形状时才文本化。达到的降级级别按 target 记忆。
  • compat.thinking_toolcall:为把工具调用编码进可见 reasoning 文本的网关 启用专用解析器。只有网关明确要求时才开启。

Provider 级 compat 是默认值;模型级 compat 可以覆盖单个模型。

请求 override 会在 Chord 构造完协议请求后应用于 HTTP 传输。如果 Codex Responses provider 配置了 override,该请求会停用 WebSocket 传输并改走 HTTP,确保最终 JSON patch 生效。

项目需要特定默认值时,在项目根目录创建:

.chord/config.yaml

常见用途:调整项目特有权限规则、配置该项目的 LSP / MCP / Hooks / Skills。

Provider 级别的 compress 控制上游 HTTP 请求体的 gzip 压缩。它和上下文管理(compaction / reduction)是两回事——只影响请求传输编码,不会总结或移除对话历史。

providers:
openai:
compress: true

启用后,Chord 仅在 gzip 能减小体积时才发送压缩请求。除非你的 provider 或网关明确受益于请求体压缩,否则无需配置。

Provider / 模型请求默认用 User-Agent: chord/<version> 标识客户端。仅当某个 provider 或网关要求特定值时,才配置 provider 级 user_agent

providers:
gateway:
user_agent: RequiredGatewayClient/1.0

该配置也会影响对应 provider 的 Responses HTTP 请求、Codex OAuth 请求、Codex 用量轮询,以及 Responses WebSocket 握手。WebFetch 使用独立的 web_fetch.user_agent

需要发送 Codex 风格 User-Agent 时,显式写入你抓到的 Codex 值,并在 Codex 客户端版本或终端环境变化后同步更新:

providers:
codex:
preset: codex
user_agent: "codex-tui/0.139.0 (Mac OS 15.3.2; arm64) ghostty/1.3.1 (codex-tui; 0.139.0)"

Provider 级超时配置都是可选项,单位为秒。省略或设为 0 会保持内置默认行为。

providers:
codex:
response_header_timeout: 180
stream_idle_timeout: 90
websocket_handshake_timeout: 45
  • response_header_timeout:从开始流式 HTTP 请求到收到响应头的超时,包括连接建立与请求体上传。收到响应头后该计时器即停止,不限制健康流的总耗时;流式 chunk 之间的最大空闲时间由 stream_idle_timeout 控制。0 保持内置默认值。
  • stream_idle_timeout:流式模型数据的最大空闲等待时间。设置后会覆盖该 provider 的普通 SSE idle timeout 和慢阶段 idle timeout,也会用于 Codex Responses WebSocket 读等待。
  • websocket_handshake_timeout:Responses WebSocket 握手超时,主要用于启用了该 transport 的 provider,例如 preset: codexresponses_websocket 生效时。

这些配置按 provider 生效,因此项目级 .chord/config.yaml 可以只覆盖某一个 provider 的超时,不影响其他 provider。它们不会改变底层固定连接默认值,例如 TCP dial 或 TLS handshake timeout。

max_output_tokens 设置全局输出 token 请求上限,默认值为 64000。实际请求上限仍受各模型 limit.output 和可用总上下文(已知时为 limit.context)限制,因此所有 provider 都会取适用限制中的最小值。

Responses provider 默认保持稳定的 Responses 请求形态,HTTP 和 WebSocket 请求都不会发送 max_output_tokens 字段。对于需要显式服务端输出上限的兼容网关,可以在 provider 下设置 compat.responses.send_max_output_tokens: true;其余 Responses 字段开关也位于同一对象下。全局值在不发送到 wire 时仍会影响 Chord 侧预算和兼容性检查。

limit.input 是另一回事:只有当模型除了总上下文窗口外,还额外存在输入上限时才需要配置。降低 max_output_tokens 有助于控制成本、降低超长输出失败风险,但不会提升 provider 的输入上限,也不能替代 limit.input

max_output_tokens: 64000

stream_retry_rounds 用来给公开 LLM 流式请求的“整轮重试”设置硬上限。 每一轮里仍会按正常顺序遍历当前模型池和 provider key;这个设置限制的是 CompleteStream 最多做多少轮完整重试。

这里的“一轮”指的是整个公开重试回合,而不是单次 provider/model 尝试。比如 stream_retry_rounds: 2 表示最多允许两次完整的路由遍历;一旦达到上限,即使是 all-keys-cooling、并发 429,或非官方兼容网关返回的可重试 HTTP 400 这类通常会等待后继续的错误,也会直接停止。

Provider HTTP 400 的处理是有意保守的:

  • 官方 API 会把 400 视为终态 invalid-request 错误;

  • 非官方兼容网关有时会把并发限制、上游容量不足等临时状态映射成 400。这类非请求形态的 400 会冷却当前 key、轮换到下一个 key,并在所有 key 都冷却时等待后继续;

  • 请求参数/模型不兼容类 400 仍会停止,避免无限重试,例如结构化 code/typeinvalid_request_errorinvalid_requestmissing_required_parameter,或仅消息文本包含 missing required parameterStore must be set to falseStream must be set to true

  • 0 保持默认行为:一直重试,直到成功、被取消,或遇到终态失败;

  • 正整数表示最多重试这么多轮,即使是 cooling / 并发 429 这类通常会继续等待的错误,也会在达到上限后停止;

  • 这个选项更适合自动化或 headless 场景:用可预测时延换取更明确的退出边界。

stream_retry_rounds: 3

以下选项影响本地 TUI,可写在全局配置中,也可由项目级 .chord/config.yaml 覆盖。

desktop_notification: true
desktop_notification_foreground: true
ime_switch_target: com.apple.keylayout.ABC
prevent_sleep: true
  • desktop_notification:启用本地 TUI 的终端通知。Chord 会按终端自动选择通知转义序列(OSC 9 或 OSC 777),并在权限确认、等待回答、agent 回到 idle 时发送通知;是否发出提示音由终端决定。
  • desktop_notification_foreground:控制 TUI 聚焦时是否发送通知,默认值为 true;设为 false 后仅在终端失焦时通知。
  • ime_switch_target:进入 Normal 模式时通过 im-select(Windows 为 im-select.exe)切换到指定输入法,回到 Insert 模式时恢复。常用于让快捷键在英文键盘布局下工作。
  • prevent_sleep:任意 agent 活跃时阻止 macOS 空闲睡眠,仅本地 TUI 模式生效。

web_fetch 默认使用类似浏览器的 User-Agent。某些站点需要不同请求头时,可在配置中覆盖:

web_fetch:
user_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36

该配置同时支持全局和项目级,项目级优先。

也可为 WebFetch 请求单独配置代理:

web_fetch:
proxy: socks5://127.0.0.1:1080 # 支持 http, https, socks5
  • proxy: nil(默认)—— 继承全局 proxy 配置
  • proxy: ""(空字符串)—— 显式直连(不走代理)
  • proxy: "http://...""https://...""socks5://..." —— 使用指定代理

web_fetch 保持轻量级静态 HTTP 读取,不运行本地浏览器。对 JS-heavy 页面,若返回的 HTML 只有应用空壳而非可读正文,结果会标记为 Content-Quality: suspect-shell

顶层 orchestration 配置用于限制单个 Chord 进程内 MainAgent/SubAgent 工作流占用的资源。它不授予工具权限,也不改变 delegation.max_children 等单个 Agent 委派限制;它控制已准入 runtime 和 LLM 请求的并发量、SubAgent 输入队列容量,以及 mailbox 在内存中的保留量。

大多数用户应保留内置默认值。只有当 provider 有严格并发配额、运行主机内存有限,或编排指标显示持续排队/拒绝时,才建议调整。

orchestration:
max_live_runtimes: 10
max_borrowed_runtimes: 1
max_active_llm_requests: 10
provider_max_active_requests:
openai: 6
anthropic: 4
model_max_active_requests:
openai/gpt-5.5: 3
subagent_queue_messages: 256
subagent_queue_bytes: 4194304 # 4 MiB
mailbox_memory_messages: 512
mailbox_memory_bytes: 8388608 # 8 MiB
subagent_compact_usage: 0.8
字段 默认值 说明
max_live_runtimes 10 正常准入的 Agent runtime 最大数量。达到上限后,后续普通 runtime 获取会等待已有槽位释放。这是进程内软上限:唤醒重激活可使用有界 borrowed pool;仅当两个池都耗尽时,才使用不计数的紧急 bypass,避免 event loop 死锁。
max_borrowed_runtimes 1 为必须继续推进的编排工作临时增加的 runtime 准入量,例如子 Agent 事件到达后恢复父 Agent。借用额度单独设限;紧急 bypass 可通过编排统计中的 RuntimeBypassActive / RuntimeBypassPeak 观察。
max_active_llm_requests 10 进程内所有编排 Agent 的 LLM 请求总并发上限。达到上限后,符合条件的请求等待。
provider_max_active_requests 可选的 provider 级请求并发上限,key 如 openai。请求必须同时满足该限制和进程总限制。
model_max_active_requests 可选的 provider/model 级请求并发上限。匹配时忽略 @high 等 inline variant,因此 openai/gpt-5.5 覆盖该模型的所有 variant。
subagent_queue_messages 256 每个 SubAgent 的待处理输入消息上限。消息数或字节数任一达到上限时,新的入队会被拒绝,已排队消息不会被丢弃。
subagent_queue_bytes 4194304 每个 SubAgent 待处理输入的估算字节数上限。这是内存准入限制,不会溢写到磁盘 spool。
mailbox_memory_messages 512 MainAgent inbox 和按 owner 分类的 mailbox 在内存中保留的 SubAgent 消息总数上限。
mailbox_memory_bytes 8388608 上述内存 mailbox 的估算总字节数上限。超过内存预算的持久化非 progress 消息会通过磁盘 mailbox spool 引用;progress 更新可能在内存中合并或省略。
subagent_compact_usage 0.8 当 SubAgent 的估算上下文用量达到可用输入预算的这一比例时,主动压缩其上下文。默认值与 context.compaction.threshold 一致;之所以保留单独配置,是因为 SubAgent 使用本地 token 估算和轻量滑动窗口 checkpoint,而不是 MainAgent 的 usage 驱动压缩管线。有效值必须严格大于 0 且小于 1
  • 这些设置既可写在全局配置,也可写在项目 .chord/config.yaml 中。项目配置中的正数标量会覆盖对应的全局值。
  • provider_max_active_requestsmodel_max_active_requests 按 key 合并:项目配置替换同名全局条目,同时保留其他全局条目。
  • 标量为零或负数不表示“无限制”,而是保留继承值或内置默认值。subagent_compact_usage 只有严格位于 (0, 1) 时才有效,否则回退到 0.8;与 context.compaction.threshold: 0 不同,零不会关闭 SubAgent 上下文保护。
  • provider/model map 中只有正数限制会生效。建议使用明确的 key 和正整数,不要把零当作通用的“无限制”开关。
  • 所有限制只在单个进程内生效,不会协调多个 Chord 进程之间的配额。
  • 为满足 API 配额,优先设置 provider 或 model 限制,并将 max_active_llm_requests 保留为整体安全上限。
  • 在内存有限的主机上,逐步降低 mailbox 消息数/字节数限制。overflow 使用持久化存储,因此更低的内存限制会以更多磁盘 I/O 为代价。
  • 只有当消息生产方能够处理入队拒绝时,才降低 SubAgent 队列限制。这些队列不会溢写到磁盘,限制过小可能中断父子 Agent 协作。
  • max_borrowed_runtimes 应保持较小的正数。借用槽位用于解除编排推进停滞,不用于提高普通吞吐量。
  • 降低 subagent_compact_usage 可减少上下文溢出风险,但会更早、更频繁地压缩;提高它可减少压缩开销,但会缩小恢复余量。
  • 提高并发不一定更快:provider 限流、模型延迟、本地内存压力和 workspace lease 竞争都可能降低实际吞吐。应依据排队/拒绝指标和端到端延迟调参,而不是只看 CPU 数量。

MCP server 可能暴露大量工具。通过 allowed_tools 只允许部分远端工具进入 Chord,避免把不必要的 tool schema 发送给模型:

mcp:
search:
url: https://mcp.exa.ai/mcp
allowed_tools:
- web_search_exa
- web_fetch_exa

被过滤的工具不会注册,也不会进入 LLM 工具列表。上例中 search 是用户自定义的 MCP server 名;Chord 只会注册 mcp_search_web_search_examcp_search_web_fetch_exa

默认情况下,已配置的 MCP server 会自动启动,并成为默认 LLM 工具上下文的一部分。对于不是每轮对话都需要的 MCP,可设置 manual: true:启动时保持禁用,平时不连接该 server,也不把它的工具描述加入默认上下文,从而降低上下文开销;需要用到时再手动启用。

mcp:
exa:
url: https://mcp.exa.ai/mcp
manual: true
  • manual: true 时,启动后该 server 处于禁用(灰色)状态,不会主动连接。
  • 只有配置了 manual: true 的 server 才能在运行时通过 /mcp 修改状态。自动启动的 server 在 MCP 选择器中是只读的,也不会受 /mcp enable|disable 影响。
  • 运行时可用 /mcp(TUI 菜单)或带参数命令启用/禁用:
    • /mcp enable <server>
    • /mcp disable <server>
    • /mcp status
  • Agent 运行中也可以执行 /mcp enable|disable。当前正在进行的请求继续使用它启动时的工具表面;新的 MCP 工具和 MCP system-prompt block 会在下一次 LLM 请求(包括自动重试 / 恢复请求)时应用。
  • 在 Codex loop 模式下,如果任一受跟踪的 Codex 额度窗口剩余不到 10%,Chord 会保留现有的 LLM 可见上下文表面,不重写工具描述或 system prompt。运行时权限与 MCP 工具执行状态仍会变化,但模型继续看到之前的工具列表 / prompt,以便低额度 loop 能在同一个 Codex 会话上继续推进,避免因为上下文形态变化而无法续用。 这是有意的取舍。在额度恢复或构建新的会话 / 上下文表面之前,模型看到的状态可能会短暂不同于运行时状态:新启用的 MCP 工具可能不会被模型发现;已禁用的 MCP 工具可能仍看起来可调用,但执行时失败;权限从 deny / ask 改为 allow 时,prompt / 工具描述中可能仍未体现;权限从 allow 改为 deny / ask 时,模型可能以为可以调用,但实际调用时会被拦截。Chord 接受这种短期不一致,以避免 Codex loop 在额度窗口末尾因上下文形态变化而耗尽或无法继续复用当前会话。

自动启动的 MCP server 仍会在 TUI 启动后异步连接,但 第一次 LLM 请求会等待:每个自动启动的 server 要么连接成功,要么明确失败后才会继续发起请求,以避免工具描述不一致。

内置角色包括 builderplanner。可新增自定义 agent 或覆盖内置 agent。Agent 文件可放在:

  • ~/.config/chord/agents/
  • .chord/agents/

支持的文件格式:

  • .md:YAML frontmatter 加 Markdown 正文,正文作为 system prompt。
  • .yaml / .yml:普通 YAML 文档,通过 promptsystem_prompt 配置 system prompt。

Markdown agent 示例:

---
name: backend-coder
description: Backend developer
mode: subagent
permission:
write: ask
edit: ask
---
你是一个专注于后端开发的 Agent。

等价的 YAML agent 示例:

name: backend-coder
description: Backend developer
mode: subagent
permission:
write: ask
edit: ask
prompt: |
你是一个专注于后端开发的 Agent。

常用字段:

  • name:agent 名称。省略时使用不带扩展名的文件名;显式填写时,必须与不带扩展名的文件名一致(例如 builder.yaml 必须声明 name: builder)。同一目录内不能存在重名 agent,包括 .md.yaml.yml 之间的重名;项目级 agent 仍可按既有设计覆盖同名的全局 agent。
  • description:简短描述,在可委派给该 agent 时展示给 main agent。
  • modemain 表示 MainAgent 角色,subagent 表示 SubAgent。为空或其他值时按 main 处理;sub_agentsub 也可作为 SubAgent 别名。
  • model_pools:可选的有序池名列表,用于限制该 agent 可使用的池。池定义位于 config.yaml 顶层 model_pools;省略时,该 agent 可使用所有顶层池并按池名排序。openai/gpt-5.5@high 这类 inline variant 写在池定义中。
  • variant:model ref 未写 @variant 时的默认 variant。
  • permission:该 agent 的逐工具权限策略。权限直接保存在 agent 配置文件中;确认弹窗里选择“记住规则”时,project 会更新当前项目的 .chord/agents/<role>.yamlglobal 会更新用户配置目录的 agents/<role>.yaml(默认 ~/.config/chord/agents/<role>.yaml),不会写入单独的 permissions 文件夹。部分编排工具有特殊语义(delegate 的 pattern 会匹配 agent_type,并联动控制委派工作相关能力,如 cancelhandoffdoneallow / ask 都表示工作流可用,并由 Chord 自己的确认 gate 控制关键节点)。依赖精细控制工具规则前,请先阅读权限与安全
  • mcp:作用域限定在该 agent 的增量、自动启动 MCP 配置。Agent MCP 不能与最终生效的全局/项目 mcp server 重名,否则启动时报错;也不能设置 manual: true,因为运行时 MCP 控制只管理顶层 server,如需手动启停请改在项目/全局配置中声明。要继承顶层 server,请删除 agent 中的重复项;要使用独立私有 server,请改名;要为整个项目替换顶层 server,请在 .chord/config.yaml 中覆盖。不同 agent 可以使用相同的私有 server 名称而互不共享连接,同一 agent 定义的多个实例则会复用连接。
  • delegation:如 max_childrenmax_depthchild_join 等委派限制。
  • prompt / system_prompt:纯 YAML agent 文件中的 system prompt。

示例:

name: builder
mode: main
model_pools: [default]
permission:
"*": deny
read: allow
view_image: allow
grep: allow
glob: allow
web_fetch:
"localhost:8000": ask
shell: allow
edit: ask
write: ask

长会话的上下文处理——上下文压缩(Compaction)(调用 LLM 生成摘要并改写会话历史)和上下文剪裁(Reduction)(请求前裁剪过时工具输出)——通过顶层 context: 配置,详见独立页面:上下文管理

editapply_patchwrite 修改文件后,Chord 可以把语言诊断追加到工具结果里,让模型立刻看到编译或 lint 问题。这由 diagnostics 配置控制,默认对 Python 启用(LSP 语义后端 + Ruff quick 回退)。设 diagnostics.enabled: false 可整体关闭这条流水线。

Chord 的原生文件工具会在同步 textDocument 前向匹配的 LSP 服务发送 workspace/didChangeWatchedFiles 文件事件:write 新建文件发送 Created,覆盖已有文件和 edit / apply_patch 发送 Changed,delete 成功删除文件发送 Deleted。这让 Pyright、TypeScript、gopls、rust-analyzer 等服务更容易及时刷新项目图,减少“新建模块已存在但 import 仍报 unresolved”的暂态误报。诊断仍会在文件工具结果中即时返回,便于模型判断问题是否由本次改动引入;但通过 shell 或外部程序创建/删除的文件目前不会由 Chord 的原生文件工具自动上报为文件系统 watcher 事件。

Python 使用两个后端:

  • diagnostics.python.semantic_backend —— 主 LSP 服务(默认 pyright)。其 server 字段必须与 lsp 下的某个 server key 一致,语言服务器才真正配置生效。
  • diagnostics.python.quick_backend —— 一次性回退命令(默认 ruff check),用于大文件,或语义后端不可用时。

diagnostics.python.large_file.{line_threshold, byte_threshold, strategy} 决定文件多大时改用 quick backend 而非语义后端;run_semantic_when_quick_unavailable: true 会在 quick backend 缺失时,对大文件也强制跑语义后端。Ruff quick diagnostics 不更新 LSP 侧边栏——只出现在 editapply_patchwrite 结果中,并提示完整语义诊断已跳过。

推荐 Python 配置骨架:

lsp:
pyright:
command: pyright-langserver
args: ["--stdio"]
file_types: [".py", ".pyi"]
diagnostics:
python:
semantic_backend:
server: pyright
quick_backend:
type: command
command: ruff

diagnostics.python.output.{max_near_diagnostics, max_outside_diagnostics, max_total_diagnostics, near_range_before_lines, near_range_after_lines} 控制追加诊断文本的长度,并按错误/警告优先于 info/hint 的顺序展示。完整字段表见配置字段速查表

Terminal window
# 用代表模型冒烟测试所有 provider
chord doctor models
# 测试单个 provider 的代表模型
chord doctor models --provider openai
# 测试精确模型或 variant
chord doctor models --model openai/gpt-5.5@high
chord doctor models --provider openai --model gpt-5.5@high
# 独立审计模型池中的每个条目
chord doctor models --pool thinking

该命令适合做认证、endpoint、transport、模型存在性以及 variant tuning 的冒烟测试。它读取的配置视图与正常运行时一致:会先加载全局配置,再叠加项目级 provider / proxy / model 覆盖。Pool 诊断会逐项独立请求,不走正常 fallback 链。

下面是 config.yaml 的全部顶层 key(同时适用于全局 ~/.config/chord/config.yaml 和项目级 .chord/config.yaml)。除特别注明外,所有 key 均可选。

Key 类型 默认值 适用层级 简述
providers map[name]Provider global / project 各 provider 的配置(typeapi_urlpresetkey_rotationkey_ordermodelscompress)。见 最小 provider 配置
model_templates map[name]YAML global / project 仅用于 YAML anchor 命名空间;条目可通过 alias 复用,不会直接作为运行时模型定义。
model_pools map[name][]ref global / project 可复用的命名模型池,元素为完整 provider/model[@variant] ref。见 模型池
thinking_translation object 关闭(max_chars: 1000 global / project 可选的 thinking / reasoning 卡片附加翻译预览。需要 target_languagemodel_pool;失败只跳过受影响的 thinking block。
context object 见下文 global / project compaction(上下文压缩)和 reduction(上下文剪裁)两项配置。见上下文管理
diagnostics object 启用(Python LSP + Ruff 回退) global / project editapply_patchwrite 完成后追加的诊断信息。diagnostics.python.semantic_backend 是主 LSP 服务(默认 pyright);diagnostics.python.quick_backend 是一次性回退命令(默认 ruff check)。diagnostics.python.large_file.{line_threshold, byte_threshold, strategy} 决定大文件何时走 quick backend;run_semantic_when_quick_unavailable: true 在 quick backend 不可用时仍强制跑语义诊断。diagnostics.python.output.{max_near_diagnostics, max_outside_diagnostics, max_total_diagnostics, near_range_before_lines, near_range_after_lines} 控制追加文本的长度和裁剪窗口。诊断按严重级别优先展示(错误/警告优先,仍有名额时再显示 info/hint)。设 diagnostics.enabled: false 可整体关闭。
skills object global / project paths: [...] —— 在默认目录外追加 skill 目录。
confirm_timeout int(秒) 0(不超时) global / project TUI 确认浮层超时;0 表示永远等。
diff object {inline_max_columns: 200} global / project TUI diff 渲染。inline_max_columns 限制单行 inline diff 宽度。
desktop_notification bool false global / project 启用本地 TUI 终端通知;Chord 会按终端自动选择 OSC 9 或 OSC 777(不支持的终端通常会忽略该序列)。
desktop_notification_foreground bool true global / project TUI 聚焦时是否发送本地终端通知;设为 false 后仅在终端失焦时通知。
prevent_sleep bool false global / project agent 活动时阻止 macOS idle sleep。仅 macOS 生效,其他平台 no-op。
keymap map[action][]key 快捷键 — Action 名速查 global / project 覆盖键位绑定。Action 名采用 lower snake_case。
commands map[/cmd]text global / project 自定义 slash 命令;"/cmd" → 作为用户消息发送的文本。见 扩展与定制 — 自定义 slash 命令
ime_switch_target string global / project 进 Normal 模式时传给 im-select / im-select.exe 的 IM 标识。
log_level string info global / project debug / info / warn / errordebug 输出较多。
paths object XDG 默认值 仅 global state_dircache_dirsessions_dirlogs_dir。会被 CLI flag 与 CHORD_* 环境变量覆盖。
maintenance object 关闭 仅 global size_check_on_startupwarn_state_byteswarn_cache_bytes
lsp map[name]Server global / project 各 language server 的配置。见 扩展与定制 — LSP
mcp map[name]MCP global / project / agent 各 MCP 服务器的配置。见 MCP
hooks object global / project / agent 按触发点分组的 hooks。见 Hooks
max_output_tokens int 64000 global / project 全局输出 token 上限。实际请求还会受各模型 limit.output 限制;reasoning 请求同样遵守该上限。
stream_retry_rounds int 0(重试直到成功/取消) global / project 公开 LLM 流式请求的整轮重试硬上限。0 表示一直重试,直到成功、取消或终态失败。
proxy string 空(用环境变量或直连) global / project 全局代理 URL。可通过 web_fetch.proxy 单独覆盖。
web_fetch object global / project user_agentproxy(nil 继承全局;空字符串 = 显式直连)。见 WebFetch
worktree object global / project chord --worktreechord worktree … 子命令的默认值。

Chord 会把当前 Chord session id 自动传给 OpenAI 系 provider,作为缓存 / 路由亲和元数据:OpenAI Responses 请求会包含 prompt_cache_key,OpenAI Chat Completions / Responses HTTP 请求会在有 session id 时包含 X-Session-Idsession-id header。这些字段不能手动配置,会随当前 Chord session 自动切换 / 恢复。Anthropic prompt caching 由 cache_control block 驱动;Chord 还会自动发送 JSON 格式的 metadata.user_id,其中包含稳定匿名的 device_id,以及由本地 / provider 身份派生出的稳定路由 session_id。这些 Anthropic metadata 字段不能手动配置。在 explicit 模式(Anthropic 模型默认)下,Chord 按优先级放置最多 4 个 cache_control 断点:最后一个 system block、冻结的已剪裁前缀边界(当渐进式剪裁已冻结稳定前缀时)、最新的持久化消息、最后一条 assistant 消息——使长 agent loop 能复用冻结的历史前缀,而不是每轮重新写入移动的尾部。最新断点会刻意跳过 request-scoped overlay(追加在对话尾部的运行时提示),因为这些内容在下一次请求中就不存在了,写在它们之后的缓存条目永远不可能被读回。

对于 Anthropic 模型,prompt_cache.ttl 接受 5m(省略时的默认值)和 1h,且在 autoexplicit 两种模式下都会应用到 Chord 放置的每一个断点:

providers:
anthropic:
models:
claude-sonnet-4-5:
prompt_cache:
ttl: 1h

Gemini 在 Chord 当前的 generateContent transport 中没有简单的逐请求 session-id cache key;它的缓存信号来自 provider 专用 cached-content API / usage 字段,而不是 Chord session id header。

字段 类型 说明
type string messages / chat-completions / responses / generate-content。省略时按 api_urlpreset 自动推断。
api_url string 接口地址。Chord 根据 URL path 自动识别 provider type,忽略 query string 和 fragment。Gemini 用 /models 基础路径,Chord 自动附加 /{model}:streamGenerateContent?alt=sse。Azure Responses 的 ?api-version=... 是可选项,可用于固定特定 API 版本。
preset string 可选 codex(OpenAI Codex / ChatGPT OAuth)或 azure(Azure OpenAI Responses,使用 api-key 认证)。
official_api bool 将该 endpoint 视为官方 provider API;HTTP 400 通常表示请求无效,不应按临时网关错误重试。preset: codexpreset: azure 默认按官方 API 处理;聚合或代理网关可省略或设为 false
key_rotation string on_failure(默认)/ per_request。控制何时重新选择 credential / API key。
key_order string sequential(非 Codex 默认)/ random / smart(仅 Codex)。控制在候选 key 中如何选择。
compress bool gzip 能减小体积时启用请求体压缩。默认关闭。
response_header_timeout int 从开始该 provider 的流式 HTTP 请求到收到响应头的超时,单位秒,包括连接建立与请求体上传。0 / 省略表示使用内置默认值;健康流由 stream_idle_timeout 约束,而不是总请求计时器。
stream_idle_timeout int 该 provider 的流式空闲超时,单位秒。0 / 省略表示使用内置 SSE/WebSocket idle 默认值。
websocket_handshake_timeout int Responses WebSocket 握手超时,单位秒。0 / 省略表示使用内置默认值。
parallel_tool_calls bool true — provider 级 Responses / Chat Completions 工具并行默认值;模型和变体配置会覆盖它。
compat.responses.* object 协议默认值 — provider 级 Responses 可选字段开关:send_storesend_reasoning_includesend_tool_choicesend_prompt_cache_keysend_max_output_tokens
compat.chat_completions.send_stream_options bool true — 对拒绝 stream_options 的网关设为 false;此时流式 token usage 不再可用。
compat.usage.input_includes_cache_read bool 协议默认值 — 覆盖 provider 顶层 input 是否已包含 cache read。默认:Messages 为 false;Chat Completions / Responses / Generate Content 为 true
compat.usage.input_includes_cache_write bool 协议默认值 — 覆盖 provider 顶层 input 是否已包含 cache write/cache creation。默认:Chat Completions / Responses 为 true;Messages / Generate Content 为 false
models map model id → 模型配置
字段 类型 说明
limit.context int 已知时表示总请求窗口上限;未配置 limit.input 时,Chord 会从中扣除有效请求输出后推导输入预算。
limit.input int provider 单独公布输入上限时填写。Chord 用它判断何时在 prompt 过大前压缩或恢复重试。
limit.output int 输出 token 上限;运行时还会受 max_output_tokens 限制。
context.compaction.reserved int 可选的输入预算预留值。在应用 compaction.threshold 前先扣除,适合为 tokenizer 误差、tool 开销和恢复安全余量留空间。
reasoning object OpenAI reasoning 选项。reasoning.effort 会先归一化再原样透传,因此 provider 支持的任意取值(如 GLM 的 max / minimal / none)都能不变地到达上游(留空 = 不发送,使用 provider/model 默认)。Responses 的 reasoning.summary 支持 auto / concise / detailed / none;启用 reasoning 时留空默认使用 auto,配置 none 可明确关闭。
text.verbosity string 可选的 OpenAI 文本详细程度提示,支持的模型生效;除非明确要覆盖为 low / medium / high,否则建议留空使用 provider/model 默认值。
thinking object Anthropic 扩展思考选项。type: adaptive 让 Chord 按 effort 推算预算;thinking.effort 在 Messages 请求中会生成 output_config.effortdisplay: summarized 启用 summarized thinking block(仅 type: enabledadaptive 有效)。
compat.reasoning_continuity.mode string 可选的连续性覆盖项。Chat Completions 模型需要原样回放 assistant reasoning_content,并把其他 wire 的可移植可见 reasoning 转为 reasoning_content 时使用 openai_visible;只有已验证的 Messages 兼容模型需要回放或接收可见无签名 thinking 时使用 anthropic_unsigned;模型级 none 可关闭 provider 级默认值。
compat.request_overrides.body object Chord 构造完协议请求后应用的递归 JSON patch。null 删除字段。
compat.request_overrides.rename_body_fields map 重命名最终 JSON 字段,同时保留 Chord 动态计算的值。目标值为 null 时删除源字段。
compat.request_overrides.headers map 设置最终请求 header。值为 null 时删除该 header。
variants map 命名参数预设。引用方式:provider/model@variant
modalities.input array text / image / pdf 的子集。默认仅 [text];支持时需显式声明 image / pdf
supported_service_tiers 列表 provider-level 默认值或 model-level 覆盖值,用于声明可接收的非 standard tier,例如 [fast, slow][fast]。省略时使用 preset 默认值。

服务层和 prompt cache 是 provider-specific 的:OpenAI 支持 priority/flex 风格的 tiering 以及 prompt_cache_key / prompt_cache_retention;Anthropic 支持 cache_control,并提供 5 分钟和 1 小时 TTL;Gemini 则使用它自己的路由 / thinking / cached-content 机制。Chord 会把用户侧的 tier 映射到当前 provider 能支持的最接近行为,而不是强行统一成同一种 wire 格式。

若兼容网关的 usage 字段与它声明的协议不同,应显式配置语义。例如某个 Responses 兼容网关把普通 input、cache read、cache write 三个桶分开返回:

compat:
usage:
input_includes_cache_read: false
input_includes_cache_write: false

OpenAI 的 reasoning item 还可能通过 reasoning.encrypted_content 返回,用于无状态续传。这个字段是加密后的续传载荷,不适合直接在 UI 里展示;如果有可读摘要,应优先展示摘要而不是 encrypted payload。