Windows 11 Terminal Beautification: A Complete From-Scratch Guide
Windows 11 Terminal Beautification Complete Guide
Applicable environment: Windows 11 22H2 and above, Windows Terminal 1.20+, PowerShell 7.2+ Tab bar UI theme: requires Windows Terminal 1.24 and above (see section 3.5) Goal: from "white background black text, full of square boxes" to a modern terminal with "frosted glass, Nerd icons, Git status, smart completion" How to read: in a hurry → see Chapter 2 "10 Minute Quick Start"; want to understand everything → read sequentially from Chapter 0
github: https://github.com/sumigmomo/Windows11-Terminal-Setup-Offline Provides a one-click installation script, recommended to download and use directly, double-click
Setup-NewPc.cmd
Font link: https://github.com/subframe7536/maple-font/releases/download/v7.9/MapleMono-NF-CN.zip Font size about 150M, if the script download is too slow you can download manually, put it in the root directory \fonts directory, the script will automatically find and install the font
Effect preview
Preface
This is a from-scratch Windows 11 terminal beautification tutorial, covering Windows Terminal appearance, Nerd Font, Oh My Posh prompt, PSReadLine completion, common command-line tools, and a ready-to-use profile.
The text uses Catppuccin Mocha and Tokyo Night Storm as two color scheme examples, but all steps are not bound to a specific theme: you can replace them with any color scheme and OMP theme you like.
The text uses relatively recent versions of Windows Terminal and Oh My Posh as examples; when version differences occur, compatibility ranges are noted in the text.
- No need to reinstall the system, all configuration is in the user directory
- Every step can be rolled back individually, there is an uninstall and restore section at the end
- Commands are executed by default in PowerShell 7, not Windows PowerShell 5.1
Table of Contents
- 0. First figure out: what exactly are you beautifying
- 1. Environment self-check
- 2. 10 Minute Quick Start (lazy version)
- 3. Step 1: Windows Terminal configuration
- 4. Step 2: Nerd Font font
- 5. Step 3: Oh My Posh prompt
- 6. Step 4: PSReadLine completion and prediction
- 7. Step 5: Efficiency tools family bucket
- 8. Step 6: Complete profile template
- 9. Step 7: Unified color scheme
- 10. Advanced play
- 11. Troubleshooting manual
- 12. Rollback and uninstall
- Appendix A: Solidify configuration into a script (optional)
- Appendix B: Command cheat sheet
0. First figure out: what exactly are you beautifying
Many people copy a bunch of configs at the start and don't know which layer went wrong. Terminal beautification actually only has four layers:
┌─────────────────────────────────────────────────────┐
│ Windows Terminal (terminal host) │
│ Responsible for: window, tabs, font rendering, color scheme, transparency, background image │
│ ┌───────────────────────────────────────────────┐ │
│ │ PowerShell 7 (Shell) │ │
│ │ Responsible for: executing commands, history, completion, syntax highlighting │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ Oh My Posh (prompt framework) │ │ │
│ │ │ Responsible for: path, Git branch, execution time, version numbers… │ │
│ │ └─────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────┘ │
│ Font (Nerd Font): provides arrows, file/language icons and monospaced alignment │
└─────────────────────────────────────────────────────┘
| Layer | Component | When something goes wrong you'll see |
|---|---|---|
| Terminal host | Windows Terminal | Wrong color scheme, not transparent, font not selectable |
| Shell | PowerShell 7 | Commands not working, profile errors |
| Prompt | Oh My Posh | Prompt is still the old PS C:\> |
| Font | Nerd Font | Full of □, ?, icons misaligned |
Correct order: terminal → font → prompt → completion → toolchain. If the font is not right, all icons later will become boxes — this is the most common pitfall for beginners.
1. Environment self-check
First spend 1 minute confirming the current state. Execute in PowerShell 7 (not Windows PowerShell 5.1):
# 1. PowerShell version, should be 7.x
$PSVersionTable.PSVersion
# 2. Whether Windows Terminal exists
(Get-Command wt.exe).Source
# 3. PowerShell 7 profile path (not existing is normal)
$PROFILE
Test-Path $PROFILE
# 4. Execution policy, RemoteSigned is fine
Get-ExecutionPolicy -List
# 5. Whether Nerd Font is installed (output means installed)
@(
(Get-ItemProperty 'HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts').PSObject.Properties.Name
(Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts').PSObject.Properties.Name
) | Where-Object { $_ -match 'Nerd|NF|Maple|Cascadia|Sarasa|Meslo' } | Sort-Object -Unique
How to judge your environment:
| Check item | Normal situation |
|---|---|
| PowerShell | 7.x; if only 5.1, need to install PowerShell 7 first |
| Windows Terminal | Get-Command wt.exe has a result |
| PowerShell 7 profile | Path not existing is also normal, Chapter 8 will create it |
| Nerd Font | Not installed is fine, Chapter 4 will install it |
| Execution policy | RemoteSigned or Unrestricted both work |
As long as PowerShell 7 and Windows Terminal are in place, other components can be installed as you go. This text does not require cleaning up old configs first; profile and settings.json are plain text, and can be restored if messed up.
⚠️ Don't confuse the two PowerShells
Windows PowerShell 5.1: built-in, profile inDocuments\WindowsPowerShellPowerShell 7: installed by you, profile inDocuments\PowerShellAll configs in this text are written in the profile of 7; it's normal that they don't take effect in 5.1.
2. 10 Minute Quick Start (lazy version)
If you just want to quickly look better, follow these 5 steps, details in later chapters:
# ① Install Oh My Posh (skip if already installed)
winget install --id JanDeDobbeleer.OhMyPosh -e --source winget --accept-package-agreements --accept-source-agreements
# ② Install font (interactive list, use arrow keys to select CascadiaCode and press Enter; Chinese users see Chapter 4)
oh-my-posh font install
# ③ Copy all themes, write the current theme, then create profile
$ompThemes = if ($env:POSH_THEMES_PATH) { $env:POSH_THEMES_PATH } else { (Get-AppxPackage ohmyposh.cli).InstallLocation + '\themes' }
New-Item -ItemType Directory "$HOME\.config\oh-my-posh" -Force | Out-Null
Copy-Item "$ompThemes\*.omp.json" -Destination "$HOME\.config\oh-my-posh" -Force
Set-Content "$HOME\.config\oh-my-posh\active-theme.txt" 'catppuccin_mocha' -Encoding utf8
New-Item -ItemType File -Path $PROFILE -Force
notepad $PROFILE # paste the template from Chapter 8, save
If
Get-AppxPackagereports "access denied", use theGet-OmpThemesDirfunction from section 5.3 instead.
④ Open Windows Terminal → Ctrl + , → Appearance → set font to Cascadia Code NF (based on the name shown in the font dropdown, Chinese users select Maple Mono NF CN), font size 11. If you want to use Catppuccin color scheme, first add the JSON from section 3.5 to schemes; if you're too lazy to change, first select the built-in One Half Dark.
⑤ Close all terminal tabs and reopen. You should see a prompt with icons and Git info.
If you want more refinement (frosted glass, Catppuccin color scheme, smart completion, ll/z/fzf), continue reading.
3. Step 1: Windows Terminal configuration
3.1 Set Windows Terminal as the default terminal
If not set, double-clicking .ps1, launching cmd from Run, etc. will still pop up the old conhost window.
Method one (recommended): Windows Settings → System → Developer options → find Terminal → set Default terminal application to Windows Terminal.
Method two: Windows Terminal → Ctrl + , → Startup → Default terminal application → Windows Terminal.
3.2 Open PowerShell 7 by default
Ctrl + , → Startup → Default profile → select PowerShell (the one with black >_ icon, not Windows PowerShell).
Conveniently set Startup to "Maximized" or "Default", depending on your habit.
3.3 Find and back up settings.json
All appearance of Windows Terminal ultimately falls on settings.json. The GUI can only change a subset; transparent frosted glass, background image, scrollbar hidden, antialiasing must be changed in JSON.
Ctrl + , → click Open JSON file at bottom left. The file is usually at:
# Store version (most people)
%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json
# Non-Store version (winget / scoop / portable)
%LOCALAPPDATA%\Microsoft\Windows Terminal\settings.json
Backup (strongly recommended, so you can roll back instantly if you mess up):
$wt = "$env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json"
if (Test-Path $wt) {
Copy-Item $wt "$wt.bak" -Force
"Backed up to $wt.bak"
} else {
"Store version config not found, check %LOCALAPPDATA%\Microsoft\Windows Terminal\settings.json"
}
💡 You can also directly edit:
code $wt(requires VS Code), ornotepad $wt.
3.4 Appearance: core JSON
In settings.json, find "profiles" → "defaults". If there is no defaults, manually add one, then merge the following keys into it (if the same key already exists, change the value; don't repeat-listen):
"profiles":
{
"defaults":
{
"font":
{
"face": "Maple Mono NF CN",
"size": 11,
"weight": "normal"
},
"colorScheme": "Catppuccin Mocha",
"opacity": 88,
"useAcrylic": true,
"padding": "10, 10, 8, 10",
"cursorShape": "bar",
"antialiasingMode": "grayscale",
"scrollbarState": "hidden",
"intenseTextStyle": "bright",
"copyOnSelect": true,
"multiLinePasteWarning": false
}
}
The above is just a schematic structure. When actually editing: if
profilesalready hasdefaults, only merge the keys inside; leave thelistarray unchanged.
Explanation item by item:
| Key | Function | Suggestion |
|---|---|---|
font.face |
Font name, must exactly match the system one | Maple Mono NF CN / Cascadia Code NF |
font.size |
Font size | 1080p use 11, 2K use 12, 4K use 13–14 |
font.weight |
Font weight | normal; high-DPI screens can try light |
colorScheme |
Color scheme name | see 3.5 |
opacity |
Opacity 0–100 | 85–92 is comfortable, too low strains eyes |
useAcrylic |
Acrylic frosted glass | true; if old GPU feels laggy, change to false |
padding |
Inner padding, left, top, right, bottom | "10, 10, 8, 10" whitespace is just right |
cursorShape |
Cursor shape | bar (vertical line) / filledBox (block) / doubleUnderline |
antialiasingMode |
Antialiasing | grayscale is clearer for thin fonts; cleartype is sharper |
scrollbarState |
Scrollbar | hidden is cleanest; change to visible if needed (older WT may not support) |
intenseTextStyle |
Bold color enhancement | bright makes the 16 colors more vibrant |
copyOnSelect |
Copy on selection | true, once you use it you know |
multiLinePasteWarning |
Multi-line paste warning | false saves one Enter press |
defaultsapplies to all profiles (including cmd, WSL). If you only want to change PowerShell 7, write the same keys into the corresponding item inprofiles.list.
3.5 Color scheme: Catppuccin Mocha
Windows Terminal comes with several color schemes (Campbell, One Half Dark, Solarized…), but none are as pleasing as community color schemes. Here is a complete usable Catppuccin Mocha.
Find or add "schemes": [ ... ] at the root level of settings.json, and add the following entire block to the array:
{
"name": "Catppuccin Mocha",
"background": "#1E1E2E",
"foreground": "#CDD6F4",
"cursorColor": "#F5E0DC",
"selectionBackground": "#585B70",
"black": "#45475A",
"red": "#F38BA8",
"green": "#A6E3A1",
"yellow": "#F9E2AF",
"blue": "#89B4FA",
"purple": "#F5C2E7",
"cyan": "#94E2D5",
"white": "#BAC2DE",
"brightBlack": "#585B70",
"brightRed": "#F38BA8",
"brightGreen": "#A6E3A1",
"brightYellow": "#F9E2AF",
"brightBlue": "#89B4FA",
"brightPurple": "#F5C2E7",
"brightCyan": "#94E2D5",
"brightWhite": "#A6ADC8"
}
Then confirm that the value of profiles.defaults.colorScheme and "name" are exactly the same (including spaces).
Windows Terminal 1.24 and above also has an independent
"themes"array, controlling the tab bar/title bar colors, which is not the same as"schemes". When both are configured, the visual is unified.
If the color scheme name conflict is reported after saving: it means your WT version has a built-in scheme with the same name, just delete the block you pasted and select it in the UI; or change both
Catppuccin Mochaoccurrences toCatppuccin Mocha Custom.
Alternative: Tokyo Night Storm (more blue-purple, higher contrast)
{
"name": "Tokyo Night Storm",
"background": "#24283B",
"foreground": "#C0CAF5",
"cursorColor": "#C0CAF5",
"selectionBackground": "#364A82",
"black": "#1D202F",
"red": "#F7768E",
"green": "#9ECE6A",
"yellow": "#E0AF68",
"blue": "#7AA2F7",
"purple": "#BB9AF7",
"cyan": "#7DCFFF",
"white": "#A9B1D6",
"brightBlack": "#414868",
"brightRed": "#F7768E",
"brightGreen": "#9ECE6A",
"brightYellow": "#E0AF68",
"brightBlue": "#7AA2F7",
"brightPurple": "#BB9AF7",
"brightCyan": "#7DCFFF",
"brightWhite": "#C0CAF5"
}
3.6 Background image and frosted glass (optional)
If you like anime wallpapers/dark textures, add to profiles.defaults:
"backgroundImage": "C:\\Users\\<your username>\\Pictures\\terminal-bg.jpg",
"backgroundImageOpacity": 0.22,
"backgroundImageStretchMode": "uniformToFill",
"backgroundImageAlignment": "center"
Note:
- Replace
<your username>with your Windows username, or directly change to any image path. - Path backslashes must be written as double backslashes (JSON escaping).
useAcrylic: trueand background image at the same time: on some drivers the background image will be covered — choose one.- Background image opacity recommended 0.15–0.3, too high affects text contrast.
3.7 Startup and window
At the root level (sibling of "profiles"):
"launchMode": "maximized",
"startOnUserLogin": false,
"confirmCloseAllTabs": true
launchMode:default/maximized/fullscreen/focusconfirmCloseAllTabs: regret medicine when accidentally closing a bunch of tabs
3.8 Shortcut cheat sheet
| Shortcut | Function |
|---|---|
Ctrl + Shift + T |
New tab |
Ctrl + Shift + W |
Close tab |
Alt + Shift + D |
Duplicate current profile and split (default vertical) |
Alt + Shift + + / - |
Split left-right / top-bottom |
Ctrl + Shift + P |
Command palette (search all actions) |
Ctrl + Shift + F |
Find |
Win + backtick |
Quake dropdown terminal (global summon) |
Ctrl + + / Ctrl + - |
Font size zoom |
Split screen + Quake mode are the two features with the biggest efficiency boost, worth practicing.
4. Step 2: Nerd Font font
4.1 Why you must change the font
PowerShell itself doesn't need a special font, but Oh My Posh / Terminal-Icons / eza / Starship output these characters:
- Powerline arrows:
U+E0B0,U+E0B2 - Git branch:
U+E725 - Folder:
U+F07B - Various language logos, battery, clock icons (
U+F179etc.)
Normal fonts (Microsoft YaHei, Consolas, original Cascadia Code) don't have these glyphs, so they display as □ or ?.
Nerd Font = patched 3000+ icons onto monospaced programming fonts, solving it once and for all.
4.2 How to choose a font
| Font | Chinese | Icons | Ligatures | Style | Suitable for |
|---|---|---|---|---|---|
| Maple Mono NF CN | ✅ | ✅ | ✅ | Rounded, slightly handwritten, gentle italic | First choice for Chinese users, default in this text |
| Sarasa Term SC Nerd Font (更纱黑体) | ✅✅ | ✅ | ❌ | Rigorous, widest glyph coverage | Chinese-first, hate fancy |
| Cascadia Code NF | ❌ | ✅ | ✅ | Microsoft official, modern | English-only environments |
| JetBrainsMono Nerd Font | ❌ | ✅ | ✅ | Hard, highly recognizable | Code writing |
| MesloLGS NF | ❌ | ✅ | ❌ | p10k standard | Copying macOS config |
⚠️ Key pitfall for Chinese users: Cascadia Code / JetBrains Mono do not contain Chinese. Windows Terminal will fall back character by character to Microsoft YaHei, causing Chinese to become proportional-width — width misalignment, line height jumping, table misalignment. So in Chinese environments, prioritize Maple Mono NF CN or Sarasa Term SC Nerd Font with CJK.
4.3 Install Maple Mono NF CN (recommended, manual is most stable)
- Open the Release page: https://github.com/subframe7536/maple-font/releases
- Download
MapleMono-NF-CN.zipfrom the latest version's AssetsNF= Nerd Font (with icons)CN= includes Chinese- Don't select the
Variableversion; static version has better compatibility
- Unzip, enter the directory, select all
.ttffiles - Right-click → Install (or "Install for all users", requires administrator)
- Windows 11's right-click menu requires clicking "Show more options" first to see "Install"
- Completely close and reopen Windows Terminal (font cache needs refreshing)
4.4 Install with scoop (one command, suitable for those with scoop already)
If you don't have scoop, install it first:
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned -Force
Invoke-RestMethod get.scoop.sh | Invoke-Expression
Then:
scoop bucket add nerd-fonts
scoop install nerd-fonts/Maple-Mono-NF-CN
Sarasa (package name based on scoop search results):
scoop search sarasa # first look at the package name
scoop install nerd-fonts/Sarasa-Term-SC-Nerd
The benefit of scoop: upgrade and uninstall are one command, no need to manually delete fonts.
4.5 Verify the font is installed
# The registry should show the full font name
@(
(Get-ItemProperty 'HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts').PSObject.Properties.Name
(Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts').PSObject.Properties.Name
) | Where-Object { $_ -match 'Maple|Nerd|Sarasa|Cascadia' } | Sort-Object -Unique
Or directly print a test string of icons in the terminal:
"`u{e0b0} `u{e0b2} `u{f07b} `u{e725} `u{f1d3} `u{e70f}"
- Displaying as a string of colorful/monochrome icons → font is working ✅
- Displaying as
□ □ □or?→ font not working or name wrong ❌
Finally confirm in Windows Terminal → Settings → Appearance → Font → Font face dropdown that you can search for Maple Mono NF CN.
4.6 Font size and clarity
| Resolution | Suggested font size |
|---|---|
| 1920×1080 | 11 |
| 2560×1440 | 12 |
| 3840×2160 | 13–14 (or 12 + system scaling 150%) |
With "antialiasingMode": "grayscale", thin font weights look cleaner.
4.7 Font-related pitfalls
| Phenomenon | Reason | Solution |
|---|---|---|
| Can't find font in WT | Didn't restart terminal after install | Completely exit WT and reopen |
| Selected correct font but icons still boxes | Installed the non-NF version | Reinstall *NF* package |
| Font name written wrong | Actually called Maple Mono NF CN, not Maple Mono |
Copy the exact name from the dropdown |
| Chinese width misaligned | Font doesn't contain CJK, fell back to YaHei | Switch to Maple Mono NF CN / Sarasa |
| Icons squeezed together | Used a non-monospaced Nerd Font | Switch to monospaced version |
5. Step 3: Oh My Posh prompt
5.1 What it is
Oh My Posh does only one thing: renders a beautiful prompt line based on the current directory, Git status, last command execution time, language versions, and other information. It doesn't take over your Shell, nor change command behavior — so you can delete it anytime with zero risk.
Competing product: Starship (written in Rust, faster and simpler, config is TOML). Chapter 10 later will cover how to choose.
5.2 Install
# Recommended: winget
winget install --id JanDeDobbeleer.OhMyPosh -e --source winget --accept-package-agreements --accept-source-agreements
# Or scoop
scoop install oh-my-posh
After installation open a new terminal to verify:
oh-my-posh --version
5.3 MSIX installation has a pitfall: themes are not in POSH_THEMES_PATH
Most online tutorials will tell you to use $env:POSH_THEMES_PATH to build the theme path. Under some MSIX installation methods, this variable may be empty, and copying that will get CONFIG NOT FOUND.
Theme directories for different installation methods:
| Installation method | Theme directory |
|---|---|
| MSIX (newer winget install) | C:\Program Files\WindowsApps\ohmyposh.cli_<version>_x64__<hash>\themes |
| Portable / old winget | %LOCALAPPDATA%\Programs\oh-my-posh\themes (= $env:POSH_THEMES_PATH) |
| winget portable package | %LOCALAPPDATA%\Microsoft\WinGet\Packages\JanDeDobbeleer.OhMyPosh_*\themes |
| scoop | %USERPROFILE%\scoop\apps\oh-my-posh\current\themes |
Use the following to automatically locate (paste into terminal and run once):
function Get-OmpThemesDir {
# Old version / portable
if ($env:POSH_THEMES_PATH -and (Test-Path $env:POSH_THEMES_PATH)) {
return $env:POSH_THEMES_PATH
}
# MSIX version
$pkg = $null
try { $pkg = Get-AppxPackage -Name ohmyposh.cli -ErrorAction Stop } catch { $pkg = $null }
if ($pkg) {
$p = Join-Path $pkg.InstallLocation 'themes'
if (Test-Path $p) { return $p }
}
# If Get-AppxPackage is blocked by policy, find the install directory directly
$pkgDir = $null
try {
$pkgDir = Get-ChildItem 'C:\Program Files\WindowsApps' -Directory -Filter 'ohmyposh.cli_*' -ErrorAction Stop |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
}
catch {
$pkgDir = $null
}
if ($pkgDir) {
$p = Join-Path $pkgDir.FullName 'themes'
if (Test-Path $p) { return $p }
}
# winget portable package
$wingetPkg = Get-ChildItem (Join-Path $env:LOCALAPPDATA 'Microsoft\WinGet\Packages') -Directory -Filter 'JanDeDobbeleer.OhMyPosh*' -ErrorAction SilentlyContinue |
Select-Object -First 1
if ($wingetPkg) {
$p = Join-Path $wingetPkg.FullName 'themes'
if (Test-Path $p) { return $p }
}
# scoop
$scoop = Join-Path $HOME 'scoop\apps\oh-my-posh\current\themes'
if (Test-Path $scoop) { return $scoop }
return $null
}
$ompThemes = Get-OmpThemesDir
$ompThemes
Get-ChildItem $ompThemes -Filter *.omp.json |
ForEach-Object { $_.Name -replace '\.omp\.json$', '' }
The last line will list more than a hundred theme names (catppuccin_mocha, tokyonight_storm, atomic…).
If
Get-OmpThemesDirreturns empty: runGet-AppxPackage ohmyposh.cli | Select-Object InstallLocationin a normal (non-admin is fine) PowerShell, and manually append\themesto the output path.
5.4 First step: copy all themes to your own directory
Do not directly reference the installation directory — MSIX upgrades change the version number in the path, and the next startup won't find the theme. Copy all themes out, keeping the original file names:
$configDir = "$HOME\.config\oh-my-posh"
New-Item -ItemType Directory -Path $configDir -Force | Out-Null
Copy-Item "$ompThemes\*.omp.json" -Destination $configDir -Force
(Get-ChildItem $configDir -Filter *.omp.json).Count
This way each theme keeps its original name, and you can switch by name later without overwriting one file repeatedly. Upgrading Oh My Posh also won't affect this copy.
Re-running this step will overwrite same-named themes with the version from the installation directory; if you've modified a theme, back it up first, or only copy the needed files.
You can also keep only a few themes; just copy the needed
.omp.jsonfiles into it; the following is described assuming you copy all.
5.5 Initialize
First write the current theme name:
Set-Content "$HOME\.config\oh-my-posh\active-theme.txt" 'catppuccin_mocha' -Encoding utf8
Then write in $PROFILE:
$ompThemeDir = "$HOME\.config\oh-my-posh"
$ompThemeState = Join-Path $ompThemeDir 'active-theme.txt'
$ompThemeName = if (Test-Path $ompThemeState) {
(Get-Content $ompThemeState -Raw).Trim()
}
else {
'catppuccin_mocha'
}
$ompTheme = Join-Path $ompThemeDir "$ompThemeName.omp.json"
if (-not (Test-Path $ompTheme)) {
$ompTheme = Join-Path $ompThemeDir 'catppuccin_mocha.omp.json'
}
if ((Get-Command oh-my-posh -ErrorAction SilentlyContinue) -and (Test-Path $ompTheme)) {
oh-my-posh init pwsh --config $ompTheme | Invoke-Expression
}
After saving, execute . $PROFILE, the prompt immediately changes. From then on, every time you open a new tab, the profile reads active-theme.txt and automatically loads the current theme.
If you haven't copied themes yet and just want to see the default effect:
oh-my-posh init pwsh | Invoke-Expression
If you get
oh-my-posh is not recognized as an internal or external command: PATH hasn't refreshed. Close all terminals and reopen; if still not working, manually add:$env:Path = [Environment]::GetEnvironmentVariable('Path','Machine') + ';' + [Environment]::GetEnvironmentVariable('Path','User')
5.6 Pick a theme
Newer versions of the init script may no longer provide Get-PoshThemes; if your version still has this command, you can also use it directly. First list all themes:
Get-ChildItem "$HOME\.config\oh-my-posh" -Filter *.omp.json |
ForEach-Object { $_.Name -replace '\.omp\.json$', '' }
To preview a single theme (without switching):
function Show-OmpTheme {
param([Parameter(Mandatory)][string]$Name)
$dir = Get-OmpThemesDir
if (-not $dir) {
"First execute Get-OmpThemesDir from section 5.3, confirm you can find the theme directory"
return
}
$file = Join-Path $dir "$Name.omp.json"
if (Test-Path $file) {
oh-my-posh print primary --config $file
}
else {
"No such theme: $Name"
}
}
Show-OmpTheme catppuccin_mocha
Show-OmpTheme tokyonight_storm
A few well-reviewed ones (theme name is filename without .omp.json):
| Theme | Style |
|---|---|
jandedobbeleer |
Default, complete info, balanced |
catppuccin_mocha |
Perfect match with this text's color scheme, soft |
tokyonight_storm |
Blue-purple neon, tech feel |
atomic |
Simple two-segment, fast |
clean-detailed |
Minimalist, only path and Git |
powerlevel10k_rainbow |
p10k-like, flashy |
montys |
Colorful blocks, highly recognizable |
Switch themes with poshtheme. Put the following two functions into $PROFILE (the Chapter 8 template already includes them):
function poshthemes {
$dir = "$HOME\.config\oh-my-posh"
$state = Join-Path $dir 'active-theme.txt'
$active = if (Test-Path $state) { (Get-Content $state -Raw).Trim() } else { '' }
Get-ChildItem $dir -Filter *.omp.json |
ForEach-Object {
$name = $_.Name -replace '\.omp\.json$', ''
[pscustomobject]@{
Active = if ($name -eq $active) { '*' } else { '' }
Name = $name
}
} |
Sort-Object Name
}
function poshtheme {
param([Parameter(Position = 0)][string]$Name)
$dir = "$HOME\.config\oh-my-posh"
$state = Join-Path $dir 'active-theme.txt'
if (-not $Name) {
$current = if (Test-Path $state) { (Get-Content $state -Raw).Trim() } else { '(not set)' }
"Current theme: $current"
"Usage: poshtheme <theme name>"
"View all: poshthemes"
return
}
$file = Join-Path $dir "$Name.omp.json"
if (-not (Test-Path $file)) {
Write-Warning "No such theme: $Name"
return
}
Set-Content -Path $state -Value $Name -Encoding utf8
Remove-Module oh-my-posh-core -Force -ErrorAction SilentlyContinue
$global:_ompInitialized = $false
oh-my-posh init pwsh --config $file | Invoke-Expression
Write-Host "Switched theme: $Name" -ForegroundColor Green
}
Usage:
poshthemes # list all, * is current
poshtheme tokyonight_storm # switch
poshtheme catppuccin_mocha # switch back
poshtheme # current theme
poshtheme writes the name into active-theme.txt and reinitializes the current session; new tabs also read this file.
If the prompt doesn't change after switching:
. $PROFILEor reopen the tab. Some OMP versions have different module names, auto-reload may fail, but the theme name is already written; reopening will definitely take effect.
5.7 Custom theme
Themes are placed under $HOME\.config\oh-my-posh with original names. To modify the current theme:
$name = (Get-Content "$HOME\.config\oh-my-posh\active-theme.txt" -Raw).Trim()
code "$HOME\.config\oh-my-posh\$name.omp.json" # if no VS Code, use notepad
Or directly modify any file, for example:
code "$HOME\.config\oh-my-posh\catppuccin_mocha.omp.json"
A minimal usable theme looks like this (newer v4 syntax):
{
"version": 4,
"final_space": true,
"blocks": [
{
"type": "prompt",
"alignment": "left",
"segments": [
{
"type": "path",
"style": "powerline",
"powerline_symbol": "\ue0b0",
"foreground": "#1e1e2e",
"background": "#89b4fa",
"options": { "style": "folder", "max_depth": 3 }
},
{
"type": "git",
"style": "powerline",
"powerline_symbol": "\ue0b0",
"foreground": "#1e1e2e",
"background": "#a6e3a1",
"options": { "branch_icon": "\ue725 " }
},
{
"type": "executiontime",
"style": "plain",
"foreground": "#6c7086",
"template": " {{ .FormattedMs }}"
},
{
"type": "text",
"style": "plain",
"foreground": "#89b4fa",
"template": "\u276f"
}
]
}
]
}
blocks: one line of prompt (can have multiple lines, left/right alignment)segments: individual information blocks (path, Git, Node, Python, execution time…)template: Go template syntax, controls display contentstyle:plain/powerline/diamondforeground/background: colors, supports#RRGGBB,transparent,p:palette nameoptions: segment-specific settings (old version calledproperties, newer versions still compatible with old syntax)
Version differences: old themes are "version": 3 + "properties"; newer versions default export "version": 4 + "options". Both load fine, new configs are advised to use v4.
Common options:
{
"style": "folder",
"max_depth": 3,
"fetch_status": false,
"branch_max_length": 25,
"display_mode": "directory"
}
style: folderonly shows folder name (not full path)max_depthlimits depthfetch_status: falsedoesn't query Git working tree status, noticeably fasterdisplay_mode:directory/compact/files
To make colors maintainable, add palette at the top of the theme, then write colors as p:blue:
"palette": {
"blue": "#89B4FA",
"green": "#A6E3A1",
"text": "#CDD6F4"
}
After saving, poshtheme <theme name> or reopen a tab to see the effect.
5.8 Upgrade and uninstall
winget upgrade --id JanDeDobbeleer.OhMyPosh -e
winget uninstall --id JanDeDobbeleer.OhMyPosh -e
5.9 Performance
Oh My Posh executes once per prompt, and on large Git repositories may lag (100ms+ can be felt).
oh-my-posh debug
It prints the execution time of each segment. Optimization methods:
- Turn off
fetch_status(most effective) - Fewer language version segments
- In large repositories use lightweight themes like
clean-detailed - Still slow → switch to Starship
6. Step 4: PSReadLine completion and prediction
PSReadLine is PowerShell's "line editor", responsible for syntax highlighting, history, completion, prediction. PowerShell 7 has it built-in, generally no need to install separately.
6.1 Must-enable configuration
Write into profile:
Set-PSReadLineOption -EditMode Windows
Set-PSReadLineOption -PredictionSource HistoryAndPlugin
Set-PSReadLineOption -PredictionViewStyle ListView
Set-PSReadLineOption -HistorySearchCursorMovesToEnd
Set-PSReadLineOption -HistoryNoDuplicates
Set-PSReadLineOption -MaximumHistoryCount 20000
Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete
Set-PSReadLineKeyHandler -Key UpArrow -Function HistorySearchBackward
Set-PSReadLineKeyHandler -Key DownArrow -Function HistorySearchForward
If the
PredictionViewStyle ListViewline reports an error, it means PSReadLine version is old; delete that line, the rest is unaffected.
Effects:
- While typing, gray text predicts in real time based on history, press
→to accept - A list view pops up below,
↑/↓to select Tabbecomes menu completion (instead of cycling)↑/↓search history by prefix, not line by line
6.2 Optional: syntax highlight colors
Default colors are fine on dark backgrounds, but to unify with Catppuccin you can add this (if it doesn't work, delete it, other functions unaffected):
Set-PSReadLineOption -Colors @{
Command = "`e[38;2;137;180;250m"
Parameter = "`e[38;2;249;226;175m"
Operator = "`e[38;2;148;226;213m"
Variable = "`e[38;2;245;194;231m"
String = "`e[38;2;166;227;161m"
Number = "`e[38;2;250;179;135m"
Type = "`e[38;2;249;226;175m"
Comment = "`e[38;2;108;112;134m"
Keyword = "`e[38;2;203;166;247m"
Error = "`e[38;2;243;139;168m"
InlinePrediction = "`e[38;2;108;112;134m"
}
6.3 Plugin prediction (more accurate)
By default it predicts only history. After installing CompletionPredictor, it can predict parameters from module completion results:
Install-Module CompletionPredictor -Scope CurrentUser -Force
In profile:
Import-Module CompletionPredictor -ErrorAction SilentlyContinue
The Plugin in PredictionSource will then be enabled automatically.
6.4 Key table
| Key | Function |
|---|---|
→ / End |
Accept inline prediction |
Tab |
Open completion menu / next in menu |
Shift + Tab |
Previous in completion menu |
↑ / ↓ |
Prefix history search |
Ctrl + R |
Reverse search history (fuzzy after PSFzf) |
Ctrl + L |
Clear screen (keep current input) |
Ctrl + C |
Cancel current line |
F2 |
Switch prediction view (needs manual binding) |
To bind F2 to view switching:
Set-PSReadLineKeyHandler -Key F2 -Function SwitchPredictionView
7. Step 5: Efficiency tools family bucket
These are not "looks good", but after installing them your terminal is truly usable. All optional, install as needed.
| Tool | Replaces/enhances | Function | winget ID |
|---|---|---|---|
| Terminal-Icons | ls |
Files and folders show icons | PSGallery module |
| zoxide | cd |
Smart jump, z proj goes straight to usual directory |
ajeetdsouza.zoxide |
| fzf | Ctrl+R |
Fuzzy search history/files | junegunn.fzf |
| PSFzf | — | fzf and PSReadLine integration | PSGallery module |
| posh-git | — | Git branch/command Tab completion | PSGallery module |
| ConsoleGuiTools | — | Out-ConsoleGridView interactive table selection |
PSGallery module |
| PSScriptAnalyzer | — | PowerShell script static check | PSGallery module |
| bat | cat |
Syntax highlighting + line numbers | sharkdp.bat |
| eza | ls |
Color, icons, Git status, tree | eza-community.eza |
| ripgrep | grep |
Much faster recursive search | BurntSushi.ripgrep.MSVC |
| fd | find |
Friendlier file search | sharkdp.fd |
| delta | git diff |
Side-by-side diff, syntax highlighting | dandavison.delta |
| fastfetch | systeminfo |
Show system info at startup | Fastfetch-cli.Fastfetch |
| gsudo | — | Linux-like sudo |
gerardog.gsudo |
7.1 One-time installation
$apps = @(
'ajeetdsouza.zoxide',
'junegunn.fzf',
'sharkdp.bat',
'eza-community.eza',
'BurntSushi.ripgrep.MSVC',
'sharkdp.fd',
'dandavison.delta',
'Fastfetch-cli.Fastfetch',
'gerardog.gsudo'
)
foreach ($id in $apps) {
winget install --id $id -e --source winget --accept-package-agreements --accept-source-agreements
}
PowerShell modules:
Install-Module Terminal-Icons, PSFzf, CompletionPredictor, posh-git, Microsoft.PowerShell.ConsoleGuiTools, PSScriptAnalyzer -Scope CurrentUser -Force -AllowClobber
The first
Install-Modulemay prompt to install the NuGet provider, pressY. If it reports "untrusted repository", first executeSet-PSRepository PSGallery -InstallationPolicy Trusted, or pressYat the prompt.
7.2 How to use each tool
Terminal-Icons: after install, import it, ls automatically gets icons:
Import-Module Terminal-Icons
zoxide: remembers directories you've visited, jumps by frequency:
zoxide init powershell | Out-String | Invoke-Expression # write into profile
z proj # jump to any common directory whose name contains proj
z - # go back to last directory
zi # interactive selection
Advanced: zoxide init powershell --cmd cd makes cd itself support fuzzy jumping.
fzf + PSFzf:
Ctrl + R # fuzzy search command history
Ctrl + T # fuzzy select a file under current directory, insert into command line
posh-git: adds Tab completion for commands like git checkout, git branch (branch names, remote names), doesn't take over the prompt.
git checkout feat<Tab> # complete branch name
ConsoleGuiTools: Get-Process | Out-ConsoleGridView, filter, sort, multi-select objects in a table.
PSScriptAnalyzer: Invoke-ScriptAnalyzer -Path .\script.ps1, checks scripts for common issues.
bat:
bat README.md
bat --list-themes # see available themes
To use bat instead of cat by default: Set-Alias -Name cat -Value bat -Force (bat automatically falls back to plain text when piping, so it won't pollute scripts).
eza:
eza -la --group-directories-first --icons
eza --tree --level=2 --icons
ripgrep / fd:
rg "TODO" -n
fd "\.ps1$"
delta: configure to ~/.gitconfig:
[core]
pager = delta
[interactive]
diffFilter = delta --color-only
[delta]
navigate = true
line-numbers = true
side-by-side = false
syntax-theme = Catppuccin Mocha
[merge]
conflictstyle = zdiff3
If
syntax-themeerrors, executebat --list-themesto change to an existing name, e.g.,Monokai Extended.If
git diffdoesn't seem to use delta: rungit var GIT_PAGER, should bedelta. If it outputscat, the environment variableGIT_PAGERoverridescore.pager, executeRemove-Item Env:GIT_PAGERor clear it in profile. Git only enables pager in interactive terminals; redirected output won't go through delta.
fastfetch:
fastfetch
fastfetch --gen-config # generate config file, path is in output
Config file at ~\.config\fastfetch\config.jsonc (fastfetch --gen-config prints actual path).
This color scheme is based on Tokyo Night's blue/purple/cyan; to change colors, modify
display.colorandlogo.color.
gsudo:
gsudo Get-Service # elevate a single command, pops UAC
sudo ... # Windows 11 24H2+ has built-in sudo, can be enabled in Settings → System → Developer options
8. Step 6: Complete profile template
Copy the entire block below into $PROFILE (first New-Item -ItemType File -Path $PROFILE -Force, then code $PROFILE or notepad $PROFILE).
It already has existence checks: uninstalled tools are automatically skipped, no errors.
This is the minimal usable version. If you need Git shortcut commands, system utility functions, theme switching, etc., you can extend based on this template.
# ============================================================
# PowerShell 7 terminal beautification configuration
# Location: %USERPROFILE%\Documents\PowerShell\Microsoft.PowerShell_profile.ps1
# After editing, run: . $PROFILE or reopen a tab
# ============================================================
# ---------- 0. UTF-8 (fix Chinese garbled text) ----------
$OutputEncoding = [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
# ---------- 1. PSReadLine: prediction, history, completion ----------
if (Get-Module -ListAvailable -Name PSReadLine) {
try {
Set-PSReadLineOption -EditMode Windows
Set-PSReadLineOption -PredictionSource HistoryAndPlugin
Set-PSReadLineOption -PredictionViewStyle ListView
Set-PSReadLineOption -HistorySearchCursorMovesToEnd
Set-PSReadLineOption -HistoryNoDuplicates
Set-PSReadLineOption -MaximumHistoryCount 20000
Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete
Set-PSReadLineKeyHandler -Key UpArrow -Function HistorySearchBackward
Set-PSReadLineKeyHandler -Key DownArrow -Function HistorySearchForward
}
catch {
# A few hosts that don't support virtual terminals error here, skip
}
}
# ---------- 2. Modules ----------
Import-Module Terminal-Icons -ErrorAction SilentlyContinue
Import-Module CompletionPredictor -ErrorAction SilentlyContinue
# posh-git: Git branch/command Tab completion (doesn't take over prompt)
Import-Module posh-git -ErrorAction SilentlyContinue
if ((Get-Module -ListAvailable -Name PSFzf) -and (Get-Command fzf -ErrorAction SilentlyContinue)) {
Import-Module PSFzf
Set-PsFzfOption -PSReadlineChordProvider 'Ctrl+t' -PSReadlineChordReverseHistory 'Ctrl+r'
}
# ---------- 3. zoxide ----------
if (Get-Command zoxide -ErrorAction SilentlyContinue) {
zoxide init powershell | Out-String | Invoke-Expression
}
# ---------- 4. Aliases and small functions ----------
function ll {
Get-ChildItem -Force @args
}
function la {
Get-ChildItem -Force @args
}
function .. {
Set-Location ..
}
function ... {
Set-Location ../..
}
function mkcd {
param(
[Parameter(Mandatory)]
[string]$Path
)
New-Item -ItemType Directory -Force -Path $Path | Out-Null
Set-Location $Path
}
function reload {
. $PROFILE
}
function myprofile {
if (Get-Command code -ErrorAction SilentlyContinue) {
code $PROFILE
}
else {
notepad $PROFILE
}
}
# eza exists, use eza to rewrite ll / lt
if (Get-Command eza -ErrorAction SilentlyContinue) {
function ll {
eza --long --all --group-directories-first --icons @args
}
function lt {
eza --tree --level=2 --icons @args
}
}
# bat exists, cat goes through bat
if (Get-Command bat -ErrorAction SilentlyContinue) {
$env:BAT_THEME = 'Catppuccin Mocha'
Set-Alias -Name cat -Value bat -Force
}
# ---------- 5. Theme switching ----------
function poshthemes {
$dir = "$HOME\.config\oh-my-posh"
$state = Join-Path $dir 'active-theme.txt'
$active = if (Test-Path $state) { (Get-Content $state -Raw).Trim() } else { '' }
Get-ChildItem $dir -Filter *.omp.json |
ForEach-Object {
$name = $_.Name -replace '\.omp\.json$', ''
[pscustomobject]@{
Active = if ($name -eq $active) { '*' } else { '' }
Name = $name
}
} |
Sort-Object Name
}
function poshtheme {
param([Parameter(Position = 0)][string]$Name)
$dir = "$HOME\.config\oh-my-posh"
$state = Join-Path $dir 'active-theme.txt'
if (-not $Name) {
$current = if (Test-Path $state) { (Get-Content $state -Raw).Trim() } else { '(not set)' }
"Current theme: $current"
"Usage: poshtheme <theme name>"
"View all: poshthemes"
return
}
$file = Join-Path $dir "$Name.omp.json"
if (-not (Test-Path $file)) {
Write-Warning "No such theme: $Name"
return
}
Set-Content -Path $state -Value $Name -Encoding utf8
Remove-Module oh-my-posh-core -Force -ErrorAction SilentlyContinue
$global:_ompInitialized = $false
oh-my-posh init pwsh --config $file | Invoke-Expression
Write-Host "Switched theme: $Name" -ForegroundColor Green
}
# ---------- 6. Oh My Posh (placed last, overrides prompt) ----------
if (Get-Command oh-my-posh -ErrorAction SilentlyContinue) {
$ompThemeDir = "$HOME\.config\oh-my-posh"
$ompThemeState = Join-Path $ompThemeDir 'active-theme.txt'
$ompThemeName = if (Test-Path $ompThemeState) { (Get-Content $ompThemeState -Raw).Trim() } else { 'catppuccin_mocha' }
$ompTheme = Join-Path $ompThemeDir "$ompThemeName.omp.json"
if (-not (Test-Path $ompTheme)) {
$ompTheme = Join-Path $ompThemeDir 'catppuccin_mocha.omp.json'
}
try {
if (Test-Path $ompTheme) {
oh-my-posh init pwsh --config $ompTheme | Invoke-Expression
}
else {
# haven't copied themes yet, fall back to Oh My Posh default config
oh-my-posh init pwsh | Invoke-Expression
}
}
catch {
# prompt load failure should not affect Shell startup
}
}
8.1 Save and apply
. $PROFILE
Or use the quick function from the template (after new session takes effect): reload.
If there are errors, first look at the error message to locate the line; temporarily bypass profile startup with:
pwsh -NoProfile
8.2 If you use VS Code
VS Code's integrated terminal defaults to Windows PowerShell 5.1, and the font is set independently. In settings.json add:
"terminal.integrated.defaultProfile.windows": "PowerShell",
"terminal.integrated.fontFamily": "Maple Mono NF CN",
"terminal.integrated.fontSize": 13
9. Step 7: Unified color scheme
The key to visual unity: terminal background color, Oh My Posh theme, bat theme, delta theme, PSReadLine highlighting use the same palette.
Catppuccin Mocha family bucket:
| Component | Setting |
|---|---|
| Windows Terminal | colorScheme: "Catppuccin Mocha" or "Tokyo Night Storm" (section 3.5) |
| Windows Terminal UI | root-level "theme" select same-named UI theme, controls tab bar/title bar |
| Oh My Posh | poshtheme catppuccin_mocha / poshtheme tokyonight_storm |
| bat | $env:BAT_THEME = 'Catppuccin Mocha' |
| delta | syntax-theme = Catppuccin Mocha |
| PSReadLine | RGB colors from section 6.2 |
Tokyo Night users: WT select Tokyo Night Storm, OMP use poshtheme tokyonight_storm; if bat/delta don't have a matching theme, keep Catppuccin or OneHalfDark.
bat / delta theme names must actually exist, check with
bat --list-themes. If Catppuccin isn't found, bat version is old,winget upgrade sharkdp.batwill fix it.
10. Advanced play
10.1 Oh My Posh vs Starship, how to choose
| Oh My Posh | Starship | |
|---|---|---|
| Config format | JSON | TOML |
| Theme count | 100+ ready-made | few but refined, you assemble |
| Speed | medium | faster |
| Getting started | install and use | need to write config |
| Cross-shell | all platforms | all platforms |
Suggestion: if you want "install and look good" use Oh My Posh; if you pursue minimalism and speed use Starship.
Starship install:
winget install --id Starship.Starship -e
Profile:
Invoke-Expression (&starship init powershell)
Config: $HOME\.config\starship.toml, official presets at https://starship.rs/presets/.
Don't initialize both at the same time, or the prompts will conflict.
10.2 Add color and icons to Git
Oh My Posh's git segment automatically reads repository status, no extra config needed. For more detail you can add:
{
"type": "git",
"style": "powerline",
"powerline_symbol": "\ue0b0",
"foreground": "#1e1e2e",
"background": "#a6e3a1",
"options": {
"branch_icon": "\ue725 ",
"fetch_status": true,
"fetch_upstream_icon": true
}
}
fetch_status: true shows +3 ~2 -1 (added/modified/deleted), but large repositories become slower.
10.3 SSH to Linux, want the same style
Oh My Posh supports remote; a simpler approach is install Starship on the remote, local terminal only handles rendering. Font icons are rendered locally, so having Nerd Font locally is enough.
10.4 Chinese alignment: don't rely on font fallback
Windows Terminal's font fallback is automatic: when the current font lacks a glyph, the system temporarily finds another font to fill it. There is no reliable configuration option, and width can't be controlled.
The result: using Cascadia Code with Chinese, characters fall back to Microsoft YaHei — proportional font, misaligned with English monospaced grid, tables, eza columns, progress bars all skew.
The only reliable solution is to choose a monospaced font that includes Chinese (Maple Mono NF CN, Sarasa Term SC Nerd Font), rather than configuring fallback.
10.5 Use Windows Terminal Preview
To experience new features first (command palette enhancements, new renderer):
winget install --id Microsoft.WindowsTerminal.Preview -e
Preview and stable can coexist, configs are independent.
11. Troubleshooting manual
11.1 Full of boxes / question marks
Cause: font not installed, not selected correctly, or name wrong. Check:
"`u{e0b0} `u{e725} `u{f07b}"
Still boxes → install Nerd Font; icons fine but some OMP icons are boxes → the theme uses private-use area characters not in the font, switch theme.
11.2 Chinese garbled / width misaligned
- Run
chcpin terminal,65001is best; if936, runchcp 65001, or add the UTF-8 line to profile. - PowerShell 7 defaults to UTF-8; old sessions started from 5.1 or cmd may not.
- Width misalignment = font lacks CJK, switch to Maple Mono NF CN.
11.3 Prompt didn't change
Check in order:
- Is it PowerShell 7?
$PSVersionTable.PSVersion - Is the profile path correct?
$PROFILE, does the file exist? - Are there errors in the profile?
pwsh -NoProfilestarts fine, means it's a profile issue. - Is the OMP initialization line at the end of the profile? Overwritten by later code?
- Did you run
. $PROFILEafter editing?
11.4 "Cannot load file because running scripts is disabled on this system"
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
11.5 oh-my-posh command not found
PATH hasn't refreshed. Close all terminals and reopen; or temporarily add PATH:
$env:Path = [Environment]::GetEnvironmentVariable('Path','Machine') + ';' + [Environment]::GetEnvironmentVariable('Path','User')
11.6 Startup noticeably slower
oh-my-posh debug
See which segment takes time. Most common is Git's fetch_status. To compare, start a session without profile using pwsh -NoProfile.
11.7 winget errors
winget source reset --force
winget source update
Still not working, update "App Installer" from Microsoft Store.
11.8 Settings saved but terminal won't open / crashes
settings.json JSON syntax error. Restore backup:
$wt = "$env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json"
Copy-Item "$wt.bak" $wt -Force
Common syntax errors: extra comma, missing quote, path not escaped (backslash must be doubled).
11.9 VS Code terminal shows boxes for icons
VS Code's terminal font must be set separately in terminal.integrated.fontFamily, doesn't follow Windows Terminal.
11.10 Installed Oh My Posh but Git icon doesn't show
- Font is not NF version
- Current directory is not a Git repository
- Git segment disabled in theme
12. Rollback and uninstall
12.1 Rollback config only
# back up/clear entire profile
Copy-Item $PROFILE "$PROFILE.bak" -Force
Set-Content $PROFILE -Value '' -Encoding utf8
# Windows Terminal
$wt = "$env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json"
Copy-Item "$wt.bak" $wt -Force
12.2 Uninstall software
$ids = @(
'JanDeDobbeleer.OhMyPosh','ajeetdsouza.zoxide','junegunn.fzf','sharkdp.bat',
'eza-community.eza','BurntSushi.ripgrep.MSVC','sharkdp.fd','dandavison.delta',
'Fastfetch-cli.Fastfetch','gerardog.gsudo'
)
foreach ($id in $ids) { winget uninstall --id $id -e }
Modules:
Uninstall-Module Terminal-Icons, PSFzf, CompletionPredictor, posh-git, Microsoft.PowerShell.ConsoleGuiTools, PSScriptAnalyzer -AllVersions -Force
12.3 Delete fonts
Settings → Personalization → Fonts → search font name → uninstall (only works for fonts installed for current user).
Or manually delete registry key + file:
# first confirm what to delete!
Get-ItemProperty 'HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts' |
Select-Object -Property *Maple* | Format-List
Deleting fonts is risky, recommend using the settings interface.
Appendix A: Solidify configuration into a script (optional)
If you often configure new machines, you can write the steps into a PowerShell script. Suggested order:
- Check
winget, PowerShell 7, Windows Terminal - Use winget to install Oh My Posh, Git, common tools
- Install PowerShell modules
- Install Nerd Font: download font package, or call
oh-my-posh font install - Copy OMP themes to
~\.config\oh-my-posh - Write profile (use marker blocks for later replacement)
- Merge Windows Terminal's
settings.json(backup first) - Write
~\.gitconfig
Several key points:
- Each step first checks whether already installed, ensuring the script can be re-run
- Backup before modifying
settings.json; useConvertFrom-Json -AsHashtableto merge, not overwrite whole file - Profile wrap with
# >>> ... >>>and# <<< ... <<<markers, script only replaces content between markers - Install fonts to current user (
%LOCALAPPDATA%\Microsoft\Windows\Fonts+ HKCU registry), no admin needed
This way even if a step fails, you can roll back and re-run.
Appendix B: Command cheat sheet
# reload config
. $PROFILE
# list themes / switch theme
poshthemes
poshtheme tokyonight_storm
# preview current theme
$name = (Get-Content "$HOME\.config\oh-my-posh\active-theme.txt" -Raw).Trim()
oh-my-posh print primary --config "$HOME\.config\oh-my-posh\$name.omp.json"
# current profile path
$PROFILE
# verify font
"`u{e0b0} `u{e725} `u{f07b}"
# test OMP performance
oh-my-posh debug
# update all software
winget upgrade --all --include-unknown
# open WT settings JSON
code "$env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json"
Last sentence
The end goal of terminal beautification is not "how many plugins installed", but you feel good when opening the terminal, and your hands aren't tired when typing commands.
If one day it feels too fancy, clear the profile, run poshtheme clean-detailed, you can always start over — all configs are plain text, delete them and it's gone, nothing breaks.
Hope this tutorial helps you build a comfortable terminal.