A Guide to Overengineering a Windows Terminal
Avi Avinav
Posted on June 4, 2022
For decades, Windows users have been made fun of by the Linux community for the lack of a cool terminal (among other things). Well, it's about time we fight!
In this article, we will go through setting up a development workflow in the Windows terminal.
Prerequisites
- Know how to type
- Windows 10/11 (Some things may not work for you in this article if you are on some other version)
- (Optional) Know Basic Unix Commands such as
cd
,mkdir
, etc
What will we be doing
We will set up the following:
- Powershell
- Nerd Fonts
- Theme
- Scoop
- z Directory Jumper
- Terminal Icons
- Node & Git
- Neovim
- Oh-My-Posh
- Autocomplete
- Aliases
- Utilities
Well, then, let's get started!
Things to remember during the article
-
~
stands for your root or home directory, the default directory where the terminal will generally open. - If anything doesn't work even after installing/configuring just close and reopen the terminal.
- The command pallete opens with
ctrl+shift+p
. - Terminal settings open with
ctrl+,
Getting Started
Powershell
First of all, let's install Powershell, this is not Windows Powershell that comes with Windows. You will have to go to the Microsoft Store and search for it, it's free so don't worry.
After you have done that open Terminal (not PowerShell or Command Prompt), you can search it up, it's pre-installed on your PC.
Press Ctrl+,
to open settings, here we will set Powershell as our default, it would be Command Prompt in default if you haven’t changed it before.
In the startup menu, change the default profile to PowerShell and save, that's it!
Nerd Fonts
So, what are Nerd Fonts? Nerd fonts let you use font ligatures and more glyphs in general, it's something everyone should use while coding. You might actually be using it without knowing in your IDE/text editor. I used Fira Code for a long time before knowing it was a Nerd Font.
To install a nerd font, first, go to the nerd-fonts GitHub Repo and download the zip file of your preferred Nerd Font from the latest release. Extract the zip file and install the fonts. If you have never installed a font before, that’s fine, you can just double-click the .ttf
files and click on install.
I use the JetBrains Mono NF and another of my favorites is Hack NF (NF stands for Nerd Fonts).
Themes
To change the theme of your terminal, open settings and click on "Open JSON file", this will open the settings.json file for your terminal.
Now to change the theme you have three options:
- Choose a theme from the themes already present in the terminal by default
- Create your own theme from scratch or modify one already present.
- Use a pre-written theme
I use a pre-written theme, you can find a lot of them here and paste it into your settings.json under “schemes”. Save the file.
Now, go back to your Terminal settings (not settings.json) and choose the theme you just added.
Terminal Tools
Scoop
Let's first install scoop, a package manager for Windows. We will be then using scoop to install other tools.
To install scoop run the following in PowerShell:
winget install scoop
This will install scoop. If you are wondering what winget is, it is a package manager that comes by default in Windows 10/11.
In case, you don't have winget do the following:
iwr -useb get.scoop.sh | iex
Now type scoop
and if it returns an output like the below then all is good.
Usage: scoop <command> [<args>]
Some useful commands are:
alias Manage scoop aliases
bucket Manage Scoop buckets
cache Show or clear the download cache
cat Show content of specified manifest. If available, `bat` will be used to
pretty-print the JSON.
checkup Check for potential problems
cleanup Cleanup apps by removing old versions
config Get or set configuration values
create Create a custom app manifest
depends List dependencies for an app
download Download apps in the cache folder and verify hashes
export Exports (an importable) list of installed apps
help Show help for a command
hold Hold an app to disable updates
home Opens the app homepage
info Display information about an app
install Install apps
list List installed apps
prefix Returns the path to the specified app
reset Reset an app to resolve conflicts
search Search available apps
shim Manipulate Scoop shims
status Show status and check for new app versions
unhold Unhold an app to enable updates
uninstall Uninstall an app
update Update apps, or Scoop itself
virustotal Look for app's hash on virustotal.com
which Locate a shim/executable (similar to 'which' on Linux)
Type 'scoop help <command>' to get help for a specific command.
If it doesn't return an output, just close and reopen the terminal, and it will work.
This is the moment you stop using those installers, now you are a terminal guy. You can even install Mozilla Firefox, just do scoop install firefox
.
There is also choco/chocolatey which you can use as a package manager but we will stick with scoop for this article.
z
z is a directory jumper. What is a directory jumper? Let's say you are in the directory ~/Desktop/Development/NextJS/tutorial
, and you want to go to ~/SomewhereElse/Products/Product1/prod-website
, the one way of doing this in your terminal would be this:
cd ../../../../
cd SomewhereElse/Products/Product1/prod-website
This looks small but you don't always remember where all your projects are so add 4-5 more commands in there. This wastes our time, especially over a prolonged period. This is where a directory jumper comes in, with just a single command you can go from one project to another.
Let's take the above example this time you just have to do this (assume you are in ~/Desktop/Development/NextJS/tutorial
):
z prod-website
That's it! You just should have visited the directory once in your lifetime (which you most probably will during the project setup). You don't even need to use the full name of your project directory, you can just do z prod
and you would jump to the most recent directory which has prod
in its name somewhere (in this case, the prod-website).
One thing to note is, to try not to include spaces in your directory names that may make it hard for the directory jumper to find them. It's a good practice in general too to not include spaces in directory names.
Now to install z
, just type in the following and hit enter and there you go:
Install-Module -Name z -Force
Huh? This is not scoop, is it? Yes, it is not, we are currently installing a PowerShell Module (you can install some modules using scoop or winget too) and thus, we are using the Install-Module
command that is builtin into PowerShell.
Try it out, if it doesn't work open a new Terminal tab (shortcut: ctrl+shift+t), and it should work now.
Terminal Icons
As the name suggests it adds icons for when you do ls
. To install it do the following:
Install-Module -Name Terminal-Icons
This will install the module. To be able to use it globally, we need to add it to our powershell profile, which we will cover in this article later.
Node & Git
If you use Node.js install it but if you don’t there is no need to.
To install Node, first install nvm
which stands for Node Version Manager, it also lets you have multiple versions of node installed at the same time.
scoop install nvm
This will install nvm.
Now download the stable release of Node.js with:
nvm install lts
for the latest release do:
nvm install latest
you can even specify a certain version like this:
nvm install 18.1.0
To list out the versions of node available use nvm list
, the one with a *
denotes the one being used currently. To change the version do nvm use version_number
.
Quick Tip: You can also install sudo
by doing scoop install sudo
, by using that you don’t have to close and reopen the terminal for admin commands. You can use it like, sudo nvm use 18.1.0
.
Now for git just do either of the following:
using scoop:
scoop install git
or
using winget
winget install git
That's it!
Neovim
Neovim is a fork of Vim that is better for plugins and extensions.
To install Neovim, type in the following and hit the enter key:
scoop install neovim
Also, install any other packages it asks you to. I don't recommend jumping into Neovim right ahead if you haven't seen it ever before in your life or don't know the common commands/keybindings. You can check out this article of mine for learning a bit about it and how to set it up.
I will be using Neovim here for editing files, but it's alright you can just follow along with the steps in your preferred text editor or IDE too.
Oh-My-Posh
Now that all your terminal tools are all set up, let's start with customizing your prompt.
First of all, to install it you can do either of the following:
winget install oh-my-posh
or
scoop install https://github.com/JanDeDobbeleer/oh-my-posh/releases/latest/download/oh-my-posh.json
Now, we will start messing with config files!
First, let's create a config file for our PowerShell, we will be using this file to customize our prompt as well as to set aliases and utilities. The config file will be in PowerShell script.
You can create it anywhere but you will have to link it accordingly in your PowerShell profile. PowerShell profile is from where PowerShell will load its config, you can write your config there directly but we will write it in a separate file.
Let's make ours in ~/.config/powershell
.
cd .config
mkdir powershell && cd powershell
Again, you can name your file anything just make sure it will be the same in your PowerShell profile.
Let's get started with the editing then, create a file user_profile.ps1
in your preferred editor, I will be using Neovim here.
nvim user_profile.ps1
Now type in the following into your powershell config:
oh-my-posh init pwsh --config ~/.config/powershell/avi.omp.json | Invoke-Expression
Save it now. In here you can see "avi.omp.json" and you can name it anything like "your_name.omp.json" just make sure to replace it in the config. Now, you may ask me though, what even is that file? That file is the one that will contain our oh-my-posh configuration for the prompt.
You can create your own custom prompt from scratch by looking at the docs, but there are a lot of awesome ones already there. I use one of them and just modified it a bit. You can check it out on their website and copy the config. Here's the one I am using:
{
"$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes
/schema.json",
"blocks": [
{
"alignment": "left",
"segments": [
{
"foreground": "#41A6B5",
"style": "plain",
"template": "@avi",
"type": "session"
},
{
"foreground": "#7AA2F7",
"properties": {
"folder_separator_icon": "/",
"style": "full"
},
"style": "plain",
"template": " \uf07b {{ .Path }} ",
"type": "path"
},
{
"foreground": "#BB9AF7",
"powerline_symbol": "\ue0b0",
"properties": {
"fetch_stash_count": true,
"fetch_upstream_icon": true
},
"style": "plain",
"template": "{{ .UpstreamIcon }}{{ .HEAD }}{{ if gt .StashCount 0 }} \uf692
{{ .StashCount }}{{ end }} ",
"type": "git"
}
],
"type": "prompt"
},
{
"alignment": "left",
"newline": true,
"segments": [
{
"foreground": "#cd5e42",
"style": "plain",
"template": "\ue3bf ",
"type": "root"
},
{
"foreground": "#CD4277",
"style": "plain",
"template": "> ",
"type": "text"
}
],
"type": "prompt"
}
],
"version": 2
}
Next, open your powershell profile (you can do it by nvim $profile
, do it from the home directory if you are not on Neovim, the file is located at ~/My Documents/powershell/Microsoft.PowerShell_profile.ps1), and type in the following:
. $env:USERPROFILE\.config\powershell\user_profile.ps1
Save that. Close and reopen the terminal. Your prompt should load now.
Awesome! Now, let's add autocomplete.
Autocomplete
PSReadline is a module of PowerShell that comes pre-installed which will help us out with the autocomplete.
To configure it open your user_profile.ps1
and add the following:
Set-PSReadLineOption -PredictionSource History
Set-PSReadLineOption -PredictionViewStyle ListView
You can choose "HistoryAndPlugin" or "Plugin" too as PredictionSource. For PredictionViewStyle, the other option is InlineView, you can also switch between them by pressing the F2 key.
I talked about adding Terminal Icons to the config before, you can do it by just adding the following line into your config:
Import-Module Terminal-Icons
Aliases
Aliases can be useful in saving time.
It's quite simple to set aliases, for example:
Set-Alias g git
The above will set the alias for git
as g
, but that will only make it the alias for this particular terminal session/tab not globally. To make it a global alias add the exact same command as above in your powershell config file. Now, g is the alias for git. Similarly, you can set other aliases. Here are a few of mine:
Set-Alias v nvim
Set-Alias g git
Set-Alias y yarn
Set-Alias p pnpm
Set-Alias tig 'C:\Program Files\Git\usr\bin\tig.exe'
Set-Alias explorer explorer.exe
These are PowerShell aliases, you can also setup aliases for git to speed up your development process, I won't go into the detail of it here.
There is another way to set aliases for commands like npm start
, yarn dev
. Here is an example of making alias yd
for yarn dev
:
function yarnDev {
yarn dev
}
New-Alias yd yarnDev
I don’t have experience with PowerShell script, so in the above, I can only explain that we create a function yarnDev
and add whatever we want to run when we call the function. After that, we set the alias to call the function as yd
.
Similarly, you can setup other aliases for such commands.
Utilities
You can even make your own little commands by setting them in your PowerShell config. For example, touch
command (used to create a file) which is not present in PowerShell, here is how you can add it:
function touch ($command) {
New-Item -Path $command -ItemType File | out-null && Write-Host Created $command
}
What we are doing above is creating a function touch
and letting it have a parameter. Then, in New-Item -Path $command -ItemType File
, we are using built-in PowerShell commands to create a file, you will have to research PowerShell commands to create more utilities on your own, the documentation is amazing, so it won’t be a problem. In the second half of the function, we are just telling it to output Created [file_name]
.
Here is how you can add rm
command from Linux:
function rm ($command) {
Remove-Item $command -Recurse && Write-Host Removed $command
}
To use this just do rm [file_name/directory_name]
and it will delete the file.
It is not exactly the same as the rm
command in Linux though.
Other tools
Here are some of the other CLI tools you can use:
- Commitizen - Commitizen is used for defining a standard way of committing rules and communicating them in Git. It is designed for teams, but I also use it for my personal projects.
- gh CLI - gh is GitHub on the command line. It brings pull requests, issues, and other GitHub concepts to the terminal next to where you are already working with git and your code.
- gh-dash extension - An extension of gh cli to display a dashboard with pull requests and issues.
- dunk - You can use this to get prettier git diffs.
- Rich CLI - Rich-cli is a command-line toolbox for fancy output in the terminal.
WSL Setup
Now, you might have already heard of WSL or might even be using it, nothing wrong with it if you are not. WSL stands for Windows Subsystem For Linux, it lets you have the Linux terminal on your windows machine.
I will not be discussing WSL setup here but you can check out "The Complete Windows Developer Setup Guide" by @stephanlamoureux, it goes through setting up WSL quite nicely.
Conclusion
So, that's finished! You can find my config files here on GitHub if you want, before copying anything go through the readme once, also do not copy anything you don’t know the meaning of.
If anyone wants to add something, correct me somewhere, or ask anything please feel free to do so in the comments.
Resources
- for themes - https://windowsterminalthemes.dev/ or https://github.com/atomcorp/themes
- docs for PSReadline - https://docs.microsoft.com/en-us/powershell/module/psreadline/?view=powershell-7.2
- video by devsalife on setting up powershell - https://www.youtube.com/watch?v=5-aK2_WwrmM
- Documentation for all other tools has been linked with their introductions in the article
Posted on June 4, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.