A Nix flake that packages VS Code (Microsoft's official build) directly from binaries, with automated daily updates, Garnix binary caching, and declarative configuration for extensions, settings, and keybindings.
- Official Microsoft VS Code binaries (not VSCodium)
- Supports Linux x64, Linux aarch64, macOS x64, and macOS aarch64
- Automated daily updates via GitHub Actions
- Pre-built binaries via Garnix for instant installation
- Declarative extensions management
- Settings and keybindings configuration via Nix
- Smart Home Manager integration detection
# Run VS Code directly (no installation needed)
nix run github:dominicnunez/vscode-nix
# Or try it in a temporary shell
nix shell github:dominicnunez/vscode-nix -c codeThis flake uses Garnix for CI and binary caching. The nixConfig in flake.nix automatically configures the cache, so pre-built binaries are fetched without any manual setup.
If prompted to allow configuration from the flake, answer yes or add accept-flake-config = true to your Nix configuration.
Add to your flake.nix:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
vscode-nix.url = "github:dominicnunez/vscode-nix";
};
outputs = { self, nixpkgs, vscode-nix, ... }: {
# NixOS system configuration
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
({ pkgs, ... }: {
environment.systemPackages = [
vscode-nix.packages.${pkgs.system}.default
];
})
];
};
};
}{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
home-manager.url = "github:nix-community/home-manager";
vscode-nix.url = "github:dominicnunez/vscode-nix";
};
outputs = { self, nixpkgs, home-manager, vscode-nix, ... }: {
homeConfigurations."user@host" = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.x86_64-linux;
modules = [
({ pkgs, ... }: {
home.packages = [
vscode-nix.packages.${pkgs.system}.default
];
})
];
};
};
}{
inputs.vscode-nix.url = "github:dominicnunez/vscode-nix";
outputs = { self, nixpkgs, vscode-nix }: {
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
{
nixpkgs.overlays = [ vscode-nix.overlays.default ];
environment.systemPackages = [ pkgs.vscode-nix ];
}
];
};
};
}The lib.vscodeWithExtensions function creates a VS Code derivation with extensions pre-configured. The second argument accepts a settings attrset, or an attrset with settings and keybindings when you want both:
{
inputs.vscode-nix.url = "github:dominicnunez/vscode-nix";
outputs = { self, nixpkgs, vscode-nix }: {
packages.x86_64-linux.my-vscode = vscode-nix.lib.x86_64-linux.vscodeWithExtensions
# Extensions list
[
"ms-python.python"
"esbenp.prettier-vscode"
"dbaeumer.vscode-eslint"
"ms-vscode.cpptools@1.20.0" # Pin specific version
]
# Settings and keybindings (optional)
{
settings = null;
keybindings = null;
};
};
}You can also configure extensions directly when calling the package:
vscode-nix.packages.${system}.default.override {
extensions = [
"ms-python.python"
"esbenp.prettier-vscode@10.0.0" # Pinned version
];
}Extensions are:
- Installed on first run via VS Code's
--install-extensioncommand - Stored in
~/.local/share/vscode-nix/extensions(persists across updates) - Only reinstalled when the extension list changes
Provide VS Code settings as a Nix attribute set:
{
packages.x86_64-linux.my-vscode = vscode-nix.lib.x86_64-linux.vscodeWithExtensions
[ "ms-python.python" ]
# Settings
{
"editor.fontSize" = 14;
"editor.tabSize" = 2;
"editor.formatOnSave" = true;
"workbench.colorTheme" = "One Dark Pro";
"files.autoSave" = "afterDelay";
"python.languageServer" = "Pylance";
};
}Or using override:
vscode-nix.packages.${system}.default.override {
userSettings = {
"editor.fontSize" = 14;
"editor.minimap.enabled" = false;
};
}Settings behavior:
- Nix settings are used as defaults on first run
- User modifications in VS Code are preserved and take precedence
- If Nix settings change, they are merged with user settings (user wins on conflicts)
- Settings stored in
~/.local/share/vscode-nix/user-data/User/settings.json
Provide custom keybindings as a list of attribute sets:
{
packages.x86_64-linux.my-vscode = vscode-nix.lib.x86_64-linux.vscodeWithExtensions
[ "ms-python.python" ]
{
settings = { "editor.fontSize" = 14; };
# Keybindings
keybindings = [
{ key = "ctrl+k ctrl+t"; command = "workbench.action.terminal.focus"; }
{ key = "ctrl+k ctrl+e"; command = "workbench.action.focusActiveEditorGroup"; }
{ key = "ctrl+shift+d"; command = "editor.action.duplicateSelection"; }
{
key = "ctrl+shift+/";
command = "editor.action.blockComment";
when = "editorTextFocus";
}
];
};
}Or using override:
vscode-nix.packages.${system}.default.override {
userKeybindings = [
{ key = "ctrl+k ctrl+t"; command = "workbench.action.terminal.focus"; }
];
}Keybindings behavior:
- Nix keybindings are added as defaults on first run
- User modifications in VS Code are preserved
- If Nix keybindings change, they are merged (user keybindings take precedence)
- Duplicate keybindings are deduped by
key, keeping the user entry - Keybindings stored in
~/.local/share/vscode-nix/user-data/User/keybindings.json
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
vscode-nix.url = "github:dominicnunez/vscode-nix";
};
outputs = { self, nixpkgs, vscode-nix }: {
packages.x86_64-linux.my-dev-environment =
vscode-nix.lib.x86_64-linux.vscodeWithExtensions
# Extensions
[
# Python development
"ms-python.python"
"ms-python.vscode-pylance"
# JavaScript/TypeScript
"esbenp.prettier-vscode"
"dbaeumer.vscode-eslint"
# Git
"eamodio.gitlens"
# Nix
"jnoortheen.nix-ide"
# Theme
"zhuangtongfa.material-theme"
]
{
# Settings
settings = {
# Editor
"editor.fontSize" = 13;
"editor.fontFamily" = "'JetBrains Mono', 'Fira Code', monospace";
"editor.fontLigatures" = true;
"editor.tabSize" = 2;
"editor.formatOnSave" = true;
"editor.minimap.enabled" = false;
# Files
"files.autoSave" = "afterDelay";
"files.trimTrailingWhitespace" = true;
# Theme
"workbench.colorTheme" = "One Dark Pro";
"workbench.iconTheme" = "material-icon-theme";
# Terminal
"terminal.integrated.fontSize" = 12;
# Python
"python.languageServer" = "Pylance";
# Nix
"nix.enableLanguageServer" = true;
};
# Keybindings
keybindings = [
{ key = "ctrl+k ctrl+t"; command = "workbench.action.terminal.focus"; }
{ key = "ctrl+k ctrl+e"; command = "workbench.action.focusActiveEditorGroup"; }
];
};
};
}This package includes smart Home Manager detection. When running VS Code:
If Home Manager is detected:
- Skips creating
~/.local/bin/codesymlink - Cleans up symlinks that were created by this package
- Respects your declarative Home Manager configuration
If Home Manager is NOT detected:
- Creates
~/.local/bin/codesymlink for convenience - Allows running
codefrom anywhere if~/.local/binis in your PATH
Automatic cleanup: If you previously installed vscode-nix standalone (creating a ~/.local/bin/code symlink) and later enable Home Manager, the package will automatically remove the symlink on first run to prevent PATH conflicts.
Home Manager is detected if any of these conditions are true:
HM_SESSION_VARSenvironment variable is set~/.config/home-managerdirectory exists/etc/profiles/per-user/$USERdirectory exists
To enable informational messages from the wrapper:
export VSCODE_NIX_VERBOSE=1Or add to your shell profile:
# ~/.bashrc or ~/.zshrc
export VSCODE_NIX_VERBOSE=1| Variable | Description | Default |
|---|---|---|
VSCODE_NIX_VERBOSE |
Set to 1 to enable wrapper messages |
unset |
XDG_DATA_HOME |
Base directory for VS Code data | ~/.local/share |
XDG_CONFIG_HOME |
Base directory for VS Code config | ~/.config |
When using extensions, settings, or keybindings configuration:
| Path | Purpose |
|---|---|
~/.local/share/vscode-nix/extensions |
Installed extensions |
~/.local/share/vscode-nix/user-data |
User settings, keybindings, state |
- Daily Check: GitHub Actions runs
update.shdaily at 00:00 UTC - Version Detection: Script queries GitHub API for latest VS Code release
- Hash Fetching: If newer version found, fetches SHA256 hashes for all platforms
- Validation: Runs
nix flake checkto verify package builds correctly - Push: Pushes update directly to main
To manually trigger an update check:
- Go to Actions tab in GitHub
- Select "Update VS Code" workflow
- Click "Run workflow"
# Enter development shell
nix develop
# Check for updates (dry run)
./update.sh
# Check and apply update
./update.sh --update
# Build the package
nix build
# Run the built package
nix run
# Run flake checks
nix flake check.
├── flake.nix # Flake definition with outputs
├── flake.lock # Locked dependencies
├── package.nix # VS Code package derivation
├── version.json # Current version and platform hashes
├── update.sh # Update detection and hash fetching script
├── README.md # This file
├── garnix.yaml # Garnix CI configuration
└── .github/workflows/
├── update.yml # Daily update workflow
└── ci.yml # Garnix build validation
VS Code is proprietary software from Microsoft. This flake packages the official binaries. See VS Code License for terms.
The Nix packaging code in this repository is MIT licensed.