Skip to content

Configuration

Everything personal lives in ~/.config/loadout/config.yaml. It is the only file you maintain.

version: 1
paths:
project_root: ~/Projects
venv_root: ~/.venv
git:
main_branch: main
dev_branch: development
identities:
- id: personal
git_user: Your Name
email: you@example.com
ssh_key: ~/.ssh/id_ed25519
default: true
workspaces:
- name: api
path: ~/Projects/api/api.code-workspace
tmux_session: api
hosts:
- alias: staging
hostname: staging.example.com
user: deploy
key: ~/.ssh/deploy
packs: [ansible, cloudflared]

Every section is optional except version. A section you leave out simply produces no aliases — a configuration with no hosts generates no host shortcuts, and msh reports that it needs some.

The full field-by-field listing is in the configuration schema. This page is about how the file behaves.

Config values reach the generated shell as data, not as text substitution you have to think about. Paths are written in $HOME form rather than with a tilde, because a tilde does not expand inside double quotes and an interpolated "~/Projects" produces a literal directory called ~. That was a real bug, and there is now a test that fails on any "~/ appearing in generated output.

The same config.yaml landing on a laptop and a headless server will reference things that exist on only one of them.

Most of that needs no special handling. An entry whose binary or path is missing degrades to a doctor finding rather than generating something broken — that is what the requires mechanism is for, and it removes the need for a profile system.

For values that genuinely differ per machine rather than merely being absent, ~/.config/loadout/local.yaml overlays config.yaml:

# ~/.config/loadout/local.yaml — this machine only
paths:
project_root: /srv/work

Two files, one merge step, no profile machinery. local.yaml is never synced — that is its entire purpose. See Sync.

Scalars replace. Maps merge key by key. Lists replace wholesale, so an overlay that sets packs replaces the list rather than appending to it.

loadout apply refuses to render an invalid configuration rather than generating something odd and letting you discover it later.

Errors name the file, the key, what was expected, and what to do:

loadout.toml:12 unknown key `git.user`
expected one of: git.name, git.email, git.signing_key
run `loadout doctor` to check the whole config

A few rules are worth knowing because they exist to prevent silent breakage:

  • Two credentials resolving to the same environment variable is rejected. Otherwise one would overwrite the other and the loser would be whichever sorted last.
  • A credential active on an entry not in its entries list is rejected. That state is always a typo.
  • A host password must be cred:<name>, never a literal. See Credentials.

Three ways, all writing the same file:

Terminal window
loadout init # create it, interactively
loadout ui # browse and toggle in a browser
$EDITOR ~/.config/loadout/config.yaml

Whichever you use, the file is only half the story. Run loadout apply afterwards, or nothing in your shell changes.

loadout describe <command> names the configuration sections that shape a given command, so you can work backwards from a command that is not behaving to the section it reads:

Terminal window
loadout describe pw

reports that pw is shaped by workspaces, editors and paths.project_root, and tells you which of those are currently satisfied on this machine.