Final rebrand: rename remaining Rust source file to complete the gsd → forge transition. All parser references already use forge_parser after earlier commits. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
852 lines
30 KiB
Markdown
852 lines
30 KiB
Markdown
# 配置
|
||
|
||
SF 偏好设置保存在 `~/.sf/PREFERENCES.md`(全局)或 `.sf/PREFERENCES.md`(项目级)中。可以通过 `/sf prefs` 进行交互式管理。
|
||
|
||
## `/sf prefs` 命令
|
||
|
||
| 命令 | 说明 |
|
||
|------|------|
|
||
| `/sf prefs` | 打开全局偏好设置向导(默认) |
|
||
| `/sf prefs global` | 全局偏好设置交互向导(`~/.sf/PREFERENCES.md`) |
|
||
| `/sf prefs project` | 项目偏好设置交互向导(`.sf/PREFERENCES.md`) |
|
||
| `/sf prefs status` | 显示当前偏好文件、合并后的值以及 skill 解析状态 |
|
||
| `/sf prefs wizard` | `/sf prefs global` 的别名 |
|
||
| `/sf prefs setup` | `/sf prefs wizard` 的别名;若偏好文件不存在会自动创建 |
|
||
| `/sf prefs import-claude` | 将 Claude marketplace plugins 和 skills 以命名空间化的 SF 组件形式导入 |
|
||
| `/sf prefs import-claude global` | 导入到全局作用域 |
|
||
| `/sf prefs import-claude project` | 导入到项目作用域 |
|
||
|
||
## 偏好文件格式
|
||
|
||
偏好设置使用 markdown 文件中的 YAML frontmatter:
|
||
|
||
```yaml
|
||
---
|
||
version: 1
|
||
models:
|
||
research: claude-sonnet-4-6
|
||
planning: claude-opus-4-6
|
||
execution: claude-sonnet-4-6
|
||
completion: claude-sonnet-4-6
|
||
skill_discovery: suggest
|
||
auto_supervisor:
|
||
soft_timeout_minutes: 20
|
||
idle_timeout_minutes: 10
|
||
hard_timeout_minutes: 30
|
||
budget_ceiling: 50.00
|
||
token_profile: balanced
|
||
---
|
||
```
|
||
|
||
## 全局与项目偏好
|
||
|
||
| 作用域 | 路径 | 适用范围 |
|
||
|--------|------|----------|
|
||
| 全局 | `~/.sf/PREFERENCES.md` | 所有项目 |
|
||
| 项目 | `.sf/PREFERENCES.md` | 仅当前项目 |
|
||
|
||
**合并规则:**
|
||
|
||
- **标量字段**(`skill_discovery`、`budget_ceiling`):如果项目级定义了,则项目级优先
|
||
- **数组字段**(`always_use_skills` 等):拼接,顺序为全局在前、项目在后
|
||
- **对象字段**(`models`、`git`、`auto_supervisor`):浅合并,项目级按 key 覆盖
|
||
|
||
<a id="global-api-keys-sf-config"></a>
|
||
## 全局 API Keys(`/sf config`)
|
||
|
||
工具 API keys 会全局保存在 `~/.sf/agent/auth.json` 中,并自动应用到所有项目。只需用 `/sf config` 配置一次,无需在每个项目里维护 `.env`。
|
||
|
||
```bash
|
||
/sf config
|
||
```
|
||
|
||
这会打开一个交互式向导,显示哪些 key 已配置、哪些仍缺失。你可以选择一个工具并输入相应的 key。
|
||
|
||
### 支持的 keys
|
||
|
||
| 工具 | 环境变量 | 用途 | 获取地址 |
|
||
|------|----------|------|----------|
|
||
| Tavily Search | `TAVILY_API_KEY` | 为非 Anthropic models 提供 Web 搜索 | [tavily.com/app/api-keys](https://tavily.com/app/api-keys) |
|
||
| Brave Search | `BRAVE_API_KEY` | 为非 Anthropic models 提供 Web 搜索 | [brave.com/search/api](https://brave.com/search/api) |
|
||
| Context7 Docs | `CONTEXT7_API_KEY` | 库文档检索 | [context7.com/dashboard](https://context7.com/dashboard) |
|
||
|
||
### 工作方式
|
||
|
||
1. `/sf config` 会把 keys 保存到 `~/.sf/agent/auth.json`
|
||
2. 每次会话启动时,`loadToolApiKeys()` 都会读取该文件并设置环境变量
|
||
3. 这些 keys 对所有项目生效,无需单独配置
|
||
4. 环境变量(例如 `export BRAVE_API_KEY=...`)优先级高于保存下来的 keys
|
||
5. Anthropic models 不需要 Brave/Tavily,因为它们自带 Web 搜索
|
||
|
||
## MCP Servers
|
||
|
||
SF 可以连接配置在项目文件中的外部 MCP servers。这适合接入本地工具、内部 API、自托管服务,或者那些未作为 SF 原生扩展内置的集成。
|
||
|
||
### 配置文件位置
|
||
|
||
SF 会从以下项目本地路径读取 MCP client 配置:
|
||
|
||
- `.mcp.json`
|
||
- `.sf/mcp.json`
|
||
|
||
如果两个文件都存在,会按 server 名称做合并,先找到的定义优先。通常建议:
|
||
|
||
- 把你愿意提交到仓库的共享 MCP 配置放在 `.mcp.json`
|
||
- 把仅本机使用、不希望共享的 MCP 配置放在 `.sf/mcp.json`
|
||
|
||
### 支持的 transport
|
||
|
||
| Transport | 配置形状 | 适用场景 |
|
||
|-----------|----------|----------|
|
||
| `stdio` | `command` + 可选 `args`、`env`、`cwd` | 启动本地 MCP server 进程 |
|
||
| `http` | `url` | 连接到已经运行中的 MCP server |
|
||
|
||
### 示例:stdio server
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"my-server": {
|
||
"type": "stdio",
|
||
"command": "/absolute/path/to/python3",
|
||
"args": ["/absolute/path/to/server.py"],
|
||
"env": {
|
||
"API_URL": "http://localhost:8000"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 示例:HTTP server
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"my-http-server": {
|
||
"url": "http://localhost:8080/mcp"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 验证一个 server
|
||
|
||
添加配置后,可以在 SF 会话中这样验证:
|
||
|
||
```text
|
||
mcp_servers
|
||
mcp_discover(server="my-server")
|
||
mcp_call(server="my-server", tool="<tool_name>", args={...})
|
||
```
|
||
|
||
推荐验证顺序:
|
||
|
||
1. `mcp_servers`:确认 SF 能看到配置文件并正确解析 server 条目
|
||
2. `mcp_discover`:确认 server 进程能启动,并能响应 `tools/list`
|
||
3. `mcp_call`:确认至少有一个真实 tool 可以成功调用
|
||
|
||
### 说明
|
||
|
||
- 尽量为本地可执行文件和脚本使用绝对路径
|
||
- 对于 `stdio` servers,优先在 MCP 配置里显式设置需要的环境变量,而不是依赖交互式 shell profile
|
||
- SF 和 `sf-mcp-server` 都会自动加载保存在 `~/.sf/agent/auth.json` 中的 model / tool keys,因此 MCP 配置可以安全地通过 `${ENV_VAR}` 占位符引用这些值,而不必提交原始凭据
|
||
- 如果某个 server 是团队共享且适合提交到仓库,通常更适合放在 `.mcp.json`
|
||
- 如果某个 server 依赖本机路径、个人服务或本地 secrets,更适合放在 `.sf/mcp.json`
|
||
|
||
## 环境变量
|
||
|
||
| 变量 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `SF_HOME` | `~/.sf` | 全局 SF 目录。除非单独覆盖,否则其它路径都从这里派生。影响偏好、skills、sessions 以及项目状态。(v2.39) |
|
||
| `SF_PROJECT_ID` | (自动哈希) | 覆盖自动生成的项目身份哈希。这样项目状态会写入 `$SF_HOME/projects/<SF_PROJECT_ID>/`,而不是计算出的哈希目录。适用于 CI/CD 或多个克隆共享状态。(v2.39) |
|
||
| `SF_STATE_DIR` | `$SF_HOME` | 项目状态根目录。控制 `projects/<repo-hash>/` 的创建位置。对项目状态的优先级高于 `SF_HOME`。 |
|
||
| `SF_CODING_AGENT_DIR` | `$SF_HOME/agent` | agent 目录,包含托管资源、扩展和 auth。对 agent 相关路径的优先级高于 `SF_HOME`。 |
|
||
| `SF_ALLOWED_COMMAND_PREFIXES` | (内置列表) | 允许用于 `!command` 值解析的命令前缀,逗号分隔。会覆盖 settings.json 中的 `allowedCommandPrefixes`。见 [自定义模型:命令允许列表](custom-models.md#command-allowlist)。 |
|
||
| `SF_FETCH_ALLOWED_URLS` | (无) | 对 `fetch_page` URL block 免检的 hostnames,逗号分隔。会覆盖 settings.json 中的 `fetchAllowedUrls`。见 [URL Blocking](#url-blocking-fetch_page)。 |
|
||
|
||
## 全部设置
|
||
|
||
### `models`
|
||
|
||
按阶段选择 model。每个 key 都可以是一个 model 字符串,或者是带 fallbacks 的对象。
|
||
|
||
```yaml
|
||
models:
|
||
research: claude-sonnet-4-6
|
||
planning:
|
||
model: claude-opus-4-6
|
||
fallbacks:
|
||
- openrouter/z-ai/glm-5
|
||
execution: claude-sonnet-4-6
|
||
execution_simple: claude-haiku-4-5-20250414
|
||
completion: claude-sonnet-4-6
|
||
subagent: claude-sonnet-4-6
|
||
```
|
||
|
||
**阶段键:** `research`、`planning`、`execution`、`execution_simple`、`completion`、`subagent`
|
||
|
||
- `execution_simple`:用于被 [complexity router](./token-optimization.md#complexity-based-task-routing) 判断为 “simple” 的 task
|
||
- `subagent`:委派给 subagent 的 task 所使用的 model(scout、researcher、worker)
|
||
- 指定 provider:使用 `provider/model` 格式(例如 `bedrock/claude-sonnet-4-6`),或者在对象格式里额外写 `provider` 字段
|
||
- 省略某个 key 时,会使用当前 active model
|
||
|
||
### 自定义 Model 定义(`models.json`)
|
||
|
||
你可以在 `~/.sf/agent/models.json` 里定义自定义 models 和 providers。这允许你添加默认注册表里没有的 models,适合自托管 endpoints(Ollama、vLLM、LM Studio)、微调模型、代理,或者刚发布的新 provider。
|
||
|
||
SF 读取 `models.json` 的顺序如下:
|
||
|
||
1. `~/.sf/agent/models.json`:主位置(SF)
|
||
2. `~/.pi/agent/models.json`:回退位置(Pi)
|
||
3. 如果两者都不存在,则创建 `~/.sf/agent/models.json`
|
||
|
||
**本地 models(Ollama)的快速示例:**
|
||
|
||
```json
|
||
{
|
||
"providers": {
|
||
"ollama": {
|
||
"baseUrl": "http://localhost:11434/v1",
|
||
"api": "openai-completions",
|
||
"apiKey": "ollama",
|
||
"models": [
|
||
{ "id": "llama3.1:8b" },
|
||
{ "id": "qwen2.5-coder:7b" }
|
||
]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
每次打开 `/model` 时,这个文件都会重新加载,无需重启。
|
||
|
||
关于 provider 配置、model overrides、OpenAI compatibility 和更多高级示例,见 [自定义模型指南](./custom-models.md)。
|
||
|
||
**带 fallbacks 的示例:**
|
||
|
||
```yaml
|
||
models:
|
||
planning:
|
||
model: claude-opus-4-6
|
||
fallbacks:
|
||
- openrouter/z-ai/glm-5
|
||
- openrouter/moonshotai/kimi-k2.5
|
||
provider: bedrock # 可选:固定到某个 provider
|
||
```
|
||
|
||
当某个 model 切换失败(provider 不可用、被限流、额度耗尽)时,SF 会自动尝试 `fallbacks` 列表中的下一个 model。
|
||
|
||
### Community Provider Extensions
|
||
|
||
对于 SF 未内置的 providers,社区扩展可以添加完整 provider 支持,包括正确的 model 定义、thinking format 配置以及交互式 API key 设置。
|
||
|
||
| 扩展 | Provider | Models | 安装命令 |
|
||
|------|----------|--------|----------|
|
||
| [`pi-dashscope`](https://www.npmjs.com/package/pi-dashscope) | Alibaba DashScope(ModelStudio) | Qwen3、GLM-5、MiniMax M2.5、Kimi K2.5 | `sf install npm:pi-dashscope` |
|
||
|
||
对于 DashScope models,更推荐使用社区扩展而不是内置的 `alibaba-coding-plan` provider,因为前者会走正确的 OpenAI-compatible endpoint,并包含适配 thinking mode 的 per-model compatibility flags。
|
||
|
||
### `token_profile`
|
||
|
||
负责协调 model 选择、阶段跳过和上下文压缩。详见 [Token 优化](./token-optimization.md)。
|
||
|
||
可选值:`budget`、`balanced`(默认)、`quality`
|
||
|
||
| 配置 | 行为 |
|
||
|------|------|
|
||
| `budget` | 跳过 research + reassessment 阶段,优先使用便宜模型 |
|
||
| `balanced` | 默认行为:所有阶段运行,使用标准模型选择 |
|
||
| `quality` | 所有阶段运行,优先更高质量模型 |
|
||
|
||
### `phases`
|
||
|
||
对自动模式中哪些阶段运行做细粒度控制:
|
||
|
||
```yaml
|
||
phases:
|
||
skip_research: false # 跳过 milestone 级 research
|
||
skip_reassess: false # 在每个 slice 后跳过 roadmap reassessment
|
||
skip_slice_research: true # 跳过每个 slice 的 research
|
||
reassess_after_slice: true # 每个 slice 后执行 roadmap reassessment(reassessment 的前提)
|
||
require_slice_discussion: false # 每个 slice 前暂停,等待讨论
|
||
```
|
||
|
||
这些值通常由 `token_profile` 自动设置,但也可以显式覆盖。
|
||
|
||
> **注意:** Roadmap reassessment 需要显式设置 `reassess_after_slice: true`。如果没有它,无论 `skip_reassess` 怎么配,reassessment 都不会运行。
|
||
|
||
### `skill_discovery`
|
||
|
||
控制 SF 在自动模式中如何发现并应用 skills。
|
||
|
||
| 值 | 行为 |
|
||
|----|------|
|
||
| `auto` | 自动查找并应用 skills |
|
||
| `suggest` | 在 research 阶段识别到 skills,但不自动安装(默认) |
|
||
| `off` | 关闭 skill discovery |
|
||
|
||
### `auto_supervisor`
|
||
|
||
自动模式监督器使用的超时阈值:
|
||
|
||
```yaml
|
||
auto_supervisor:
|
||
model: claude-sonnet-4-6 # 可选:supervisor 使用的 model(默认当前 active model)
|
||
soft_timeout_minutes: 20 # 提醒 LLM 收尾
|
||
idle_timeout_minutes: 10 # 检测停滞
|
||
hard_timeout_minutes: 30 # 暂停自动模式
|
||
```
|
||
|
||
### `budget_ceiling`
|
||
|
||
自动模式期间允许消耗的最大美元金额。不需要 `$`,直接填数字:
|
||
|
||
```yaml
|
||
budget_ceiling: 50.00
|
||
```
|
||
|
||
### `budget_enforcement`
|
||
|
||
预算上限的执行方式:
|
||
|
||
| 值 | 行为 |
|
||
|----|------|
|
||
| `warn` | 记录警告,但继续运行 |
|
||
| `pause` | 暂停自动模式(设置 ceiling 时的默认值) |
|
||
| `halt` | 彻底停止自动模式 |
|
||
|
||
### `context_pause_threshold`
|
||
|
||
上下文窗口使用率达到多少(0-100)时,自动模式会暂停并进行 checkpoint。设为 `0` 可关闭。
|
||
|
||
```yaml
|
||
context_pause_threshold: 80 # 在上下文使用达到 80% 时暂停
|
||
```
|
||
|
||
默认值:`0`(关闭)
|
||
|
||
### `uat_dispatch`
|
||
|
||
在 slice 完成后自动运行 UAT(User Acceptance Test):
|
||
|
||
```yaml
|
||
uat_dispatch: true
|
||
```
|
||
|
||
### Verification(v2.26)
|
||
|
||
配置在每次 task 执行后自动运行的 shell 命令。若失败,会先尝试自动修复重试,再决定是否继续。
|
||
|
||
```yaml
|
||
verification_commands:
|
||
- npm run lint
|
||
- npm run test
|
||
verification_auto_fix: true # 失败时自动重试修复(默认:true)
|
||
verification_max_retries: 2 # 最大重试次数(默认:2)
|
||
```
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `verification_commands` | string[] | `[]` | task 执行后要运行的 shell 命令 |
|
||
| `verification_auto_fix` | boolean | `true` | verification 失败时是否自动重试 |
|
||
| `verification_max_retries` | number | `2` | 自动修复重试的最大次数 |
|
||
|
||
<a id="url-blocking-fetch_page"></a>
|
||
### URL Blocking(`fetch_page`)
|
||
|
||
`fetch_page` 工具默认会阻止访问私有网络和内部网络地址,以防 SSRF(server-side request forgery)。这能防止 agent 被诱导去访问内部服务、云 metadata endpoint 或本地文件。
|
||
|
||
**默认会被拦截:**
|
||
|
||
| 类别 | 示例 |
|
||
|------|------|
|
||
| 私有 IP 段 | `10.x.x.x`、`172.16-31.x.x`、`192.168.x.x`、`127.x.x.x` |
|
||
| Link-local / 云 metadata | `169.254.x.x`(AWS/GCP instance metadata) |
|
||
| 云 metadata hostname | `metadata.google.internal`、`instance-data` |
|
||
| Localhost | `localhost`(任意端口) |
|
||
| 非 HTTP 协议 | `file://`、`ftp://` |
|
||
| IPv6 私有地址段 | `::1`、`fc00:`、`fd`、`fe80:` |
|
||
|
||
公共 URL(例如 `https://example.com`、`http://8.8.8.8`)不受影响。
|
||
|
||
**允许特定内部主机:**
|
||
|
||
如果你确实需要 agent 访问内网 URL(例如自托管文档、VPN 后的内部 API),可以在全局设置 `~/.sf/agent/settings.json` 中添加 `fetchAllowedUrls`:
|
||
|
||
```json
|
||
{
|
||
"fetchAllowedUrls": ["internal-docs.company.com", "192.168.1.50"]
|
||
}
|
||
```
|
||
|
||
或者设置 `SF_FETCH_ALLOWED_URLS` 环境变量(逗号分隔)。环境变量优先级高于 settings.json:
|
||
|
||
```bash
|
||
export SF_FETCH_ALLOWED_URLS="internal-docs.company.com,192.168.1.50"
|
||
```
|
||
|
||
被允许的 hostname 会绕过 blocklist 检查。但协议限制依然有效,也就是说 `file://` 和 `ftp://` 仍然不能加入 allowlist。
|
||
|
||
> **注意:** 这是一个仅全局生效的设置。项目级 settings.json 不能覆盖 URL allowlist,以防克隆下来的仓库把 `fetch_page` 指向内部基础设施。
|
||
|
||
### `auto_report`(v2.26)
|
||
|
||
在 milestone 完成后自动生成 HTML 报告:
|
||
|
||
```yaml
|
||
auto_report: true # 默认:true
|
||
```
|
||
|
||
报告会以自包含 HTML 文件的形式写入 `.sf/reports/`,所有 CSS / JS 都内嵌。
|
||
|
||
### `unique_milestone_ids`
|
||
|
||
为 milestone IDs 添加随机后缀,以避免团队协作中的 ID 冲突:
|
||
|
||
```yaml
|
||
unique_milestone_ids: true
|
||
# 输出示例:M001-eh88as,而不是 M001
|
||
```
|
||
|
||
### `git`
|
||
|
||
Git 行为配置。所有字段都是可选的:
|
||
|
||
```yaml
|
||
git:
|
||
auto_push: false # 提交后推送到远程
|
||
push_branches: false # 推送 milestone 分支到远程
|
||
remote: origin # git remote 名称
|
||
snapshots: true # 长 task 执行期间做 WIP snapshot commits
|
||
pre_merge_check: auto # worktree merge 前执行检查(true / false / "auto")
|
||
commit_type: feat # 覆盖 conventional commit 前缀
|
||
main_branch: main # 主分支名称
|
||
merge_strategy: squash # worktree 分支合并方式:"squash" 或 "merge"
|
||
isolation: worktree # git isolation:"worktree"、"branch" 或 "none"
|
||
commit_docs: true # 是否把 .sf/ 产物提交到 git(设为 false 时仅保留本地)
|
||
manage_gitignore: true # 设为 false 时,SF 不再修改 .gitignore
|
||
worktree_post_create: .sf/hooks/post-worktree-create # worktree 创建后执行的脚本
|
||
auto_pr: false # milestone 完成时自动创建 PR(要求 push_branches)
|
||
pr_target_branch: develop # 自动创建 PR 的目标分支(默认:main branch)
|
||
```
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `auto_push` | boolean | `false` | 提交后推送到远程 |
|
||
| `push_branches` | boolean | `false` | 把 milestone 分支推送到远程 |
|
||
| `remote` | string | `"origin"` | Git remote 名称 |
|
||
| `snapshots` | boolean | `true` | 长 task 期间做 WIP snapshot commits |
|
||
| `pre_merge_check` | bool/string | `"auto"` | merge 前是否执行检查(`true` / `false` / `"auto"`) |
|
||
| `commit_type` | string | (自动推断) | 覆盖 conventional commit 前缀(`feat`、`fix`、`refactor`、`docs`、`test`、`chore`、`perf`、`ci`、`build`、`style`) |
|
||
| `main_branch` | string | `"main"` | 主分支名称 |
|
||
| `merge_strategy` | string | `"squash"` | worktree 分支合并方式:`"squash"`(合并为单个提交)或 `"merge"`(保留单独提交) |
|
||
| `isolation` | string | `"worktree"` | 自动模式隔离方式:`"worktree"`(独立目录)、`"branch"`(直接在项目根目录工作,适合子模块多的仓库)、`"none"`(无隔离,直接提交到当前分支) |
|
||
| `commit_docs` | boolean | `true` | 是否把 `.sf/` planning 产物提交到 git。设为 `false` 则仅保留本地 |
|
||
| `manage_gitignore` | boolean | `true` | 设为 `false` 后,SF 将完全不修改 `.gitignore`,不会添加基础规则,也不会做自愈 |
|
||
| `worktree_post_create` | string | (无) | worktree 创建后执行的脚本。环境变量中会传入 `SOURCE_DIR` 和 `WORKTREE_DIR` |
|
||
| `auto_pr` | boolean | `false` | milestone 完成时自动创建 pull request。要求 `auto_push: true` 且已安装认证 `gh` CLI |
|
||
| `pr_target_branch` | string | (main branch) | 自动创建 PR 的目标分支,例如 `develop`、`qa`。未设置时默认回退到 `main_branch` |
|
||
|
||
#### `git.worktree_post_create`
|
||
|
||
在 worktree 创建后执行脚本(自动模式和手动 `/worktree` 都适用)。适合复制 `.env`、建立资源目录软链,或者执行那些 worktree 不会继承的 setup 步骤。
|
||
|
||
```yaml
|
||
git:
|
||
worktree_post_create: .sf/hooks/post-worktree-create
|
||
```
|
||
|
||
脚本会收到两个环境变量:
|
||
|
||
- `SOURCE_DIR`:原始项目根目录
|
||
- `WORKTREE_DIR`:新创建的 worktree 路径
|
||
|
||
示例 hook(`.sf/hooks/post-worktree-create`):
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
# Copy environment files and symlink assets into the new worktree
|
||
cp "$SOURCE_DIR/.env" "$WORKTREE_DIR/.env"
|
||
cp "$SOURCE_DIR/.env.local" "$WORKTREE_DIR/.env.local" 2>/dev/null || true
|
||
ln -sf "$SOURCE_DIR/assets" "$WORKTREE_DIR/assets"
|
||
```
|
||
|
||
路径既可以是绝对路径,也可以相对项目根目录。脚本有 30 秒超时限制。失败不会中断流程,SF 会记录告警后继续。
|
||
|
||
<a id="gitauto_pr"></a>
|
||
#### `git.auto_pr`
|
||
|
||
在 milestone 完成时自动创建 pull request。适用于 Gitflow 或分支工作流团队,在合并到目标分支前通过 PR 做审查。
|
||
|
||
```yaml
|
||
git:
|
||
auto_push: true
|
||
auto_pr: true
|
||
pr_target_branch: develop # 或 qa、staging 等
|
||
```
|
||
|
||
**要求:**
|
||
|
||
- `auto_push: true`:创建 PR 前必须先把 milestone 分支推送到远程
|
||
- 已安装并认证 [`gh` CLI](https://cli.github.com/)(`gh auth login`)
|
||
|
||
**工作方式:**
|
||
|
||
1. milestone 完成后,SF 先把 worktree squash merge 回主分支
|
||
2. 如果 `auto_push: true`,把主分支推送到远程
|
||
3. 把 milestone 分支推送到远程
|
||
4. 通过 `gh pr create` 从 milestone 分支向 `pr_target_branch` 创建 PR
|
||
|
||
如果没有设置 `pr_target_branch`,PR 会默认指向 `main_branch`(或者自动检测出的主分支)。PR 创建失败不会中断流程,SF 会记录日志后继续。
|
||
|
||
### `github`(v2.39)
|
||
|
||
GitHub 同步配置。启用后,SF 会自动把 milestones、slices 和 tasks 同步到 GitHub Issues、PRs 和 Milestones。
|
||
|
||
```yaml
|
||
github:
|
||
enabled: true
|
||
repo: "owner/repo" # 省略时从 git remote 自动检测
|
||
labels: [sf, auto-generated] # 应用到创建出的 issues / PRs 的标签
|
||
project: "Project ID" # 可选的 GitHub Project board
|
||
```
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `enabled` | boolean | `false` | 是否启用 GitHub 同步 |
|
||
| `repo` | string | (自动检测) | `owner/repo` 格式的 GitHub 仓库名 |
|
||
| `labels` | string[] | `[]` | 创建的 issues / PRs 要附加的标签 |
|
||
| `project` | string | (无) | GitHub Project ID,用于接入 Project board |
|
||
|
||
**要求:**
|
||
|
||
- 已安装并认证 `gh` CLI(`gh auth login`)
|
||
- 同步映射会保存在 `.sf/.github-sync.json`
|
||
- 具备速率限制感知:当 GitHub API rate limit 偏低时会跳过同步
|
||
|
||
**命令:**
|
||
|
||
- `/github-sync bootstrap`:初始化配置并执行同步
|
||
- `/github-sync status`:显示同步映射数量
|
||
|
||
### `notifications`
|
||
|
||
控制 SF 在自动模式中发出哪些通知:
|
||
|
||
```yaml
|
||
notifications:
|
||
enabled: true
|
||
on_complete: true # 单元完成时通知
|
||
on_error: true # 出错时通知
|
||
on_budget: true # 预算阈值通知
|
||
on_milestone: true # milestone 完成时通知
|
||
on_attention: true # 需要人工介入时通知
|
||
```
|
||
|
||
**macOS 通知方式:** SF 会优先使用 [`terminal-notifier`](https://github.com/julienXX/terminal-notifier),不可用时回退到 `osascript`。建议安装 `terminal-notifier`,获得更稳定的通知体验:
|
||
|
||
```bash
|
||
brew install terminal-notifier
|
||
```
|
||
|
||
原因:`osascript display notification` 的通知权限是算在你的终端应用(Ghostty、iTerm2 等)上的,而这些应用在 System Settings → Notifications 中未必被允许。`terminal-notifier` 会注册成独立 App,并在首次使用时主动请求通知权限。如果通知异常,见 [故障排查:macOS 上通知不显示](troubleshooting.md#notifications-not-appearing-on-macos)。
|
||
|
||
### `remote_questions`
|
||
|
||
把交互式问题路由到 Slack 或 Discord,以支持 headless 自动模式:
|
||
|
||
```yaml
|
||
remote_questions:
|
||
channel: slack # 或 discord
|
||
channel_id: "C1234567890"
|
||
timeout_minutes: 15 # 问题超时(1-30 分钟)
|
||
poll_interval_seconds: 10 # 轮询间隔(2-30 秒)
|
||
```
|
||
|
||
### `post_unit_hooks`
|
||
|
||
在特定单元完成后触发的自定义 hooks:
|
||
|
||
```yaml
|
||
post_unit_hooks:
|
||
- name: code-review
|
||
after: [execute-task]
|
||
prompt: "Review the code changes for quality and security issues."
|
||
model: claude-opus-4-6 # 可选:覆盖 model
|
||
max_cycles: 1 # 每次触发最多执行几轮(1-10,默认 1)
|
||
artifact: REVIEW.md # 可选:若该文件已存在则跳过
|
||
retry_on: NEEDS-REWORK.md # 可选:若生成该文件,则回退并重跑触发单元
|
||
agent: review-agent # 可选:指定使用哪个 agent 定义
|
||
enabled: true # 可选:保留配置但临时禁用
|
||
```
|
||
|
||
`after` 可识别的 unit types 包括:`research-milestone`、`plan-milestone`、`research-slice`、`plan-slice`、`execute-task`、`complete-slice`、`replan-slice`、`reassess-roadmap`、`run-uat`
|
||
|
||
**Prompt 占位符:** `{milestoneId}`、`{sliceId}`、`{taskId}` 会自动替换成当前上下文值。
|
||
|
||
### `pre_dispatch_hooks`
|
||
|
||
在 dispatch 前拦截某个单元。支持三种动作:
|
||
|
||
**Modify**:在单元 prompt 前后拼接文本
|
||
|
||
```yaml
|
||
pre_dispatch_hooks:
|
||
- name: add-standards
|
||
before: [execute-task]
|
||
action: modify
|
||
prepend: "Follow our coding standards document."
|
||
append: "Run linting after changes."
|
||
```
|
||
|
||
**Skip**:完全跳过该单元
|
||
|
||
```yaml
|
||
pre_dispatch_hooks:
|
||
- name: skip-research
|
||
before: [research-slice]
|
||
action: skip
|
||
skip_if: RESEARCH.md # 可选:仅当该文件存在时才跳过
|
||
```
|
||
|
||
**Replace**:完全替换该单元 prompt
|
||
|
||
```yaml
|
||
pre_dispatch_hooks:
|
||
- name: custom-execute
|
||
before: [execute-task]
|
||
action: replace
|
||
prompt: "Execute the task using TDD methodology."
|
||
unit_type: execute-task-tdd # 可选:覆盖 unit type 标签
|
||
model: claude-opus-4-6 # 可选:覆盖 model
|
||
```
|
||
|
||
所有 pre-dispatch hooks 都支持 `enabled: true/false`,用于开关而不删除配置。
|
||
|
||
### `always_use_skills` / `prefer_skills` / `avoid_skills`
|
||
|
||
Skill 路由偏好:
|
||
|
||
```yaml
|
||
always_use_skills:
|
||
- debug-like-expert
|
||
prefer_skills:
|
||
- frontend-design
|
||
avoid_skills: []
|
||
```
|
||
|
||
Skills 既可以写裸名称(去 `~/.agents/skills/` 和 `.agents/skills/` 查找),也可以写绝对路径。
|
||
|
||
### `skill_rules`
|
||
|
||
基于人类可读触发条件的情景化 skill 路由:
|
||
|
||
```yaml
|
||
skill_rules:
|
||
- when: task involves authentication
|
||
use: [clerk]
|
||
- when: frontend styling work
|
||
prefer: [frontend-design]
|
||
- when: working with legacy code
|
||
avoid: [aggressive-refactor]
|
||
```
|
||
|
||
### `custom_instructions`
|
||
|
||
附加到每个会话上的持久指令:
|
||
|
||
```yaml
|
||
custom_instructions:
|
||
- "Always use TypeScript strict mode"
|
||
- "Prefer functional patterns over classes"
|
||
```
|
||
|
||
如果是项目特有知识(模式、坑点、经验),请优先放到 `.sf/KNOWLEDGE.md` 中,因为它会自动注入每个 agent prompt。你也可以通过 `/sf knowledge rule|pattern|lesson <description>` 添加。
|
||
|
||
### `RUNTIME.md`:运行时上下文(v2.39)
|
||
|
||
你可以在 `.sf/RUNTIME.md` 中声明项目级运行时上下文。这个文件会内联进 task execution prompt,让 agent 能准确知道运行环境,而不必靠猜测路径或 URL。
|
||
|
||
**位置:** `.sf/RUNTIME.md`
|
||
|
||
**示例:**
|
||
|
||
```markdown
|
||
# Runtime Context
|
||
|
||
## API Endpoints
|
||
- Main API: https://api.example.com
|
||
- Cache: redis://localhost:6379
|
||
|
||
## Environment Variables
|
||
- DEPLOYMENT_ENV: staging
|
||
- DB_POOL_SIZE: 20
|
||
|
||
## Local Services
|
||
- PostgreSQL: localhost:5432
|
||
- Redis: localhost:6379
|
||
```
|
||
|
||
适合放在这里的信息,是那些执行时需要知道、但又不属于 `DECISIONS.md`(架构)或 `KNOWLEDGE.md`(规则 / 模式)的内容。典型例子包括:API base URL、服务端口、部署目标,以及环境特有配置。
|
||
|
||
### `dynamic_routing`
|
||
|
||
基于复杂度的 model 路由。详见 [动态模型路由](./dynamic-model-routing.md)。
|
||
|
||
```yaml
|
||
dynamic_routing:
|
||
enabled: true
|
||
capability_routing: true # 按 task capability 评分 models(v2.59)
|
||
tier_models:
|
||
light: claude-haiku-4-5
|
||
standard: claude-sonnet-4-6
|
||
heavy: claude-opus-4-6
|
||
escalate_on_failure: true
|
||
budget_pressure: true
|
||
cross_provider: true
|
||
```
|
||
|
||
### `context_management`(v2.59)
|
||
|
||
控制自动模式会话中的 observation masking 和 tool result truncation。可在不增加 LLM 开销的前提下,减少 compaction 之间的上下文膨胀。
|
||
|
||
```yaml
|
||
context_management:
|
||
observation_masking: true # 用占位符替换旧 tool result(默认:true)
|
||
observation_mask_turns: 8 # 保留最近 N 个 user turn 的结果(1-50,默认:8)
|
||
compaction_threshold_percent: 0.70 # 在 70% 上下文使用率处触发 compaction(0.5-0.95,默认:0.70)
|
||
tool_result_max_chars: 800 # 单个 tool result 的最大字符数(200-10000,默认:800)
|
||
```
|
||
|
||
### `service_tier`(v2.42)
|
||
|
||
OpenAI 支持模型的 service tier 偏好。可通过 `/sf fast` 切换。
|
||
|
||
| 值 | 行为 |
|
||
|----|------|
|
||
| `"priority"` | Priority tier:2 倍成本,更快响应 |
|
||
| `"flex"` | Flex tier:0.5 倍成本,更慢响应 |
|
||
| (未设置) | 默认 tier |
|
||
|
||
```yaml
|
||
service_tier: priority
|
||
```
|
||
|
||
### `forensics_dedup`(v2.43)
|
||
|
||
可选启用:在 `/sf forensics` 提交 issue 之前,先搜索现有 issues 和 PRs。会额外消耗一些 AI tokens。
|
||
|
||
```yaml
|
||
forensics_dedup: true # 默认:false
|
||
```
|
||
|
||
### `show_token_cost`(v2.44)
|
||
|
||
可选启用:在 footer 中显示每次 prompt 和累计会话的 token 成本。
|
||
|
||
```yaml
|
||
show_token_cost: true # 默认:false
|
||
```
|
||
|
||
### `auto_visualize`
|
||
|
||
在 milestone 完成后自动显示工作流可视化器:
|
||
|
||
```yaml
|
||
auto_visualize: true
|
||
```
|
||
|
||
详见 [工作流可视化器](./visualizer.md)。
|
||
|
||
### `parallel`
|
||
|
||
同时运行多个 milestones。默认关闭。
|
||
|
||
```yaml
|
||
parallel:
|
||
enabled: false # 总开关
|
||
max_workers: 2 # 并发 workers 数(1-4)
|
||
budget_ceiling: 50.00 # 聚合成本上限(美元)
|
||
merge_strategy: "per-milestone" # "per-slice" 或 "per-milestone"
|
||
auto_merge: "confirm" # "auto"、"confirm" 或 "manual"
|
||
```
|
||
|
||
完整细节见 [并行编排](./parallel-orchestration.md)。
|
||
|
||
## 完整示例
|
||
|
||
```yaml
|
||
---
|
||
version: 1
|
||
|
||
# Model selection
|
||
models:
|
||
research: openrouter/deepseek/deepseek-r1
|
||
planning:
|
||
model: claude-opus-4-6
|
||
fallbacks:
|
||
- openrouter/z-ai/glm-5
|
||
execution: claude-sonnet-4-6
|
||
execution_simple: claude-haiku-4-5-20250414
|
||
completion: claude-sonnet-4-6
|
||
|
||
# Token optimization
|
||
token_profile: balanced
|
||
|
||
# Dynamic model routing
|
||
dynamic_routing:
|
||
enabled: true
|
||
escalate_on_failure: true
|
||
budget_pressure: true
|
||
|
||
# Budget
|
||
budget_ceiling: 25.00
|
||
budget_enforcement: pause
|
||
context_pause_threshold: 80
|
||
|
||
# Supervision
|
||
auto_supervisor:
|
||
soft_timeout_minutes: 15
|
||
hard_timeout_minutes: 25
|
||
|
||
# Git
|
||
git:
|
||
auto_push: true
|
||
merge_strategy: squash
|
||
isolation: worktree # "worktree", "branch", or "none"
|
||
commit_docs: true
|
||
|
||
# Skills
|
||
skill_discovery: suggest
|
||
skill_staleness_days: 60 # Skills unused for N days get deprioritized (0 = disabled)
|
||
always_use_skills:
|
||
- debug-like-expert
|
||
skill_rules:
|
||
- when: task involves authentication
|
||
use: [clerk]
|
||
|
||
# Notifications
|
||
notifications:
|
||
on_complete: false
|
||
on_milestone: true
|
||
on_attention: true
|
||
|
||
# Visualizer
|
||
auto_visualize: true
|
||
|
||
# Service tier
|
||
service_tier: priority # "priority" or "flex" (for /sf fast)
|
||
|
||
# Diagnostics
|
||
forensics_dedup: true # deduplicate before filing forensics issues
|
||
show_token_cost: true # show per-prompt cost in footer
|
||
|
||
# Hooks
|
||
post_unit_hooks:
|
||
- name: code-review
|
||
after: [execute-task]
|
||
prompt: "Review {sliceId}/{taskId} for quality and security."
|
||
artifact: REVIEW.md
|
||
---
|
||
```
|