A development environment is the set of tools on your machine that lets you write, run, debug and ship code: a terminal, an editor, Git, language runtimes, a package manager and any local services you need. On Windows, setting one up comes down to one decision first, stay native with winget and PowerShell 7, or run a real Linux userland through WSL 2. Pick that path, install the six components below in order, and verify each one before you move on.
Most guides get this wrong by starting with download links. The tools are the easy part. What actually bites people later is PATH changes that never take effect, a Git identity nobody configured, and project files stored on the Windows drive where every file operation crawls. The order below is deliberate.
Table of Contents
- What You Need
- Step-by-Step
- 1. Install Windows Updates and Enable Developer Features
- 2. Install Git and Configure Your Identity
- 3. Choose and Install a Code Editor
- 4. Install Language Runtimes and Package Managers
- 5. Configure a Terminal, Shell, and Environment Variables
- 6. Add Project Services and Container or Virtualization Tools
- 7. Create a Test Project and Verify the Environment
- 8. Automate Setup and Keep the Environment Reproducible
- Common Mistakes
- Frequently Asked Questions
- What is a development environment?
- Do I need WSL 2 to develop on Windows, or is native Windows enough?
- Which Linux distribution should I install for WSL development?
- How do I install and switch between multiple versions of Node.js or Python?
- Is WSL 2 or a full virtual machine better for isolated work?
- What should I do first after moving to a new Windows machine?
What You Need

Windows 10 or Windows 11 with administrator access. Administrator rights matter because WSL, the Virtual Machine Platform and Hyper-V all install as Windows features, and a non-elevated PowerShell cannot enable them. Check your build by pressing Win+R, typing winver and hitting Enter. If Windows Update has pending work, clear it first.
Beyond the OS itself, here is what a working setup actually consists of.
- A terminal. Windows Terminal with PowerShell 7 is the sensible default. It handles tabs, multiple shells and copy-paste cleanly, and it renders modern prompts without fighting you.
- Git. Version control, plus the credential helper that stops you typing a token into every terminal.
- An editor. Visual Studio Code for most work, a full IDE such as Visual Studio or JetBrains Rider when a project needs a debugger, profiler and solution model built in.
- A language runtime and package manager. Node.js, Python, a JDK, the .NET SDK or Go, depending on what you build.
- Optional: containers or a virtual machine. Docker Desktop with the WSL 2 backend, or Hyper-V, when your project needs services like Postgres, Redis or Nginx running side by side.
Which of those are essential depends on your stack. Git, a terminal and an editor are non-negotiable. Everything past that you can add later without breaking what works. Install containers last, because it is the only step that touches virtualization settings in your firmware.
Step-by-Step
1. Install Windows Updates and Enable Developer Features
Open Settings, go to Windows Update and install everything pending, including optional updates. Reboot. Then search for “Developer settings” in the Start menu, or use the Run dialog command winver again to confirm your build number has moved.
Developer Mode lives in Settings, System, For developers. It is not required for Git or any editor, so skip it unless you are sideloading unsigned apps or need a specific USB driver. What WSL 2 does require is virtualization support, which Windows enables through two optional features: Virtual Machine Platform and the WSL package itself. From an elevated PowerShell:
wsl --install
This installs WSL 2, the kernel and a default distribution, then asks you to restart. After the restart, run wsl --version and you should see the WSL version, the kernel version and the WSLg version. If wsl --install fails with an error mentioning virtualization, your CPU or BIOS has it disabled, or a corporate policy blocks the Virtual Machine Platform feature.
Verify the step worked by opening PowerShell and running wsl --status. If you get a version banner rather than an error, the layer below Windows is ready.
2. Install Git and Configure Your Identity
Install Git for Windows from gitforwindows.org, or from the Windows Package Manager if you already use it:
winget install --id Git.Git -e
Open a fresh terminal, because Git’s folder has to reach your PATH before the commands below resolve. Configure your identity. Git refuses to commit without these two values, which is exactly why new users hit an “Author identity unknown” error an hour into a project.
git config --global user.name "Your Name"
git config --global user.email "[email protected]"
git config --global init.defaultBranch main
Confirm what Git actually read, and from which file each value came:
git config --list --show-origin
Handle credentials through Git Credential Manager, which ships with Git for Windows and stores tokens in the Windows Credential Manager, or through an SSH key added to your agent. Do not put personal access tokens in shell history or inside a committed .gitconfig.
3. Choose and Install a Code Editor
Visual Studio Code is the practical default on Windows. It is fast, it opens large repositories without ceremony, and the extension ecosystem covers almost every stack. Install it with winget install --id Microsoft.VisualStudioCode -e.
Install only the extensions the project needs. A good VS Code install has a language pack, a formatter, and little else. The habit of adding ten extensions on day one ends with a 20-second startup and conflicting formatters fighting over the same file.
Turn on format-on-save for the language you use so you stop thinking about style. Then create a throwaway folder, open it with File, Open Folder, and check three things: the integrated terminal opens, your file shows correct syntax highlighting, and Git changes show up in the Source Control panel. If Git does not appear, the folder is not a repository yet, which is what step 7 fixes.
4. Install Language Runtimes and Package Managers
Install the runtime your project actually needs, not the one you think you might need. Each has a version check that tells you immediately whether the terminal can find it.
- Node.js:
winget install --id OpenJS.NodeJS.LTS -e, thennode -vandnpm -v. The LTS channel is the right pick for most work. - Python:
winget install --id Python.Python.3.13 -e, thenpython --version. Tick “Add python.exe to PATH” in the installer or the command will not resolve. - Java: install a JDK rather than a JRE, then
java -versionandjavac -version. Both need to print. - .NET:
winget install --id Microsoft.DotNet.SDK.9 -e, thendotnet --list-sdks. - Go:
winget install --id GoLang.Go -e, thengo version.
Proof it works is a hello world, not the version string alone. Write it, run it, delete it.
node -e "console.log('hello from ' + process.version)"
python -c "print('hello from', __import__('sys').version)"
For projects that need several runtime versions at once, that belongs in step 8 rather than here. Install one clean version now and add a version manager once you actually hit the need.
5. Configure a Terminal, Shell, and Environment Variables
Windows Terminal is the terminal emulator; PowerShell 7 is the shell. They are separate. Install both:
winget install --id Microsoft.WindowsTerminal -e
winget install --id Microsoft.PowerShell -e
Open the settings JSON with Ctrl+Shift+, and set the default profile to PowerShell. Add a Git Bash profile too if you use it, since Git for Windows ships bash.exe and it becomes a fourth tab without any extra work.
Environment variables need one rule: add a tool directory to the user PATH, never the machine PATH, and only when the installer did not already do it. Read what is there before you touch anything:
$env:PATH -split ';'
The most common failure here is editing PATH in one terminal and testing in another. Windows copies the PATH into each process at launch, so an existing window never sees the change. Close every terminal, open a new one, and only then run the version check again. Restarting one tab is not enough.
6. Add Project Services and Container or Virtualization Tools
This step is optional, and that is not a hedge. If your project runs services in containers, you need Docker Desktop. If it does not, skip this entirely and install a database the normal way.
Install Docker Desktop with winget install --id Docker.DockerDesktop -e, then accept the WSL 2 backend option in the installer. Docker needs the Virtual Machine Platform and WSL 2, so verify wsl --version reports version 2 before you start. If virtualization is unavailable, Docker Desktop will refuse to start with an error naming the missing platform.
Verify with a container that needs no configuration:
docker run hello-world
Seeing the welcome banner means the daemon, the image pull and the container lifecycle all work. After that, open Docker Desktop settings, go to Resources, WSL Integration and switch on integration for your distribution, otherwise containers started inside your WSL shell will not see local images.
For heavier isolation, Hyper-V gives you full virtual machines and costs more memory. Reach for it when you need a second OS, snapshots of a whole machine, or kernel work, not for routine web development.
7. Create a Test Project and Verify the Environment
Create a folder outside your usual documents pile, initialise a repository, add one file, and run it through the whole chain: editor, Git, runtime, build.
mkdir ~/dev/hello
cd ~/dev/hello
git init
git status
An empty repository reporting “No commits yet” is the correct output. Add a source file, then stage, commit and run it:
git add hello.js
git commit -m "Add hello script"
node hello.js
That commit succeeding proves your identity, and the script printing proves the runtime. Now run the checks in the order they layer:
git --versionproves the version control client is on PATH.node -v,python --version,java -versionordotnet --list-sdksproves the runtime resolves.npm installorpip install requestsproves the package manager reaches the network and writes to disk.docker run hello-worldproves containers, if you installed them.- Opening the folder in VS Code and running a build task proves editor integration.
If all five pass, your environment on Windows is done. Anything that fails later is almost always one of the items above, and the fixes are in the next section.
8. Automate Setup and Keep the Environment Reproducible
A setup you cannot repeat is a setup you will rebuild from scratch on the next machine. Two things make it repeatable: pinned versions in the project, and configuration in a repository you control.
Most ecosystems already read version files from the project root, and you should commit all of them: .nvmrc or .node-version for Node, .python-version for Python, global.json for .NET, and a lock file for every package manager you use. These travel with the code, so a new machine reads them rather than guessing.
Put your Git config, shell configuration and editor settings in a private repository, then bootstrap a new machine with a short script. Keep that script boring: install tools from the Windows Package Manager, clone the config repository, apply it. A provisioning script that edits system settings or reboots your machine will eventually do something you did not expect.
Write a short onboarding note with the commands above in order. It takes ten minutes now and saves an hour for you or a new hire later. Keep it next to the project, not in your head.
What never belongs in that repository: credentials, tokens, SSH private keys, machine-specific absolute paths, caches and build output. Add those to .gitignore in the config repository before the first push, not after.
Common Mistakes
Nearly every Windows setup problem falls into one of these categories. Find your symptom, apply the fix, then re-run the step 7 checklist to confirm you solved the real problem.
| Symptom | Cause | Fix |
|---|---|---|
| A newly installed tool is “not recognized” | The PATH change has not reached running processes | Close every terminal window and reopen; check with $env:PATH -split ';' |
| Git asks for identity on first commit | user.name and user.email were never set | Run git config --global user.name "Your Name" and the matching email command |
| Wrong runtime version is active | An older installer sits earlier in PATH | Run the version check, then remove the stale entry from the user PATH |
| PowerShell refuses to run a script | Execution policy blocks unsigned scripts | Inspect with Get-ExecutionPolicy -List, then set a CurrentUser policy rather than bypassing per script |
| Port already in use when starting a service | Another process holds the port | Find the listener with Get-NetTCPConnection -LocalPort 3000, then stop the old process or move the app |
| Docker will not start | Virtualization or the WSL 2 backend is unavailable | Run wsl --version, confirm version 2, and check the Virtual Machine Platform feature state |
| Files copied from the web are read-only or blocked | Windows marks downloaded files with a Zone.Identifier stream | Right-click, Properties, Unblock, or clear the stream on files you trust |
| Every diff touches every file | Line-ending conversion differs between Windows and Linux tooling | Set git config --global core.autocrlf input so Git stores line endings as sent |
| File watching and installs feel very slow | The project lives on the Windows drive, where every operation crosses the filesystem boundary | Move the project into your Linux user home directory and keep paths on one filesystem |
That last row is the one people argue about most. A project kept on the Windows drive and worked on from a Linux shell pays a translation cost on every file open, every stat and every watcher event, and install steps that touch tens of thousands of files become obvious. Store the project inside the Linux filesystem instead. Windows tools can still open Linux files through the network path, and editors handle the boundary properly when the file lives on the Linux side.
For day-to-day upkeep, run Windows Update on a schedule rather than on a whim, since Virtual Machine Platform updates arrive with it and an out-of-date WSL kernel is behind several strange hangs. Restart the terminal after any PATH edit. Keep one distribution per project type rather than mixing unrelated stacks in a single environment, because a broken global install then only affects one folder.
Frequently Asked Questions
What is a development environment?
A development environment is the combined set of tools on your machine that lets you write, run, debug and ship code: a terminal, a code editor, version control, language runtimes, a package manager, and any local services such as a database or container engine. On Windows it also includes the decision about whether those tools run natively or inside the Windows Subsystem for Linux. Configuring them once, in a known order, saves rebuilding the whole thing on your next machine.
Do I need WSL 2 to develop on Windows, or is native Windows enough?
Native Windows is enough for .NET, C, C++, Java, PowerShell and most Windows-targeted work, and it avoids a virtualization layer entirely. WSL 2 earns its place when your project leans on Linux behaviour: shell scripting, containers, a CI pipeline that runs on Linux, or a toolchain you already know from another machine. Pick one path for a project rather than splitting file locations between the two, because working across the filesystem boundary is what causes the slowness people complain about.
Which Linux distribution should I install for WSL development?
Ubuntu is the safest default because its documentation, package versions and community answers are the ones most tutorials assume. Debian suits servers and a lighter footprint, while Arch suits people who already maintain Arch systems. Install it from the Windows Store or with wsl –install -d Ubuntu, set version 2 as the default with wsl –set-default-version 2, and confirm with wsl –version before you install any tooling. You can add a second distribution later without disturbing the first.
How do I install and switch between multiple versions of Node.js or Python?
Use a version manager rather than reinstalling the runtime. For Node, install nvm-windows on native Windows or nvm or fnm inside WSL, then run nvm install 22 and nvm use 22 to switch. For Python, pyenv-win on Windows or pyenv in WSL handles the same job, with pyenv install and pyenv local. Record the version the project expects in .nvmrc or .python-version and commit it, so a teammate or a fresh machine starts on the right version automatically.
Is WSL 2 or a full virtual machine better for isolated work?
WSL 2 wins for day-to-day development: it starts in seconds, shares files with Windows without a network share, forwards localhost automatically and needs far less memory. A full virtual machine wins on isolation: it has its own kernel, its own network segment and a snapshot system, which matters for kernel work, untrusted code or testing operating system changes. Most people end up with WSL for daily work and a virtual machine for the occasional isolated experiment or server practice.
What should I do first after moving to a new Windows machine?
Work through the eight steps in order rather than installing tools as you need them. Install Windows updates and confirm virtualization support, install Git and set your name and email, then add your editor and exactly one runtime with its package manager. Configure the terminal and check the PATH, add containers only if the project needs them, and finish with the test project from step 7. Keep your Git and shell configuration in a private repository so the second machine takes minutes.
Start tomorrow with two things: clear your Windows updates and set your Git identity. Then install one editor, one runtime, and run the test project from step 7. Everything after that, containers, version managers, a second shell, is something you add the day a project needs it, not on day one.


