Worktree Colors
A VS Code extension that tints the window chrome (title bar, activity bar, status
bar) so you can tell which repo and which git worktree a window belongs to at
a glance — plus optional manual per-file tab colors.
Features
- Per-repo color family. Each repository is assigned a distinct base hue, so
different projects look clearly different.
- Per-worktree shade. Worktrees of the same repo share that hue but differ
by a small lightness step, so they read as one family while staying tellable
apart. The main worktree gets the base shade.
- Smart, stable assignment. Repos are given distinct, spread-apart hues from
a shared registry (collisions are bumped to a free slot) and remembered across
sessions, so a repo keeps its color.
- Warm, dark defaults — tunable to any palette, dark or light, via settings
or the Choose Palette command.
- Theme-aware. Works under light and dark editor themes; text color is
auto-picked for contrast.
- Manual tab colors. Assign a fixed color to individual file tabs,
independent of the worktree theming.
How the colors work
A color is generated in HSL from two parts:
- Hue comes from the repository identity (its shared git common dir), so
it's the same across every worktree of that repo and distinct between repos.
- Lightness comes from the worktree — a monochromatic shade of the repo hue.
Saturation and the hue range are fixed per palette. By default the hue arc is
warm (300°→75°: magenta → rose → red → orange → amber → gold).
Commands
Run from the Command Palette (⌘⇧P):
| Command |
Description |
| Worktree Colors: Choose Palette |
Pick a preset (Warm, Cool, Vibrant, Full wheel, Muted/dark); written to User settings. |
| Worktree Colors: Import Palette |
Paste a coolors.co URL or hex list to use as repo base colors. |
| Worktree Colors: Set Color for This Repo |
Pin the current repo to a specific color (or clear the pin). |
| Worktree Colors: Reset Repo Colors |
Forget all repo color assignments and pins, then reshuffle. |
| Worktree Colors: Remove Colors from Workspace |
Strip the chrome customizations from this workspace's settings. |
| Worktree Colors: Exclude IDE Colors from Git |
Set up a clean filter or gitignore so the colors aren't committed. |
| Worktree Colors: Assign Color to Active Tab |
Give the current file tab a fixed color. |
| Worktree Colors: Clear Color for Active Tab |
Remove a manual tab color. |
| Worktree Colors: Refresh |
Recompute and re-apply the chrome colors. |
| Worktree Colors: Inspect Tabs |
Dump current tab/color state to an output channel. |
Settings
All under worktreeColors.*. Set them in User settings so they don't end up
in a repo's .vscode/settings.json. Changes apply live.
| Setting |
Default |
Description |
customPalette |
[] |
Hex colors used as repo base colors instead of generated hues. Empty = generated. Use Import Palette to set. |
tint |
all |
Which chrome elements to color: titleBar, activityBar, statusBar. |
colorSingleWorktreeRepos |
true |
Tint repos that have only one worktree; turn off to tint only multi-worktree repos. |
hueRangeStart |
300 |
Start of the hue arc (degrees) repos draw from. Wraps if start > end. |
hueRangeEnd |
75 |
End of the hue arc. Use 0/360 for the full wheel. |
hueBuckets |
12 |
Number of distinct repo hues within the arc. |
dark.saturation |
58 |
Saturation (%) under a dark editor theme. |
dark.baseLightness |
34 |
Base lightness (%) under a dark theme. |
dark.lightnessStep |
5 |
Lightness gap between worktree shades (dark). |
light.saturation |
58 |
Saturation (%) under a light editor theme. |
light.baseLightness |
38 |
Base lightness (%) under a light theme. |
light.lightnessStep |
5 |
Lightness gap between worktree shades (light). |
The Set Color for This Repo / Reset Repo Colors pins and assignments are
stored globally (shared across windows), so colors stay stable between sessions.
Keeping the IDE colors out of your commits
To color a window, the extension must write workbench.colorCustomizations into
that workspace's .vscode/settings.json — that's the only place VS Code reads
per-window chrome colors from. There's no machine-local per-workspace settings
file, so this write is unavoidable and the file lives inside your repo.
The quickest path is the Worktree Colors: Exclude IDE Colors from Git command,
which sets this up for the current repo — pick either gitignore the file or
clean filter. The rest of this section explains what it does (and how to set it
up globally / by hand).
If you don't otherwise commit .vscode/settings.json, just gitignore it. The
tricky case is when you do need to commit other settings in that file (env
vars, formatter config, …) but not the colors. Git tracks whole files, not
regions — so the clean way to commit part of the file is a git clean
filter that strips the color block on staging.
One-time global setup
This makes git strip workbench.colorCustomizations from any
.vscode/settings.json when it's staged, while leaving your working copy (and
the live colors) untouched. Requires jq.
mkdir -p ~/.config/git
# 1. The filter script (falls back to passthrough if a file isn't valid JSON)
cat > ~/.config/git/strip-vscode-colors.sh <<'EOF'
#!/bin/sh
jq --indent 4 'del(.["workbench.colorCustomizations"])' 2>/dev/null || cat
EOF
chmod +x ~/.config/git/strip-vscode-colors.sh
# 2. Register the filter
git config --global filter.vscode-settings.clean "$HOME/.config/git/strip-vscode-colors.sh"
# 3. Apply it to .vscode/settings.json in every repo via global gitattributes
echo '.vscode/settings.json filter=vscode-settings' >> ~/.config/git/attributes
git config --global core.attributesfile "$HOME/.config/git/attributes"
Per repo (only if colors were already committed)
A clean filter only runs on files as they're staged, so a settings.json that
already has committed colors needs a one-time re-stage to drop them:
git add --renormalize .vscode/settings.json
git commit -m "Stop tracking IDE chrome colors in settings.json"
--renormalize re-runs the filter over already-tracked files without editing
them, producing a commit that removes the existing color block. After that,
git status stays clean even as the extension keeps rewriting the colors
locally.
Notes
- Prefer a committed
.gitattributes (with the .vscode/settings.json filter=vscode-settings line) if you want teammates covered — git just no-ops
the filter for anyone who hasn't defined it.
- If a
settings.json contains // comments (JSONC), jq can't parse it; the
|| cat fallback passes it through unchanged so a commit never breaks (colors
aren't stripped that time).
Contributing
See CONTRIBUTING.md for build, test, and release instructions.