My Bash on Windows Dev Environment

March 03, 2017 •

Screenshot of my Windows Development Setup

On my new desktop PC I decided to go all-in on Bash on Windows. I’ve intentionally kept any Windows system command line installs very minimal, pretending it doesn’t even exist unless I get in a jam. My current environment is three core pieces:

I’ll cover each of these and explain how they all fit together and share some “gotchas” I encountered along the way.

Bash on Ubuntu on Windows

Screenshot of Bash shell working on Windows

I’m using Bash on Windows (aka the Windows Subsystem for Linux) daily to build, run, and deploy Node and Ruby apps. It’s Linux running on Windows, not a quirky utility like Cygwin or a VM, it’s Linux.

The Windows Subsystem for Linux is easy to install, just a few clicks, and then you’re off to the races using the newly installed bash.exe terminal app.

Custom Prompt

λ [master !?] $

First step is getting yourself a cool, color-coded command prompt so you don’t look like a dork. I “designed” mine in a website called EZPrompt. It shortens the path to just the directory name and checks which git branch I’m on and whether it’s “clean” or “dirty” (has modifications).

Install Git

$ sudo apt update
$ sudo apt install git

If you use Github 2FA (and you should be using Github 2FA), you’ll need to generate a new ssh-key and add it to your Github profile. Tiny gotcha: be sure to use the “Linux” directions.

Install n for Node

$ curl -L | bash

I was using nvm for Node version managing but ran into a recent performance regression that was causing 30s+ start times for Bash. Uf. So I did what anyone in my position would do… complained on Twitter!

Thankfully, someone suggested trying “n”. n is a hard to google alternative node version manager and it works great. Same’ish API, but it starts up instantly.

Install rbenv for Ruby

$ sudo apt update
$ sudo apt install autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev
$ git clone ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
$ source ~/.bashrc

If you use Ruby, you’ll want a version manager to avoid sudo gem hell. To do this, I followed a “How To Install Ruby on Rails with rbenv on Ubuntu 16.04” tutorial from Digital Ocean. This is Ubuntu afterall. It works great.

🚀 Can I Subsystem It?

You may be interested in whether your favorite web development tools are available on WSL. Me too! So I decided to make Can I Subsystem It? to track whether stuff works or doesn’t work.

Can I Subsystem It Github Repo

Some programs don’t work. Sometimes you can use the Windows system version (e.g. ngrok or pwmetrics). But some of these might be a dealbreaker for your environment. Good news is you can see lots of progress has been made in the Insider updates. The next stable release, the “Creators Update”, is on track to be a major upgrade.


  1. Never change Linux files in Windows apps or you risk data corruption.
  2. Prepend your $PATH changes because of a helpful new feature where you can access to Windows apps from within Bash. One by-product of this convenience means if you append anything to your $PATH it might get superceeded by the auto-appended Windows’ Environment Variables. I ran into an issue where Bash was trying to use Windows’ version of Node instead of the Linux version. This does not work. Thankfully, it’s only a matter of making sure path modifications are prepended like..

     export PATH="$HOME/.thing/bin:$PATH
  3. Colors render bad from time to time. Even with 24-bit color support, colors in shell themes don’t render as expected.


Screenshot of Hyper terminal console

Hyper for Windows has solved a longstanding problem of “feeling cool” using a shell on Windows. I consider it a requirement for a great developer experience on Windows. It’s two biggest improvements over the default cmd.exe terminal is that it has tabs and is JSON configurable.

  1. Tabs - While I could use something like tmux to split my terminal, my brain just wants tabs. Tab A does Task A, Tab B does Task B, etc.
  2. Configuration - It’s hard to explain how important shell configuration is to people who simply don’t value it. Something as simple as changing the colors makes a shell more readable and makes it feel like its mine. In Hyper, you edit the .hyper.js JSON file or install a sweet plugin that someone else created.

Contrast that to cmd.exe, managing colors means editing hex values in the Windows Registry. I’m a nerd but even that is a big “Hell, naw” from me. Out of the box, vim is completely inaccessible and unreadable in the cmd.exe shell.

The previous command line forerunner was Cmder - it’s still a great terminal - but configuring it means pouring over panes and panes of options screens, nothing as simple and succinct as Hyper’s JSON config. Hyper’s tab design is also more elegant.

By default Hyper uses the Windows system prompt. You need to type bash at the prompt to use Bash, but you can configure Hyper to use Bash as the default in .hyper.js config file.

shell: 'C:\\Windows\\System32\\bash.exe'

Now I’m automatically dropped into my bash shell. If you need to eject from Bash, just type cmd.exe to pull up the Windows system prompt.


  • Hyper requires Node to npm install its plugins inside of your .hyper_plugins/ directory. You’ll need to install Node for Windows for this to work properly.
  • Like bash.exe, some color themes render wrong, notably highlighting is very inaccessible.

Visual Studio Code

Screenshot of Visual Studio Code text editor

You might balk at the name “Visual Studio”, but Code is a minimalist code editor like Atom or SublimeText from Microsoft. It has a few killer features that have won out over my beloved Atom.

  1. Git Diff viewing in-editor has already saved me countless times.
  2. Intellisense is “enterprise grade” code completion.
  3. Run Tasks from the editor without opening the commandline.
  4. Start NPM with the F5 key, this triggers npm start which launches my local server.
  5. Node Debugging can inspect Node apps just like using a web inspector inside Chrome.

By default, Code will launch processes in the default Windows system shell. Wouldn’t it be great if you could launch things using Bash? Well you can! Just add the following to your Settings file:

"": "C:\\WINDOWS\\sysnative\\bash.exe"

Now my VS Code uses Linux. It’s baffling to me how this even works, but it’s great.

Crossing the uncanny valley

Recent improvements to Bash and Hyper have nearly eliminated the imposter syndrome of using Linux on Windows. In the latest releases of Bash on Windows Insider Fast Ring (15002+) I saw a 10× improvement in Jekyll compile times from 5s to 0.5s. The addition of inotify support has also made things faster, requiring less workarounds.

Hyper has improved boot times, stability and added a subjective improvement to my development flow; feeling stylish. This goes miles.

Visual Studio Code is a reliable workhorse. The Node integration is top notch.

I gotta say, I’m really happy with my environment right now. The developer experience is starting to feel really good and natural. And like I say with most #davegoeswindows posts, though I might experience a slight hiccup, things keep getting better month after month.