The chezmoi run-once script is only a wrapper. It detects the current platform
and runs a committed binary from installer/bin/. The installer logic lives in
the Rust crate under installer/, and package data lives in
installer/packages.toml.
bash -n run_once_install-packages.sh.tmpl
chezmoi execute-template < run_once_install-packages.sh.tmpl | bash -n
chezmoi execute-template < dot_config/fish/config.fish.tmpl | fish -n
cd installer && cargo fmt --check
cd installer && cargo check
actionlint .github/workflows/install-script.yml
git diff --checkOr run the grouped checks:
just checkjust check currently covers shell syntax and cargo check. Run
cargo fmt --check and actionlint separately when touching Rust formatting or
workflow YAML.
Run the Bitwarden template regression tests separately:
just test-templatesThese require Python 3 and chezmoi. They run real chezmoi diff and apply
commands against temporary directories with a fake bw executable. They check
macOS and Linux behavior for missing, empty, unlocked, and invalid sessions,
including preservation of existing private files when no session is exported.
They do not read the real vault or modify the home directory.
To validate the installer package schema, run from the repository root:
cargo test --locked --manifest-path installer/Cargo.tomlBuild the local platform binary:
cd installer
cargo build --releaseThen copy it into installer/bin/ using the platform name expected by the
wrapper:
# Linux x86_64
cp installer/target/release/dotsetup installer/bin/dotsetup-linux-x86_64
# macOS Apple Silicon
cp installer/target/release/dotsetup installer/bin/dotsetup-macos-arm64The wrapper currently supports these asset names:
dotsetup-linux-x86_64dotsetup-linux-arm64dotsetup-macos-x86_64dotsetup-macos-arm64
Only commit binaries for platforms that are actually supported and tested.
Run the committed binary through the rendered chezmoi wrapper:
chezmoi execute-template < run_once_install-packages.sh.tmpl | shOr run a locally built binary directly:
cd installer
cargo build --release
./target/release/dotsetup installDRY_RUN=1 does not make the installer print commands only. It makes prompts
non-interactive, which is useful in CI, but install commands still execute.
Use it only in disposable environments or with the current command behavior in
mind:
cd installer
DRY_RUN=1 ./target/release/dotsetup installThe installer supports Arch and CachyOS through the same pacman/AUR path. It
detects Arch-like systems from /etc/os-release.
Use the Docker targets for disposable Arch verification:
just test-arch
just test-arch-ci
just test-arch-bootstrap
just test-arch-bootstrap-citest-arch runs the installer interactively in an Arch container.
test-arch-ci sets CI=1 DRY_RUN=1 so prompts take defaults, but package
commands still run inside the container.
test-arch-bootstrap and test-arch-bootstrap-ci run dotsetup bootstrap.
They build the dotsetup binary in a builder stage, copy it into a clean Arch
runtime image, assert that cargo, rustc, and rustup are not installed
there, run as a non-root user with passwordless sudo, execute the real
bootstrap package-manager installs, and verify an AUR helper, Linuxbrew, and
rustup are installed.
The Docker images compile and run the Rust installer binary:
docker build -f Dockerfile.arch-test-ci -t dotfiles-arch-test-ci .
docker run --rm -v "$PWD:/work:ro" dotfiles-arch-test-ci
docker build -f Dockerfile.arch-bootstrap-test-ci -t dotfiles-arch-bootstrap-test-ci .
docker run --rm -v "$PWD:/work:ro" dotfiles-arch-bootstrap-test-ciThe Arch image used by these tests requires x86_64. On Apple Silicon, select that platform for both image builds and container runs:
DOCKER_DEFAULT_PLATFORM=linux/amd64 just test-arch-ci
DOCKER_DEFAULT_PLATFORM=linux/amd64 just test-arch-bootstrap-ciLocal runs on Apple Silicon have failed during image setup with
error restricting syscalls via seccomp: 22 and
switching to sandbox user 'alpm' failed. This happens before the installer
runs. If encountered, run the Arch tests on an x86_64 Linux Docker host;
just check and just test-templates can still run locally.
The macOS installer supports Apple Silicon only. It rejects Intel macOS.
On a real macOS machine:
cd installer
cargo build --release
./target/release/dotsetup installBy default, local macOS runs install both Homebrew formulae and casks. In CI, skip GUI/system-extension casks such as Docker Desktop and Tailscale:
cd installer
INSTALL_CASKS=0 CI=1 DRY_RUN=1 ./target/release/dotsetup installOnly INSTALL_CASKS=1, INSTALL_CASKS=true, or INSTALL_CASKS=yes enables
cask installation explicitly. If INSTALL_CASKS is unset, casks are installed.
The GitHub Actions macOS job also repairs a stale xcode-select developer path
before compiling the installer. This handles hosted runner images where
xcode-select -p points at a removed Xcode bundle.
.github/workflows/install-script.yml runs:
- Arch: builds
Dockerfile.arch-test-ciand runs the installer in the container. - Apple Silicon: runs on
macos-15, repairs the Xcode developer path, builds the Rust installer, runs it withCI=1 DRY_RUN=1 INSTALL_CASKS=0, then verifies expected commands are available.
The macOS job intentionally skips casks because hosted CI runners are not a good place to install GUI apps or system-extension apps.