Settings
Where settings.toml lives, per-key precedence, captain init, and how bad values are handled.
Captain Barbossa reads optional settings from .captain/settings.toml. There is no required configuration: with no file anywhere, every setting falls back to the built-in default and nothing warns about it.
Where the files live#
| File | Scope |
|---|---|
<project>/.captain/settings.toml | This project only. Commit it to share the settings with the repo, or ignore it to keep them yours. |
~/.captain/settings.toml | Every project on this machine. |
captain_barbossa/defaults.toml | The shipped defaults, inside the installed package. The bottom layer, not meant to be edited. |
defaults.toml is the single source of the shipped defaults: the tier table the code resolves against is read from it, and captain init writes it back out with the values commented, so the defaults, the code, and the template cannot drift apart.
The project root is the one the rest of the CLI uses: $CAPTAIN_PROJECT when a captain set it, otherwise the enclosing git repository, otherwise the current directory.
Precedence#
Settings resolve per key, not per file or per table:
project key > global key > defaults.tomlA file that sets one key overrides only that key. Everything it leaves out keeps falling back. So these two files:
[captain]
model = "strong"
[models.claude]
cheap = "sonnet"[models.claude]
cheap = "fable"resolve to [captain] model = "strong" (only the global file sets it), [models.claude] cheap = "claude-fable-5-1" (the project file wins), and mid/strong still on their built-in defaults (neither file mentions them). CLI flags still win over settings for one invocation.
captain init#
captain init # writes <project>/.captain/settings.toml
captain init --global # writes ~/.captain/settings.tomlinit writes a template with every setting commented out at its current default, so a freshly written file changes nothing until you uncomment a line. It creates the .captain directory if needed and prints the path it wrote. --global is the only flag, and init needs no Herdr pane, so it works from any shell.
What can be configured#
| Table | Covers |
|---|---|
[captain] | The captain's CLI and optional starting model. |
[crew] | The default crew model and wait timeout. |
[dashboard] | Automatic launch, refresh interval, pane ratio, context limit, and price-file override. See dashboard. |
[placement] | The captain-tab and crew-tab shapes. See placement. |
[models.<provider>] | The model behind each provider-neutral tier. See models. |
- An empty
[captain] modelpasses no model flag, leaving the choice to the native CLI. pihas no fixed catalogue: its tiers are ranked frompi --list-models, and overrides use theprovider/modelIDs pi prints.- Dashboard
prices_fileexpands~. Changingintervalneeds no captain restart, because the dashboard reads it in its own process.
The commented list of every shipped key and default is exactly what captain init writes, so the authoritative reference is the file on your own disk.
Unknown and invalid values#
| Situation | What happens |
|---|---|
A tier value in [models.<provider>] matching no known model | Kept literally and passed to that CLI as written, so a model newer than this release still works. |
[captain] model matching no known model | The launch fails, naming the options: No claude model matches 'gigantic'. Tiers: cheap, mid, strong. |
[captain] agent outside claude, codex, pi, grok | The launch fails naming them, rather than trying to run it. |
A value of the wrong type (model = 123, enabled = "true") | Ignored, falling back to the shipped default. Nothing is coerced across types. The one latitude is an int where a float is wanted, so interval = 5 works. |
A malformed [placement] shape | The one exception: it fails loudly. See placement validation. |
| An unknown table or key | Ignored. |
The difference between the first two rows is deliberate. A [models.*] tier is a pass-through to the CLI, while [captain] model is resolved up front, so a typo fails loudly at launch instead of silently starting the wrong model.
Malformed files#
A file that is not valid TOML is an error naming the file, and no command runs with half-read settings:
captain: Could not read settings from /path/to/.captain/settings.toml: Expected ']'
at the end of a table declaration (at line 1, column 9)An unreadable file — permissions, or a directory in its place — reports the same way. A file that simply does not exist is not an error: that is the normal case.