hue‑shift

reference

The CLI, in full.

Every flag, how they combine, and a builder that writes the command for you.

Command builder

Set the target, colour and parts. The preview and command follow.

1 which projects
2 what colour
3 which parts
shift amount
4 what to do
live preview #6d28d9
your command
npx hue-shift-cli --random

Which projects get coloured

There are three ways to say what to colour. They can be combined.

No argument — the current directory

cd ~/code/my-app
npx hue-shift-cli --random

One project. The folder you are standing in.

--root <dir> — every folder inside

npx hue-shift-cli --root ~/Documents/projects --random --seed 42

Every immediate subfolder becomes a project. Hidden folders (.git, .config) and node_modules are skipped. Results are sorted by name. Scanning is one level deep — nested packages need their own run or an explicit path.

The palette lock

The first --root run writes hue-shift.lock.json in the root, mapping each folder to its colour. Later runs reuse those colours, so adding, removing or renaming a folder never recolours the projects that are already there. New folders get the next generated colour.

{
  "version": 1,
  "projects": {
    "api": "#0f766e",
    "web": "#b45309"
  }
}

Commit the lock if the root is a git repository, so a fresh clone gets the same palette. Delete it to re-roll every colour. --reset and --restore leave it alone.

Positional paths — name them exactly

npx hue-shift-cli ./api ./web ./admin --random

Each path is one project. Use this when the projects are not siblings.

Combining them

npx hue-shift-cli --root ~/code ~/scratch/experiment --random

Targets are de-duplicated by absolute path, so listing a folder twice colours it once. ~ is expanded. A path that is not a directory is a usage error.

Watch out: --color with --root paints every project the same colour. To give each one a different colour, use --random.

Choosing a colour

Random, but never muddy

npx hue-shift-cli --root ~/projects --random --seed 42

Hues are placed on a jittered even grid, at least 22° apart, with saturation 55–78% and lightness 25–38%. That band keeps white or black text readable on the bar. The wheel holds 16 hues at that spacing; past 16 projects the gap shrinks and the tool takes the widest empty arc.

--seed <n> makes the sequence reproducible. Same seed, same folders, same colours — on any machine.

One exact colour

npx hue-shift-cli . --color "#6d28d9"
npx hue-shift-cli . --color 6d28d9
npx hue-shift-cli . --color "#0af"
npx hue-shift-cli . --color teal
InputAccepted
#rrggbbSix digits, with or without #, any case
#rgbShorthand, expanded
#rrggbbaaAlpha is dropped — VS Code bars are opaque
nameOne of the 20 built-in names, case-insensitive

Anything else is a usage error, and nothing is written.

The built-in palette

npx hue-shift-cli --list-colors
npx hue-shift-cli --list-colors --json
NameHexNameHex
amber#b45309magenta#a21caf
angular-red#dd0531mandalorian-blue#1857a4
azure-blue#007fffnode-green#215732
burnt-orange#c2410colive#4d7c0f
crimson#9f1239peacock-blue#0f4c81
cyan#0e7490react-blue#61dafb
green#15803drose#be123c
javascript-yellow#f9e64fslate#334155
svelte-orange#ff3d00teal#0f766e
violet#6d28d9vue-green#42b883

Popular editor palettes

The builder's swatch row can switch between the built-in palette and popular editor palettes: Dracula, Nord, Catppuccin Mocha, Solarized Dark, One Dark, Gruvbox Dark, Tokyo Night and GitHub Dark. These are ordinary hex values, so --color "#bd93f9" works with no extra flag or config.

Which colour wins

When several sources are present, the first match wins:

  1. --color on the command line
  2. color in the project's .hue-shift.json
  3. color in ~/.hue-shift.json
  4. the project's entry in hue-shift.lock.json (--root only)
  5. --random, or random: true in a config file
  6. A stable colour derived from the project's position in the sorted list

--seed only affects colours that are generated. It never recolours a locked project.

Which parts of the window

npx hue-shift-cli . --color teal --parts title,status

Default is title,activity,status. Each part owns a fixed set of keys:

PartKeys written
titletitleBar.activeBackground, titleBar.activeForeground, titleBar.inactiveBackground, titleBar.inactiveForeground
activityactivityBar.background, activityBar.foreground, activityBar.inactiveForeground, activityBar.activeBackground
statusstatusBar.background, statusBar.foreground, statusBar.debuggingBackground, statusBar.noFolderBackground
borderwindow.activeBorder, window.inactiveBorder
tabtab.activeBackground, tab.activeForeground, tab.activeBorderTop
sashsash.hoverBorder
sidebarsideBar.background, sideBar.foreground

Foreground colours are chosen automatically: whichever of black or white has the higher contrast on that background. Inactive variants use the same colour with alpha appended (cc, 99, 88).

An unknown part name is a usage error listing the valid ones.

Shifting parts apart

npx hue-shift-cli . --color teal --parts title,status \
  --adjust title=lighten,status=darken --adjust-pct 8

A flat colour across three bars looks like one big block. --adjust moves individual parts along the lightness axis so they read as related but distinct.

ModeEffect
lightenRaises lightness by --adjust-pct points
darkenLowers lightness by --adjust-pct points
noneLeaves the part at the base colour

--adjust-pct defaults to 6. Values are clamped, so a light colour cannot be lightened into white.

The reported colour stays the base colour; only the written keys shift. --check without --color therefore validates whatever is on disk — it has no base to compare against.

Leaving one key alone

npx hue-shift-cli . --color teal --exclude statusBar.noFolderBackground
npx hue-shift-cli . --color teal \
  --exclude statusBar.noFolderBackground \
  --exclude tab.activeForeground

Repeatable. Excluded keys are never written, and any value already there is preserved. Useful when a theme or another extension owns a particular bar.

Theme and icons

npx hue-shift-cli . --color teal \
  --theme "Default Dark Modern" --icons Seti

Sets workbench.colorTheme and workbench.iconTheme in the same file, so a project can carry its whole visual identity. Both are ordinary settings — --reset leaves them alone, because they are not colour keys.

Use the exact name VS Code shows in the theme picker. A wrong name is written as-is and VS Code falls back to its default.

Modes

Write — the default

npx hue-shift-cli . --color amber

Merges the colour block into .vscode/settings.json, creating the file if needed.

--dry — show the plan, write nothing

npx hue-shift-cli --root ~/projects --random --seed 42 --dry

Every line reports the colour it would use. The filesystem is untouched, including the .vscode directory and the lock.

--check — two different jobs

npx hue-shift-cli --root ~/projects --random --seed 42 --check
npx hue-shift-cli . --color amber --check

With a colour (from --color, a config file, or the root lock): compares every expected key against what is on disk and reports each difference.

Without a colour (no lock and no explicit colour): validates what is there — that a colour exists, and that its foreground reaches 4.5:1 contrast.

In --root mode with a lock, a folder that has no entry reports missing.

Exits 2 on drift, invalid JSON, a project with no colour, or a missing lock entry. Safe in CI.

--reset — remove everything it wrote

npx hue-shift-cli --root ~/projects --reset
npx hue-shift-cli . --reset --dry

Removes every key hue-shift manages, drops the workbench.colorCustomizations object if it becomes empty, and deletes peacock.color only if it still holds a colour hue-shift wrote. Other settings, comments, BOM and line endings survive. Running it twice is safe — the second run reports clean.

--parts and --adjust are ignored by reset: it removes all managed keys, not just the selected parts. It leaves hue-shift.lock.json alone.

--restore — put settings.json back

npx hue-shift-cli --root ~/projects --restore
npx hue-shift-cli . --restore --dry

The first time hue-shift writes a project it saves .vscode/settings.json to .vscode/.hue-shift-backup.json — byte for byte, including comments, BOM and CRLF. --restore writes that copy back and deletes the backup. If the file did not exist before the first apply, restore removes it.

Reset vs restore: --reset removes hue-shift's colour keys and leaves the rest of the file alone. --restore reverts the whole file to its pre-hue-shift state, including values hue-shift overwrote. Backups start at the first apply with this version, so a project coloured by an older release has no backup and reports missing.

The backup sits next to the settings file. If you commit .vscode, add .hue-shift-backup.json to .gitignore — it is a copy of your settings.

--json — for scripts

npx hue-shift-cli --root ~/projects --check --json
{
  "version": "1.2.1",
  "mode": "check",
  "results": [
    {
      "project": "api",
      "dir": "/home/me/projects/api",
      "color": "#0f766e",
      "status": "ok",
      "diffs": [],
      "warnings": []
    }
  ]
}

Statuses: created, inserted, updated, unchanged, dry, ok, drift, missing, invalid, reset, restored, clean.

Config files

Two files, merged. The project wins over the global one. CLI flags win over both.

~/.hue-shift.json — defaults everywhere

{
  "parts": ["title", "activity", "status"],
  "adjust": { "activity": "lighten" },
  "adjustPct": 6,
  "theme": "Default Dark Modern",
  "icons": "Seti"
}

<project>/.hue-shift.json — this project only

{
  "color": "teal",
  "parts": ["title"],
  "exclude": ["statusBar.background"]
}
KeyTypeMeaning
colorstringHex or named colour, pinned for this project
randombooleanUse a generated colour when no color is set
seednumberSeed for the generated colour
partsstring[]Which window parts to colour
adjustobject{ "title": "lighten" }
adjustPctnumberLightness shift, default 6
excludestring[]Colour keys to never write
themestringworkbench.colorTheme
iconsstringworkbench.iconTheme

A malformed config file stops the run with the file name and the JSON error.

Exit codes

CodeMeaning
0Success. Also --check when everything matches.
1Usage error: unknown flag, bad colour, bad part, missing directory.
2A project failed: drift, invalid JSON, unreadable file, or --restore with no backup.
npx hue-shift-cli --root ~/projects --random --seed 42 --check || echo "palette drifted"

Recipes

Colour everything once, reproducibly

npx hue-shift-cli --root ~/Documents/projects --random --seed 42

Preview before touching 75 repos

npx hue-shift-cli --root ~/Documents/projects --random --seed 42 --dry

Give each project a pinned colour that survives a rescan

# in each project
echo '{ "color": "teal" }' > .hue-shift.json
npx hue-shift-cli .

Title bars only, no status bar noise

npx hue-shift-cli --root ~/code --random --parts title

Two-tone window

npx hue-shift-cli . --color "#6d28d9" --parts title,status \
  --adjust title=lighten,status=darken --adjust-pct 8

Monorepo: neutral root, coloured packages

npx hue-shift-cli . --color slate --parts title
npx hue-shift-cli packages/api packages/web packages/admin --random --seed 7

CI guard

npx hue-shift-cli --root . --random --seed 42 --check --json

Undo the last apply

npx hue-shift-cli --root ~/Documents/projects --restore

Remove colours but keep other settings

npx hue-shift-cli --root ~/Documents/projects --reset

Machine-readable report of what changed

npx hue-shift-cli --root ~/code --random --json | jq -r '.results[] | "\(.project) \(.color)"'

All flags

FlagValueWhat it does
--rootdirTreat every subfolder of dir as a project. Repeatable.
--random—Generate a colour per project, spread across the wheel.
--seedintegerMake --random reproducible.
--colorhex or nameUse one exact colour.
--list-colors—Print the built-in palette and exit.
--partslistComma-separated parts. Default title,activity,status.
--adjustpart=modeComma-separated lighten, darken, none.
--adjust-pctnumberLightness shift, default 6.
--excludekeyNever write this colour key. Repeatable.
--themenameAlso set workbench.colorTheme.
--iconsnameAlso set workbench.iconTheme.
--check—Report drift or validate contrast. Writes nothing.
--reset—Remove every managed colour key.
--restore—Put settings.json back as it was before the first apply.
--dry—Print the plan, write nothing.
--json—Machine-readable output.
-h, --help—Usage text.
-v, --version—Print the version.

--check and --reset cannot be combined. --restore cannot be combined with either.

Environment

VariableEffect
HUE_SHIFT_CONFIGPath to the global config file. Default ~/.hue-shift.json. Useful in tests and CI.

No network access, no telemetry, no daemon.