Nix development shells
Command-line tooling for this repository is not installed on the host. It comes
from the Nix development shells that the flake in config/nix defines, so every
contributor and automation runs the same pinned tool versions.
The flake defines two shells:
| Shell | Definition | Purpose |
|---|---|---|
default |
config/nix/shells/shell.nix |
Develop, format, and lint the Nix code. |
operations |
config/nix/shells/shell-operations.nix |
Provision, deploy, and operate the environment. |
The flake also registers both shells as flake checks (shell-devShell and
shell-opsShell), so nix flake check fails when a shell no longer builds. The
CI workflow does not build these checks.
Use a shell
Run the following commands from the repository root.
-
To open an interactive shell:
nix develop ./config/nix#operationsOmit the
#operationssuffix to open thedefaultshell. -
To run a single command without opening an interactive shell:
nix develop ./config/nix#operations --command <command> [<argument> ...]
Keep these points in mind:
- The shells write their activation banner to the standard error stream, and so does Nix for its own warnings (for example, the warning about uncommitted changes in the Git tree). The standard output stream only carries the output of the command, so it is safe to parse or to redirect to a file.
- Nix flakes evaluate only Git-tracked files:
git adda new shell definition before using it. - The operational scripts do not open a shell on their own. Scripts that depend on tools from a shell must run inside that shell.
Default shell tools
| Tool | Purpose |
|---|---|
deadnix |
Find unused code in Nix files. |
nixd |
Nix language server, for editor integration. |
nixfmt |
Format Nix files. |
statix |
Lint Nix files for antipatterns and suggest replacements. |
To format and lint the whole Nix codebase, prefer the flake's formatter and
check, which run deadnix, nixfmt, and statix with the repository
configuration (config/nix/treefmt.nix). See the
Nix development guide.
Operations shell tools
| Tool | Purpose | How to invoke |
|---|---|---|
gh |
Interact with GitHub: CI workflow runs, pull requests. | Directly. See GitHub CLI. |
jq |
Parse and filter JSON, such as Terraform outputs. | Directly. |
nixos-anywhere |
Install NixOS on hosts that have a disko.nix disk layout. |
Through scripts/bootstrap-host.sh, inside the shell. |
nixos-rebuild |
Push a NixOS configuration to a running host over SSH. | Through scripts/bootstrap-host.sh, inside the shell. |
terraform |
Provision the infrastructure. | Only through scripts/run-terraform.sh, inside the shell. |
The operational scripts guide describes the scripts that wrap these tools.
GitHub CLI
The GitHub CLI (gh) authenticates with per-user
state that gh auth login stores outside the repository. Verify it with
gh auth status.
Use the GitHub CLI to:
-
Inspect CI workflow runs after a push, which matters most for the workflows that have no convenient local equivalent. List the runs for the current commit, then capture the logs of the failed jobs in full to a log file:
nix develop ./config/nix#operations --command \ gh run list --commit "$(git rev-parse HEAD)" nix develop ./config/nix#operations --command \ gh run view <run-id> --log-failed > <log file> 2>&1To tell a regression from a failure that predates the change, compare with the latest runs of the same workflow on the default branch (
gh run list --workflow <workflow file> --branch master). -
Review pull requests, including the ones that Dependabot and Renovate open (
gh pr list,gh pr view,gh pr checks). - Read issues and releases (
gh issue list,gh issue view,gh release list).
Read-only subcommands (list, view, checks, status, and gh api GET
requests) are safe for discovery. Subcommands that change state on GitHub are
outward-facing and need explicit approval first: for example gh pr create,
gh pr merge, gh pr comment, gh issue create, gh workflow run,
gh run rerun, gh release create, and gh api requests with a method other
than GET.
Filter JSON output with the built-in --jq flag:
nix develop ./config/nix#operations --command \
gh pr list --json number,title --jq '.[] | "\(.number) \(.title)"'
Tools outside the shells
Some tools run in containers instead, through the scripts that the operational scripts guide describes. Neither the host nor the shells provide them:
- Ansible, including
ansible-vault:scripts/run-ansible.sh. - Linters and formatters for the languages other than Nix:
scripts/lint.shandscripts/format.sh. - Material for MkDocs:
scripts/run-mkdocs.sh.
A tool that neither the host, the shells, nor the containers provide can run once from nixpkgs without installing it, for example poppler-utils to extract the text of a PDF:
nix shell nixpkgs#poppler-utils --command pdftotext -layout <file.pdf> <output.txt>
Add a tool to a shell
- Add the package to the
packageslist of the shell definition, keeping the list sorted alphabetically. - Add a row for the tool to the matching table in this document, in the same change. If the tool needs usage guidance, add a dedicated section like the one for the GitHub CLI.
-
Verify that the shell builds and provides the tool:
nix develop ./config/nix#<shell> --command <tool> --version