How it works¶
Splashdown is the glue between git and your env loader (mise, direnv, devbox). It installs a post-checkout git hook that forwards each checkout event to Splashdown, coexisting with your hook manager if you already use one. For a trusted clone, each checkout's free ports and other resources are allocated and handed to your loader automatically.
Run splash init once in your project. Splashdown walks the filesystem, identifies your apps and their frameworks, and writes a recipe (splashdown.toml) declaring per-checkout resources (ports, db urls, UUIDs, sim/emulator variants). On every git checkout or git worktree add, the post-checkout event handler checks clone trust and then allocates concrete values into a gitignored splashdown.env. Your shell-env loader (mise / direnv / devbox) sources that file automatically, so every process in the checkout sees the right PORT, DATABASE_URL, etc.
Four generated/config files end up in the project, and existing agent instructions may be updated:
| File | Committed? | Purpose |
|---|---|---|
splashdown.toml |
Yes | Recipe: project/apps/resources, team-shared targets, and optional trusted bootstrap commands |
splashdown.local.toml |
No (gitignored) | Per-checkout additional [targets.*] variants on top of the recipe's |
splashdown.env |
No (gitignored) | Generated KEY=VALUE env file, the default destination. Splashdown rewrites the keys the recipe declares and leaves everything else, so point [project] env_file at a shared .env when you prefer |
mise.toml (or .envrc / devbox.json) |
Yes | Your shell-env loader's config, gains a line that sources splashdown.env |
existing AGENTS.md / independent CLAUDE.md |
Yes | A managed block names each detected app's actual port variables, the configured env destination, and stable launch commands. No instruction file is created when neither exists, and a file another tool generates is left untouched |
The agent-guidance block is regenerated by every init path, including --overwrite. It explains that recipe ranges are allocation pools rather than assigned ports,
names the env destination your recipe configures, and directs agents away from numeric port
overrides. It never contains an allocated value, so the block is safe to commit, and it tells
agents to keep using the project's own scripts where those already read the environment.
deinit removes only the complete
sentinel-wrapped block. A CLAUDE.md that imports @AGENTS.md is skipped to avoid duplicate
instructions after any older complete local block is removed. Symlinked and non-regular
instruction files are never rewritten.
An AGENTS.md or CLAUDE.md that another tool generates is left alone. Splashdown recognizes
the generator header at the top of the file, prints the marker it found, and asks you to add,
replace, or remove the block in that file's source instead, because an edit here would be lost
on the generator's next sync. When there is a block to carry over, Splashdown prints it between
two rule lines so you can copy it straight into that source. deinit skips those files too. A
file that only mentions generated content in its prose is still updated normally.
The registry at ~/.local/state/splashdown/ is machine-wide, so when two checkouts both want port 8081 splashdown gives one of them 8082, even across unrelated repos.
Provision output is change-aware: the first run (or any run that allocates a new port or rewrites a file) prints only the changed vars and writer lines. A no-op run (git pull --rebase on a checkout already provisioned) collapses to one line:
This is what you see through a hook manager when nothing actually changed.
The hook does nothing until the clone has Splashdown trust, so a cloned repository cannot make an
installed Splashdown write recipe-controlled output. splash init grants no trust. Clone-local
splash trust grants sync and, when [bootstrap] is currently present, authorizes those
commands. It also installs the local post-checkout hook that init left for it. Only an actual linked-worktree creation can trigger
bootstrap automatically. See
Trusted worktree bootstrap.