spec.md 6.9 KB

ADDED Requirements

Requirement: 配置文件定位与初始化

工具 SHALL 按如下优先级解析配置文件路径:$CC_SWITCH_CONFIG > $XDG_CONFIG_HOME/cc-switch/config.yaml > ~/.config/cc-switch/config.yaml。若目标文件不存在,SHALL 在首次需要写入时创建父目录(权限 0700)与空骨架文件(权限 0600)。读操作遇文件不存在 MUST 返回"空配置"而非错误。

Scenario: 默认路径首次读

  • WHEN 用户未设置 CC_SWITCH_CONFIGXDG_CONFIG_HOME,也从未运行过 cc-switch
  • THEN cc-switch list 成功执行,输出 "(no providers configured)" 提示,且不在磁盘创建任何文件

Scenario: 默认路径首次写

  • WHEN 用户执行 cc-switch add foo ... 且配置文件从未被创建
  • THEN 工具创建 ~/.config/cc-switch/(权限 0700)与 config.yaml(权限 0600),并写入新增 provider

Scenario: XDG 路径覆盖

  • WHEN 环境变量 XDG_CONFIG_HOME=/tmp/xdg 已设置
  • THEN 工具使用 /tmp/xdg/cc-switch/config.yaml 作为配置文件路径

Scenario: 显式路径覆盖

  • WHEN 环境变量 CC_SWITCH_CONFIG=/custom/path.yaml 已设置
  • THEN 无论 XDG 如何设置,工具均使用 /custom/path.yaml

Scenario: 宽松权限 warning

  • WHEN 配置文件存在且权限为 0644
  • THEN 工具继续执行命令,并向 stderr 打印一条 warning 提示权限过宽、建议 chmod 600

Requirement: 配置 schema

配置文件 SHALL 使用 YAML 编码,顶层字段包括:claude_path(string,可选)、default_provider(string,可选)、providers(map,key 为 provider 名)。每个 provider SHALL 包含 env(map[string]string,必填且至少一个键)与可选 description(string)。Provider 名 SHALL 为非空且仅含字母、数字、-_

Scenario: 合法配置解析

  • WHEN 配置文件内容合法,包含两个 provider 及 default_provider: foo
  • THEN 工具解析成功并在后续命令中识别这两个 provider

Scenario: 非法 provider 名

  • WHEN 配置文件中 provider 名包含空格或非法字符
  • THEN 工具返回非零退出码并指出哪一个 provider 名不合法

Scenario: 空 env map

  • WHEN 某个 provider 的 env 字段为空 map
  • THEN 工具返回非零退出码并提示该 provider 至少需要一个环境变量

Requirement: Env 值的间接引用语法

Provider 的 env map 中,value 为字符串类型;若 value 严格匹配正则 ^env:[A-Za-z_][A-Za-z0-9_]*$,SHALL 被识别为"间接引用",表示"启动时从父进程环境中读取名为 VAR_NAME 的变量的值作为实际 value"。所有其他 value MUST 被视为字面字符串,不做任何展开。引用仅在"启动阶段"解析(见 provider-launch spec),在 list -v / config show / config get 等展示命令中,引用 value 按原字符串展示(不脱敏、不展开),让用户一眼识别"这一项是指针"。

Scenario: 字面 value 保留

  • WHEN provider 的 env.FOO 值为 hello
  • THEN 工具视为字面 hellolist -v 显示脱敏后的 he*** 或等价样式

Scenario: env 引用被识别

  • WHEN provider 的 env.ANTHROPIC_API_KEY 值为 env:MY_ANTHROPIC_KEY
  • THEN 工具视为对父环境变量 MY_ANTHROPIC_KEY 的引用;list -v 显示 env:MY_ANTHROPIC_KEY(按原字符串,不脱敏、不解析)

Scenario: 非法引用形式回退为字面

  • WHEN provider 的 env.FOO 值为 env:env:1NAME(不符合正则)
  • THEN 工具视为普通字面字符串,不报错也不解析

Requirement: 原子写入

工具修改配置文件时 SHALL 采用"写临时文件 → fsync → 重命名"模式;MUST 不允许部分写入后崩溃导致的文件损坏。

Scenario: 写入中途崩溃

  • WHENcc-switch add 写入 config.yaml 过程中进程被强制终止
  • THEN config.yaml 要么保留原内容、要么是完整的新内容,不会出现截断或空文件

Requirement: Provider 增删改查

工具 SHALL 支持以下 provider 管理操作:

  • add:新增 provider,禁止与已有同名冲突
  • list:列出所有 provider,标记 default,可选 -v 显示 env 键名(value 脱敏)
  • edit:修改已有 provider 的 env 或 description
  • remove:按名称删除 provider;若删除的是当前 default_providerdefault_provider 字段 SHALL 被一并清空
  • use-default 支持(见 provider-launch 与 cli 能力)

所有写操作 SHALL 在修改成功后原子落盘。

Scenario: 新增 provider

  • WHEN 用户执行 cc-switch add official --env ANTHROPIC_API_KEY=sk-xxx --env ANTHROPIC_BASE_URL=https://api.anthropic.com
  • THEN providers.official.env 写入两个键,cc-switch list 能列出 official

Scenario: 重名 add

  • WHEN 已存在名为 official 的 provider,用户再次 cc-switch add official ...
  • THEN 工具返回非零退出码并提示使用 edit 或换一个名字

Scenario: list 脱敏

  • WHEN 用户执行 cc-switch list -v
  • THEN 输出中对每个 env 值展示为 *** 或前 4 位 + ***,不打印完整 value

Scenario: 删除默认 provider

  • WHEN 当前 default_provider=foo,用户执行 cc-switch remove foo
  • THEN foo 被删除,default_provider 被置空,cc-switch list 不再展示 default 标记

Scenario: 删除不存在 provider

  • WHEN 用户执行 cc-switch remove nonexistent
  • THEN 工具返回非零退出码并提示 provider 不存在

Requirement: 全局 claude 可执行文件路径

工具 SHALL 支持通过 cc-switch config set claude-path <path> 命令设置 claude_path;支持 ~ 展开;SHALL 在设置时校验路径存在且可执行,不通过则拒绝写入。未设置时后续启动流程回落到 exec.LookPath("claude")

Scenario: 设置有效路径

  • WHEN 用户执行 cc-switch config set claude-path ~/.claude/local/claude 且该文件存在且可执行
  • THEN claude_path 被写入展开后的绝对路径

Scenario: 设置无效路径

  • WHEN 用户执行 cc-switch config set claude-path /not/exist
  • THEN 工具返回非零退出码且不修改配置文件

Requirement: 默认 provider

工具 SHALL 支持通过 cc-switch config set default <name> 设置默认 provider,前提是该 provider 存在。cc-switch use 在未指定 <name> 且处于非 tty 环境时 SHALL 使用默认 provider;tty 下仍进入交互选择(默认值为 default_provider)。

Scenario: 设置默认

  • WHEN 用户已有 foo provider,执行 cc-switch config set default foo
  • THEN default_provider: foo 被写入配置

Scenario: 设置不存在 provider 为默认

  • WHEN 用户执行 cc-switch config set default barbar 不存在
  • THEN 工具返回非零退出码且不修改配置