This project provides two options for setting up a development environment with all the linting and development tools used in CI.
Option 1: Nix Flakes (Recommended)
Nix flakes provide a reproducible development environment that works on any Linux distribution.
Prerequisites
Enabling Flakes
If you haven’t enabled flakes, add this to ~/.config/nix/nix.conf:
experimental-features = nix-command flakes
Entering the Development Shell
# One-time use
nix develop
# Or with direnv (recommended)
direnv allow
Available Tools
The development shell includes all tools used in CI:
| Tool | Purpose |
|---|---|
shellcheck | Bash script linting |
shfmt | Bash script formatting |
nil | Nix language diagnostics |
nixfmt-rfc-style | Nix code formatting |
hadolint | Dockerfile linting |
markdownlint-cli2 | Markdown linting |
cspell | Spell checking |
actionlint | GitHub Actions workflow linting |
yamllint | YAML linting |
podman | Container runtime |
gh | GitHub CLI |
Option 2: VS Code Devcontainer
If you use VS Code and prefer containers over Nix, a devcontainer configuration is included.
Requirements
- VS Code
- Dev Containers extension
- Docker or Podman
Getting Started
- Open the project in VS Code
- When prompted, click “Reopen in Container”
- Or use the command palette:
Dev Containers: Reopen in Container
The devcontainer includes:
- Docker-in-docker for building images
- Nix with
nillanguage server - shellcheck and hadolint
- VS Code extensions for real-time linting feedback
Running Linters Locally
Run these before submitting a PR to catch issues early:
# Bash scripts
shellcheck *.sh bin/*.sh
shfmt -d *.sh bin/*.sh
# Nix files
nil diagnostics *.nix
nixfmt-rfc-style --check *.nix
# Dockerfile
hadolint Dockerfile
# Markdown
markdownlint-cli2 "**/*.md"
cspell "**/*.md"
# GitHub Actions
actionlint
# YAML
yamllint .github/workflows/
Building the Documentation Locally
The documentation uses Jekyll with the just-the-docs theme.
cd docs
bundle install
bundle exec jekyll serve
Then open http://localhost:4000 in your browser.
Building the Container Image
# Build the image
podman build -t zwift:dev .
# Or use the build script
./bin/build-image.sh
Testing Changes
# Dry run to see what would be executed
DRYRUN=1 ./zwift.sh
# Run in foreground for debugging
ZWIFT_FG=1 ./zwift.sh
# Interactive mode (drops into container shell)
INTERACTIVE=1 ./zwift.sh