Append VSCode personal extensions with nix-shell defined ones

Hi there,

I’m trying to use nix-shell to append needed VSCode extensions for specifics projects without losing personal ones.

I’ve defined in nixpkgs/home.nix (home-manager):

programs.vscode = {
    enable = true;
    extensions = with pkgs.vscode-extensions; [ vscodevim.vim /* ... */ ];
    userSettings = { /* */ };
}

And for a Python project in shell.nix:

{ pkgs ? import <nixpkgs> { } }:

with pkgs;
let extensions = (with vscode-extensions; [ ms-python.python /* ... */ ]);
     vscodePython = vscode-with-extensions.override { vscodeExtensions = extensions };
in mkShell {
    name = "Python project"
    nativeBuildInputs = [ vscodePython /* ... */ ];
}

Personal configuration is kept, but extensions are overridden by the destructive vscode-with-extensions.override { }.

How can I keep personal extensions when appending ones with nix-shell?

In order to resolve this, I tried to fetch home-manager configuration.

If it’s possible, the shell.nix would become:

{ pkgs ? import <nixpkgs> { }, config ? /* Do something to fetch configuration */ }:

with pkgs;
let userExtensions = config.programs.vscode.extensions;
    extensions = (with vscode-extensions; [ ms-python.python /* ... */ ]);
    vscodePython = vscode-with-extensions.override {  vscodeExtensions = extensions ++ userExtensions };
in /* ... */

For now, I’m only able to fetch system configuration with:

{ pkgs ? import <nixpkgs> { }, config ? (import <nixpkgs/nixos> { }).config, /* ... */ }:

/* ... */

How can I fetch home-manager configuration (or is there another way to append VSCode extensions)?

By using home-manager NixOS module instead of home-manager standalone, I’ve successfully fetch user configuration:

{ pkgs ? import <nixpkgs> { }, config ? (import <nixpkgs/nixos> { }).config }:

let userName = builtins.getEnv "USER";

    userExtensions = if builtins.hasAttr "home-manager" config then
      if builtins.hasAttr userName config.home-manager.users then
        config.home-manager.users."${userName}".programs.vscode.extensions
      else [ ]
    else [ ];

    /* ... */

Is there a better way to achieve this goal (For example, without home-manager NixOS module)?

2 Likes

Did you ever find a satisfactory solution? I’m now faced with a similar issue.

I’m using a flake-based system/HM config, possibly complicating things, but I’m using “classical” nix shells without having to use channels by adding in the configuration.nix which is called by the flake:

    nixPath = [ "nixpkgs=${pkgs.outPath}" "unstable=${unstable.outPath}" ];

Similarly, I figured one could set an env var from within home.nix which could be used to hook into the home-configuration later from a shell.

However, since for vscode-extensions the situation is a bit special (compared to other parts of HM installed stuff) because your links to the nix-store actually end up in ~/.vscode/extensions/ (not a link farm but a real dir), it could be better to consider a leaner “build-wrapper” (within the nix-shell expression) that just symlinks your additional extensions there. Not sure how to handle GC though…