Explorer gives you no way to tell folders apart at a glance. Every one of them is the same manila rectangle, so on a drive with thirty project directories I was reading filenames instead of recognising shapes. I wanted right-click → pick a colour, applied instantly, with no installer, no admin prompt, and nothing left running in the background.
That is what this does. It generates a tinted .ico, points the folder's
desktop.ini at it, and tells the shell to repaint.
desk-clock shares this workspace because it came out of the same Win32
experiments and reuses the %APPDATA%\folder-color config directory. It is a
transparent desktop clock widget — unrelated in purpose, same toolbox.
cargo build --release --workspaceBoth binaries land in target\release\. --workspace matters here: the root of
this workspace is itself a package, so a plain cargo build builds only
folder-color and skips the clock.
Then install the right-click menu once:
folder-color.exe install-menuThat writes the menu keys and pre-builds all 17 preset icons, so the first click of any colour is already a cache hit. You do not need the console again.
- Right-click the folder.
- On Windows 11, click "Show more options" at the bottom of the menu. This step is not optional — see below.
- Hover Colorize Folder.
- Click a colour.
The icon changes immediately. No F5, no sign-out, no Explorer restart.
Windows 11 splits the context menu in two. The short menu you get first is
reserved for entries from packaged apps that implement IExplorerCommand.
folder-color registers itself the classic way, as a shell verb under
HKCU\Software\Classes\Directory\shell, and Windows 11 does not surface those
in the short menu at all — they are all pushed into the legacy menu behind
Show more options. Nothing is broken if the entry is not in the first menu;
you are simply looking at the wrong one of the two.
Two faster routes to the same legacy menu:
- Shift + right-click the folder — opens it directly, skipping a click.
- Shift + F10 with the folder selected, if you prefer the keyboard.
On Windows 10 there is only one context menu, so Colorize Folder appears in it directly and none of this applies.
The colours are listed alphabetically — Aqua, Black, Blue, Fuchsia, Gray, Green,
Lime, Maroon, Navy, Olive, Orange, Pink, Purple, Red, Teal, White, Yellow — not
in the order they appear in color::PRESETS. The flyout is built from child
keys under ...\ColorizeFolder\shell, and Windows sorts those by key name.
Explicit ordering is possible, but only by listing the verbs in the
SubCommands value and defining each one in the CommandStore, which lives in
HKLM and therefore needs admin — so I left it alphabetical rather than give up
the no-elevation install.
To take the menu back out:
folder-color.exe uninstall-menufolder-color.exe colorize "C:\Users\you\Projects" --color blue
folder-color.exe colorize "C:\Users\you\Projects" --color "#3498db"
# Undo it
folder-color.exe reset "C:\Users\you\Projects"
# Drop every generated icon from %LOCALAPPDATA%\folder-color\icons
folder-color.exe clear-cache--color takes a hex value or any of the 17 preset names above. Both binaries
are built as GUI-subsystem executables with no console attached, so errors
arrive as a message box rather than on stderr, and the exit code is 0 either
way — worth knowing before scripting around them.
The clock is just desk-clock.exe. Drag it anywhere — the position is saved on
release. Right-click it for a menu with a "Start with Windows" toggle and Exit.
colorize decodes the grayscale folder silhouette embedded in the binary from
assets/folder_base.png, multiplies each pixel by the target colour using the
source brightness as a shading factor, and packs 16/32/48/256px frames into one
.ico. That file goes into a content-addressed cache keyed on the base image
bytes, an algorithm version, and the RGB triple — so the same colour always
resolves to the same path and is generated exactly once. Then it writes a
desktop.ini with an absolute IconResource, sets the attribute bits Explorer
requires, and fires SHChangeNotify so the icon changes immediately rather than
on the next F5.
The clock renders text into a 32bpp DIB section, converts it to premultiplied
BGRA, and hands the whole bitmap to UpdateLayeredWindow. It wakes once per
minute, aligned to the minute boundary, and does nothing in between.
Icons live in one shared cache, not inside each folder. IconResource
accepts an absolute path, so I keep every generated .ico in
%LOCALAPPDATA%\folder-color\icons instead of dropping a hidden file into every
folder I colour. The trade-off is real: copy a coloured folder to another machine,
or clear the cache, and desktop.ini points at nothing — Explorer silently falls
back to the default icon. I decided a lost colour beats littering hidden files
across the disk. If an earlier version left an icon inside a folder, colorize
and reset still clean it up.
Content-addressed filenames. Because the bytes at a given cache path can never change, Explorer's own icon cache stops being a problem — there is no such thing as a stale entry, and switching colours changes the path. Getting this wrong is why custom folder icons have a reputation for needing a reboot.
SHCNE_UPDATEDIR on the parent, never SHCNE_ASSOCCHANGED. The icon you are
looking at is drawn by the parent's view, so notifying the folder itself is not
enough. SHCNE_ASSOCCHANGED also works, and forces a synchronous system-wide
association rebuild that stalls Explorer for minutes. It is the obvious-looking
call and the wrong one.
Attributes are read-modify-write. SetFileAttributesW replaces the entire
mask rather than OR-ing into it, so setting READONLY naively will quietly clear
HIDDEN, SYSTEM and ARCHIVE on someone's folder. Also worth knowing: the READONLY
bit on a folder means "read my desktop.ini", not "lock the contents" — files
inside stay writable.
Everything is HKCU. Context menu keys and the clock's autostart entry both
go under HKEY_CURRENT_USER, so nothing needs elevation and uninstalling is a
key delete. Task Scheduler would buy start delays and pre-logon runs; a clock
needs neither, and registering a task can itself require elevation.
No serde, no chrono. The clock persists two integers and reads the wall
clock. That is a six-line k=v parser and GetLocalTime(), not fifteen crates
and a proc-macro. Same reasoning trimmed image down to the png feature — its
defaults drag in AVIF, EXR, TIFF, WebP and rayon to decode one embedded PNG —
and dropped clap's colour and suggestion features, which do nothing in a
binary with no console.
The clock's transparency is a GDI trick. UpdateLayeredWindow wants
premultiplied alpha, but DrawTextW predates alpha and never writes that byte,
so the obvious implementation produces a perfectly invisible clock. Drawing white
text on a zeroed buffer with ANTIALIASED_QUALITY makes the grey GDI writes
equal to the glyph's coverage at that pixel, which is exactly the alpha mask
needed to rebuild the pixels properly. It has to be ANTIALIASED_QUALITY and not
ClearType — subpixel rendering writes different coverage per channel, so there
is no single value to read back and the edges come out colour-fringed.
- On Windows 11 the menu entry lives behind Show more options, because a
plain registry verb cannot appear in the short context menu. Getting it into
the short menu means shipping an MSIX/sparse package with an
IExplorerCommandhandler, which is a lot of machinery for one verb. - Enabling the clock's autostart records whatever path the
.exehad at that moment. If that istarget\release\, acargo cleanbreaks it silently. Copy the binary somewhere stable first. - No tests. The Win32 surface is almost entirely side effects against the live shell and registry, and I have not decided what a worthwhile test double looks like here.
- Windows only, by construction.
- Custom colour entry in the flyout instead of presets only
- Remember the previous icon so
resetrestores it rather than clearing - Cap the icon cache size
- Colour swatch icons next to each entry in the flyout, instead of bare labels
- Move the clock's hardcoded size, font and colour constants into
clock.cfg - Sparse-package the shell verb so it shows up in the Windows 11 short menu
