While Windows has come a long way with PowerShell, the default terminal experience can still feel dated compared to modern CLI setups. The good news? You can bring the same productivity-boosting tools that Linux users enjoy to your Windows environment.
In this guide, I’ll show you how to transform your PowerShell into a modern, efficient development environment using tools like fuzzy finding, syntax highlighting, and smart navigation—all native to Windows, no WSL required.
Table of Contents#
- Prerequisites: Package Managers
- Fuzzy Finding with fzf, fd, and bat
- Smart Navigation with zoxide
- Better Directory Listings with eza
- Putting It All Together
Prerequisites: Package Managers#
Before we begin, you’ll need either Chocolatey or winget installed. These are package managers for Windows that make installing and updating software much easier.
Chocolatey#
If you don’t have Chocolatey yet, install it from chocolatey.org by running this in an elevated PowerShell:
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))winget#
Windows 11 comes with winget pre-installed. For Windows 10, you can install it from the Microsoft Store by installing “App Installer.”
Fuzzy Finding with fzf, fd, and bat#
What Are These Tools?#
If you’ve used a modern code editor, you’re familiar with fuzzy finding—type a few characters and instantly filter through thousands of files. These three tools bring that power to your command line:
- fzf: The fuzzy finder itself—a fast, interactive filter for any list
- fd: A modern, user-friendly alternative to the
findcommand - bat: A
catclone with syntax highlighting and Git integration
Together, they create a powerful search experience with beautiful previews.
Installation#
Install all three tools using Chocolatey:
choco install fzf
choco install fd
choco install batPowerShell Integration#
To make fzf work seamlessly with PowerShell, you need the PSFzf module:
Install-Module -Name PSFzf -Scope CurrentUser -ForceConfiguring Your PowerShell Profile#
Your PowerShell profile is like the .bashrc or .zshrc on Linux—it runs every time you start a new PowerShell session. Let’s configure it to integrate these tools.
First, open your PowerShell profile (it will create it if it doesn’t exist):
notepad $PROFILEAdd the following configuration:
# Import necessary modules
Import-Module PSReadLine
Import-Module PSFzf
# Manually bind Ctrl+t to the Search-Files function
Set-PSReadLineKeyHandler -Chord 'Ctrl+t' -ScriptBlock {
Search-Files
}
# Bind Ctrl+r for reverse command history with fzf
Set-PSReadLineKeyHandler -Chord 'Ctrl+r' -ScriptBlock {
$selectedCommand = Get-History | Sort-Object -Property Id -Descending | ForEach-Object { "$($_.Id) $($_.CommandLine)" } |
fzf --height=40% --reverse --prompt "History> " |
ForEach-Object { ($_ -split '\s{2,}', 2)[1] } # Extract the command
if ($selectedCommand) {
[Microsoft.PowerShell.PSConsoleReadLine]::Insert($selectedCommand)
}
}
# Define the Search-Files function
function Search-Files {
fd --type file --hidden --exclude .git | fzf --prompt "Files> " --preview "bat --style=numbers --color=always --line-range :500 {}"
}This configuration does three important things:
- Ctrl+T: Opens a fuzzy file finder with syntax-highlighted previews
- Ctrl+R: Searches through your command history interactively
- Search-Files function: Combines fd for finding files and bat for previewing them
Save the file and restart PowerShell (or run . $PROFILE to reload it).
Customizing bat with Themes#
By default, bat looks great, but you can customize it with themes. The Tokyo Night theme is particularly popular.
Create the themes directory if it doesn’t exist:
mkdir C:\Users\thors\AppData\Roaming\bat\themesDownload your preferred theme file (.tmTheme format) and place it in that directory. Then rebuild the cache:
bat cache --buildTo use the theme, add this to your PowerShell profile:
$env:BAT_THEME = "tokyonight_night"Using fzf#
Once configured, here are the key combinations you’ll use:
| Key Combination | Description |
|---|---|
| CTRL-t | Look for files and directories |
| CTRL-r | Look through command history |
| Enter | Select the item |
| Ctrl-j or Ctrl-n or Down arrow | Go down one result |
| Ctrl-k or Ctrl-p or Up arrow | Go up one result |
| Tab | Mark a result |
| Shift-Tab | Unmark a result |
| cd **Tab | Open up fzf to find directory |
| export **Tab | Look for env variable to export |
| unset **Tab | Look for env variable to unset |
| unalias **Tab | Look for alias to unalias |
| ssh **Tab | Look for recently visited host names |
| kill -9 **Tab | Look for process name to kill to get pid |
| any command (like nvim or code) + **Tab | Look for files & directories to complete command |
Pro tip: Press Ctrl+T, start typing part of a filename, and watch as fzf instantly filters through your entire directory tree. The preview pane on the right shows you the file contents with syntax highlighting!
Smart Navigation with zoxide#
What is zoxide?#
zoxide is a smarter cd command that learns from your habits. Instead of typing full paths, you can jump to frequently-used directories with just a few characters. Think of it as autocomplete for your entire file system.
For example, after visiting D:\Repositories\my-project a few times, you can jump there with just cd proj.
Installation#
Install zoxide using Chocolatey:
choco install zoxideConfiguration#
Add this to your PowerShell profile:
Invoke-Expression (& { (zoxide init powershell | Out-String) })
Remove-Item Alias:cd
function cd {
param (
[string]$path
)
if ($path -eq "repo") {
Set-Location "D:\Repositories"
} elseif ($path -eq "gitlab") {
Set-Location "D:\Repositories\toto-gitlab"
} else {
z $path
}
}This configuration does two clever things:
- Integrates zoxide as the backend for the
cdcommand - Adds custom shortcuts:
cd repoandcd gitlabjump directly to your most-used directories
How It Works#
- First time:
cd D:\Repositories\my-project\src\components(zoxide learns) - After a few visits:
cd comp(instantly jumps to the components directory) - The more you use directories, the higher they rank in zoxide’s scoring
Better Directory Listings with eza#
What is eza?#
eza is a modern replacement for ls (or dir on Windows) with colors, icons, Git integration, and better formatting. It makes understanding directory contents much faster and more pleasant.
Installation#
Install eza using winget:
winget install eza-community.ezaConfiguration#
Add this to your PowerShell profile to replace both ls and dir:
Remove-Item Alias:ls
function ls {
eza --color=always --long --git --all --icons=always --no-time
}
Remove-Item Alias:dir
function dir {
eza --color=always --long --git --all --icons=always --no-time
}Now when you run ls or dir, you’ll see:
- Color-coded file types: directories, executables, images, etc.
- Icons: visual indicators for different file types
- Git status: see which files are modified, staged, or ignored
- Better formatting: easier to read with proper alignment
Command Breakdown#
Let’s understand the flags we’re using:
--color=always: Enable colors--long: Show detailed information (size, permissions)--git: Display Git status for files--all: Include hidden files--icons=always: Show icons for file types (requires a Nerd Font)--no-time: Hide timestamps for a cleaner view
Note: For icons to display properly, you’ll need to install a Nerd Font in your terminal. Popular choices include “FiraCode Nerd Font” or “JetBrains Mono Nerd Font.”
Putting It All Together#
Your Complete PowerShell Profile#
Here’s what your complete $PROFILE file should look like with all the configurations:
# Import necessary modules
Import-Module PSReadLine
Import-Module PSFzf
# fzf key bindings
Set-PSReadLineKeyHandler -Chord 'Ctrl+t' -ScriptBlock {
Search-Files
}
Set-PSReadLineKeyHandler -Chord 'Ctrl+r' -ScriptBlock {
$selectedCommand = Get-History | Sort-Object -Property Id -Descending | ForEach-Object { "$($_.Id) $($_.CommandLine)" } |
fzf --height=40% --reverse --prompt "History> " |
ForEach-Object { ($_ -split '\s{2,}', 2)[1] }
if ($selectedCommand) {
[Microsoft.PowerShell.PSConsoleReadLine]::Insert($selectedCommand)
}
}
function Search-Files {
fd --type file --hidden --exclude .git | fzf --prompt "Files> " --preview "bat --style=numbers --color=always --line-range :500 {}"
}
# bat theme
$env:BAT_THEME = "tokyonight_night"
# zoxide integration
Invoke-Expression (& { (zoxide init powershell | Out-String) })
Remove-Item Alias:cd
function cd {
param (
[string]$path
)
if ($path -eq "repo") {
Set-Location "D:\Repositories"
} elseif ($path -eq "gitlab") {
Set-Location "D:\Repositories\toto-gitlab"
} else {
z $path
}
}
# eza (better ls/dir)
Remove-Item Alias:ls
function ls {
eza --color=always --long --git --all --icons=always --no-time
}
Remove-Item Alias:dir
function dir {
eza --color=always --long --git --all --icons=always --no-time
}Testing Your Setup#
After saving your profile and reloading PowerShell, try these commands:
- Press Ctrl+T and start typing a filename
- Run
lsto see your new directory listing - Navigate with
cdto a directory, then later type just part of its name - Press Ctrl+R and search through your command history
Conclusion#
You now have a modern, productive PowerShell environment that rivals any Linux terminal setup! Here’s what you’ve gained:
- Lightning-fast file finding with fzf and fd
- Beautiful syntax highlighting with bat
- Intelligent navigation with zoxide
- Information-rich directory listings with eza
- Seamless PowerShell integration for all tools
Next Steps#
- Explore fzf further: Try creating custom functions for project switching or log searching
- Customize eza: Experiment with different flags and create aliases for specific views
- Install a Nerd Font: Get proper icon support in your terminal
- Consider Windows Terminal: Microsoft’s modern terminal app with tabs, themes, and better rendering
- Share your dotfiles: Put your PowerShell profile in version control
The beauty of this setup is that these are native Windows tools with Windows-native installation—no virtualization, no compatibility layers, just pure PowerShell power.
Happy scripting!

