#7722·oh-my-posh

Add a repository-aware semantic shortening style to the Path segment

Author: GraviferCreated Jul 26, 2026Updated Jul 26, 2026
Labels🤩 enhancement

Code of Conduct

  • I agree to follow this project's Code of Conduct

What would you like to see changed?

Would you be open to adding an opt-in Path style that shortens long paths around repository landmarks instead of uniformly abbreviating every directory?

The working name is twit, as a light wordplay on Git. A more descriptive name such as repository would also be fine if preferred.

The intended result is:

[meaningful origin]/…/repository/repository-child/…/tail/current

For example:

D:\very\long\collection\repo\src\platform\deep\current
→ D:\very\…\repo\src\…\deep\current

This proposal is issue-first so that the exact behavior and public API can be agreed before implementation.

Motivation

The existing Path styles shorten the current path as one value. They do not preserve both repository identity and useful context near the current directory.

Themes can access the raw repository split through:

  • .Segments.Git.Dir
  • .Segments.Git.RelativeDir

However, the Path style option only transforms .Path. This means a template such as:

template
{{ .Format .Segments.Git.Dir }} | {{ .Format .Segments.Git.RelativeDir }}

can display the two raw values separately, but switching between fish, powerlevel, agnoster, and other styles has no shortening effect on them. .Format applies separator, cycle, and folder formatting; it does not apply the selected path style.

The raw data therefore already exists, but there is no style-aware repository split.

Proposed behavior

For a twit Path segment:

  1. Build the ordinary mapped path first.
  2. If max_width is unset, zero, or the full path fits, return it unchanged.
  3. For an over-width path, find the nearest .git file or directory using the existing filesystem abstraction.
  4. Preserve a semantic skeleton and replace each omitted contiguous run with folder_icon.
  5. Add the longest contiguous tail that fits, working backward from the current directory.
  6. Treat max_width as a soft limit: protected landmarks are never truncated merely to satisfy it.

The proposed landmarks are:

  • an explicit home or mapped_locations prefix;
  • an identity-bearing Windows drive or UNC server/share;
  • the current repository/worktree directory;
  • the first repository-relative component, when distinct;
  • the current directory;
  • the longest fitting tail nearest the current directory.

The first repository-relative component is deliberately proposed because it often identifies a monorepo namespace such as packages, services, apps, or src. I would welcome guidance on whether this should be guaranteed or only preferred.

For an identity-bearing Windows or explicitly mapped origin, the first following component could also be preferred origin context:

D:\work\clients\acme\repo\src\platform\deep\current
→ D:\work\…\repo\src\…\deep\current

At the repository root, only the long ancestry should be shortened:

~/very/long/worktree/location/repo
→ ~/very/…/repo

For a focused first version, paths outside Git would remain unchanged. A generic origin-plus-tail fallback could be considered separately if that would make the style more coherent.

Cross-platform model

A raw filesystem root is not uniformly meaningful.

On POSIX, / is presentation syntax rather than a semantic landmark. Its visibility should continue to follow display_root, and the first directory beneath it should not automatically be protected:

/srv/git/acme/repo/packages/platform/services/auth
→ …/repo/packages/…/services/auth

With display_root: true:

/…/repo/packages/…/services/auth

A home mapping is meaningful:

/home/alice/work/acme/repo/packages/platform/services/auth
→ ~/work/…/repo/packages/…/services/auth

A custom mapping provides the portable way to declare another prefix meaningful:

yaml
mapped_locations:
  /srv/git/acme: acme
/srv/git/acme/repo/packages/platform/services/auth
→ acme/repo/packages/…/services/auth

Windows drives and UNC shares carry location identity:

\\build01\source$\teams\platform\repo\src\deep\current
→ \\build01\source$\teams\…\repo\src\…\current

The UNC host/share must remain indivisible.

The style should not hard-code special handling for directory names such as:

  • /home, /Users, /usr, /usr/local, /opt, /srv, or /var;
  • /Applications, /Volumes, or /System/Volumes;
  • /mnt/c, /cygdrive/c, /workspace, or /workspaces;
  • /nix/store;
  • Program Files, XDG directories, package-manager roots, or guessed mountpoints.

These conventions vary across operating systems, distributions, containers, WSL configurations, and individual machines. Existing mapped_locations is the appropriate user-controlled mechanism for making one of these locations significant.

Style-aware parts

There is an API question beyond the selection algorithm.

A single .Path value is sufficient for the default template, and it must remain the joined backward-compatible representation. But themes may want to render the path to the repository and the repository-relative path as separate prompt pieces or with different styles.

Starship handles this by computing one directory result with three separately formatable values:

  • before_root_path
  • repo_root
  • path, meaning the repository-relative remainder

A similar conceptual result in Oh My Posh could be:

BeforeRepo + RepoRoot + RepoRelative = Path

Possible approaches include:

  1. Expose styled template properties such as .BeforeRepo, .RepoRoot, and .RepoRelative, while keeping .Path as their concatenation.
  2. Keep only .Path, but add repository-aware formatting hooks for those three regions.
  3. Add a reusable path-style function.

My preference is the first or second approach. Calling a style function independently for the repository path and relative path would give each call a separate max_width budget, so the combined output would no longer be coherent.

The existing Git .Dir and .RelativeDir remain useful raw values; this proposal would not replace or change them.

Performance and fallback behavior

The implementation should:

  • perform no Git subprocess;
  • perform no mount, XDG, program-directory, or symlink-resolution probing;
  • return before repository discovery when the full path already fits;
  • use at most one .git parent walk per Path render;
  • share that result with gitdir_format so enabling both does not perform two walks;
  • recognize linked-worktree .git files as well as ordinary .git directories;
  • use the nearest repository for nested repositories and submodules;
  • avoid cross-render caching in the first implementation.

A parent walk can be comparatively expensive on network filesystems, so the fast path is important.

If repository discovery fails or its result cannot be aligned component-by-component with the displayed path, the segment should return the existing full rendering. The same conservative fallback should apply to unsupported Windows device paths, non-filesystem PowerShell providers, ambiguous PSDrive aliases, and symlink namespace mismatches.

Compatibility

This would be a new opt-in style. Existing styles, templates, schemas, and default visual output would remain unchanged.

It should continue to honor the applicable existing Path options, including:

  • max_width
  • folder_icon
  • folder_separator_icon and folder_separator_template
  • mapped_locations
  • display_root
  • cycle and folder formatting
  • gitdir_format

Width should be calculated before text-style markup. Rune/code-point width would be consistent with part of the current implementation, although terminal-cell width could be discussed separately.

Suggested test coverage

The implementation should cover:

  • full paths below and exactly at max_width;
  • paths outside Git;
  • repository root, immediate child, and deeply nested directories;
  • nested repositories, submodules, and linked worktrees;
  • POSIX / with both display_root values;
  • home mappings and custom mappings above, equal to, and inside the repository;
  • Windows drives, UNC shares, WSL/Cygwin presentation, and conservative device-path fallback;
  • macOS, container, mount-style, and Nix paths without hard-coded recognition;
  • mapping or repository alignment failure;
  • permission and filesystem errors;
  • Unicode component names;
  • overlapping landmarks without duplicated output;
  • a soft limit when the mandatory skeleton itself exceeds max_width;
  • zero discovery calls on the fast path and at most one parent walk otherwise;
  • zero subprocess calls;
  • .Path remaining the joined result if structured properties are exposed.

Prior art

Related requests and implementations include:

Questions

  1. Is a new repository-aware style welcome?
  2. Is twit acceptable, or would a descriptive name such as repository be preferable?
  3. Should the first repository-relative component be protected, preferred, or treated like the rest of the tail?
  4. Should over-width paths outside Git remain full or receive a generic tail-shortening fallback?
  5. Should repository-aware styled parts be exposed to templates, or should their formatting remain internal to .Path?
  6. Should width follow rune count, the current style-specific behavior, or terminal display-cell width?

I would be happy to prepare a focused implementation after the intended behavior and API are agreed.

Source: JanDeDobbeleer/oh-my-posh