A Windows Terminal Stack That Finally Matches macOS
Windows development has suffered for too long
Windows' cmd black window has poor performance, an ugly style, and encoding issues — nobody wants to use it. Although Windows Terminal now exists, without bash the development experience still lags behind. Using WSL2? Cross-filesystem communication performance is also poor. Oh My Posh? No! PowerShell is long and clunky, lacking the flexibility and elegance of bash. Is there no better choice?
Actually, there is! Today we'll overhaul the Windows terminal step by step, transforming it from a despised piece of junk into an efficiency tool you can't put down. We'll use Windows Terminal + Cmder + Starship to comprehensively upgrade the experience from three angles: performance, shell, and aesthetics. The tutorial is quite long, but please follow along patiently — the final result is absolutely worth it!
Windows Terminal
Windows 11 comes with Windows Terminal built-in, no separate installation needed. However, some lower versions of Windows 10 may not have it and require a system update or installation from the Microsoft Store.
Cmder
Cmder is an enhanced command-line tool built for Windows. Think of it as a "professional, beautified, enhanced version" of Windows' built-in cmd. Its original purpose was to fill the gap of a good-looking and easy-to-use terminal emulator on Windows.
It's essentially a software package that integrates several powerful tools:
ConEmu: Provides rich interface features like multi-tab, split panes, and transparent backgrounds.
Clink: Brings bash-style command auto-completion, history search, and other enhancements to cmd.
Git for Windows (full version): Lets you directly use a large number of Linux/Unix commands like grep, ls, ssh, etc., under Windows.
Here we are not going to use Cmder directly, but rather use Cmder as the kernel wrapped inside Windows Terminal, because Cmder's rendering performance is far inferior to Windows Terminal and it has quite a few bugs.
Configuring Windows Terminal
Open Windows Terminal, open Settings, then add a new profile. You can also open the JSON file to configure it. Below is my personal configuration for reference. The font used is Maple Mono Normal NL NF CN. Note the Cmder configuration path "cmd.exe /k \"C:\\cmder\\vendor\\init.bat\"". Since I placed the Cmder directory on the C drive, you can modify this according to your actual path. However, it's recommended not to place it on the C drive, as you may encounter some permission issues that cause history reading to fail.
{
"$help": "https://aka.ms/terminal-documentation",
"$schema": "https://aka.ms/terminal-profiles-schema",
"actions": [
{
"command": {
"action": "copy",
"singleLine": false
},
"id": "User.copy.644BA8F2"
},
{
"command": {
"action": "globalSummon"
},
"id": "User.globalSummon.51A3D78C"
},
{
"command": {
"action": "quakeMode"
},
"id": "User.quakeMode.F1E129A4"
},
{
"command": "paste",
"id": "User.paste"
},
{
"command": "duplicateTab",
"id": "User.duplicateTab"
},
{
"command": "find",
"id": "User.find"
},
{
"command": {
"action": "splitPane",
"split": "auto",
"splitMode": "duplicate"
},
"id": "User.splitPane.A6751878"
}
],
"alwaysShowTabs": true,
"copyFormatting": "none",
"copyOnSelect": true,
"defaultProfile": "{f15b60f6-b700-472a-8b2f-d79c7bd4b9a5}",
"disabledProfileSources": [
"Windows.Terminal.Azure"
],
"firstWindowPreference": "defaultProfile",
"keybindings": [
{
"id": "User.copy.644BA8F2",
"keys": "ctrl+c"
},
{
"id": "User.duplicateTab",
"keys": "ctrl+shift+d"
},
{
"id": "User.paste",
"keys": "ctrl+v"
},
{
"id": "User.globalSummon.51A3D78C",
"keys": "alt+s"
},
{
"id": "User.splitPane.A6751878",
"keys": "alt+shift+d"
},
{
"id": "User.quakeMode.F1E129A4",
"keys": "alt+f2"
},
{
"id": "User.find",
"keys": "ctrl+f"
},
{
"id": null,
"keys": "alt+enter"
}
],
"newTabMenu": [
{
"type": "remainingProfiles"
}
],
"profiles": {
"defaults": {
"antialiasingMode": "grayscale",
"colorScheme": "Dark+",
"font": {
"face": "Cascadia Code"
},
"opacity": 79
},
"list": [
{
"adjustIndistinguishableColors": "indexed",
"antialiasingMode": "cleartype",
"colorScheme": "Dark+",
"commandline": "cmd.exe /k \"C:\\cmder\\vendor\\init.bat\"",
"elevate": false,
"experimental.rainbowSuggestions": true,
"font": {
"cellHeight": "1.4",
"face": "Maple Mono Normal NL NF CN",
"size": 12,
"weight": "semi-light"
},
"guid": "{f15b60f6-b700-472a-8b2f-d79c7bd4b9a5}",
"historySize": 9001,
"icon": "C:\\cmder\\icons\\cmder_green.ico",
"name": "Terminal",
"opacity": 73,
"padding": "6",
"snapOnInput": true,
"startingDirectory": "%USERPROFILE%",
"useAcrylic": true
},
{
"commandline": "%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
"font": {
"face": "Maple Mono Normal NL NF CN"
},
"guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
"hidden": true,
"name": "Windows PowerShell",
"opacity": 73
},
{
"colorScheme": "Dark+",
"font": {
"face": "Maple Mono Normal NL NF CN"
},
"guid": "{574e775e-4f2a-5b96-ac1e-a2962a402336}",
"hidden": false,
"name": "PowerShell",
"opacity": 74,
"source": "Windows.Terminal.PowershellCore",
"useAcrylic": true
}
]
},
"rendering.graphicsAPI": "direct3d11",
"schemes": [],
"showTabsInTitlebar": true,
"theme": "dark",
"themes": [],
"useAcrylicInTabRow": true,
"windowingBehavior": "useAnyExisting"
}
Configuring VS Code
Of course, after configuration, you'll also want to use our Cmder in the VS Code terminal. You can add the following to setting.json:
{
"terminal.integrated.profiles.windows": {
"Cmder": {
"overrideName": true,
"path": [
"${env:windir}\\Sysnative\\cmd.exe",
"${env:windir}\\System32\\cmd.exe"
],
"args": [
"/k",
"C:\\cmder\\vendor\\init.bat"
],
"icon": "terminal-cmd"
}
},
"terminal.integrated.defaultProfile.windows": "Cmder",
"terminal.integrated.copyOnSelection": true,
"terminal.integrated.fontFamily": "Maple Mono Normal NL NF CN",
}
}
About the Font
Maple Mono Normal NL NF CN is a programming font developed by a Chinese developer with excellent support for both Chinese and English characters. The NF in Maple Mono Normal NL NF CN refers to the version with embedded Nerd Fonts. Installing this font as the terminal font prepares the terminal to display icons. We often see macOS terminals with many emoji fonts, which look vivid and appealing, improving the otherwise dull compilation and execution experience. Windows always displays ugly question marks and garbled characters, which is infuriating. With this font, the experience will be completely on par with the macOS terminal.
Starship
Starship is a high-performance terminal beautification tool written in Rust, supporting Linux, Windows, and macOS. It is the key to matching the macOS terminal experience on Windows.
Installation
winget install --id Starship.Starship
Cmder Configuration
Since we are using Cmder, we need to add a starship.lua file in the cmder/config directory to load Starship in Clink using Lua for it to take effect. The content is as follows:
Starship Configuration
Create a starship.toml file in the C:\Users{your personal computer username}.config directory to configure it. My personal content is as follows:
"$schema" = 'https://starship.rs/config-schema.json'
# Replace '❯' in the prompt with '➜'
[character] # This component name is 'character'
success_symbol = '[➜](bold green)'
error_symbol = '[➜](bold red)'
[dart]
format = "[$symbol]($style)"
[deno]
format = "[$symbol]($style)"
[golang]
format = '[$symbol]($style)'
[java]
format = '[$symbol]($style)'
[lua]
format = '[$symbol]($style)'
[nodejs]
disabled = true
[php]
format = '[$symbol]($style)'
[python]
format = '[$symbol]($style)'
[bun]
disabled = true
[package]
symbol = '🏷️ '
[git_status]
conflicted = '💥'
ahead = '🏎💨'
behind = '😰'
diverged = '😵'
up_to_date = '✨'
untracked = '⚡️'
stashed = '📦'
modified = '📝'
staged = '⏳[++\($count\)](green)'
renamed = '👅'
deleted = '🗑'
After configuration, the home directory becomes ~, giving it that certain feel. Git status also adds vivid emoji representations. You can also modify it according to your own understanding.
Further Cmder Configuration
Auto-completion
Cmder is based on Clink, and Clink actually extends auto-completion functionality through Lua, which is very useful. You can enable it by entering the following command in the terminal:
# Enable auto-suggestions. When enabled, it will display suggestions based on past history as you type commands.
# When you press F2, you can also switch to a history dropdown list for fuzzy searching. Press F2 again to disable this feature.
clink set autosuggest.enable true
Aliases
In macOS or Linux terminals, configuring aliases improves our efficiency. However, in native Windows terminals, alias support is not great. Configure your aliases in cmder\config\user_aliases.cmd to achieve the same experience.
You can use $1 to get the first parameter. If there are multiple parameters, you can use $*. Note that the e. command opens the current directory in File Explorer, similar to the open command in macOS, which is also very useful.
e.=explorer .
gcb=git checkout $1
gc=git stash
gd=git diff
glg=git log --stat
gcbn=git checkout -b $1
gs=git status
gl=git log
gpr=git pull origin $1
gpo=git push -u origin HEAD
gpc=git push origin HEAD
gbd=git branch -d $*
gbdf=git branch -D $*
gbm=git branch -m $1
gp=git push origin $*
ga=git add .
gf=git fetch
glg=git log --stat
clone=git clone $*
gbl=git branch
gcp=git stash pop
gcl=git stash list
gcne=git commit --amend --no-edit
pw
gfs=git flow feature start $1
gff=git flow feature finish $1
grs=git flow release start $1
grf=git flow release finish $1
ghs=git flow hotfix start $1
ghf=git flow hotfix finish $1
vi=vim $*
cc=claude --dangerously-skip-permissions $*
Home Directory Jump
Although our home directory has become ~, using cd ~ will not jump to the home directory. The system cannot recognize this symbol, so we need to use a Lua extension to implement this functionality. Add a file HomeClink.lua in the cmder\vendor directory with the following content:
-- Small clink script to automatically expand ~ to %HOME% in any command the user executes via Windows' CMD shell.
-- Look for escaped tildes, replaces any instance of "|~" with placeholder text.
local function tilde_escape(command)
return string.gsub(command, "|~", "##EXPANDEDTILDEFORTILDEEXPANDER##")
end
-- Turn escaped tildes back into a regular tilde "~" after we've expanded unescaped tildes.
local function tilde_descape(command)
return string.gsub(command, "##EXPANDEDTILDEFORTILDEEXPANDER##", "~")
end
-- Expand unescaped tildes with rl.expandetilde. Returns two values, the first is the expanded input command, the second is a boolean indicating whether any tildes were expanded. This second value not used in this script.
local function cmd_tilde_expander(input)
local escaped_input = tilde_escape(input)
local expanded_input, was_expanded = rl.expandtilde(escaped_input, true)
local descaped_input = tilde_descape(expanded_input)
return descaped_input
end
-- Register the main tilde expander function to run after the user has executed a command.
clink.onfilterinput(cmd_tilde_expander)
There are more Clink auto-completion Lua scripts available at https://github.com/chrisant996/clink-gizmos — see if there are any scripts suitable for your use.
Directory Jumping
Switching directories in the terminal requires frequent use of cd, first exiting then entering, which is very cumbersome. On macOS using zsh, there are plugins like autojump and z that implement directory memory functionality, allowing you to jump with a z or j command. Windows can actually do this too. Install zoxide, a directory jumping tool implemented in Rust with excellent performance.
winget install ajeetdsouza.zoxide
Since we are using Cmder as a wrapper, we can't use it directly. We also need a Lua plugin to support it. We can use clink-zoxide and place it in the cmder\vendor directory to use it.
List Icons
LSD is also a high-performance tool written in Rust, a replacement for ls that supports displaying file icons by file type. However, you need to have a font with embedded Nerd Font installed for it to display correctly. We have already installed Maple Mono Normal NL NF CN above, so we can install it directly.
winget install --id lsd-rs.lsd
LSD can directly replace ls, so let's modify the alias here to point the ls command to lsd:
ls=lsd $*
la=lsd -a
ll= lsd -l
Experience Optimization
Includes hidden file completion. If you find that Tab isn't working as well as before, it might be because this setting is false. Enabling this will allow Tab to complete many things, such as completing when you switch Git branches.
clink set files.hidden true
Add an .inputrc configuration in the cmder/config directory to enhance the auto-completion experience:
# Basic configuration
set colored-stats on # Enable colored completion
set colored-completion-prefix on # Color the completion prefix
set completion-ignore-case on # Ignore case in completion
set show-all-if-ambiguous on # Immediately show all matches
set mark-symlinked-directories on # Mark symlinked directories
set mark-symlinked-directories on # Mark symlinked directories
Summary
After the above configuration, I believe our terminal experience can reach the level of macOS, and the performance is also quite good. Overall, the Windows terminal can also have a Mac-like experience, but it's not an out-of-the-box kind of thing; it requires rather tedious configuration. However, once configured, it can multiply your experience several times over. Clink is actually a very powerful tool with many features not yet used. You can tinker with it yourself to unlock more fun and useful functions.