mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-10-16 04:33:16 +00:00
## Summary
Provider `extra_headers` previously required values to be typed TOML
tables (`{ env = "X" }`, `{ literal = "Y" }`, `{ vault = "Z" }`). This
PR migrates them to the project's standard interpolation string format:
plain text for literals, `{{ env.NAME }}` tokens for environment
variables, and `{{ secrets.NAME }}` tokens for vault secrets. This
brings `extra_headers` in line with the rest of the interpolation system
and unlocks mixed-segment values like `Bearer {{ secrets.GATEWAY_TOKEN
}}`.
### What changed and why
**Config authoring surface (`fabro-config`):**
`ProviderSettings.extra_headers` changes from `Option<HashMap<String,
HeaderValueRef>>` to `Option<HashMap<String, InterpString>>`. The
`Combine` impl and all re-exports are updated accordingly.
**Catalog layer (`fabro-model`):**
`ProviderCatalogSettings.extra_headers` and
`CatalogProvider.extra_headers` become `HashMap<String, String>` — raw
interpolation source strings. This is required by the crate dependency
direction: `fabro-types` (which owns `InterpString`) depends on
`fabro-model`, so `fabro-model` cannot hold `InterpString` without
creating a cycle. The source string is re-parsed and resolved in
`fabro-auth` at credential-build time.
**Credential resolution (`fabro-auth`):** Both `CredentialResolver`
(vault-backed) and `EnvCredentialSource` (env-only) are rewritten to
parse each header source string as an `InterpString` and resolve it with
a `ResolveCtx` scoped to `env` + `secrets` only. A new
`resolve_extra_headers` helper is shared between the two paths. Vault
resolution uses `vault_token_lookup`, which wraps `vault_get_token` and
maps any non-Token vault entry to `None` — so file and OAuth vault
entries fail closed rather than resolving incorrectly. `vars.*` and
`inputs.*` tokens are not in scope and produce `Unavailable` errors
automatically.
**New error variant:** `ResolveError::Interpolation { provider, source
}` surfaces header resolution failures as diagnosable auth issues. The
inner `source` (an `InterpResolveError`) names only the token namespace
and name — never a resolved value.
**`{ literal = "..." }` guardrail removed:** `HeaderValueRef`
deliberately rejected bare string header values to discourage pasting
credentials. `InterpString` accepts any string. This is an intentional
change; the mitigation is documentation — use `{{ secrets.NAME }}` for
credential-shaped values, not bare literals.
**Redactor registration gap (noted, not fixed here):** Secrets resolved
into provider headers at the credential boundary do not flow through the
run boundary's exact-match redaction registry. Exposure is low (headers
are host-side and outbound-only, never logged), but a follow-up should
thread a registering lookup through `VaultCredentialSource`. A code
comment at the resolution site marks the gap.
### Breaking change
Existing `extra_headers` config using `{ env = "X" }`, `{ literal = "Y"
}`, or `{ vault = "Z" }` table syntax **will fail to parse** after this
change. Users must migrate to the token form: plain strings for
literals, `{{ env.X }}` for env vars, `{{ secrets.X }}` for vault
secrets. A changelog entry is included.
### Plan Summary
- Update `ProviderSettings.extra_headers` → `InterpString` in
`fabro-config`
- Collapse authoring `InterpString` → source `String` in
`provider_settings_to_catalog` (allowlisted `as_source()` call)
- Delete `HeaderValueRef` and its serde/display/parse machinery from
`fabro-model`
- Rewrite both auth resolution paths to use `InterpString::parse +
resolve_with`; add `Interpolation` error variant
- Add `vault_token_lookup` helper for token-only fail-closed vault
resolution
- Update test TOML in `fabro-llm`, builtin catalog comment in
`openrouter.toml`, and all hand-written + generated docs
### Fabro Details
<details>
<summary>Ran 8 stages in 108m 43s for $34.44</summary>
| Stage | Duration | Cost | Retries |
|---|---|---|---|
| start | 0s | – | 0 |
| toolchain | 1s | – | 0 |
| preflight_compile | 5m 33s | – | 0 |
| preflight_lint | 5m 59s | – | 0 |
| implement | 43m 23s | $17.34 | 0 |
| simplify_fable | 32m 49s | $13.09 | 0 |
| simplify_gpt | 6m 25s | $4.01 | 0 |
| verify | 13m 58s | – | 0 |
| **Total** | **108m 43s** | **$34.44** | **0** |
</details>
<details>
<summary>Ran <code>ImplementPlan.fabro</code> (11 nodes and 14
edges)</summary>
```dot
digraph ImplementPlan {
graph [
goal="Implement and simplify",
model_stylesheet="
* { model: claude-opus-4-8; }
"
]
rankdir=LR
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
toolchain [label="Toolchain", shape=parallelogram, script="command -v cargo >/dev/null || { curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && sudo ln -sf $HOME/.cargo/bin/* /usr/local/bin/; }; cargo --version 2>&1", max_retries=0]
preflight_compile [label="Preflight Compile", shape=parallelogram, script="cargo check -q --workspace 2>&1", max_retries=0]
preflight_lint [label="Preflight Lint", shape=parallelogram, script="cargo +nightly-2026-04-14 clippy -q --workspace --all-targets -- -D warnings 2>&1", max_retries=0]
fix_lints [label="Fix Lints", prompt="The preflight lint step failed. Read the build output from context and fix all clippy lint warnings.", max_visits=3]
implement [label="Implement", prompt="Read the plan file referenced in the goal and implement every step. Make all the code changes described in the plan. Use red/green TDD. Be sure to use the rust-style-guide skill to help you follow this repo's Rust style conventions.", model="gpt-55", reasoning_effort="xhigh"]
simplify_fable [label="Simplify (Fable)", prompt="@prompts/simplify.md", model="claude-fable-5", reasoning_effort="xhigh"]
simplify_gpt [label="Simplify (GPT-55)", prompt="@prompts/simplify.md", model="gpt-55"]
verify [label="Verify", shape=parallelogram, timeout="1800s", script="git fetch origin main 2>&1 && git merge --no-edit --no-stat origin/main 2>&1 && cargo +nightly-2026-04-14 fmt --all 2>&1 && cargo dev docs refresh 2>&1 && cargo +nightly-2026-04-14 fmt --check --all 2>&1 && { command -v rg >/dev/null 2>&1 || { echo 'rg is required for verify'; exit 127; }; } && ! rg -n 'AuthMode::Disabled|RunAuthMethod|RunSubjectProvenance|\bActorRef\b|\bActorKind\b|AuthenticatedSubject|AuthenticatedService|AuthorizeRunScoped|AuthorizeRunBlob|AuthorizeStageArtifact|AuthorizeCommandLog|auth_method\s*==\s*\"disabled\"' lib/crates apps lib/packages docs/public/api-reference/fabro-api.yaml 2>&1 && cargo +nightly-2026-04-14 clippy --workspace --all-targets -- -D warnings 2>&1 && cargo nextest run --workspace --status-level slow --profile ci 2>&1 && cargo dev docs check 2>&1 && bun install --frozen-lockfile 2>&1 && (cd apps/fabro-web && bun run typecheck) 2>&1 && (cd apps/fabro-web && bun run test) 2>&1 && (cd lib/packages/fabro-api-client && bun run typecheck) 2>&1 && cargo dev build -- -p fabro-cli --release 2>&1", goal_gate=true, retry_target="fixup"]
fixup [label="Fixup", prompt="The verify step failed. Read the build output from context and fix all format, clippy, Rust test, docs, TypeScript typecheck/test, and build failures.", max_visits=3]
start -> toolchain
toolchain -> preflight_compile [condition="outcome=succeeded"]
toolchain -> exit
preflight_compile -> preflight_lint [condition="outcome=succeeded"]
preflight_compile -> exit
preflight_lint -> implement [condition="outcome=succeeded"]
preflight_lint -> fix_lints
fix_lints -> preflight_lint
implement -> simplify_fable -> simplify_gpt -> verify
verify -> exit [condition="outcome=succeeded"]
verify -> fixup
fixup -> verify
}
```
</details>
⚒️ Generated with [Fabro](https://fabro.sh)
---------
Co-authored-by: Fabro <noreply@fabro.sh>
474 lines
18 KiB
Text
474 lines
18 KiB
Text
---
|
|
title: "Settings Configuration"
|
|
description: "Configure CLI and shared machine defaults with settings.toml"
|
|
---
|
|
|
|
Fabro loads machine defaults from `~/.fabro/settings.toml`. The file is optional. If it does not exist, Fabro falls back to built-in defaults.
|
|
|
|
The CLI and server each read the sections relevant to their own process. On a remote deployment, the CLI machine and the server machine each have their own `settings.toml`.
|
|
|
|
<Note>
|
|
Fabro only reads `settings.toml`. Older `cli.toml`, `user.toml`, and `server.toml` filenames are no longer part of the supported config surface.
|
|
</Note>
|
|
|
|
## File location
|
|
|
|
The default path is `~/.fabro/settings.toml`.
|
|
|
|
Use `fabro server start --config /path/to/settings.toml` if the server should read a different file.
|
|
|
|
## Schema version
|
|
|
|
Every Fabro config file must declare its schema version with a top-level `_version` key:
|
|
|
|
```toml title="settings.toml"
|
|
_version = 1
|
|
```
|
|
|
|
Files that omit `_version` are treated as version `1`. The legacy top-level `version` key is no longer accepted and raises a targeted rename hint.
|
|
|
|
## Who reads what
|
|
|
|
`settings.toml` uses the same schema as `.fabro/project.toml` and `workflow.toml`, but each process only reads the fields it understands. The top-level schema is strictly namespaced — the only allowed domains are `[project]`, `[workflow]`, `[run]`, `[llm]`, `[cli]`, and `[server]`.
|
|
|
|
| Scope | Examples |
|
|
|---|---|
|
|
| CLI-only | `[cli.target]`, `[cli.auth]`, `[cli.exec]`, `[cli.output]`, `[cli.updates]`, `[cli.logging]` |
|
|
| Shared run defaults | `[run.model]`, `[run.environment]`, `[environments.<slug>]`, `[run.checkpoint]`, `[run.inputs]`, `[run.prepare]`, `[run.pull_request]`, `[run.integrations.github.permissions]`, `[run.hooks]`, `[run.agent.mcps]` |
|
|
| Shared LLM catalog | `[llm.providers.<id>]`, `[llm.models.<id>]`, model limits, features, controls, and costs |
|
|
| Server-only | `[server.listen]`, `[server.api]`, `[server.web]`, `[server.auth]`, `[server.storage]`, `[server.artifacts]`, `[server.slatedb]`, `[server.scheduler]`, `[server.logging]`, `[server.integrations]` |
|
|
|
|
`[cli.*]` and `[server.*]` stanzas are owner-specific: they are only consumed from `~/.fabro/settings.toml` (plus process-local flags and env overrides). The same stanzas in `.fabro/project.toml` or `workflow.toml` remain schema-valid but runtime-inert.
|
|
|
|
See [Server Configuration](/administration/server-configuration) for the server-owned sections.
|
|
|
|
## Precedence
|
|
|
|
Shared layered domains (`[project]`, `[workflow]`, `[run]`) use this override order:
|
|
|
|
1. **CLI flags** — always win
|
|
2. **Environment overrides** — Fabro-defined override channels
|
|
3. **`workflow.toml`** — per-workflow overrides
|
|
4. **`.fabro/project.toml`** — project defaults
|
|
5. **`~/.fabro/settings.toml`** — machine defaults
|
|
6. **Built-in defaults**
|
|
|
|
Owner-specific domains (`[cli.*]`, `[server.*]`) use a narrower trust boundary — only CLI flags, env overrides, `~/.fabro/settings.toml`, and built-in defaults apply.
|
|
|
|
## Full example
|
|
|
|
```toml title="settings.toml"
|
|
_version = 1
|
|
|
|
[cli.target]
|
|
type = "http"
|
|
url = "https://fabro.example.com/api/v1"
|
|
|
|
[cli.exec]
|
|
prevent_idle_sleep = true
|
|
|
|
[cli.exec.model]
|
|
provider = "anthropic"
|
|
name = "claude-opus-4-6"
|
|
|
|
[cli.exec.agent]
|
|
permissions = "read-write"
|
|
|
|
[cli.output]
|
|
format = "text"
|
|
verbosity = "normal"
|
|
|
|
[cli.updates]
|
|
check = true
|
|
|
|
[cli.logging]
|
|
level = "info"
|
|
|
|
[llm.providers.proxy]
|
|
display_name = "Acme Gateway"
|
|
adapter = "openai_compatible"
|
|
base_url = "https://llm-gateway.example.com/v1"
|
|
aliases = ["gateway"]
|
|
|
|
[llm.providers.proxy.auth]
|
|
credentials = ["env:ACME_GATEWAY_API_KEY", "vault:ACME_GATEWAY_API_KEY"]
|
|
|
|
[llm.providers.proxy.extra_headers]
|
|
x-portkey-api-key = "{{ env.PORTKEY_API_KEY }}"
|
|
x-portkey-config = "@bedrock-prod"
|
|
|
|
[llm.models."team-code-large"]
|
|
provider = "proxy"
|
|
api_id = "provider-wire-model-name"
|
|
agent_profile = "anthropic"
|
|
display_name = "Team Code Large"
|
|
default = true
|
|
aliases = ["team-code"]
|
|
|
|
[llm.models."team-code-large".controls]
|
|
reasoning_effort = ["low", "medium", "high"]
|
|
speed = ["fast"]
|
|
|
|
[llm.models."team-code-large".costs]
|
|
input_cost_per_mtok = 1.50
|
|
output_cost_per_mtok = 8.00
|
|
|
|
[llm.models."team-code-large".costs.speed.fast]
|
|
input_cost_per_mtok = 3.00
|
|
output_cost_per_mtok = 16.00
|
|
|
|
[run.model]
|
|
name = "claude-sonnet-4-5"
|
|
|
|
[run.git.author]
|
|
name = "fabro-bot"
|
|
email = "fabro-bot@company.com"
|
|
|
|
[run.pull_request]
|
|
enabled = true
|
|
|
|
[run.integrations.github.permissions]
|
|
contents = "write"
|
|
pull_requests = "write"
|
|
|
|
[run.agent.mcps.filesystem]
|
|
type = "stdio"
|
|
command = ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/workspace"]
|
|
startup_timeout = "15s"
|
|
tool_timeout = "90s"
|
|
|
|
[run.agent.mcps.filesystem.env]
|
|
NODE_ENV = "production"
|
|
|
|
[run.agent.mcps.sentry]
|
|
type = "http"
|
|
url = "https://mcp.sentry.dev/mcp"
|
|
|
|
[run.agent.mcps.sentry.headers]
|
|
Authorization = "Bearer sk-xxx"
|
|
```
|
|
|
|
All fields are optional. Include only the sections and keys you want to override. A single file can still include both CLI and server sections when you run both processes on one machine, but explicit remote targets do not read remote server state from the local machine.
|
|
|
|
{/* generated:options */}
|
|
## `[cli.target]`
|
|
|
|
Connection info for commands that target a remote Fabro server.
|
|
|
|
```toml title="settings.toml"
|
|
[cli.target]
|
|
type = "http"
|
|
url = "https://fabro.example.com/api/v1"
|
|
```
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `type` | `"http"` \| `"unix"` | None | Explicit transport selection. |
|
|
| `url` | string | None | Required for `type = "http"`; the API base URL. |
|
|
| `path` | string | None | Required for `type = "unix"`; the absolute Unix socket path. |
|
|
|
|
## `[llm.providers.<id>]`
|
|
|
|
Define or override an LLM provider. Provider IDs are strings, so custom
|
|
providers can be added when they use an adapter Fabro already supports.
|
|
|
|
```toml title="settings.toml"
|
|
[llm.providers.proxy]
|
|
display_name = "Acme Gateway"
|
|
adapter = "openai_compatible"
|
|
base_url = "https://llm-gateway.example.com/v1"
|
|
priority = 50
|
|
enabled = true
|
|
aliases = ["gateway"]
|
|
|
|
[llm.providers.proxy.auth]
|
|
credentials = ["env:ACME_GATEWAY_API_KEY", "vault:ACME_GATEWAY_API_KEY"]
|
|
|
|
[llm.providers.proxy.extra_headers]
|
|
x-portkey-api-key = "{{ env.PORTKEY_API_KEY }}"
|
|
x-portkey-config = "@bedrock-prod"
|
|
x-team-secret = "{{ secrets.gateway_team_secret }}"
|
|
```
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `display_name` | string | provider ID | Human-readable provider name. |
|
|
| `adapter` | string | built-in value | Adapter registry key, such as `"anthropic"`, `"openai"`, `"gemini"`, or `"openai_compatible"`. Required for new providers. |
|
|
| `agent_profile` | `"anthropic"` \| `"openai"` \| `"gemini"` | derived from `adapter` | Agent profile used for project memory, CLI/ACP command selection, and native session routing. Override only when a provider needs profile behavior different from its adapter. |
|
|
| `billing_policy` | `"openai"` \| `"anthropic"` \| `"gemini"` \| `"none"` | derived from `adapter` | Provider-owned billing algorithm for usage estimates. Override for exceptional providers such as local no-billing runtimes. |
|
|
| `base_url` | string | built-in value or adapter runtime default | Provider API base URL. Required for most custom OpenAI-compatible providers. |
|
|
| `auth` | table | omitted | API-key auth config. Omit the table entirely for providers that need no API key; any `extra_headers` are still attached. |
|
|
| `auth.credentials` | array<string> | required when `auth` present | Ordered credential refs. Accepted forms are `vault:<NAME>`, `env:<NAME>`, and `aws_sigv4` (sign requests from the AWS default credential chain — Bedrock). Literal secret strings are rejected. |
|
|
| `auth.header` | `"bearer"` or `{ custom = "Header-Name" }` | `"bearer"` | Primary API-key header policy. Omit when the provider uses a standard bearer token. |
|
|
| `extra_headers` | table | `{}` | Additional headers attached to provider requests. Values are interpolation strings: literal text, an `{{ env.NAME }}` token, or a `{{ secrets.NAME }}` token. Put credentials in a secret and reference them with a `{{ secrets.NAME }}` token, not a bare literal. |
|
|
| `priority` | integer | `0` | Higher-priority configured providers win default selection; ties use canonical provider ID. |
|
|
| `enabled` | boolean | `true` | Set `false` to disable a provider after lower-precedence layers define it. |
|
|
| `aliases` | array<string> | `[]` | Additional provider names accepted by model routing and fallback config. |
|
|
|
|
## `[llm.models.<id>]`
|
|
|
|
Define or override a model in the catalog. The table key is the canonical
|
|
model ID Fabro users reference; `api_id` is the model string sent to the
|
|
provider API.
|
|
|
|
```toml title="settings.toml"
|
|
[llm.models."team-code-large"]
|
|
provider = "proxy"
|
|
api_id = "provider-wire-model-name"
|
|
agent_profile = "anthropic"
|
|
display_name = "Team Code Large"
|
|
family = "team-code"
|
|
default = true
|
|
probe = true
|
|
enabled = true
|
|
aliases = ["team-code"]
|
|
estimated_output_tps = 80
|
|
|
|
[llm.models."team-code-large".limits]
|
|
context_window = 200000
|
|
max_output = 32000
|
|
|
|
[llm.models."team-code-large".features]
|
|
tools = true
|
|
vision = false
|
|
reasoning = true
|
|
reasoning_effort = "levels"
|
|
prompt_cache = true
|
|
|
|
[llm.models."team-code-large".controls]
|
|
reasoning_effort = ["low", "medium", "high"]
|
|
speed = ["fast"]
|
|
|
|
[llm.models."team-code-large".costs]
|
|
input_cost_per_mtok = 1.50
|
|
output_cost_per_mtok = 8.00
|
|
cache_input_cost_per_mtok = 0.30
|
|
|
|
[llm.models."team-code-large".costs.speed.fast]
|
|
input_cost_per_mtok = 3.00
|
|
output_cost_per_mtok = 16.00
|
|
cache_input_cost_per_mtok = 0.60
|
|
```
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `provider` | string | None | Provider ID this model belongs to. |
|
|
| `api_id` | string | model ID | Identifier sent to the provider API. |
|
|
| `agent_profile` | `"anthropic"` \| `"openai"` \| `"gemini"` | provider profile | Agent profile override for this model. Model overrides take precedence over provider overrides. |
|
|
| `billing_policy` | `"openai"` \| `"anthropic"` \| `"gemini"` \| `"none"` | provider policy | Billing algorithm override for this model — for models whose billing family differs from their provider's (e.g. Claude served through OpenRouter bills Anthropic-style cache reads/writes). |
|
|
| `display_name` | string | model ID | Human-readable model name. |
|
|
| `family` | string | model ID | Family label used for catalog display and matching. |
|
|
| `training` | string | None | Training data cutoff label. |
|
|
| `knowledge_cutoff` | string or TOML date | None | Public knowledge cutoff label; TOML dates normalize to `YYYY-MM-DD`. |
|
|
| `default` | boolean | `false` | Whether this is the provider default model. |
|
|
| `probe` | boolean | `false` | Whether this model should be preferred for provider connectivity probes. Set `false` in a higher-precedence layer to clear an inherited probe marker. |
|
|
| `enabled` | boolean | `true` | Set `false` to disable a model after lower-precedence layers define it. |
|
|
| `aliases` | array<string> | `[]` | Additional model names accepted by routing and fallback config. |
|
|
| `estimated_output_tps` | number | None | Estimated output tokens per second for catalog display and planning. |
|
|
|
|
## `[llm.models.<id>.limits]`
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `context_window` | integer | None | Maximum context window size in tokens. |
|
|
| `max_output` | integer | None | Maximum output tokens, if known. |
|
|
|
|
## `[llm.models.<id>.features]`
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `tools` | boolean | `false` | Whether the model supports tool calls. |
|
|
| `vision` | boolean | `false` | Whether the model accepts image inputs. |
|
|
| `reasoning` | boolean | `false` | Whether the model has reasoning behavior. |
|
|
| `reasoning_effort` | `"levels"` \| `"always_adaptive"` \| `"none"` | `"none"` | Whether the model endpoint supports a native reasoning-effort parameter. `levels` accepts discrete effort levels; `always_adaptive` accepts effort levels with natively always-on adaptive thinking; `none` has no native effort parameter. |
|
|
| `prompt_cache` | boolean | `false` | Whether prompt cache pricing/usage applies. |
|
|
| `sampling_params` | boolean | `true` | Whether the model accepts classic sampling parameters (`temperature`, `top_p`). |
|
|
|
|
## `[llm.models.<id>.controls]`
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `reasoning_effort` | array<string> | all standard levels when feature is `"levels"` or `"always_adaptive"` | User-facing reasoning effort values Fabro may send for this model. Can be set explicitly for reasoning models whose provider adapter maps effort to a non-native API shape. |
|
|
| `speed` | array<string> | `[]` | Additional speeds beyond implicit `standard`; do not list `standard`. |
|
|
|
|
## `[llm.models.<id>.costs]`
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `input_cost_per_mtok` | number | None | Input cost in USD per million tokens. |
|
|
| `output_cost_per_mtok` | number | None | Output cost in USD per million tokens. |
|
|
| `cache_input_cost_per_mtok` | number | None | Cached input/read cost in USD per million tokens. |
|
|
|
|
## `[llm.models.<id>.costs.speed.<speed>]`
|
|
|
|
Per-speed cost overrides use the same keys as `[llm.models.<id>.costs]`.
|
|
Each `<speed>` key must be declared in `[llm.models.<id>.controls].speed`.
|
|
The `standard` speed is implicit and always uses the base cost table.
|
|
|
|
## `[cli.updates]`
|
|
|
|
`[cli.updates]` — upgrade check toggle
|
|
|
|
```toml title="settings.toml"
|
|
[cli.updates]
|
|
check = true
|
|
```
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `check` | boolean | true | Check for new Fabro releases during supported CLI commands. |
|
|
|
|
## `[cli.output]`
|
|
|
|
`[cli.output]` — generic CLI output defaults
|
|
|
|
```toml title="settings.toml"
|
|
[cli.output]
|
|
format = "text"
|
|
verbosity = "verbose"
|
|
```
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `format` | "text" \| "json" | "text" | Output format for commands that support machine-readable output. |
|
|
| `verbosity` | "quiet" \| "normal" \| "verbose" | "normal" | Default output verbosity. |
|
|
|
|
## `[cli.exec]`
|
|
|
|
`[cli.exec]` — `fabro exec` defaults
|
|
|
|
```toml title="settings.toml"
|
|
[cli.exec]
|
|
prevent_idle_sleep = true
|
|
```
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `prevent_idle_sleep` | boolean | false | Prevent idle sleep on macOS while an exec run is in flight. |
|
|
|
|
## `[cli.exec.model]`
|
|
|
|
```toml title="settings.toml"
|
|
[cli.exec.model]
|
|
provider = "anthropic"
|
|
name = "claude-opus-4-6"
|
|
```
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `name` | string | None | Model name for `fabro exec`. |
|
|
| `provider` | string | None | LLM provider for `fabro exec`. |
|
|
|
|
## `[cli.exec.agent]`
|
|
|
|
```toml title="settings.toml"
|
|
[cli.exec.agent]
|
|
permissions = "read-write"
|
|
```
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `mcps` | table | None | Agent-scoped MCP entries for `fabro exec`. |
|
|
| `permissions` | "read-only" \| "read-write" \| "full" | "read-write" | Tool permission level for `fabro exec`. |
|
|
|
|
## `[run.model]`
|
|
|
|
`[run.model]` — provider-neutral default model selection
|
|
|
|
```toml title="settings.toml"
|
|
[run.model]
|
|
provider = "anthropic"
|
|
name = "claude-sonnet-4-5"
|
|
fallbacks = ["openai", "gpt-5.4"]
|
|
```
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `fallbacks` | array<string> | [] | Ordered list of fallback model references. Supports `...` splice marker<br />at layering time — see [`super::splice_array`]. |
|
|
| `name` | string | None | Model name for workflow runs. |
|
|
| `provider` | string | None | Provider name for workflow model selection. |
|
|
|
|
## `[cli.logging]`
|
|
|
|
`[cli.logging]` — process-owned logging configuration for the CLI
|
|
|
|
```toml title="settings.toml"
|
|
[cli.logging]
|
|
level = "info"
|
|
```
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `level` | "error" \| "warn" \| "info" \| "debug" \| "trace" | "info" | Default CLI log level. |
|
|
|
|
## `[run.git.author]`
|
|
|
|
```toml title="settings.toml"
|
|
[run.git.author]
|
|
name = "fabro-bot"
|
|
email = "fabro-bot@company.com"
|
|
```
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `email` | string | "fabro@local" | Git author email for checkpoint commits. |
|
|
| `name` | string | "fabro" | Git author name for checkpoint commits. |
|
|
|
|
## `[run.pull_request]`
|
|
|
|
`[run.pull_request]` — provider-neutral PR behavior
|
|
|
|
```toml title="settings.toml"
|
|
[run.pull_request]
|
|
enabled = true
|
|
```
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `auto_merge` | boolean | false | Enable GitHub auto-merge for created pull requests. Implies `draft =<br />false`. |
|
|
| `draft` | boolean | true | Open created pull requests as drafts. |
|
|
| `enabled` | boolean | false | Automatically create a PR after successful runs. |
|
|
| `merge_strategy` | "merge" \| "squash" \| "rebase" | "squash" | Merge method to configure for the pull request. |
|
|
|
|
## `[run.agent]`
|
|
|
|
`[run.agent]` — agent knobs only (Fabro tools, permissions, MCPs)
|
|
|
|
```toml title="settings.toml"
|
|
[run.agent]
|
|
fabro_tools = true
|
|
permissions = "read-write"
|
|
```
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `fabro_tools` | boolean | false | Allow workflow agents to use Fabro run-management tools. |
|
|
| `mcps` | table | None | Agent-scoped MCP server entries, keyed by name. |
|
|
| `permissions` | "read-only" \| "read-write" \| "full" | "read-write" | Default tool permission level for workflow agents. |
|
|
|
|
## `[run.agent.mcps.<name>]`
|
|
|
|
Configure MCP servers for workflow agents. For `fabro exec`-only MCPs, use `[cli.exec.agent.mcps.<name>]` with the same shape.
|
|
|
|
```toml title="settings.toml"
|
|
[run.agent.mcps.filesystem]
|
|
type = "stdio"
|
|
command = ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/workspace"]
|
|
startup_timeout = "15s"
|
|
tool_timeout = "90s"
|
|
```
|
|
|
|
| Key | Type / values | Default | Description |
|
|
|---|---|---|---|
|
|
| `type` | `"stdio"` \| `"http"` \| `"sandbox"` | None | MCP transport type. |
|
|
| `command` | array<string> | None | Command and arguments for `stdio` or `sandbox` transports. |
|
|
| `script` | string | None | Shell script alternative to `command` for process-launching transports. |
|
|
| `url` | string | None | Remote MCP URL for `http` transport. |
|
|
| `port` | integer | None | Sandbox port for `sandbox` transport. |
|
|
| `env` | table | `{}` | Additional environment variables for process-launching transports. |
|
|
| `headers` | table | `{}` | HTTP headers for `http` transport. |
|
|
| `startup_timeout` | duration | `"10s"` | Max duration for startup and MCP handshake. |
|
|
| `tool_timeout` | duration | `"60s"` | Max duration for a single MCP tool call. |
|
|
|
|
See [MCP](/agents/mcp) for transport-specific examples.
|
|
{/* /generated:options */}
|