Add a repository-aware semantic shortening style to the Path segment
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/currentFor example:
D:\very\long\collection\repo\src\platform\deep\current
→ D:\very\…\repo\src\…\deep\currentThis 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:
{{ .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:
- Build the ordinary mapped path first.
- If
max_widthis unset, zero, or the full path fits, return it unchanged. - For an over-width path, find the nearest
.gitfile or directory using the existing filesystem abstraction. - Preserve a semantic skeleton and replace each omitted contiguous run with
folder_icon. - Add the longest contiguous tail that fits, working backward from the current directory.
- Treat
max_widthas a soft limit: protected landmarks are never truncated merely to satisfy it.
The proposed landmarks are:
- an explicit home or
mapped_locationsprefix; - 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\currentAt the repository root, only the long ancestry should be shortened:
~/very/long/worktree/location/repo
→ ~/very/…/repoFor 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/authWith display_root: true:
/…/repo/packages/…/services/authA home mapping is meaningful:
/home/alice/work/acme/repo/packages/platform/services/auth
→ ~/work/…/repo/packages/…/services/authA custom mapping provides the portable way to declare another prefix meaningful:
mapped_locations:
/srv/git/acme: acme/srv/git/acme/repo/packages/platform/services/auth
→ acme/repo/packages/…/services/authWindows drives and UNC shares carry location identity:
\\build01\source$\teams\platform\repo\src\deep\current
→ \\build01\source$\teams\…\repo\src\…\currentThe 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_pathrepo_rootpath, meaning the repository-relative remainder
A similar conceptual result in Oh My Posh could be:
BeforeRepo + RepoRoot + RepoRelative = PathPossible approaches include:
- Expose styled template properties such as
.BeforeRepo,.RepoRoot, and.RepoRelative, while keeping.Pathas their concatenation. - Keep only
.Path, but add repository-aware formatting hooks for those three regions. - 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
.gitparent walk per Path render; - share that result with
gitdir_formatso enabling both does not perform two walks; - recognize linked-worktree
.gitfiles as well as ordinary.gitdirectories; - 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_widthfolder_iconfolder_separator_iconandfolder_separator_templatemapped_locationsdisplay_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 bothdisplay_rootvalues; - 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;
.Pathremaining the joined result if structured properties are exposed.
Prior art
Related requests and implementations include:
- Oh My Posh #4727, #3607, and #5016.
- Starship issue 4199 and issue 6166, plus its current
repo_root_format. - Powerlevel10k's directory anchors, which preserve repository-marker directories and the deepest components.
- Fish's composable
prompt_pwd. - Zsh
vcs_info, which exposes the repository root, repository name, and repository-relative subdirectory separately.
Questions
- Is a new repository-aware style welcome?
- Is
twitacceptable, or would a descriptive name such asrepositorybe preferable? - Should the first repository-relative component be protected, preferred, or treated like the rest of the tail?
- Should over-width paths outside Git remain full or receive a generic tail-shortening fallback?
- Should repository-aware styled parts be exposed to templates, or should their formatting remain internal to
.Path? - 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