Michael Anhari

Saving VS Code settings in your dotfiles

March 29, 2020
  • dotfiles
  • productivity
  • vscode

About a year or so ago, I decided that I wanted to move away from using vim and tmux to something that took less effort to maintain.

Don't get me wrong, I love vim and tmux.

But I've come to value other features in an editor more than maximum editing speed. For example, I've come to appreciate the value of language servers, linting, code formatting, and intellisense. All of which you can setup in vim, but if your experience is anything like mine you might find the process painful and requiring considerable upkeep.

After spending a few weeks in VS Code, I knew that I wanted to set up a way to capture my experience with the editor in my dotfiles. This post covers how you can set up a similar system, and make your VS Code setup a git pull away.

⚙️Saving your settings, keybindings, and snippets

Convert your settings, keybindings, and snippet JSON files to symbolic links

If you're on macOS, these JSON files should live here:

  • ~/Library/Application Support/Code/User/keybindings.json
  • ~/Library/Application Support/Code/User/settings.json
  • ~/Library/Application Support/Code/User/snippets/{language}.json

Move these into your dotfiles repo (create one if you need to - i.e. ~/dotfiles, and make it a git repository with git init) and symlink them. I use rcm to manage my this for me and highly recommend it.

Note on rcm

If you end up using rcm, then you need to add a file to configure it in ~/dotfiles/rcrc. Since VS Code will be looking for keybindings.json and not .keybindings.json, you have to tell rcm to sym link the file without a dot.

In ~/dotfiles/rcrc, you'll need the following

UNDOTTED="Library"

You can check out my config file here.

When set up correctly, any changes to your VS Code keybindings, snippets, and settings should show up in the git diff of your dotfiles repo.

📦Keeping your extensions in sync

Add a file to store your extensions

In ~/dotfiles add a file to store your VS Code extensions in a list. I named mine code_extensions.

Add a shell script to save your extensions to this file

Instead of having to manually write down the author and extension name in this file every time you add or remove and extension, lets set up a script that can populate this file with all of your current extensions.

In dotfiles/bin/save_code_extensions, I added the following:

#!/bin/sh

echo "Saving VSCode extensions..."
code --list-extensions > "$HOME"/dotfiles/code_extensions

Make sure to run chmod +x ~/dotfiles/bin/save_code_extensions to make this file executable.

Add a pre-commit hook to your dotfiles repo

If you want to further automate capturing changes to your VS Code extensions list, you can write a quick bash script for a pre-commit git hook that will save your extensions every time you make a commit in your dotfiles repository.

In ~/dotfiles/dotfiles-precommit-hook:

#!/bin/bash

dotfiles_dir="$HOME"/dotfiles
if [ "$PWD" = "$dotfiles_dir" ]; then
  save_code_extensions
  git add code_extensions
fi

Afterwards in your terminal:

# Make it executable
$ chmod +x ~/dotfiles/dotfiles-precommit-hook

# Run this once per machine to enable the pre-commit hook
# You can also add this to a a VS Code tasks file in your dotfiles repo to make
# it easier to remember: # https://github.com/anhari/dotfiles/blob/master/.vscode/tasks.json
$ cp ~/dotfiles/dotfiles-precommit-hook ~/dotfiles/.git/hooks/pre-commit

Add a ruby script to automate installing your VS Code extensions

I use the following ruby script in my rcm post-up hook (which you can read more about here), to automate installing extensions every time I re-sync my dotfiles.

unless 'which code'.empty?
  code_extensions = 'cat "$HOME"/dotfiles/code_extensions'.lines.sort
  installed_extensions = 'code --list-extensions'.lines.sort
  uninstalled_extensions = code_extensions - installed_extensions

  print 'Checking for uninstalled VSCode extensions...'

  if uninstalled_extensions.empty?
    print "all good!\r\n"
  else
    print "found #{uninstalled_extensions.count}.\r\n"

    uninstalled_extensions.each do |extension|
      puts "Installing #{extension}..."
      "code --install-extension #{extension}"
    end

    puts 'Done!'
  end
end

👋🏻Wrap Up

That's pretty much it. You now have a system in place that will allow you take your VS Code settings wherever you go, and you can have them stored alongside the configurations for the rest of your dev tools. If you're interested in digging into how I've set this up personally, my dotfiles are open source.