Back to Oh My Posh

Template data

website/docs/configuration/data.mdx

30.0.010.2 KB
Original Source

import Config from "@site/src/components/Config.js";

The --data flag supplies template properties from a file instead of the live environment. Use it to render a prompt deterministically, without the git repository, Azure CLI, kubectl, or any other tooling a segment normally detects: take prompt screenshots, build demos, or test a config on a machine that lacks your usual setup.

--data is available on oh-my-posh print (every prompt type) and oh-my-posh config export image.

File format

A data file has two top-level sections: env for global template properties and segments for per-segment template properties. The format is JSON, YAML, or TOML, decided by the file extension.

<Config data={{ env: { PWD: "~/dev/oh-my-posh", Code: 1, ExecutionTime: 341.0, UserName: "jan", HostName: "demo", Shell: "pwsh", Root: false, }, segments: { git: { HEAD: "main", Working: { Added: 2, Modified: 1 }, Staging: {}, UpstreamIcon: "", }, az: { Name: "posh-subscription", EnvironmentName: "AzureCloud", Origin: "CLI", }, }, }} />

The env section

Keys are the global template properties you already use in templates (PWD, AbsolutePWD, PSWD, Folder, UserName, HostName, Shell, ShellVersion, Root, OS, WSL, SHLVL, Jobs, Code, PromptCount, Version, and Var), plus ExecutionTime and PipeStatus.

A key present in the file overrides the live value. A key left out falls back to the real environment, so specify only the properties your config depends on.

Folder derives from the effective PWD automatically. Set an explicit Folder key to override it.

The maps aliases (user_name, host_name, shell_name) apply to data values as they do to live ones.

Precedence

PWD, Code, ExecutionTime, and PipeStatus feed the runtime itself, not just the template context. Live segments that compute from them, such as path, status, and executiontime, also see the overridden values.

Values are resolved in this order, highest priority first:

  1. An explicit CLI flag on print (--pwd, --status, --execution-time, ...)
  2. The data file
  3. The live environment

The segments section

Each key is a segment's alias if it has one, otherwise its type (for example git or az). The value is an object whose keys are that segment's template properties, as documented on the segment's page.

A few segments store a property under a different name than the template exposes. The wakatime segment, for example, stores .CumulativeTotal as cumulative_total. When a property you wrote by hand has no effect, run config export data and copy the names from its output: the recorder always uses the stored names.

A segment listed here is force-enabled: it renders even where its own live check would otherwise suppress it, for example a battery segment on a machine without one. A segment left out of the file executes normally against the live environment.

Whether the rest of that segment's state comes from the file or from a live probe depends on how the file was produced:

  • A recorded file carries a version marker and replays a listed segment from the supplied data alone. Detection is skipped: no git call, no HTTP request, nothing.
  • A hand-written file has no version marker. Oh My Posh runs the segment's detection first and then overlays your properties on top, which fills in whatever you left unset. Some segments only compute their template state while detecting, so skipping that step would render them blank. The cost is that the segment still touches the live environment. Oh My Posh warns and names the file each time it takes this path.

:::caution If your config has two segments of the same type, give each an alias. Without one, both segments match the same type key in the segments section and can't receive distinct data. :::

For example, this config has two path segments distinguished by alias:

<Config data={{ segments: [ { type: "path", alias: "PathMain", style: "plain", foreground: "#ffffff", }, { type: "path", alias: "PathSecondary", style: "plain", foreground: "#ffffff", }, ], }} />

The matching data file targets each segment by its alias:

<Config data={{ segments: { PathMain: { Path: "/dev/oh-my-posh" }, PathSecondary: { Path: "/dev/site" }, }, }} />

Template and method fidelity

Templates evaluate over the data you supply, so template methods and functions work as expected. .Working.String on the git segment, for example, computes from the Working property in the file, just as it would from a live repository. Only logic that reads live runtime state at render time can't be reproduced this way. This matches how a cached segment behaves: it also renders from stored properties instead of re-detecting them.

Recording data

oh-my-posh config export data renders your prompt against the real environment and writes a complete data file: the env section plus every configured segment, whether or not it was enabled at record time. The recorder omits Var: the config's own var section already defines those values, though you can still set Var in the file by hand to override them.

bash
oh-my-posh config export data --config mytheme.omp.json --output data.json
FlagDescription
--configthe configuration to render
--outputfile to write the data to, defaults to stdout

The output format is JSON. Record your data files this way. It is the only way to get one that replays hermetically: --data on a recorded file never touches the network, the filesystem, git or any other tooling, for any segment, including the ones that were disabled when you recorded it.

A recorded file carries a top-level version marker and wraps each segment in an envelope pairing its recorded enabled state with its data:

<Config data={{ version: 1, segments: { git: { enabled: true, data: { HEAD: "main" } }, wakatime: { enabled: false, data: {} }, }, }} />

A segment recorded as enabled: false renders as it did on the recording machine: disabled, and never probed again. You do not have to write this shape yourself. The recorder produces it, and the hand-written form with bare properties keeps working.

Record once, replay anywhere. Run the command on a machine where git, the cloud CLIs and the language runtimes are all set up the way you want them to look, then edit values by hand and replay the result with --data wherever you like. Editing values inside a data object is safe. So is editing enabled, with one catch: turning it on for a segment whose recorded data is empty renders a blank segment, because none of its properties were ever captured.

Deriving instead of replaying a recorded file

--data-derive applies the hand-written derive behavior to a recorded file, running every segment's detection instead of trusting the recorded enabled state and data. Use it to debug the recorder or a segment's Enabled logic. It gives up hermetic replay for the command you pass it to.

End-to-end example

Record a data file from a fully configured machine:

bash
oh-my-posh config export data --config mytheme.omp.json --output data.json

Edit data.json to adjust the values you want to show: the branch name, the exit code, the Azure subscription, and so on.

Render an image from the edited data, without touching git, Azure CLI, or anything else the config depends on:

bash
oh-my-posh config export image --config mytheme.omp.json --data data.json

Exporting an image

config export image writes an SVG of the rendered prompt. It draws from the prompt's own internal representation rather than a screenshot, so every color, style and glyph matches what the terminal would show.

<!-- markdownlint-disable MD013 -->
FlagDescription
--output, -oFile to write (defaults to the config's own name with an .svg extension)
--terminal-widthColumns to render the prompt and canvas at (default 120)
--font-familyCSS font-family the SVG renders text with (defaults to a Nerd Font stack)
--cell-widthHorizontal advance of one cell, as a multiple of font size (defaults to Hack Nerd Font's)
--line-heightVertical advance of one row, as a multiple of font size (defaults to Hack Nerd Font's)
--fill-ascentHow far a segment background reaches above the baseline, as a multiple of font size
--fill-descentHow far a segment background reaches below the baseline, as a multiple of font size
--dataRender from a recorded data file instead of the live environment
--data-onlyRefuse the environment entirely: a segment renders from --data or reports itself absent
<!-- markdownlint-enable MD013 -->

The four metric flags travel together, because they describe one font. Set them whenever --font-family names a font whose metrics differ from the default stack. Mixing one font's cell width with another's line height lays out the grid for a font that does not exist.

bash
oh-my-posh config export image --config ~/myconfig.omp.json \
  --output ~/mytheme.svg --font-family "Cascadia Code NF"