A curated, version-controlled dotfiles setup that bootstraps a secure, consistent, and productive developer environment for NHS engineers and teams.
This repository is designed with NHS engineers in mind, but can be reused or adapted by any individual or team who wants to standardise development setup. macOS is fully supported. Ubuntu/Linux has partial support (shell configuration and base packages). Windows Subsystem for Linux (WSL) is planned but not yet delivered.
Dotfiles are hidden files that define preferences and behaviours for tools such as terminals, shells, editors, and system utilities. Managing them centrally reduces setup time, improves consistency, and increases portability of developer environments.
This setup is optimised for Developer Experience (DX) and aligned with an Internal Developer Platform (IDP) model, supporting NHSβ broader software delivery strategy.
For general background, refer to the Unofficial guide to dotfiles on GitHub.
This project provides a maintainable, version-controlled baseline for configuring development machines. It captures shell, Git, editor, and utility preferences in one place so engineers can apply a reliable setup with less manual effort.
Users get a fast path to a working environment with secure defaults, consistent tooling, and documented workflows. macOS users receive a complete bootstrap experience. Ubuntu/Linux users get shell configuration and base CLI packages, with further automation planned.
Manual workstation setup is time-consuming, hard to reproduce, and easy to drift. Individual machine differences often create avoidable friction in delivery, review, and support workflows.
The repository uses chezmoi to template, apply, and maintain dotfiles, with idempotent scripts for imperative system changes where needed. It also supports secure secret handling through Bitwarden integration, local customisation through dedicated override files, and branch-based update workflows for keeping personal forks aligned with upstream.
These prerequisites ensure the bootstrap process can run without interruption and that the resulting shell and tooling configuration behaves as expected across supported platforms.
- macOS 10.15+ (fully supported), Ubuntu 20.04+ (partial β shell and base packages only), or Windows 10+ with WSL2 (planned)
- Git 2.28 or newer
- Zsh shell
- A terminal with Unicode and true colour support
- Administrator access (for system package installation)
- Permission to modify shell configuration
- SSH key configured for GitHub access
# Install chezmoi and apply NHS dotfiles in one step
bash -c "$(curl -fsLS get.chezmoi.io)" -- init --apply --branch custom "stefaniuk"On first run, chezmoi clones the dotfiles source into ~/.local/share/chezmoi/, prompts for configuration values (for example, Git committer name and email), and applies managed files to your home directory.
If this is your first time using chezmoi, expect a short interactive setup. Taking a moment to provide accurate identity and signing values at this stage will reduce follow-up edits later.
For full setup details, backup options, and re-run flows, see How to use.
The platform is intentionally opinionated: it gives a strong default baseline while still supporting local override paths for personal or team-specific workflows.
- Shell environment for Zsh and Bash with themes, prompts, aliases, and completions
- Git and GitHub configuration with commit-signing support and helper aliases
- Visual Studio Code defaults, including settings and keybindings
- Secrets integration through Bitwarden
- Platform-specific defaults for macOS (full), Ubuntu (partial), and WSL (planned)
- Secure, opinionated defaults for improved security and compliance
- GNU-compatible CLI tooling for a consistent cross-platform command-line experience
- Built-in maintenance command (
dot) for routine updates
- Oh My Zsh with Powerlevel10k
- TypeScript/JavaScript ecosystem support (Node.js, npm)
- Python tooling (pip, uv)
- Container tooling integration
- OS-specific ignore rules for Git
- macOS (fully supported)
- Linux/Ubuntu (partial β shell configuration and base packages)
- Windows WSL (planned)
- GitHub Codespaces (basic devcontainer provided)
These boundaries help keep the repository maintainable and predictable, while avoiding assumptions about machine-specific or organisation-specific requirements.
- Full native Windows (non-WSL) support is not currently delivered.
- Ubuntu/Linux support is partial: shell config and base CLI packages are managed, but developer tools, GUI apps, and system configuration scripts are macOS-only at present.
- WSL support is planned but not yet implemented.
- This repository is not a replacement for secure secret management; it integrates with Bitwarden.
- It is not intended to remove personal flexibility; forking and local overrides are first-class.
- It is not a complete manual for every tool; detailed guides live under docs/guides.
At a practical level, the workflow combines declarative templates with selective imperative scripting, so most configuration remains transparent and version-controlled while still handling OS-specific setup tasks.
- Define user and machine preferences as version-controlled dotfiles and templates.
- Bootstrap with chezmoi to pull source files into
~/.local/share/chezmoi/. - Prompt for setup values (for example, name, email, signing key) and render templates.
- Apply changes safely into the home directory with repeatable commands.
- Run imperative setup scripts only where declarative config is not enough.
- Keep sensitive data out of tracked files by using local override files and password manager integration.
- Maintain custom changes via a dedicated
custombranch and sync with upstream on a routine basis.
Key concepts:
- Dotfiles: hidden configuration files that control shell, editor, Git, and utility behaviour.
- Chezmoi: the dotfiles manager used to template, track, and apply configuration safely.
- Idempotent scripts: scripts designed to re-run without causing duplicate or unsafe changes.
Together, these concepts support repeatable machine setup, safer updates, and easier troubleshooting when environments drift.
This dotfiles repository is configured and managed by chezmoi, pronounced /ΚeΙͺ mwa/ (shay-moi), which is currently described as one of the most complete and most hackable dotfiles managers.
Use this workflow when onboarding a new machine or when moving an existing setup to a cleaner, source-controlled baseline.
Before applying changes, create a full backup of your current home configuration:
This gives you a clear rollback point if you need to compare previous settings or recover custom files that were not yet tracked.
tar -czvf /tmp/home-directory-backup.tar.gz -C ~ .Depending on your OS and terminal settings, you may be prompted for access permissions during backup. If archiving the full home directory takes too long, use chezmoi to archive dotfiles only (after following the chezmoi installation guide for your operating system):
chezmoi archive --output=/tmp/dotfiles-backup.tar.gzBackups may include sensitive files, so store them securely if you transfer them between machines.
Run this once your backup is complete and network access to your Git source is available.
bash -c "$(curl -fsLS get.chezmoi.io)" -- init --apply --branch custom "stefaniuk"For detailed chezmoi usage, see Chezmoi usage guide.
To store some configuration options, chezmoi can use a password manager. After installing dotfiles, follow the Bitwarden setup guide.
Note
If Bitwarden CLI is available on your system (typically after first installation), subsequent runs use Bitwarden CLI for password management and prompt for your Bitwarden password.
Use these commands for routine maintenance after pulling updates, changing templates, or adjusting local variables.
# Navigate to your chezmoi working directory
cd ~/.local/share/chezmoi
# Pull the latest changes from your dotfiles source repo
chezmoi update
# Or, re-apply everything from your local configuration
chezmoi apply
# To update the dotfiles from your fork from the current directory (not ~/.local/share/chezmoi) and set a custom variable, you can use
CUSTOM_COMPUTER_NAME="Dan's MacBook" chezmoi apply --source .If you changed chezmoi.toml, templates, branches, or source repositories, you can also re-initialise:
# Re-initialise from your fork (e.g. after switching branches or repos)
chezmoi init --apply git@github.com:<your-username>/dotfiles.gitPreview changes without applying:
chezmoi diffRe-apply only one file (example: .zshrc):
chezmoi apply ~/.zshrcConfiguration is split between shared tracked values and local machine-specific overrides, so you can keep consistency without exposing secrets.
After installation, chezmoi generates ~/.config/chezmoi/chezmoi.toml. You can personalise setup with variables such as:
These values are used during template rendering, so they influence generated files rather than acting as runtime shell variables.
dotfiles.nameβ your full namedotfiles.emailβ your email addressdotfiles.git_signingkeyβ GPG key ID for commit signing
Edit tracked config files directly through chezmoi:
This approach keeps your edits in the chezmoi source state and avoids accidental drift between managed files and their templates.
chezmoi edit ~/.gitconfigTwo files allow machine-specific overrides without modifying tracked dotfiles:
| File | Purpose | Committed? |
|---|---|---|
~/.extra |
Machine-specific secrets, API tokens, private PATH additions | No (mode 600) |
~/.custom |
Personal aliases and settings safe to share | Optional |
Both files are sourced automatically by .zshrc and .bashrc after all other dotfiles.
In practice, this means you can keep shared defaults stable while layering machine-specific behaviour safely at the end of shell startup.
~/.extra β never commit this file; it contains credentials:
# ~/.extra
export GITHUB_TOKEN="ghp_xxxxxxxxxxxx"
export AWS_PROFILE="my-work-profile"
alias work="cd ~/Projects/work"~/.custom β safe to version-control in your own fork:
# ~/.custom
alias projects="cd ~/Projects"
export MY_PREFERRED_EDITOR="nvim"Chezmoi creates starter templates for both files on first run.
Use the dot command to keep your environment up to date:
Start with dot help if you are unsure which subcommand to run, then choose the narrowest command that matches your goal.
dot # Update dotfiles + Homebrew packages
dot packages # Update Homebrew only
dot dotfiles # Apply chezmoi dotfiles only
dot macos # Re-apply macOS system defaults
dot diff # Show drift between expected and actual configuration
dot benchmark # Measure shell startup time
dot help # Show all subcommands~/.curlrc and ~/.wgetrc include sensible defaults:
These defaults improve reliability for scripted downloads and reduce repetitive per-command flags in day-to-day terminal use.
- Follow redirects automatically
- 60-second connection timeout
- Retry failed requests up to 3 times (5-second delay between attempts)
- Consistent user-agent string
The workflows below are designed to keep local customisations maintainable while preserving a clean path for upstream contribution.
To maintain your customisations while synchronising upstream updates, create and keep a dedicated custom branch. This isolates local changes from main, simplifies updates, and reduces merge conflict risk.
# Clone your fork of the dotfiles repository
git clone git@github.com:<your-username>/dotfiles.git
cd dotfiles
git checkout main
# Create and switch to your persistent custom branch, if it doesn't exist yet
git checkout custom || git checkout -b custom
# For each set of changes, create a feature branch from custom
git checkout -b your-custom-branch
# Make your custom changes ...
git add .
git commit -S -m "Short, descriptive summary of your custom changes"
git push origin your-custom-branch
# Open a pull request on GitHub and merge your feature branch into custom ...
# After merging on GitHub, clean up local and remote feature branches
git checkout custom
git pull origin custom
git branch -D your-custom-branch
git push origin --delete your-custom-branch
# Periodically update your fork with the latest changes from upstream
git checkout main
git fetch upstream
git merge upstream main
git push origin main
# Rebase your custom branch onto the updated main branch
git checkout custom
git rebase main
git push origin custom --force-with-lease
# (Optional) Squash your custom branch to a single commit
git checkout custom
git reset --soft $(git merge-base custom main)
git add .
git commit -S -m "Squashed: All custom changes up to $(date +"%A, %d %B %Y, %H:%M:%S %Z")"
git push origin custom --force-with-leaseThis approach keeps history cleaner and future updates more straightforward.
For teams, this branch strategy also makes code review and change ownership clearer because customisations are isolated from upstream sync activity.
Keeping all customisations directly on main is possible, but requires manual conflict resolution for each upstream pull. For most users, a dedicated custom branch is simpler and safer.
To contribute improvements, features, or fixes to upstream, follow standard GitHub flow:
# Ensure your local repository has the latest changes from upstream
git fetch upstream
git checkout upstream/main
# Create a new feature branch based on the latest upstream/main
git checkout -b your-contribution-branch
# Make your changes ..., then stage and sign your commit
git add .
git commit -S -m "Short, descriptive summary of your contribution"
# Push your contribution branch to your fork on GitHub
git push origin your-contribution-branch
# Open a pull request on GitHub ...
# - Set your fork and feature branch as the source
# - Set the upstream repository and its main branch as the target
# - Add a clear title and description for reviewers
# After your pull request is merged on GitHub, you can safely delete the local branch
git checkout main
git pull origin main
git branch -D your-contribution-branch
# Next, follow the "Keep your repository up to date" section to update your branches with any new upstream changesContributions are reviewed by maintainers and, if accepted, merged into the official repository.
When preparing a contribution, favour small, focused changes with clear commit messages to make review and rollback simpler.
Use these guides as task-oriented references; each one goes deeper into a specific domain without overloading the top-level README.
- Chezmoi usage β dotfiles manager setup and usage
- Bitwarden usage β password manager integration
- CLI usage β command-line tooling inventory and configuration map
- Git usage β version control setup and workflows
- Containers usage β container management
- Visual Studio Code usage β editor configuration
- System usage β general system configuration
- Terminal usage β terminal setup and customisation
Common issues:
If a problem persists after these checks, run chezmoi diff to inspect pending changes and isolate whether the issue is configuration, environment, or tooling related.
-
GPG signing issues
# Verify GPG key setup gpg --list-secret-keys --keyid-format LONG -
Zsh configuration problems
# Reset Zsh configuration chezmoi apply ~/.zshrc
Comprehensive guides are available under docs/guides:
For quickest navigation, start with setup guides, then move to tool and platform guides based on your current task.
- Setup guides
- Tool guides
- Platform guides
The longstanding mathiasbynens/dotfiles project, with its established practices and features, has inspired improvements to Developer Experience in NHS England. This repository has been adapted and revamped to align with the organisation's strategy.
Contributions are welcome to improve and extend this project.
Before opening a pull request, make sure your proposed change is reproducible on at least one supported platform and is documented where behaviour changes.
- Start with the contributor guide: .github/contributing.md
- Standard flow: fork β branch β pull request
- Ensure commits are signed
- For larger changes, open a discussion or issue first to align on approach
Development setup (high level):
make configQuality checks before opening a pull request:
make lint
make test
make githooks-runImportant paths for new contributors:
Understanding this layout early helps you identify where to make changes without introducing overlap between templates, scripts, and generated configuration.
assets/β setup and configuration scripts for macOS/Ubuntu, plus shared script resourcesbin/β project-managed binaries used during bootstrapdocs/β ADRs, guides, architecture placeholders, and prompt/report documentationimages/β images used by documentation (for example screenshots)private_dot_config/β template-backed configuration for local developer toolsscripts/β make modules, quality tooling config, Docker helpers, and automation scriptsMakefileβ primary orchestration entry point for local and CI workflowsinstall.shβ main installation entry scriptrun_setup.sh.tmplβ setup template used during initial machine provisioning
Managed home-directory files include:
~ ($HOME)
β
ββββ .aliases
ββββ .bash_profile
ββββ .bash_prompt
ββββ .bashrc
ββββ .exports
ββββ .functions
ββββ .gitattribute
ββββ .gitconfig
ββββ .gitignore
ββββ .gitmessage
ββββ [.macos|.ubuntu]
ββββ .p10k.zsh
ββββ .path
ββββ .zshrcSome changes use imperative (non-declarative) scripts designed to be idempotent and applied only when necessary.
You can fork this project to customise it for your own environment and workflow. For a practical downstream example, see stefaniuk/dotfiles, a downstream fork maintained and configured by the author that demonstrates adapting NHS dotfiles for personal use, applying local preferences, and keeping in sync with upstream changes.
This repository is licensed under the MIT Licence, which applies to source code and any sample code within the documentation.
All HTML or Markdown documentation is Β© Crown Copyright and available under the Open Government Licence v3.0.
