π§ Advanced Theme Customization Guide
Table of Contents
- Introduction
- Theme Structure Deep Dive
- Segment Customization
- Template Expressions
- Custom Icons & Symbols
- Color Manipulation
- Advanced Block Layouts
- Creating Custom Segments
- Performance Tuning
- Best Practices
Introduction
While the OhMyPosh Atomic Enhanced themes come pre-configured and visually complete, true mastery requires understanding how to modify and extend them. This guide covers advanced customization techniques that go beyond changing color palettes.
What Youβll Learn
- Modifying existing segments for different information
- Writing complex template expressions
- Creating entirely new segments
- Optimizing themes for your specific workflow
- Integrating custom scripts and commands
Theme Structure Deep Dive
JSON Schema Overview
Every Oh My Posh theme follows a defined JSON schema. Understanding this structure is essential for modifications.
{
"$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
"accent_color": "#00bcd4",
"blocks": [
// Prompt layout blocks
],
"console_title": "{{ .Shell }} - {{.Folder}}",
"console_title_template": "{{.Folder}}",
"final_space": true,
"palette": {
// Color definitions
},
"tooltip": {
"text": "{{.Name}}",
"background": "transparent",
"foreground": "#000000"
},
"transient_prompt": {
// Optional simplified prompt after execution
},
"version": 3
}
Key Top-Level Properties
| Property | Purpose | Example |
|---|---|---|
$schema |
Validation & IDE support | Official schema URL |
version |
Schema version for Oh My Posh | 3 (current) |
final_space |
Trailing space in prompt | true or false |
console_title_template |
Terminal tab/window title | "{{.Folder}}" |
accent_color |
Primary accent hue (not palette) | "#00bcd4" |
palette |
Color definitions object | {...} |
blocks |
Array of prompt line blocks | [{...}] |
transient_prompt |
Quick re-prompt display | Optional {...} |
Block Structure
{
"alignment": "left|right|rprompt|newline",
"segments": [
{
"type": "segment_type",
"background": "p:palette_key|#hexcolor",
"foreground": "p:palette_key|#hexcolor",
"template": "template_string",
"properties": {},
"style": "powerline|diamond|plain",
"leading_diamond": "β",
"trailing_diamond": "β",
"cache": {
"strategy": "session|folder|windows",
"duration": "5m",
"skip_cache": false
}
}
],
"vertical_offset": 0
}
Segment Customization
Common Segment Types
Oh My Posh provides numerous built-in segment types. Each type accepts different properties and templates.
Path Segment
Displays the current working directory with customizable format.
{
"background": "p:blue_primary",
"foreground": "p:white",
"properties": {
"style": "folder",
"max_depth": 3,
"folder_separator_icon": "/",
"home_icon": "~",
"hide_root_location": false,
"read_only_icon": "π",
"truncation_mode": "start",
"truncated_indicator": "....",
"mapped_locations": {
"C:\\Users\\YourName\\Documents": "π Docs",
"C:\\Users\\YourName\\Desktop": "π₯οΈ Desktop",
"/home/user/projects": "πΌ Projects"
}
},
"style": "powerline",
"template": " {{ .Path }} ",
"type": "path"
}
Customization Options:
{
"properties": {
"style": "mixed|folder|letter",
"max_depth": 2,
"folder_separator_icon": " > ",
"home_icon": "β",
"read_only_icon": " ",
"truncation_mode": "start|end|middle",
"truncated_indicator": "β¦",
"mapped_locations": {
"/home/user/dev": "π§ Dev",
"C:\\code": "π Code"
}
}
}
Git Segment
Shows git status with detailed information.
{
"background": "p:yellow_bright",
"foreground": "p:black",
"options": {
"branch_template": "{{ trunc 25 .Branch }}"
},
"style": "powerline",
"template": " {{ .UpstreamIcon }}{{ .HEAD }}{{ if .BranchStatus }} {{ .BranchStatus }}{{ end }}{{ if .Working.Changed }} {{ .Working.String }}{{ end }}{{ if .Staging.Changed }} {{ .Staging.String }}{{ end }} ",
"type": "git"
}
Oh My Posh v31 derives Git probes from referenced template fields. .Working and .Staging request local status, .BranchStatus requests ahead/behind data, and .UpstreamIcon requests upstream metadata. Remove fields you do not want fetched.
Advanced Git Template:
{
"template": "{{ if .UpstreamIcon }}{{ .UpstreamIcon }} {{ end }}{{ .HEAD }}{{ if .BranchStatus }} {{ .BranchStatus }}{{ end }}{{ if .Working.Changed }} {{ .Working.String }}{{ end }}{{ if .Staging.Changed }} {{ .Staging.String }}{{ end }}"
}
Status Segment
Indicates success/failure of last command.
{
"background": "p:green_success",
"background_templates": [
"{{ if .Error }}p:maroon_error{{ else }}p:green_success{{ end }}"
],
"foreground": "p:black",
"leading_diamond": "β",
"style": "diamond",
"template": " {{ if .Error }}β{{ else }}β{{ end }} ",
"trailing_diamond": "β",
"type": "status"
}
Custom Shell Variables Segment
Display any environment variable or command output.
{
"background": "p:blue_primary",
"cache": {
"strategy": "session",
"duration": "1h"
},
"foreground": "p:white",
"properties": {
"var_name": "CUSTOM_VAR"
},
"template": " {{ .Env.CUSTOM_VAR }} ",
"type": "env"
}
Command Segment (Advanced)
Execute custom commands and display results.
{
"background": "p:purple_session",
"cache": {
"strategy": "session",
"duration": "2s"
},
"foreground": "p:white",
"properties": {
"shell": "powershell",
"command": "Get-Date -Format 'HH:mm:ss'",
"parse": true,
"parse_separator": ":"
},
"template": "{{ .Output }}",
"type": "command"
}
Language Version Segments
Display runtime versions for Node, Python, etc.
{
"background": "p:node_green",
"cache": {
"strategy": "folder",
"duration": "5m"
},
"foreground": "p:black",
"style": "powerline",
"template": " β¬’ {{ .Full }} ",
"type": "node"
}
Under v31, the .Full reference requests the runtime version. Remove version fields from the template when only an icon or context indicator is needed.
Template Expressions
Basics
Oh My Posh uses Go template syntax (similar to Handlebars). Templates appear in the template property and background_templates array.
Simple Variable Substitution
{
"template": "User: {{ .User }}" // Output: User: john
}
Conditional Logic
{
"template": "{{ if .Error }}β Failed{{ else }}β Success{{ end }}"
}
Loops (Arrays)
{
"template": "{{ range .Items }}{{ . }}{{ end }}"
}
Advanced Template Patterns
Multi-Part Templates with Fallbacks
{
"template": "{{ if .Version }}{{ .Name }} {{ .Version }}{{ else }}{{ .Name }}{{ end }}"
}
Color Blending in Templates
{
"template": "<#00bcd4>Cyan</>{{ .Content }}<#ff0000>Red</>"
}
Complex Conditional State
{
"template": "{{ if or .Error .Detached }}{{ if .Detached }}(detached){{ else }}(error){{ end }}{{ else }}{{ .Branch }}{{ end }}",
"type": "git"
}
Conditional Spacing
{
"template": "{{ if .Value }} {{ .Value }} {{ else }}(empty){{ end }}"
}
Background Based on Condition
{
"background_templates": [
"{{ if eq .ExitCode 0 }}p:green_success{{ else }}p:red_alert{{ end }}"
]
}
Built-In Template Functions
| Function | Purpose | Example |
|---|---|---|
eq |
Equals comparison | {{ if eq .Shell "pwsh" }}PowerShell{{ end }} |
ne |
Not equals | {{ if ne .User "root" }}Regular User{{ end }} |
gt |
Greater than | {{ if gt .Memory 80 }}High Memory{{ end }} |
lt |
Less than | {{ if lt .Memory 20 }}Low Memory{{ end }} |
and |
Logical AND | {{ if and .Error .Warning }}Both{{ end }} |
or |
Logical OR | {{ if or .Error .Warning }}Either{{ end }} |
not |
Logical NOT | {{ if not .Error }}Success{{ end }} |
len |
Length of string | {{ if gt (len .Text) 5 }}Long{{ end }} |
contains |
String contains | {{ if contains .Path "node_modules" }}Has deps{{ end }} |
split |
Split string | {{ index (split .Path "/") 0 }} |
join |
Join array | {{ join (split .Path "/") "-" }} |
title |
Capitalize | {{ title .Name }} |
lower |
Lowercase | {{ lower .Text }} |
upper |
Uppercase | {{ upper .Text }} |
Practical Template Examples
Status Segment with Icons
{
"template": "{{ if .Error }}β {{ .Error.Message }}{{ else }}β
{{ end }}",
"type": "status"
}
Git with Upstream Status
{
"template": "{{ if .UpstreamIcon }}{{ .UpstreamIcon }} {{ end }}{{ .Branch }}{{ if .BranchStatus }} ({{ .BranchStatus }}){{ end }}",
"type": "git"
}
Path with Dynamic Truncation
{
"template": "{{ if gt (len .Path) 40 }}...{{ substr .Path -35 }}{{ else }}{{ .Path }}{{ end }}",
"type": "path"
}
Environment Indicator
{
"properties": {
"var_name": "ENVIRONMENT"
},
"template": "{{ if .Env.DEVELOPMENT }}[DEV]{{ else if .Env.STAGING }}[STAGING]{{ else }}[PROD]{{ end }}",
"type": "env"
}
Custom Icons & Symbols
Icon Strategy
Icons add visual richness to prompts while reducing text verbosity.
Built-in Icon Libraries
Oh My Posh includes collections of pre-designed icons:
- Powerline symbols: ` `
- Nerd Font icons: Various glyphs
- Unicode symbols: β β β β¬’ ⬑
Using Icons in Templates
{
"template": "β {{ .Branch }}",
"type": "git"
}
Conditional Icons Based on State
{
"template": "{{ if .Error }}σ°
Error{{ else }}σ°¬ Success{{ end }}",
"type": "status"
}
Custom Icon Mapping
{
"template": "{{ if contains .Output 'python' }}π Python{{ else if contains .Output 'node' }}β¬’ Node{{ else }}?{{ end }}",
"type": "command"
}
Nerd Font Resources
Use sites like nerdfonts.com to browse available icons:
- DevIcons (dev tools)
- Font Awesome
- Material Design Icons
- Powerline Symbols
Example Icons
| Icon | Unicode | Name | Use Case |
|---|---|---|---|
| β¬’ | U+2B22 | Node.js | JavaScript/TypeScript |
| π | U+1F40D | Python | Python projects |
| σ° | Custom | Rust | Rust projects |
| βΈ | U+2328 | Kubernetes | K8s contexts |
| σ° | Custom | Lock | Read-only indicator |
| β‘ | U+26A1 | Electricity | Power/speed indicator |
| π§ | U+1F527 | Wrench | Tools/configuration |
| π¦ | U+1F4E6 | Package | Dependencies |
Color Manipulation
Using the Palette System
The palette centralizes all color definitions, enabling easy theme swaps.
Palette Entry Reference Format
p:<palette_key>
Example References
{
"background": "p:blue_primary",
"foreground": "p:white"
}
Defining Custom Palette Entries
{
"palette": {
"my_custom_color": "#FF6B9D",
"my_custom_dark": "#2D1B3D",
"my_accent": "#00D9FF"
}
}
Hex Color References
When not using palettes, you can specify colors directly:
{
"background": "#000000",
"foreground": "#FFFFFF"
}
Dynamic Colors Based on Conditions
The background_templates array allows conditional colors:
{
"background_templates": [
"{{ if .Error }}p:red_alert{{ else }}p:green_success{{ end }}"
],
"foreground": "p:white",
"template": "{{ if .Error }}β{{ else }}β{{ end }}",
"type": "status"
}
Color Blending Techniques
While Oh My Posh doesnβt directly support color blending, you can simulate it by:
- Using intermediate colors in palette
- Conditional color selection based on context
- Using divider segments with blend colors
{
"palette": {
"red_to_orange": "#FF4500",
"orange_to_yellow": "#FFB347",
"yellow_to_green": "#ADFF2F"
}
}
Advanced Block Layouts
Block Alignment Options
{
"alignment": "left|right|rprompt|newline"
}
left: Primary prompt line, left-alignedright: Same line as left, but right-alignedrprompt: Right prompt (may overflow left)newline: New prompt line
Multi-Line Prompt Example
{
"blocks": [
{
"alignment": "left",
"segments": [
{ "type": "shell", "..." },
{ "type": "path", "..." }
]
},
{
"alignment": "right",
"segments": [
{ "type": "time", "..." },
{ "type": "battery", "..." }
]
},
{
"alignment": "newline",
"segments": [
{ "type": "text", "template": "β―" }
]
}
]
}
Vertical Offset for Alignment
{
"alignment": "left",
"vertical_offset": 0, // 0 = same line as previous, >0 = down, <0 = up
"segments": [...]
}
Creating Spacers and Dividers
{
"background": "transparent",
"properties": {
"prefix": "",
"suffix": ""
},
"template": " ", // Single space
"type": "text"
}
Creating Custom Segments
Using the Command Segment for Custom Logic
{
"background": "p:blue_primary",
"cache": {
"strategy": "session",
"duration": "30s"
},
"foreground": "p:white",
"properties": {
"shell": "powershell",
"command": "Get-Process -Name 'notable-app' -ErrorAction SilentlyContinue | Measure-Object | ForEach-Object { $_.Count }",
"parse": true
},
"template": "{{ .Output }}",
"type": "command"
}
Custom PowerShell Script Segment
Create a PowerShell script that returns information:
# File: CustomSegments.ps1
function Get-GitStats {
$ahead = (git rev-list --count "@{u}..HEAD" 2>/dev/null) || 0
$behind = (git rev-list --count "HEAD..@{u}" 2>/dev/null) || 0
if ($ahead -eq 0 -and $behind -eq 0) {
return ""
}
$stats = @()
if ($ahead -gt 0) { $stats += "β$ahead" }
if ($behind -gt 0) { $stats += "β$behind" }
return $stats -join " "
}
Get-GitStats
Configure in theme:
{
"properties": {
"shell": "powershell",
"command": "&{ . ./CustomSegments.ps1; Get-GitStats }"
},
"template": "{{ .Output }}",
"type": "command"
}
Environment Variable Segment
{
"background": "p:purple_session",
"cache": {
"strategy": "session"
},
"foreground": "p:white",
"properties": {
"var_name": "ENVIRONMENT"
},
"template": "[{{ .Env.ENVIRONMENT }}]",
"type": "env"
}
Performance Tuning
Segment Caching Strategies
Caching prevents expensive segment evaluations on every prompt.
Cache Strategy Types
{
"cache": {
"strategy": "session|folder|windows",
"duration": "5m",
"skip_cache": false
}
}
session: Cache for entire shell session (fastest)folder: Cache per directory (good for git status)windows: Cache per PowerShell window session
Duration Format
"2s" // 2 seconds
"5m" // 5 minutes
"1h" // 1 hour
Caching Best Practices
{
"type": "git",
"cache": {
"strategy": "folder",
"duration": "5m"
}
},
{
"type": "time",
"cache": {
"strategy": "session",
"duration": "1s" // Update every second
}
},
{
"type": "command",
"cache": {
"strategy": "session",
"duration": "30s" // Heavy commands should cache longer
}
}
Disabling Expensive Segments
If a segment is very slow, consider disabling or replacing it:
{
"background": "transparent",
"properties": {
"command": "..." // Expensive logic disabled
},
"template": "", // Empty template = hidden
"type": "command"
}
Conditional Segment Loading
Load segments only in certain conditions:
{
"properties": {
"shell": "powershell",
"command": "$PSVersionTable.PSVersion.Major"
},
"template": "{{ if eq .Shell \"pwsh\" }}β‘{{ end }}",
"type": "command"
}
Best Practices
1. Modular Configuration
Separate concerns into distinct segments:
{
"blocks": [
{
"type": "prompt",
"alignment": "left",
"segments": [
{ "type": "shell" }, // β System info
{ "type": "path" }, // β‘ Location
{ "type": "git" } // β’ VCS status
]
},
{
"type": "prompt",
"alignment": "right",
"segments": [
{ "type": "time" }, // β£ Clock
{ "type": "battery" } // β€ Power
]
}
]
}
2. Consistent Styling
Use palette colors consistently:
{
"blocks": [
{
"segments": [
{
"background": "p:bg_primary",
"foreground": "p:fg_primary"
}
]
}
],
"palette": {
"bg_primary": "#1e1e2e",
"bg_secondary": "#313244",
"fg_primary": "#cdd6f4"
}
}
3. Performance First
Cache aggressively and keep expensive data fields out of templates that do not display them:
{
"type": "git",
"cache": {
"strategy": "folder",
"duration": "5m"
},
"style": "plain",
"template": " {{ .HEAD }} "
}
This lightweight v31 Git template omits local-status, ahead/behind, upstream, user, bare-repository, and worktree-count fields, so their optional probes are skipped.
4. Readability
Ensure adequate contrast and spacing:
{
"background": "p:dark_color",
"foreground": "p:light_color", // High contrast
"template": " {{ .Content }} " // Breathing room
}
5. Testing Changes
Test your modifications before deploying:
# Test a modified theme
oh-my-posh init pwsh --config './my-modified-theme.json' | Invoke-Expression
# Reload if needed
$ExecutionContext.InvokeCommand.LocationChangedAction = $null
& $profile
Summary
Advanced customization allows you to:
β Create highly personal prompts β Integrate custom scripts and commands β Optimize for your specific workflow β Reduce visual clutter or add detail β Maintain consistent branding
Key Areas Covered:
- Theme Structure: Understanding JSON schema
- Segments: Customizing built-in segment types
- Templates: Writing dynamic template expressions
- Icons: Adding visual richness
- Colors: Palette system and conditional colors
- Layouts: Multi-line and complex block arrangements
- Custom Logic: Command segments and scripts
- Performance: Caching and optimization
- Best Practices: Professional configuration techniques
For more advanced topics, refer to the Official Oh My Posh Documentation.