Skip to content

Repository files navigation

splashdown

splashdown

CI codecov License: MIT

Per-checkout or per-worktree simulators, emulators, and dev ports for development.

Do you have any of these problems?

  • You installed an app on a simulator / emulator but you forgot which one.
  • You created two worktrees from the same project, and now the ports are clashing during dev or e2e testing.
  • You want to select a free port for a new project, so it doesn't conflict, but you don't know which one is free.

Splashdown solves them. Pin system resources to your checkouts, keep track of them globally, automatically select free ones when creating new worktrees.

📖 Full documentation: splashdown.dev

Install

brew install nielsmadan/tap/splashdown
# or, managed by mise
mise use -g pipx:splashdown

This puts splash on your PATH. The resource registry at $XDG_STATE_HOME/splashdown/ (default ~/.local/state/splashdown/) is shared across every repo on your machine.

Shell completion

splash ships bash/zsh tab-completion for subcommands, device types, and device-variant names. With Homebrew it is zero-touch, the formula installs the completion files. With any other install (mise, pipx, uv), add one line to your shell rc. splash bundles everything it needs, so there is no separate package to install and no bashcompinit step.

zsh (~/.zshrc):

eval "$(splash completion zsh)"

bash (~/.bashrc):

eval "$(splash completion bash)"

splash completion with no argument autodetects your shell. More detail at splashdown.dev/shell-completion.

Quick start

In any project (single app or monorepo, web or backend or mobile), splash init scans the filesystem, scaffolds the recipe, wires your loader and the post-checkout hook, then allocates ports for this checkout. Most popular frameworks are auto-detected, nothing to declare:

splash init
# scanning project…
#   detected: pnpm (apps/api/apps/web-admin)
#   apps/api          → node-backend
#   apps/web-admin    → vite
#   shell loader      → mise
# wrote splashdown.toml + splashdown.local.toml + mise.toml + post-checkout hook
# allocating ports…  PORT=9081  WEB_DEV_PORT=5174
# wrote splashdown.env

(Pass --no-sync to scaffold the files without reserving ports.)

The recipe is on disk, the loader is wired, the hook fires on every checkout. Add a worktree and the second checkout allocates free ports automatically, no manual editing or syncing needed:

git worktree add ../myapp.feat-x feat-x
cd ../myapp.feat-x

# post-checkout hook fired `splash`. splashdown.env now has the per-checkout ports.
pnpm dev    # api on 9082 instead of 9081, vite on 5175 instead of 5174

See examples/ for hook + mise wiring patterns. Verify wiring later with splash doctor (and splash doctor --fix to re-apply).

Multi-app / monorepo setups: see splashdown.dev/monorepos.

Mobile: simulators & emulators

For a mobile app, the scan also declares the simulator/emulator variants in [targets.*]. Each checkout gets its own sim/emulator instance (named <parent>/<cwd>/<variant>), so worktrees never fight over one device. Boot, build, and launch in one command:

splash run                            # one target type + one variant: no args needed
splash run simulator                  # name the type when you declare more than one
splash run simulator lowest-supported # ...and a specific variant

splash target                         # list declared variants + which are booted right now
splash stop simulator                 # shut the sim down (keeps it)

When a new iOS (or Android system image) lands, recreate the latest sims in place and clear out the cruft Xcode/avdmanager leave behind:

splash target refresh                 # destroy + recreate stale 'latest' sims (newer iOS landed)
splash target prune ios               # delete every sim splashdown did NOT create (the Xcode template pile)
splash gc                             # drop registry entries for checkouts you've since deleted

Variants pinned to a fixed version (ios = "17.0") are never touched by refresh — they're deliberate version coverage. See Running and managing devices for the full lifecycle.

Documentation

Full guides and reference live at splashdown.dev:

Development

just test                       # run pytest
just build                      # sdist + wheel
just install-local              # install local source as `splash` via uv
just refresh-local              # reinstall after changes
just reset-local                # uninstall the local `splash`
just tag-release-patch          # bump patch, commit, tag, push (triggers release.yml)

See Justfile and .github/workflows/release.yml for the release flow. Tagging publishes a GitHub release and auto-updates the Formula/splashdown.rb in nielsmadan/homebrew-tap.

About

Per-checkout simulators, emulators, and dev ports for parallel mobile and web development across git worktrees.

Topics

Resources

Security policy

Stars

Watchers

Forks

Releases

Contributors

Languages