oh-my-posh — 一份配置让所有 shell 都长一个样
待复核oh-my-posh 是一个用 Go 写的命令行提示符(prompt)引擎。
日常类比:你家里有四个房间,每间灯开关接线方式都不一样(PowerShell 一种、bash 一种、zsh 一种、fish 一种)。oh-my-posh 像一个统一遥控器——你只配一份”我要这种灯光”,它替每个房间生成对应的接线脚本。
具体来说:
- 写一份 JSON / YAML / TOML 配置(决定 prompt 长什么样)
- 在 bash / zsh / fish / PowerShell / cmd / nushell 任何一个里运行
oh-my-posh init <shell> - 它生成对应 shell 的 hook 脚本,你的提示符立刻变成你配置的样子
作者 Jan De Dobbeleer 2018 年最早用 PowerShell 写,2021 年第 3 个大版本整体重写为 Go 单二进制——这是它今天能跨所有 shell 的关键。
不是”prompt 漂亮”那么肤浅,三件事值得学:
-
跨 shell 抽象:bash / zsh / fish 钩 prompt 的 API 完全不同(bash 是
PROMPT_COMMAND,zsh 是precmd,fish 是fish_prompt函数)。oh-my-posh 把”如何拿到当前目录、git 状态、退出码”抽象成 shell-agnostic 的中间层——这是适配器模式的真实工业案例。 -
插件式架构:100+ 个 segment(git 状态、kubectl context、node 版本、AWS profile、电池…)每个是一个独立 Go 文件,加新功能不动核心。读
src/segments/一目了然:怎么把”功能”做成可插拔积木。 -
配置即 DSL:Go 的
text/template直接暴露给用户,每个 segment 可以写自定义模板。这比”硬编码一堆开关”灵活十倍——是”少写代码、多让用户描述”思路的好例子。
约 18k GitHub stars,MIT 协议,主流社区配置之一。跨平台二进制 + 一份配置,是它相对”每个 shell 各装一套主题框架”的核心卖点。
理解三层结构就够上手:
-
block:prompt 的位置容器。三种——
prompt(左)、rprompt(右,行尾贴右)、transient(回车后简化版)。 -
segment:block 里的小积木。每个 segment 一个类型,比如:
{ "type": "git", "style": "powerline", "foreground": "#193549", "template": "{{ .HEAD }} {{ if .Working.Changed }}*{{ end }}"}- template:用 Go
text/template决定 segment 怎么渲染。.HEAD.Working.Changed这些字段由 segment 的 Go 代码暴露。
把这三层串起来:config.json 描述一棵 block → segment → template 的树,oh-my-posh 在每次按回车时遍历这棵树渲染一次。改配置不用重装,重开一个 shell 或 exec 当前 shell 即可看到效果。
案例 1:装 + 跑默认主题(5 分钟)
Section titled “案例 1:装 + 跑默认主题(5 分钟)”mac 上:
brew install jandedobbeleer/oh-my-posh/oh-my-poshecho 'eval "$(oh-my-posh init zsh)"' >> ~/.zshrcsource ~/.zshrc立刻就能看到带颜色和 git 信息的 prompt。如果显示成方块,是 Nerd Font 没装——去 nerdfonts.com 装一个 MesloLGS NF,终端字体改成它。Linux 可用发行版包或直接下 ttf;Windows 在终端设置里把字体改成已安装的 Nerd Font。
案例 2:换主题
Section titled “案例 2:换主题”oh-my-posh 自带 200+ 主题(仓库 themes/ 目录)。看一眼挑一个:
oh-my-posh init zsh --config ~/.../themes/jandedobbeleer.omp.json把主题 JSON 拷一份到自己的 dotfiles,改字段,效果立刻反馈——这是最快感受 segment / template 关系的方式。不确定主题路径时,先 oh-my-posh print config 或查文档站 themes 列表。
案例 3:读源码学 Go 插件式架构
Section titled “案例 3:读源码学 Go 插件式架构”最值得读的两个文件:
src/segments/git.go:最常用 segment,怎么实现Enabled()(决定是否显示)和模板字段暴露src/shell/init.go:oh-my-posh init bash输出的脚本怎么生成的——理解了这个就理解了”跨 shell”是怎么做到的
读完会明白:oh-my-posh 不是在 shell 里运行,它是一个独立进程,每次按回车被 shell 调用一次输出一行字符串。主线建议:engine/(渲染)→ 任意一个 segments/*.go → shell/init.go。
-
看到方块 / 问号:99% 是 Nerd Font 没装。不是 oh-my-posh 的 bug,是字体问题。
-
Windows Terminal 字体两个地方:Windows Terminal 的字体设置 不会 自动同步到 PowerShell ISE 或 VS Code 终端。每个终端 app 单独设字体。
-
PowerShell 改
$PROFILE不生效:必须. $PROFILE显式重载(点 + 空格 + 路径),或新开一个窗口。bash / zsh 习惯的source在 PowerShell 里要换写法。 -
prompt 变慢:segment 加多了(比如 kubectl + AWS + Azure 同时启用),每次回车都跑一堆命令拿状态。解决:用
transient让历史行简化、关掉用不到的 segment、或只在特定目录启用(enable_for_path)。
适用 vs 不适用
Section titled “适用 vs 不适用”适用:
- 你需要在 mac / Linux / Windows 多机同步一套 prompt 体验
- 你同时用多个 shell(公司 PowerShell、家里 zsh)
- 你想要表达力强的 prompt(条件渲染、自定义 template、多颜色组合)
不适用:
- 只用 zsh 且想要最快启动速度 → 用 powerlevel10k(zsh-only,Instant Prompt 优化好)
- 想要最简配置 → 用 starship(Rust 写,TOML 配置更简洁)
- 受限环境无法装二进制 → 用 shell 内置 PS1 手写
历史小故事(可跳过)
Section titled “历史小故事(可跳过)”- 2018:Jan De Dobbeleer 用 PowerShell 写出第一版,解决 Windows 上 prompt 主题碎片化
- 2021:v3 整体重写为 Go 单二进制——从此一份配置覆盖 bash / zsh / fish / PowerShell / nushell
- 此后:内置主题破 200+,segment 破 100+,文档站 ohmyposh.dev 成为配置 SSOT
- 社区:与 starship / powerlevel10k 三分提示符市场——跨 shell 是它的差异化卖点
- “配置 + 模板”比”硬编码开关”灵活——把表达力让给用户,核心代码反而更小
- 跨 shell 抽象的关键不是统一 API,是统一中间表示:状态在独立进程内算,再生成各 shell 的 hook
- Go 单二进制的工程优势:一份代码编出 mac / Linux / Windows 三套,分发简单
- 插件目录 = 学源码入口:100+ segment 都长一样,读懂一个就懂整体
- prompt 是 shell 的 hook 点:oh-my-posh 把”每个 shell 各写一份”统一成”我一个进程吐字符串”
- 官方文档:ohmyposh.dev(配置字段、segment 列表都在这)
- Nerd Font 入门:nerdfonts.com(字体不对一切都白搭)
- 同类对比:starship / powerlevel10k
- 源码导读起点:
src/segments/git.go+src/shell/init.go;主线engine/→segments/→shell/ - 想自己加 segment:仓库
src/segments/任挑一个短文件照猫画虎,再在 engine 注册表加一行
- starship —— Rust 写的同类,配置更简单但表达力更弱
- promptfoo —— 名字像,干的完全不一样(LLM prompt,不是 shell prompt)
- nushell —— oh-my-posh 支持的现代 shell 之一,
oh-my-posh init nu即用 - zsh —— mac 默认 shell;案例里
oh-my-posh init zsh最常见 - fish —— 无 POSIX 的 shell;oh-my-posh 用
fish_prompthook 适配 - neovim —— 终端字体/Nerd Font 坑与 oh-my-posh 同源,常一起配
- tmux —— 多窗格里每格都要正确字体,否则方块问题成倍出现
(暂无反向链接)