Dynamic Theme Overlay
A time-based theme scheduler for VS Code.
It picks a theme and an optional darkening overlay based on the time of day, then writes the result to your settings.json.
Why
Your eyes change through the day. Your editor theme should too.
Dynamic Theme Overlay switches VS Code themes on a schedule you define, and
additionally darkens the active theme toward an overlay color by a percentage
that ramps smoothly between control points — so the editor fades gently from
crisp midday to dim evening without you touching a setting.
Plain JavaScript. No build step. No dependencies. No bundled runtime.
Features
- Themes on a schedule. Add as many themes as you want, each with a start
time. The active theme is the one with the latest start
<= now. The day
spans 00:00→24:00; a seed entry at 00:00 (your current theme) guarantees
full coverage. Add one at 10:00 → 00:00–10:00 uses the seed, 10:00–24:00
uses the new one.
- Overlays (sub-times). Within a theme's window, add sub-times that darken
the theme toward an overlay color (default black) by a percentage. The base
window (start → first sub-time) has its own overlay % too (
basePercent,
default 0). e.g. base 0%, 14:00 → 30%, 20:00 → 60%.
- Smooth linear transitions. Overlay % is piecewise-linear between control
points (theme start + each sub-time), so it ramps gradually instead of
snapping. After the last sub-time it holds until the next theme.
- Insert a midpoint in between. A
+ between any two states creates a
midpoint sub-time whose time and % are both the average of its neighbors — a
quick way to add intermediate steps.
- Active highlight + validation. The state active at the current time gets
an outline +
ACTIVE badge. Duplicate, overlapping, or out-of-order times
show a ⚠.
- Accurate canvas previews. Each theme renders a full canvas mockup of a VS
Code window for the base state and for every sub-time, using the computed
colors (only the checked overlay keys darken; everything else stays at the
theme's base). Differences invisible in tiny swatches become obvious at full
window scale.
- Modal wheel time picker. Times are clickable text on each card. Clicking
opens a centered picker with two scroll-snap wheels (hours 0–23, minutes
0–59) and Cancel / Confirm.
- Reads any installed theme's colors. Scans
vscode.extensions.all for
contributed themes, reads each JSON (resolving include) to get base colors,
and uses them both for overlay math and for the swatch preview.
- Fixed overlay key set per theme. Choose which workbench colors the overlay
affects (editor, sidebar, activity bar, …). That set is constant for the whole
theme — sub-times only change the percentage.
- Configurable refresh interval (
dynamicTheme.refreshIntervalSeconds,
default 30) — editable from the panel.
- Background scheduler. Runs on activation (
onStartupFinished), so
switching works even with the panel closed.
Quick start
Install from VSIX
# from the releases page, grab the .vsix, then:
code --install-extension vscode-dynamic-theme-overlay-0.0.2.vsix
Or in the UI: Extensions view → ... menu → Install from VSIX…
Use it
- Open the Command Palette (
Ctrl/Cmd+Shift+P).
- Run Dynamic Theme Overlay: Open Settings.
- Add themes on a schedule, tune overlay percentages, pick which colors the
overlay affects.
That's it. The scheduler runs in the background and rewrites
workbench.colorTheme + workbench.colorCustomizations in your settings.json
whenever the computed result changes.
How it works
package.json contributes the command, the refresh-interval setting, and two
bundled themes (Dynamic Light / Dynamic Dark).
- The schedule is stored in extension
globalState (key dynamicTheme.schedule).
src/themeIndex.js scans every installed extension's contributes.themes,
reads each theme JSON (resolving include) to get its base workbench colors.
src/scheduler.js evaluates the schedule for the current minute and computes
the workbench.colorTheme + workbench.colorCustomizations to apply.
src/extension.js ticks every refreshIntervalSeconds, writes settings only
when the computed result changes (de-duped by signature), and drives the panel.
src/webview.js builds the panel HTML; media/webview.{css,js} are the panel UI.
- Communication is
postMessage; nothing is inlined (nonce-gated CSP).
For developers
The live-reload loop
VS Code extensions do not hot-reload. The fast loop (instant for plain JS,
since there's nothing to compile):
- Press F5 → an Extension Development Host window opens.
- Make a change in
src/extension.js.
- Press the ↻ restart button on the floating debug toolbar —
Ctrl+Shift+F5 (Win/Linux) / Cmd+Shift+F5 (Mac). The host reloads with
your new code.
- Repeat 2–3 for every edit. Keep the dev-host window open across cycles.
Tip: the floating debug toolbar auto-hides and reappears when the dev-host
window is focused. If it's gone, click the dev-host window first.
Install locally (persistent, this machine only)
Drop the folder into VS Code's extensions dir under the
<publisher>.<name>-<version> naming convention, then reload:
cp -r /path/to/VSCode-Dynamic-Theme-Overlay \
~/.vscode/extensions/Rafatjah.vscode-dynamic-theme-overlay-0.0.2
Then fully quit and reopen VS Code (or run Developer: Reload Window).
- Update after edits: re-run the
cp, then reload the window.
- Uninstall:
rm -rf ~/.vscode/extensions/Rafatjah.vscode-dynamic-theme-overlay-0.0.2, then reload.
Use this only when you want the extension in your normal VS Code. For active
coding, prefer the F5 + restart loop above — it always runs the latest code.
Build a VSIX
A .vsix is the distributable package (shareable, installable anywhere,
publishable to the marketplace).
# one-time: install the packaging tool
npm install -g @vscode/vsce
# build the package
cd /path/to/VSCode-Dynamic-Theme-Overlay
vsce package # -> vscode-dynamic-theme-overlay-0.0.2.vsix
Other useful vsce commands:
vsce ls # preview what gets packaged (respects .vscodeignore)
vsce show # inspect the packaged metadata
vsce publish # publish to the Marketplace (needs a PAT + publisher)
If vsce package complains about a missing repository field, add a
"repository" entry to package.json or pass --allow-missing-repository.
.vscodeignore keeps the VSIX small by excluding dev-only files.
Project layout
package.json manifest, command, settings, themes
src/extension.js activation, ticking, panel, persistence
src/themeIndex.js discovers + reads installed theme colors
src/scheduler.js time evaluation + overlay/blend math
src/webview.js builds the webview HTML (CSP + nonces)
media/webview.css panel styles
media/webview.js panel client logic
themes/dynamic-light-color-theme.json bundled light palette
themes/dynamic-dark-color-theme.json bundled dark palette
.vscode/launch.json F5 = Extension Development Host
.vscodeignore excludes dev files from the VSIX
Roadmap
The activation model is open: schedule.mode is "time" today. Planned as
additional sources:
- Brightness-based activation
- Ambient light sensor
- Webcam-based scene detection
License
Source-Available Non-Commercial License © 2026 i3130002.
Personal, non-commercial use only. Modifications may not be redistributed. See
LICENSE for full terms.