CONFIGURATION LAYERS
The primitives that make up Swamp —
behaviors, workflows, vaults, extensions, skills, and data
— need configuration to do useful work, and that configuration comes from four
sources: .swamp.yaml (repo-level, checked into version control),
swamp config set (user-level, stored in ~/.config/swamp/), environment
variables prefixed with SWAMP_, and CLI flags. Precedence follows a strict
order: CLI flags override environment variables, which override user config,
which overrides repo config, which overrides built-in defaults.
This layering exists because different decisions belong to different scopes.
Repo config (.swamp.yaml) holds settings the whole team shares: which behavior
types to trust, auto-GC policies, datastore backend selection. These belong in
version control because they define how the repo behaves — changing the trusted
collective list or the garbage collection window affects everyone who works in
the repo. See the
repository configuration reference
for the full .swamp.yaml schema.
User config holds personal preferences: log verbosity, telemetry opt-out, default output format. These should not be version-controlled because one developer's preference for debug-level logging shouldn't force that on the rest of the team.
Environment variables provide the override layer for CI/CD pipelines and
scripted environments. Swamp uses the SWAMP_ prefix convention — variables
like SWAMP_REPO_DIR, SWAMP_LOG_LEVEL, SWAMP_NO_TELEMETRY, and
SWAMP_DATASTORE — so there is no ambiguity about which env vars belong to
Swamp versus the surrounding toolchain. The one deliberate exception is
DO_NOT_TRACK, covered below. Env vars always win over
both config files, which means a CI pipeline can force specific settings without
forking the repo's .swamp.yaml or modifying user config on ephemeral runners.
CLI flags sit at the top of the precedence chain for one-off overrides: a
developer running a single command with --log-level debug shouldn't need to
change any persisted configuration.
Serve-specific config: .swamp/serve.yaml
swamp serve adds a fifth source that sits alongside the repo-level
.swamp.yaml: a server config file at .swamp/serve.yaml (or a custom path via
--config). It exists because the settings it holds — port, timeouts, webhook
registrations, multi-instance tuning — are operational concerns of a running
server instance, not properties of the repository's shared behavior/workflow
definitions. A team's .swamp.yaml travels with the repo and belongs in version
control; a server's bind address and TLS proxy settings vary per deployment and
do not.
The serve config file occupies the same precedence slot as .swamp.yaml — below
environment variables and CLI flags, above built-in defaults. Within that slot
the two files are complementary, not competing: .swamp.yaml configures the
repo, .swamp/serve.yaml configures the server. Security-sensitive settings
(authentication mode, admin identity, TLS certificates) are excluded from the
serve config file entirely and remain CLI-only or environment-variable- only.
See Serve Flags — Config file for the full schema and supported keys.
Telemetry opt-outs
Usage telemetry is the one setting that does not follow this precedence. Its
opt-outs — the user's telemetry.collection, a repository's
telemetryDisabled, SWAMP_NO_TELEMETRY, DO_NOT_TRACK, and --no-telemetry
— combine rather than override each other. If any layer says off, telemetry is
off, and no layer can turn it back on.
An opt-out is a statement of consent, and consent belongs to the person it
concerns. Under ordinary precedence, SWAMP_NO_TELEMETRY=0 in a shared CI
template would outrank a developer's own user setting, and a repository's
.swamp.yaml, committed by someone else, would decide for everyone who clones
it. Earlier versions of Swamp had a version of this problem: the user-level
opt-out was read only outside repositories, so it stopped applying at the first
repository a user worked in. Making every opt-out final means each layer can
only widen what is switched off. A user who opts out is opted out in every
repository, and a team that opts out a repository covers everyone who works in
it, whatever their own setting.
DO_NOT_TRACK breaks the SWAMP_ prefix convention on purpose. It is a
cross-tool variable: set once in a shell profile or a CI image, it opts out of
every tool that honours it, so a user does not have to find each tool's own
switch.
See the Usage Telemetry reference for each opt-out and its scope.
Tradeoffs
The tradeoff this design makes is explicitness over convenience. Rather than merging configuration from implicit locations, each layer has a clear scope and a predictable override relationship. When something behaves unexpectedly, the precedence order tells you exactly where to look.