scripts/ was holding two unrelated kinds of thing: install-this-machine, and run-this-occasionally. The
eight installers now live in scripts/setup/; what stays at the top level is the build steps (gen-index,
prebuild, build/) and the two maintenance scripts (reindex-music, rebuild-soulseek-tree).
The move is not just a rename. Three of these derive the repo root from their own location:
setup.sh:51 PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
setup_mac_light.sh:51 same
cleanup-desktop.sh:134 ENV_FILE="$(dirname "$0")/../.env"
Left alone, all three would now resolve to scripts/ — and nothing downstream complains. PROJECT_DIR is
where .env is written, where `bun install`, `gen:index` and `db:push` run, and what pm2 is pointed at, so
a fresh install would have quietly provisioned scripts/ and reported success. cleanup-desktop.sh fails
the other way: it would find no .env, print "No .env — skipping", and leave the real VNC_PASSWORD in the
real file. All three are now `../..` with a comment saying why the level matters.
provision-user-dirs.ts imports data-path.ts relatively; that one tsgo caught.
Also disambiguated `setup.sh` where it had become two files. app-store/templates/<name>/setup.sh is a
per-sidecar installer with its own contract, and preflight.ts + docs/sidecar-app-store.md discussed both
in the same paragraph. The host one is now spelled with its full path at those sites.
Verified: bash -n on all six shell scripts, tsgo clean, os-user tests pass, both derivations resolve to
the repo root, starship.toml still resolves from os-user-shell.ts, and provision-user-dirs.ts runs under
DRY_RUN.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An install that discovers a missing dependency halfway through has already made a directory, possibly
started a container and written a row, and then has to unwind — leaving the user with something that
neither works nor uninstalls. A 30ms check first is worth most of that.
Verified while writing this: nothing in scripts/ installs Docker, and nothing checks for it.
setup-dockers.sh invokes `docker compose` with no preflight, so a fresh host without Docker fails
partway through setup with a bare "command not found". Recorded in the design doc rather than fixed
here — the intended fix is a setup.sh per sidecar, which is also what a sidecar needs once it ships from
its own repository.
`docker compose version` is the probe, not `docker --version`: the latter passes with a dead daemon,
which is the failure people actually hit. "Not installed" and "daemon unreachable" are reported
separately because the remedies differ.
Checked per MODE, not per entry. A host without Docker can still install Photos by pointing at an Immich
somewhere else; refusing the whole entry is the over-strict check that makes people work around the
installer instead of using it.
Dropped `requires: 'docker'` from the catalogue type. Needing Docker is exactly "this entry can
provision", which `modes` already says, so declaring it twice invites the two to disagree. Derived by
needsDocker instead, and a test asserts the derivation matches every entry.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>