839 lines
29 KiB
Markdown
839 lines
29 KiB
Markdown
# Configuration
|
|
|
|
SF preferences live in `~/.sf/PREFERENCES.md` (global) or `.sf/PREFERENCES.md` (project-local). Manage interactively with `/prefs`.
|
|
|
|
## `/prefs` Commands
|
|
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `/prefs` | Open the global preferences wizard (default) |
|
|
| `/prefs global` | Interactive wizard for global preferences (`~/.sf/PREFERENCES.md`) |
|
|
| `/prefs project` | Interactive wizard for project preferences (`.sf/PREFERENCES.md`) |
|
|
| `/prefs status` | Show current preference files, merged values, and skill resolution status |
|
|
| `/prefs wizard` | Alias for `/prefs global` |
|
|
| `/prefs setup` | Alias for `/prefs wizard` — creates preferences file if missing |
|
|
| `/prefs import-claude` | Import Claude marketplace plugins and skills as namespaced SF components |
|
|
| `/prefs import-claude global` | Import to global scope |
|
|
| `/prefs import-claude project` | Import to project scope |
|
|
|
|
## Preferences File Format
|
|
|
|
Preferences use YAML frontmatter in a markdown file:
|
|
|
|
```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
|
|
---
|
|
```
|
|
|
|
## Global vs Project Preferences
|
|
|
|
| Scope | Path | Applies to |
|
|
|-------|------|-----------|
|
|
| Global | `~/.sf/PREFERENCES.md` | All projects |
|
|
| Project | `.sf/PREFERENCES.md` | Current project only |
|
|
|
|
**Merge behavior:**
|
|
- **Scalar fields** (`skill_discovery`, `budget_ceiling`): project wins if defined
|
|
- **Array fields** (`always_use_skills`, etc.): concatenated (global first, then project)
|
|
- **Object fields** (`models`, `git`, `auto_supervisor`): shallow-merged, project overrides per-key
|
|
|
|
## Global API Keys (`/config`)
|
|
|
|
Tool API keys are stored globally in `~/.sf/agent/auth.json` and apply to all projects automatically. Set them once with `/config` — no need to configure per-project `.env` files.
|
|
|
|
```bash
|
|
/config
|
|
```
|
|
|
|
This opens an interactive wizard showing which keys are configured and which are missing. Select a tool to enter its key.
|
|
|
|
### Supported keys
|
|
|
|
| Tool | Environment Variable | Purpose | Get a key |
|
|
|------|---------------------|---------|-----------|
|
|
| Tavily Search | `TAVILY_API_KEY` | Web search for non-Anthropic models | [tavily.com/app/api-keys](https://tavily.com/app/api-keys) |
|
|
| MiniMax Search | `MINIMAX_API_KEY` (`MINIMAX_CODE_PLAN_KEY` and `MINIMAX_CODING_API_KEY` also accepted) | Web search for non-Anthropic models | MiniMax key |
|
|
| Brave Search | `BRAVE_API_KEY` | Web search for non-Anthropic models | [brave.com/search/api](https://brave.com/search/api) |
|
|
| Context7 Docs | `CONTEXT7_API_KEY` | Library documentation lookup | [context7.com/dashboard](https://context7.com/dashboard) |
|
|
|
|
### How it works
|
|
|
|
1. `/config` saves keys to `~/.sf/agent/auth.json`
|
|
2. On every session start, `loadToolApiKeys()` reads the file and sets environment variables
|
|
3. Keys apply to all projects — no per-project setup required
|
|
4. Environment variables (`export BRAVE_API_KEY=...`) take precedence over saved keys
|
|
5. Anthropic models don't need Brave/Tavily — they have built-in web search
|
|
|
|
## MCP Servers
|
|
|
|
SF can connect to external MCP servers configured in project files. This is useful for local tools, internal APIs, self-hosted services, or integrations that aren't built in as native SF extensions.
|
|
|
|
### Config file locations
|
|
|
|
SF reads MCP client configuration from these project-local paths:
|
|
|
|
- `.mcp.json`
|
|
- `.sf/mcp.json`
|
|
|
|
If both files exist, server names are merged and the first definition found wins. Use:
|
|
|
|
- `.mcp.json` for repo-shared MCP configuration you may want to commit
|
|
- `.sf/mcp.json` for local-only MCP configuration you do **not** want to share
|
|
|
|
### Supported transports
|
|
|
|
| Transport | Config shape | Use when |
|
|
|-----------|--------------|----------|
|
|
| `stdio` | `command` + optional `args`, `env`, `cwd` | Launching a local MCP server process |
|
|
| `http` | `url` | Connecting to an already-running MCP server over HTTP |
|
|
|
|
### Example: 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"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Example: HTTP server
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"my-http-server": {
|
|
"url": "http://localhost:8080/mcp"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Verifying a server
|
|
|
|
After adding config, verify it from a SF session:
|
|
|
|
```text
|
|
mcp_servers
|
|
mcp_discover(server="my-server")
|
|
mcp_call(server="my-server", tool="<tool_name>", args={...})
|
|
```
|
|
|
|
Recommended verification order:
|
|
|
|
1. `mcp_servers` — confirms SF can see the config file and parse the server entry
|
|
2. `mcp_discover` — confirms the server process starts and responds to `tools/list`
|
|
3. `mcp_call` — confirms at least one real tool invocation works
|
|
|
|
### Notes
|
|
|
|
- Use absolute paths for local executables and scripts when possible.
|
|
- For `stdio` servers, prefer setting required environment variables directly in the MCP config instead of relying on an interactive shell profile.
|
|
- SF hydrates supported model and tool keys saved in `~/.sf/agent/auth.json`, so external MCP configs can safely reference them through `${ENV_VAR}` placeholders without committing raw credentials.
|
|
- If a server is team-shared and safe to commit, `.mcp.json` is usually the better home.
|
|
- If a server depends on machine-local paths, personal services, or local-only secrets, prefer `.sf/mcp.json`.
|
|
|
|
## Environment Variables
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `SF_HOME` | `~/.sf` | Global SF directory. All paths derive from this unless individually overridden. Affects preferences, skills, sessions, and per-project state. (v2.39) |
|
|
| `SF_PROJECT_ID` | (auto-hash) | Override the automatic project identity hash. Per-project state goes to `$SF_HOME/projects/<SF_PROJECT_ID>/` instead of the computed hash. Useful for CI/CD or sharing state across clones of the same repo. (v2.39) |
|
|
| `SF_STATE_DIR` | `$SF_HOME` | Per-project state root. Controls where `projects/<repo-hash>/` directories are created. Takes precedence over `SF_HOME` for project state. |
|
|
| `SF_CODING_AGENT_DIR` | `$SF_HOME/agent` | Agent directory containing managed resources, extensions, and auth. Takes precedence over `SF_HOME` for agent paths. |
|
|
| `SF_ALLOWED_COMMAND_PREFIXES` | (built-in list) | Comma-separated command prefixes allowed for `!command` value resolution. Overrides `allowedCommandPrefixes` in settings.json. See [Custom Models — Command Allowlist](custom-models.md#command-allowlist). |
|
|
| `SF_FETCH_ALLOWED_URLS` | (none) | Comma-separated hostnames exempted from `fetch_page` URL blocking. Overrides `fetchAllowedUrls` in settings.json. See [URL Blocking](#url-blocking-fetch_page). |
|
|
|
|
## All Settings
|
|
|
|
### `models`
|
|
|
|
Per-phase model selection. Each key accepts a model string or an object with 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
|
|
```
|
|
|
|
**Phases:** `research`, `planning`, `execution`, `execution_simple`, `completion`, `subagent`
|
|
|
|
- `execution_simple` — used for tasks classified as "simple" by the [complexity router](./token-optimization.md#complexity-based-task-routing)
|
|
- `subagent` — model for delegated subagent tasks (scout, researcher, worker)
|
|
- Provider targeting: use `provider/model` format (e.g., `bedrock/claude-sonnet-4-6`) or the `provider` field in object format
|
|
- Omit a key to use whatever model is currently active
|
|
|
|
### Custom Model Definitions (`models.json`)
|
|
|
|
Define custom models and providers in `~/.sf/agent/models.json`. This lets you add models not included in the default registry — useful for self-hosted endpoints (Ollama, vLLM, LM Studio), fine-tuned models, proxies, or new provider releases.
|
|
|
|
SF resolves models.json with fallback logic:
|
|
1. `~/.sf/agent/models.json` — primary (SF)
|
|
2. `~/.pi/agent/models.json` — fallback (Pi)
|
|
3. If neither exists, creates `~/.sf/agent/models.json`
|
|
|
|
**Quick example for local 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" }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
The file reloads each time you open `/model` — no restart needed.
|
|
|
|
For full documentation including provider configuration, model overrides, OpenAI compatibility settings, and advanced examples, see the [Custom Models Guide](./custom-models.md).
|
|
|
|
**With fallbacks:**
|
|
|
|
```yaml
|
|
models:
|
|
planning:
|
|
model: claude-opus-4-6
|
|
fallbacks:
|
|
- openrouter/z-ai/glm-5
|
|
- openrouter/moonshotai/kimi-k2.5
|
|
provider: bedrock # optional: target a specific provider
|
|
```
|
|
|
|
When a model fails to switch (provider unavailable, rate limited, credits exhausted), SF automatically tries the next model in the `fallbacks` list.
|
|
|
|
### Community Provider Extensions
|
|
|
|
For providers not built into SF, community extensions can add full provider support with proper model definitions, thinking format configuration, and interactive API key setup.
|
|
|
|
| Extension | Provider | Models | Install |
|
|
|-----------|----------|--------|---------|
|
|
| [`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` |
|
|
|
|
Community extensions are recommended over the built-in `alibaba-coding-plan` provider for DashScope models — they use the correct OpenAI-compatible endpoint and include per-model compatibility flags for thinking mode.
|
|
|
|
### `token_profile`
|
|
|
|
Coordinates model selection, phase skipping, and context compression. See [Token Optimization](./token-optimization.md).
|
|
|
|
Values: `budget`, `balanced` (default), `quality`
|
|
|
|
| Profile | Behavior |
|
|
|---------|----------|
|
|
| `budget` | Skips research + reassessment phases, uses cheaper models |
|
|
| `balanced` | Default behavior — all phases run, standard model selection |
|
|
| `quality` | All phases run, prefers higher-quality models |
|
|
|
|
### `phases`
|
|
|
|
Fine-grained control over which phases run in autonomous mode:
|
|
|
|
```yaml
|
|
phases:
|
|
skip_research: false # skip milestone-level research
|
|
skip_reassess: false # skip roadmap reassessment after each slice
|
|
skip_slice_research: true # skip per-slice research
|
|
reassess_after_slice: true # enable roadmap reassessment after each slice (required for reassessment)
|
|
require_slice_discussion: false # pause autonomous mode before each slice for discussion
|
|
```
|
|
|
|
These are usually set automatically by `token_profile`, but can be overridden explicitly.
|
|
|
|
> **Note:** Roadmap reassessment requires `reassess_after_slice: true` to be set explicitly. Without it, reassessment is skipped regardless of `skip_reassess`.
|
|
|
|
### `skill_discovery`
|
|
|
|
Controls how SF finds and applies skills during autonomous mode.
|
|
|
|
| Value | Behavior |
|
|
|-------|----------|
|
|
| `auto` | Skills found and applied automatically |
|
|
| `suggest` | Skills identified during research but not auto-installed (default) |
|
|
| `off` | Skill discovery disabled |
|
|
|
|
### `auto_supervisor`
|
|
|
|
Timeout thresholds for autonomous mode supervision:
|
|
|
|
```yaml
|
|
auto_supervisor:
|
|
model: claude-sonnet-4-6 # optional: model for supervisor (defaults to active model)
|
|
soft_timeout_minutes: 20 # warn LLM to wrap up
|
|
idle_timeout_minutes: 10 # detect stalls
|
|
hard_timeout_minutes: 30 # pause autonomous mode
|
|
solver_max_iterations: 30000
|
|
solver_eval_on_autonomous_exit: true
|
|
completion_nudge_after: 10 # complete-slice tool calls before nudging sf_slice_complete
|
|
```
|
|
|
|
### `budget_ceiling`
|
|
|
|
Maximum USD to spend during autonomous mode. No `$` sign — just the number.
|
|
|
|
```yaml
|
|
budget_ceiling: 50.00
|
|
```
|
|
|
|
### `budget_enforcement`
|
|
|
|
How the budget ceiling is enforced:
|
|
|
|
| Value | Behavior |
|
|
|-------|----------|
|
|
| `warn` | Log a warning but continue |
|
|
| `pause` | Pause autonomous mode (default when ceiling is set) |
|
|
| `halt` | Stop autonomous mode entirely |
|
|
|
|
### `context_pause_threshold`
|
|
|
|
Context window usage percentage (0-100) at which autonomous mode pauses for checkpointing. Set to `0` to disable.
|
|
|
|
```yaml
|
|
context_pause_threshold: 80 # pause at 80% context usage
|
|
```
|
|
|
|
Default: `0` (disabled)
|
|
|
|
### `uat_dispatch`
|
|
|
|
Enable automatic UAT (User Acceptance Test) runs after slice completion:
|
|
|
|
```yaml
|
|
uat_dispatch: true
|
|
```
|
|
|
|
### Verification (v2.26)
|
|
|
|
Configure shell commands that run automatically after every task execution. Failures trigger auto-fix retries before advancing.
|
|
|
|
```yaml
|
|
verification_commands:
|
|
- npm run lint
|
|
- npm run test
|
|
verification_auto_fix: true # auto-retry on failure (default: true)
|
|
verification_max_retries: 2 # max retry attempts (default: 2)
|
|
```
|
|
|
|
| Field | Type | Default | Description |
|
|
|-------|------|---------|-------------|
|
|
| `verification_commands` | string[] | `[]` | Shell commands to run after task execution |
|
|
| `verification_auto_fix` | boolean | `true` | Auto-retry when verification fails |
|
|
| `verification_max_retries` | number | `2` | Maximum auto-fix retry attempts |
|
|
|
|
### URL Blocking (`fetch_page`)
|
|
|
|
The `fetch_page` tool blocks requests to private and internal network addresses to prevent server-side request forgery (SSRF). This protects against the agent being tricked into accessing internal services, cloud metadata endpoints, or local files.
|
|
|
|
**Blocked by default:**
|
|
|
|
| Category | Examples |
|
|
|----------|----------|
|
|
| Private IP ranges | `10.x.x.x`, `172.16-31.x.x`, `192.168.x.x`, `127.x.x.x` |
|
|
| Link-local / cloud metadata | `169.254.x.x` (AWS/GCP instance metadata) |
|
|
| Cloud metadata hostnames | `metadata.google.internal`, `instance-data` |
|
|
| Localhost | `localhost` (any port) |
|
|
| Non-HTTP protocols | `file://`, `ftp://` |
|
|
| IPv6 private ranges | `::1`, `fc00:`, `fd`, `fe80:` |
|
|
|
|
Public URLs (`https://example.com`, `http://8.8.8.8`) are not affected.
|
|
|
|
**Allowing specific internal hosts:**
|
|
|
|
If you need the agent to fetch from internal URLs (self-hosted docs, internal APIs behind a VPN), add their hostnames to `fetchAllowedUrls` in global settings (`~/.sf/agent/settings.json`):
|
|
|
|
```json
|
|
{
|
|
"fetchAllowedUrls": ["internal-docs.company.com", "192.168.1.50"]
|
|
}
|
|
```
|
|
|
|
Alternatively, set the `SF_FETCH_ALLOWED_URLS` environment variable (comma-separated). The env var takes precedence over settings.json:
|
|
|
|
```bash
|
|
export SF_FETCH_ALLOWED_URLS="internal-docs.company.com,192.168.1.50"
|
|
```
|
|
|
|
Allowed hostnames bypass the blocklist checks. The protocol restriction (HTTP/HTTPS only) still applies — `file://` and `ftp://` cannot be allowlisted.
|
|
|
|
> **Note:** This setting is global-only. Project-level settings.json cannot override the URL allowlist — this prevents a cloned repo from directing `fetch_page` at internal infrastructure.
|
|
|
|
### `auto_report` (v2.26)
|
|
|
|
Auto-generate HTML reports after milestone completion:
|
|
|
|
```yaml
|
|
auto_report: true # default: true
|
|
```
|
|
|
|
Reports are written to `.sf/reports/` as self-contained HTML files with embedded CSS/JS.
|
|
|
|
### `unique_milestone_ids`
|
|
|
|
Generate milestone IDs with a random suffix to avoid collisions in team workflows:
|
|
|
|
```yaml
|
|
unique_milestone_ids: true
|
|
# Produces: M001-eh88as instead of M001
|
|
```
|
|
|
|
### `git`
|
|
|
|
Git behavior configuration. All fields optional:
|
|
|
|
```yaml
|
|
git:
|
|
auto_push: false # push commits to remote after committing
|
|
push_branches: false # push milestone branch to remote
|
|
remote: origin # git remote name
|
|
snapshots: true # WIP snapshot commits during long tasks
|
|
pre_merge_check: auto # run checks before worktree merge (true/false/"auto")
|
|
commit_type: feat # override conventional commit prefix
|
|
main_branch: main # primary branch name
|
|
merge_strategy: squash # how worktree branches merge: "squash" or "merge"
|
|
isolation: worktree # git isolation: "worktree", "branch", or "none"
|
|
commit_docs: true # commit .sf/ artifacts to git (set false to keep local)
|
|
manage_gitignore: true # set false to prevent SF from modifying .gitignore
|
|
worktree_post_create: .sf/hooks/post-worktree-create # script to run after worktree creation
|
|
auto_pr: false # create a PR on milestone completion (requires push_branches)
|
|
pr_target_branch: develop # target branch for auto-created PRs (default: main branch)
|
|
```
|
|
|
|
| Field | Type | Default | Description |
|
|
|-------|------|---------|-------------|
|
|
| `auto_push` | boolean | `false` | Push commits to remote after committing |
|
|
| `push_branches` | boolean | `false` | Push milestone branch to remote |
|
|
| `remote` | string | `"origin"` | Git remote name |
|
|
| `snapshots` | boolean | `true` | WIP snapshot commits during long tasks |
|
|
| `pre_merge_check` | bool/string | `"auto"` | Run checks before merge (`true`/`false`/`"auto"`) |
|
|
| `commit_type` | string | (inferred) | Override conventional commit prefix (`feat`, `fix`, `refactor`, `docs`, `test`, `chore`, `perf`, `ci`, `build`, `style`) |
|
|
| `main_branch` | string | `"main"` | Primary branch name |
|
|
| `merge_strategy` | string | `"squash"` | How worktree branches merge: `"squash"` (combine all commits) or `"merge"` (preserve individual commits) |
|
|
| `isolation` | string | `"worktree"` | Autonomous mode isolation: `"worktree"` (separate directory), `"branch"` (work in project root — useful for submodule-heavy repos), or `"none"` (no isolation — commits on current branch, no worktree or milestone branch) |
|
|
| `commit_docs` | boolean | `true` | Commit `.sf/` planning artifacts to git. Set `false` to keep local-only |
|
|
| `manage_gitignore` | boolean | `true` | When `false`, SF will not modify `.gitignore` at all — no baseline patterns, no self-healing. Use if you manage your own `.gitignore` |
|
|
| `worktree_post_create` | string | (none) | Script to run after worktree creation. Receives `SOURCE_DIR` and `WORKTREE_DIR` env vars |
|
|
| `auto_pr` | boolean | `false` | Automatically create a pull request when a milestone completes. Requires `auto_push: true` and `gh` CLI installed and authenticated |
|
|
| `pr_target_branch` | string | (main branch) | Target branch for auto-created PRs (e.g. `develop`, `qa`). Defaults to `main_branch` if not set |
|
|
|
|
#### `git.worktree_post_create`
|
|
|
|
Script to run after a worktree is created (both autonomous mode and manual `/worktree`). Useful for copying `.env` files, symlinking asset directories, or running setup commands that worktrees don't inherit from the main tree.
|
|
|
|
```yaml
|
|
git:
|
|
worktree_post_create: .sf/hooks/post-worktree-create
|
|
```
|
|
|
|
The script receives two environment variables:
|
|
- `SOURCE_DIR` — the original project root
|
|
- `WORKTREE_DIR` — the newly created worktree path
|
|
|
|
Example hook script (`.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"
|
|
```
|
|
|
|
The path can be absolute or relative to the project root. The script runs with a 30-second timeout. Failure is non-fatal — SF logs a warning and continues.
|
|
|
|
#### `git.auto_pr`
|
|
|
|
Automatically create a pull request when a milestone completes. Designed for teams using Gitflow or branch-based workflows where work should go through PR review before merging to a target branch.
|
|
|
|
```yaml
|
|
git:
|
|
auto_push: true
|
|
auto_pr: true
|
|
pr_target_branch: develop # or qa, staging, etc.
|
|
```
|
|
|
|
**Requirements:**
|
|
- `auto_push: true` — the milestone branch must be pushed before a PR can be created
|
|
- [`gh` CLI](https://cli.github.com/) installed and authenticated (`gh auth login`)
|
|
|
|
**How it works:**
|
|
1. Milestone completes → SF squash-merges the worktree to the main branch
|
|
2. Pushes the main branch to remote (if `auto_push: true`)
|
|
3. Pushes the milestone branch to remote
|
|
4. Creates a PR from the milestone branch to `pr_target_branch` via `gh pr create`
|
|
|
|
If `pr_target_branch` is not set, the PR targets the `main_branch` (or auto-detected main branch). PR creation failure is non-fatal — SF logs and continues.
|
|
|
|
### `github` (v2.39)
|
|
|
|
GitHub sync configuration. When enabled, SF auto-syncs milestones, slices, and tasks to GitHub Issues, PRs, and Milestones.
|
|
|
|
```yaml
|
|
github:
|
|
enabled: true
|
|
repo: "owner/repo" # auto-detected from git remote if omitted
|
|
labels: [sf, auto-generated] # labels applied to created issues/PRs
|
|
project: "Project ID" # optional GitHub Project board
|
|
```
|
|
|
|
| Field | Type | Default | Description |
|
|
|-------|------|---------|-------------|
|
|
| `enabled` | boolean | `false` | Enable GitHub sync |
|
|
| `repo` | string | (auto-detected) | GitHub repository in `owner/repo` format |
|
|
| `labels` | string[] | `[]` | Labels to apply to created issues and PRs |
|
|
| `project` | string | (none) | GitHub Project ID for project board integration |
|
|
|
|
**Requirements:**
|
|
- `gh` CLI installed and authenticated (`gh auth login`)
|
|
- Sync mapping is persisted in `.sf/.github-sync.json`
|
|
- Rate-limit aware — skips sync when GitHub API rate limit is low
|
|
|
|
**Commands:**
|
|
- `/github-sync bootstrap` — initial setup and sync
|
|
- `/github-sync status` — show sync mapping counts
|
|
|
|
### `notifications`
|
|
|
|
Control what notifications SF sends during autonomous mode:
|
|
|
|
```yaml
|
|
notifications:
|
|
enabled: true
|
|
on_complete: true # notify on unit completion
|
|
on_error: true # notify on errors
|
|
on_budget: true # notify on budget thresholds
|
|
on_milestone: true # notify when milestone finishes
|
|
on_attention: true # notify when manual attention needed
|
|
```
|
|
|
|
### `remote_questions`
|
|
|
|
Route interactive questions to Slack or Discord when run control and the
|
|
permission profile require human input:
|
|
|
|
```yaml
|
|
remote_questions:
|
|
channel: slack # or discord
|
|
channel_id: "C1234567890"
|
|
timeout_minutes: 15 # question timeout (1-30 minutes)
|
|
poll_interval_seconds: 10 # poll interval (2-30 seconds)
|
|
```
|
|
|
|
### `post_unit_hooks`
|
|
|
|
Custom hooks that fire after specific unit types complete:
|
|
|
|
```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 # optional: model override
|
|
max_cycles: 1 # max fires per trigger (1-10, default: 1)
|
|
artifact: REVIEW.md # optional: skip if this file exists
|
|
retry_on: NEEDS-REWORK.md # optional: re-run trigger unit if this file appears
|
|
agent: review-agent # optional: agent definition to use
|
|
enabled: true # optional: disable without removing
|
|
```
|
|
|
|
**Known unit types for `after`:** `research-milestone`, `plan-milestone`, `research-slice`, `plan-slice`, `execute-task`, `complete-slice`, `replan-slice`, `reassess-roadmap`, `run-uat`
|
|
|
|
**Prompt substitutions:** `{milestoneId}`, `{sliceId}`, `{taskId}` are replaced with current context values.
|
|
|
|
### `pre_dispatch_hooks`
|
|
|
|
Hooks that intercept units before dispatch. Three actions available:
|
|
|
|
**Modify** — prepend/append text to the unit 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** — skip the unit entirely:
|
|
|
|
```yaml
|
|
pre_dispatch_hooks:
|
|
- name: skip-research
|
|
before: [research-slice]
|
|
action: skip
|
|
skip_if: RESEARCH.md # optional: only skip if this file exists
|
|
```
|
|
|
|
**Replace** — replace the unit prompt entirely:
|
|
|
|
```yaml
|
|
pre_dispatch_hooks:
|
|
- name: custom-execute
|
|
before: [execute-task]
|
|
action: replace
|
|
prompt: "Execute the task using TDD methodology."
|
|
unit_type: execute-task-tdd # optional: override unit type label
|
|
model: claude-opus-4-6 # optional: model override
|
|
```
|
|
|
|
All pre-dispatch hooks support `enabled: true/false` to toggle without removing.
|
|
|
|
### `always_use_skills` / `prefer_skills` / `avoid_skills`
|
|
|
|
Skill routing preferences:
|
|
|
|
```yaml
|
|
always_use_skills:
|
|
- debug-like-expert
|
|
prefer_skills:
|
|
- frontend-design
|
|
avoid_skills: []
|
|
```
|
|
|
|
Skills can be bare names (looked up in `~/.agents/skills/` and `.agents/skills/`) or absolute paths.
|
|
|
|
### `skill_rules`
|
|
|
|
Situational skill routing with human-readable triggers:
|
|
|
|
```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`
|
|
|
|
Durable instructions appended to every session:
|
|
|
|
```yaml
|
|
custom_instructions:
|
|
- "Always use TypeScript strict mode"
|
|
- "Prefer functional patterns over classes"
|
|
```
|
|
|
|
For project-specific knowledge (patterns, gotchas, lessons learned), use `.sf/KNOWLEDGE.md` instead — it's injected into every agent prompt automatically. Add entries with `/knowledge rule|pattern|lesson <description>`.
|
|
|
|
### `RUNTIME.md` — Runtime Context (v2.39)
|
|
|
|
Declare project-level runtime context in `.sf/RUNTIME.md`. This file is inlined into task execution prompts, giving the agent accurate information about your runtime environment without relying on hallucinated paths or URLs.
|
|
|
|
**Location:** `.sf/RUNTIME.md`
|
|
|
|
**Example:**
|
|
|
|
```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
|
|
```
|
|
|
|
Use this for information that the agent needs during execution but that doesn't belong in `DECISIONS.md` (architectural) or `KNOWLEDGE.md` (patterns/rules). Common examples: API base URLs, service ports, deployment targets, and environment-specific configuration.
|
|
|
|
### `dynamic_routing`
|
|
|
|
Complexity-based model routing. See [Dynamic Model Routing](./dynamic-model-routing.md).
|
|
|
|
```yaml
|
|
dynamic_routing:
|
|
enabled: true
|
|
capability_routing: true # score models by task capability (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)
|
|
|
|
Controls observation masking and tool result truncation during autonomous mode sessions. Reduces context bloat between compactions with zero LLM overhead.
|
|
|
|
```yaml
|
|
context_management:
|
|
observation_masking: true # replace old tool results with placeholders (default: true)
|
|
observation_mask_turns: 8 # keep results from last N user turns (1-50, default: 8)
|
|
compaction_threshold_percent: 0.70 # target compaction at 70% context usage (0.5-0.95, default: 0.70)
|
|
tool_result_max_chars: 800 # cap individual tool result content (200-10000, default: 800)
|
|
```
|
|
|
|
### `service_tier` (v2.42)
|
|
|
|
OpenAI service tier preference for supported models. Toggle with `/fast`.
|
|
|
|
| Value | Behavior |
|
|
|-------|----------|
|
|
| `"priority"` | Priority tier — 2x cost, faster responses |
|
|
| `"flex"` | Flex tier — 0.5x cost, slower responses |
|
|
| (unset) | Default tier |
|
|
|
|
```yaml
|
|
service_tier: priority
|
|
```
|
|
|
|
### `forensics_dedup` (v2.43)
|
|
|
|
Opt-in: search existing issues and PRs before filing from `/forensics`. Uses additional AI tokens.
|
|
|
|
```yaml
|
|
forensics_dedup: true # default: false
|
|
```
|
|
|
|
### `show_token_cost` (v2.44)
|
|
|
|
Opt-in: show per-prompt and cumulative session token cost in the footer.
|
|
|
|
```yaml
|
|
show_token_cost: true # default: false
|
|
```
|
|
|
|
### `auto_visualize`
|
|
|
|
Show the workflow visualizer automatically after milestone completion:
|
|
|
|
```yaml
|
|
auto_visualize: true
|
|
```
|
|
|
|
See [Workflow Visualizer](./visualizer.md).
|
|
|
|
### `parallel`
|
|
|
|
Run multiple milestones simultaneously. Disabled by default.
|
|
|
|
```yaml
|
|
parallel:
|
|
enabled: false # Master toggle
|
|
max_workers: 2 # Concurrent workers (1-4)
|
|
budget_ceiling: 50.00 # Aggregate cost limit in USD
|
|
merge_strategy: "per-milestone" # "per-slice" or "per-milestone"
|
|
auto_merge: "confirm" # "auto", "confirm", or "manual"
|
|
```
|
|
|
|
See [Parallel Orchestration](./parallel-orchestration.md) for full documentation.
|
|
|
|
## Full Example
|
|
|
|
```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 /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
|
|
---
|
|
```
|