# Introduction
> What Umbra is, how it works in one minute, and where to go next in these docs.
Umbra pins small, sharp, true-black widgets to the Windows desktop. They sit under every window, never steal focus, stay visible with Win+D and start with Windows.
A widget is a folder with a `widget.json` and a web page (HTML, CSS and JavaScript). Umbra's host app, written in C# on .NET 10, opens each enabled widget in its own borderless WebView2 window and pins it to the desktop. The host knows nothing about any particular widget, so anyone can build one.
## Why it feels different
- **It stays where it belongs.** Widget windows are owned by the desktop shell and kept at the bottom of the window stack, so your apps always cover them.
- **It's sharp.** Windows are opaque true black with corners and a hairline border drawn by Windows itself, so text keeps full ClearType quality. On an OLED screen the black pixels are simply off, and each card seems to float on your wallpaper.
- **It's safe.** A widget can only reach the HTTPS hosts it declares. The host blocks everything else. An update that asks for new access waits for your OK, and a widget can start a local program only if it declared that exact command and you approved it.
- **It's private.** No account, no telemetry. Settings, widget data and logs stay in `%APPDATA%\Umbra`.
- **It's scriptable.** The `umbractl` command line and a built-in [MCP server](/umbra/docs/automate/mcp/) let scripts and AI agents arrange widgets, take screenshots and write new widgets.
## Where to go next
| You want to… | Read |
|---|---|
| Install Umbra and add your first widgets | [Install](/umbra/docs/get-started/install/), then [Quickstart](/umbra/docs/get-started/quickstart/) |
| Arrange, theme and tune your desktop | [Using Umbra](/umbra/docs/using/settings/) |
| Build a widget | [Your first widget](/umbra/docs/widgets/first-widget/) and the [SDK reference](/umbra/docs/widgets/sdk-reference/) |
| Script Umbra or connect an AI agent | [Automate](/umbra/docs/automate/overview/) |
| Work on the app itself | [Internals](/umbra/docs/internals/architecture/) |
:::tip[For AI agents]
Every page has a **View as Markdown** link, and [`llms.txt`](/umbra/llms.txt) lists them all. [`llms-full.txt`](/umbra/llms-full.txt) is the whole manual in one file.
:::
## Requirements
Windows 10 version 1809 or later, or Windows 11. Umbra uses the WebView2 runtime, which ships with current Windows; the installer tells you if it's missing. A Linux version is in progress ([#172](https://github.com/AmineChr54/umbra/issues/172)).
Umbra is free and open source under the MIT license.
---
# Install
> Install Umbra with the per-user installer or as a portable copy, build it from source, and uninstall it.
## Installer (recommended)
1. Download **`UmbraSetup.exe`** from the [latest release](https://github.com/AmineChr54/umbra/releases/latest).
2. Run it. It installs for your user only, so there's no admin prompt, and asks whether Umbra should start with Windows.
3. Umbra starts in the **tray** (the notification area next to the clock). Click the tray icon, or open Umbra from the Start menu, to open **Settings**.
4. Go to **Browse** and install your first widgets.
The installer puts the app in `%LOCALAPPDATA%\Programs\Umbra` and adds `umbractl` to your `PATH`. Your data lives in `%APPDATA%\Umbra`:
| Path | What's in it |
|---|---|
| `settings.json` | All settings: general options, each widget's options, position and size |
| `widgets\` | Widgets you installed from Browse or wrote with an agent |
| `data\.json` | Data each widget saved with `umbra.store` (1 MB cap per widget) |
| `themes\` | Installed themes |
| `trash\` | Widgets you removed in Settings, kept 7 days for **Undo** |
| `umbra.log` | The log (Settings → Data & privacy → Open log) |
Umbra checks GitHub once a day for a new version and downloads it in the background. A dot on the tray icon means an update is ready; see [Updates](/umbra/docs/using/updates/).
:::note[SmartScreen]
If Windows shows "Windows protected your PC", click **More info** → **Run anyway**. New releases build up SmartScreen reputation over time.
:::
## Portable copy
Download `Umbra--portable.zip` from the [releases page](https://github.com/AmineChr54/umbra/releases), unzip it anywhere and run `Umbra.exe`.
The `portable.txt` file next to `Umbra.exe` keeps all data (settings, widgets, logs and the WebView2 cache) in a `data` folder beside the exe. Portable copies:
- don't start with Windows and don't update themselves (Settings → About shows a download link instead),
- run alongside an installed copy without sharing anything,
- work with the `umbractl.exe` next to them, which finds the same copy.
To make any folder portable, create an empty `portable.txt` next to `Umbra.exe`. See [Portable mode](/umbra/docs/internals/portable-mode/) for how it works.
## winget
A winget package (`AmineChr54.Umbra`) is prepared with every release but not yet published to the winget repository. Until then, use the installer.
## Build from source
You need the .NET 10 SDK, Node.js and Inno Setup 6.
```powershell
git clone https://github.com/AmineChr54/umbra
cd umbra
powershell -File build.ps1 # both exes + installer -> dist/UmbraSetup-.exe
dotnet run --project src/Umbra # or run from source (quit the installed Umbra first)
```
See [Dev setup and tests](/umbra/docs/internals/dev-setup/) for the full workflow.
## Uninstall
Open **Settings → Apps → Installed apps** in Windows, find **Umbra** and choose **Uninstall**. Your data in `%APPDATA%\Umbra` stays, so a reinstall picks up where you left off. Delete that folder to remove everything. For a portable copy, quit Umbra from the tray and delete its folder.
---
# Quickstart
> From a fresh install to an arranged desktop in five minutes, plus your first command-line and widget experiments.
This walks you from a fresh [install](/umbra/docs/get-started/install/) to a desktop you've arranged yourself.
## 1. Add widgets
Click the Umbra icon in the tray (the notification area next to the clock), or open Umbra from the Start menu, to open **Settings**. Go to **Browse** and click **Install** on a few widgets: Clock, Weather and To Do are a good start. Each card lists exactly what the widget can reach (for example `api.open-meteo.com`, or **No network access**), so you know what you're installing.
New widgets appear on your desktop at once, each in its default position.
## 2. Arrange them
Open the tray menu and choose **Edit mode** (or turn it on from **My widgets**). Every unlocked widget gets an outline and a corner handle:
- **Drag** a widget to move it. Guide lines show when it lines up with an edge, a center or a neighbour. Hold Shift while dragging to skip snapping.
- **Drag the corner** (or hold Ctrl and scroll) to resize. Widgets zoom like a web page, so text stays sharp.
- **Click a widget** to select it, then nudge it with the arrow keys: 1 px, or 10 px with Shift.
A small **Editing widgets · Snap · Done** pill appears at the top of each monitor that has widgets. Click **Done** (or press Esc on a clicked widget) to leave edit mode. See [Arranging widgets](/umbra/docs/using/arranging-widgets/) for everything edit mode can do.
## 3. Make them yours
In **My widgets**, each widget has its own card: change its options (a city, a currency, a time format), its size, its opacity, and when it should be visible. Under **General** you can set the accent color, corner radius and fonts, and **Themes** switches the whole look in one click. All changes apply live.
## 4. Peek and show the desktop
Press Win+D: your widgets stay where they are. To bring them above your apps for a few seconds without moving anything, use **Peek**. Assign hotkeys for it, for edit mode, for refresh and for show/hide in **Settings → Hotkeys** ([details](/umbra/docs/using/hotkeys-peek-layouts/)).
## 5. Try the command line
The installer puts `umbractl` on your `PATH`. Every command prints JSON, and starts Umbra in the background if it isn't running:
```powershell
umbractl list # your widgets, options and positions
umbractl install sp500 # install from the catalog
umbractl set sp500 symbol ^IXIC # follow the Nasdaq instead; applies instantly
umbractl configure sp500 --scale 1.5 # 150 % size
umbractl capture sp500 shot.png # a PNG of just that widget
```
The [command reference](/umbra/docs/automate/cli/) lists every command.
## 6. Build your own
```powershell
umbractl new my-widget
```
This creates a working widget in `%APPDATA%\Umbra\widgets\my-widget` and shows it on your desktop. Edit its files, run `umbractl reload`, and follow [Your first widget](/umbra/docs/widgets/first-widget/).
:::tip
If something looks wrong, **Settings → About → Copy diagnostics** gives you a block you can paste into a bug report, and **safe mode** turns community widgets off without deleting anything. See [Troubleshooting](/umbra/docs/using/troubleshooting/).
:::
---
# FAQ
> Short answers about how Umbra works, what it can access, and how it compares to other desktop widget tools.
## Does Umbra work with Win+D?
Yes. Each widget window is owned by the desktop shell and kept at the bottom of the window stack, so Win+D leaves your widgets visible and every app covers them. See [Desktop pinning](/umbra/docs/internals/desktop-pinning/).
## Will a widget steal focus while I type?
No. Widget windows never activate themselves. A widget gets the keyboard only right after you press the mouse on it (for example to type in a text field). A widget can't pull focus on its own.
## Is it safe to install community widgets?
Each widget runs in a sandbox. It can load only Umbra's own virtual hosts and the HTTPS hosts it declares in its `widget.json`; every other request is blocked by the app. An update that asks for new access (more hosts, notifications, media, commands) waits for your approval, and a widget can start a local program only if it declared that exact command and you approved it. Every catalog widget is also reviewed in a pull request. Details: [Sandbox and permissions](/umbra/docs/widgets/sandbox/) and the [security model](/umbra/docs/internals/security/).
## Does Umbra collect data?
No telemetry and no account. Settings, widget data and logs stay in `%APPDATA%\Umbra` on your PC. The only network traffic Umbra itself makes is a daily check for a new release on GitHub, the widget catalog when you open **Browse**, and the requests widgets make to hosts they declare. **Settings → Data & privacy** shows what each widget can reach and store.
## Why are the windows opaque black, not transparent?
On Windows, translucent layered windows lose ClearType, so text gets blurrier. Umbra's windows are opaque true black with DWM-drawn rounded corners and a hairline border, which keeps full text quality. On an OLED display black pixels are off, so each card still looks like it floats on your wallpaper.
## How is this different from Rainmeter?
Rainmeter skins are described in its own format and drawn on translucent windows. Umbra widgets are ordinary web pages (HTML, CSS, JavaScript) in WebView2, so anything you can build for the web works, with a small SDK for refresh, options, saved data, notifications and media. The original Rainmeter skin of this project is still in [`extras/rainmeter`](https://github.com/AmineChr54/umbra/tree/main/extras/rainmeter).
## Does it use a lot of memory or battery?
Each widget is a WebView2 window. Umbra pauses widgets while the PC is locked or the display is off, stretches refresh intervals 4x on Windows Energy Saver (you can turn that off), and can hide widgets during fullscreen apps and games. Keep the number of widgets reasonable on low-end machines.
## Can I run two copies of one widget?
Yes: **My widgets → Add another copy**. Each copy has its own options, position, size and saved data, so you can show the S&P 500 and the Nasdaq side by side. See [Copies and tab groups](/umbra/docs/using/copies-and-tab-groups/).
## Where is my data?
In `%APPDATA%\Umbra`: `settings.json`, `widgets\` (installed widgets), `data\.json` (what each widget saved), `themes\`, `trash\` and `umbra.log`. Portable copies keep all of it in a `data` folder next to `Umbra.exe`. Use **Data & privacy → Export backup** (or `umbractl backup `) to save it.
## How do I update Umbra and its widgets?
Umbra checks GitHub daily, downloads updates in the background and shows a dot on the tray icon when one is ready; install it from the tray menu or **Settings → About**. Widget updates appear on **Browse**. See [Updates](/umbra/docs/using/updates/).
## Does it run on macOS or Linux?
Not yet. Umbra needs Windows 10 version 1809 or later, or Windows 11. A Linux version is in progress, see [Linux port](/umbra/docs/internals/linux-port/).
## Can an AI agent build widgets for me?
Yes. Run `claude mcp add umbra -- umbractl mcp` (or point any MCP client at `umbractl mcp`) and ask for the widget you want. The agent reads the authoring guide, writes the widget, takes a screenshot of just that widget and fixes what it sees. See [MCP server](/umbra/docs/automate/mcp/).
## I found a bug. What do I do?
Open **Settings → About → Copy diagnostics**, then use the issue link on the same page (it pre-fills your version) and paste the diagnostics. For security problems, read [SECURITY.md](https://github.com/AmineChr54/umbra/blob/main/SECURITY.md) instead.
---
# Settings tour
> A page-by-page tour of Umbra's Settings window, with keyboard shortcuts and where each setting is stored.
Open Settings from the tray icon, from the Start menu, or by launching Umbra a second time (a second launch opens Settings in the running copy). The window reopens where you left it: size, monitor, maximized state and last page.
## Pages
| Page | What it does |
|---|---|
| **General** | Start with Windows, refresh interval, animations, appearance (corner radius, border, accent color or the Windows accent, interface font and size, light text, reduce transparency) and advanced options (log level, developer mode, GPU, startup delay, proxy). |
| **My widgets** | Turn each widget on or off, edit its options, size and opacity, lock it, give it its own refresh interval, schedule when it shows, add another copy or reset its position. Also where you start edit mode and approve or revoke widget commands. |
| **Layouts** | Save the arrangement of your widgets under a name, then apply, rename or delete it. Layouts can switch automatically when you dock or undock. |
| **Browse** | The community catalog: install, update or remove widgets in one click. Each card shows the hosts, notifications, media and commands a widget asks for. |
| **Themes** | Install community themes and switch between them live. |
| **Hotkeys** | Global shortcuts for edit mode, refresh, show/hide, peek and Settings. |
| **Data & privacy** | What each widget can reach and store, recent blocked requests, backup and restore, reset, and safe mode. |
| **About** | Version, update status (with release notes once after an update), source link, **Copy diagnostics** for bug reports and pre-filled issue links. |
## Keyboard
- Esc closes Settings.
- Ctrl+F or / jumps to the Browse search.
- Ctrl+1 to Ctrl+7 switch pages.
- The arrow keys move through the sidebar and the refresh interval.
Switches and buttons have names for screen readers.
## Changes apply live
There is no Save button. Changing a setting updates widgets immediately, and `settings.json` in your data folder is written for you. Settings that need a restart say so: the proxy and hardware acceleration.
## The tray menu
The tray icon's tooltip shows the widget count and whether edit mode or safe mode is on. A dot on the icon means an Umbra update is ready. The menu opens Settings, toggles edit mode, opens the data folder, restarts Umbra, and offers **Undo** for a widget copy you just removed.
## The same settings from a script
Everything in Settings is also available from [`umbractl`](/umbra/docs/automate/cli/) and the [MCP server](/umbra/docs/automate/mcp/), for example `umbractl general --refresh 120` and `umbractl configure sp500 --scale 1.5`.
---
# Arranging widgets
> Edit mode, snapping, resizing and zooming, locking, and moving widgets between monitors.
## Edit mode
Turn edit mode on from the tray menu, from **My widgets**, with a [hotkey](/umbra/docs/using/hotkeys-peek-layouts/), or with `umbractl edit-mode on`. Unlocked widgets get an outline and a corner handle, and Umbra covers them with an overlay so presses move them instead of clicking inside the page.
| Action | How |
|---|---|
| Move | Drag the widget |
| Resize | Drag the right edge, bottom edge or corner handle |
| Zoom | Hold Ctrl and scroll over the widget |
| Select | Click it (stronger outline); it also takes the keyboard |
| Nudge | Arrow keys: 1 px, or 10 px (one grid step when snapping is on) with Shift |
| Snap | Hold Shift while dragging (default); or set `--snap-mode always` or General > Advanced > Snapping so widgets always snap and Shift skips it |
| Leave | **Done** on the pill, or Esc on a clicked widget |
A small **Editing widgets · Snap · Done** pill is drawn at the top of each monitor that has widgets. It has the snap switch and the **Done** button. Edit mode is off again after a restart.
## Size and zoom
Each widget has a design size from its `widget.json`. You can resize freely from **50 %** to **300 %** of it on each side. Widgets zoom like a web page, so text and charts stay sharp. A widget made only wider or taller keeps its zoom and gets more room; one made bigger on both sides is drawn larger. Set the size exactly in **My widgets**, or with `umbractl configure --scale 1.5`.
## Snapping
While you drag in edit mode, widgets snap to a grid, to the edges and centers of other widgets, and to a gap you choose, and guide lines show what you're aligning to. Configure it in **General** or from the command line:
```powershell
umbractl general --snap-grid 20 # grid in px (0 = off)
umbractl general --snap-edges on # snap to other widgets' edges and centers
umbractl general --snap-gap 12 # px kept between neighbours (0 = touch)
umbractl general --snap off # master switch (also on the edit-mode pill)
umbractl general --snap-mode always # shift (default) = snap only while Shift is held; always = Shift skips snapping
```
## Locking
A locked widget doesn't move, resize or zoom, even in edit mode. Lock widgets once you're happy with the layout: **My widgets → Lock**, the right-click menu, or `umbractl lock `.
## Positions and monitors
Positions are screen coordinates in physical pixels. A widget remembers which monitor it was on, keeps its offset, and survives monitor changes. Move one to another monitor with `umbractl configure --monitor 2` (a number from `umbractl status`, or `primary`). **Reset position** puts a widget back at its default.
## The right-click menu
Right-click a widget for **Refresh, Options** (opens Settings on its card), **Lock, Edit mode, Hide** and **Add another copy**. Extra copies can be removed from the menu, with **Undo** in the tray menu. A widget that handles right-click itself keeps its own menu; Shift+right-click always opens Umbra's.
## Save the arrangement
Once it looks right, [save it as a layout](/umbra/docs/using/hotkeys-peek-layouts/#layouts) so you can bring it back after a dock or undock.
---
# Hotkeys, peek and layouts
> Global hotkeys, the peek gesture, and named layouts that follow your monitor setup.
## Hotkeys
Global hotkeys work from any app. None are set by default. Assign them in **Settings → Hotkeys** or from the command line.
| Action | What it does |
|---|---|
| `edit-mode` | Turns [edit mode](/umbra/docs/using/arranging-widgets/) on or off |
| `refresh-all` | Asks every widget to fetch fresh data now |
| `toggle-widgets` | Shows or hides all widgets |
| `peek` | Raises widgets above other windows for a few seconds |
| `open-settings` | Opens Settings |
```powershell
umbractl hotkeys # read the current hotkeys and their status
umbractl hotkeys edit-mode Ctrl+Alt+E # set one
umbractl hotkeys edit-mode off # clear one
umbractl hotkeys reset # clear all
```
Each hotkey reports a status: `active`, `off`, or `failed` with the reason, for example when another app already uses that combination.
## Peek
Peek raises your widgets above every other window for a few seconds, then puts them back at the bottom, without moving or focusing anything. It's the quick way to glance at your widgets without closing your apps. The duration is 5 seconds by default; change it with `umbractl general --peek-seconds 1-60`, or run it directly:
```powershell
umbractl peek # default duration
umbractl peek 10 # ten seconds
```
Peek does nothing while widgets are hidden.
## Layouts
A layout is a saved arrangement: the position, size and enabled state of every widget. Options and saved data are never touched by a layout.
```powershell
umbractl layouts # list
umbractl layouts save Work # store the current arrangement
umbractl layouts apply Work # switch to it, live
umbractl layouts rename Work Docked
umbractl layouts delete Docked
```
Saving pins the layout to the monitor setup you saved it on. An opt-in setting makes Umbra apply the matching layout automatically when you dock or undock. Layouts are managed on the **Layouts** page of Settings, where you can also rename and delete them.
## Hide during fullscreen
**General → Hide widgets during fullscreen apps and games** (`umbractl general --hide-fullscreen on`) keeps widgets out of the way while a fullscreen window is in the foreground.
---
# Copies and tab groups
> Run a widget more than once with separate options, and stack several widgets in one spot with tab groups.
## Copies
**My widgets → Add another copy** (or `umbractl add-instance `) runs the same widget a second time. A copy has an id like `sp500#2`, and that id works anywhere a widget id does.
Each copy is a separate window with its own:
- options (follow the S&P 500 in one and the Nasdaq in the other),
- enabled and locked state, position and size,
- saved data (`umbra.store`).
```powershell
umbractl add-instance sp500 # creates sp500#2
umbractl set sp500#2 symbol ^IXIC
umbractl remove-instance sp500#2 # removes the copy and its data
```
The first copy can't be removed, only disabled. Removing an extra copy from the right-click menu offers **Undo** in the tray menu for a short while.
## Tab groups
A tab group lets several widgets share one spot on the screen with only one visible at a time. A hover tab strip switches between them, and the visible tab takes over the group's shared position and size.
```powershell
umbractl groups # list groups
umbractl groups create todo "Work" # a new group, starting from the widget copy "todo"
umbractl groups join clock # add a widget copy to a group
umbractl groups activate clock # show one
umbractl groups next # also: previous
umbractl groups cycle 30 # rotate every 30 s (5-3600; off to stop)
umbractl groups rename "Focus"
umbractl groups icon clock rocket # tab icon: a bundled name, or `default`
umbractl groups reorder clock 0
umbractl groups leave clock # remove a widget from its group
umbractl groups delete # ungroup; the widgets stay
```
`` is the group id that `umbractl groups` prints.
Tab icons come from the widget's own `icon.png` (64×64, light grey on transparent) or from the bundled icon set, which you pick in Settings or with `umbractl groups icon`. Your choice wins over the widget's icon.
---
# Visibility and refresh rules
> Control when each widget is shown, how opaque it is, and how often it updates, including what Umbra does while the PC is locked or on battery saver.
Everything here is per widget (and per copy) unless noted, in **Settings → My widgets**, from the right-click menu, or with `umbractl configure`.
## When a widget is shown
| Setting | What it does | `umbractl configure` flag |
|---|---|---|
| Enabled | Show or hide the widget | `--enabled on\|off` (or `enable`/`disable `) |
| Start hidden | Opens hidden until you show it | `--start-hidden on\|off` |
| Show only between | A daily time range | `--show-from 08:00 --show-to 18:00` (`--show-from always` clears it) |
| Show only on AC power | Hide on battery | `--show-on-ac on` |
| Opacity | Dim a widget, `0.2` to `1` | `--opacity 0.8` (or `opaque`) |
```powershell
umbractl configure clock --show-from 08:00 --show-to 18:00 --show-on-ac on
umbractl configure clock --opacity 0.6
```
**All widgets at once:** the `toggle-widgets` [hotkey](/umbra/docs/using/hotkeys-peek-layouts/) shows or hides every widget, and **General → Hide widgets during fullscreen apps and games** (`umbractl general --hide-fullscreen on`) hides them while a fullscreen app is in the foreground.
## How often a widget updates
Widgets that fetch data refresh on an interval. The default is set in **General** (30 to 600 seconds), and each widget can have its own:
```powershell
umbractl general --refresh 120 # default for all widgets
umbractl configure sp500 --refresh 300 # this widget only (or `default`)
umbractl refresh # fetch fresh data now, for all (or one id)
```
Umbra also refreshes widgets after the PC resumes from sleep, when the network comes back and after a long lock, at most once every 10 seconds.
## Automatic slowing and pausing
- **Locked or display off:** widgets are paused. They get one refresh when the PC is unlocked or the display is back on.
- **Windows Energy Saver:** refresh intervals are stretched 4x while it's on. Turn this off with `umbractl general --energy-saver off`.
- **Animations:** off in **General**, or follow the Windows reduced-motion preference. Calm animation speed doubles animation durations.
Widget authors read these from `umbra.settings` (`paused`, `energySaver`, `refreshSeconds`), see the [JavaScript API](/umbra/docs/widgets/javascript-api/).
---
# Appearance and themes
> Change corner radius, accent color, fonts, borders and motion for every widget, and switch community themes live.
Umbra styles widgets through design tokens, so one setting restyles every widget that follows them. Changes apply live.
## Appearance settings
In **Settings → Appearance → Customize colors, text and size**:
| Setting | Effect |
|---|---|
| **Corner radius** | `default`, `sharp` or `round`. Overrides the theme's `--radius-s/m/l`. |
| **Accent color** | A color of your choice, or **Match Windows accent**, which follows the system accent live (lightened if it is too dark for black). Empty uses the theme's accent. |
| **Interface font and size** | Sets `--font` and `--font-scale`. Widgets that size text in `em`/`rem` follow the scale. |
| **Light text** | Brighter `--text*` colors. |
| **Window border** | On or off, and its color. |
| **Reduce transparency** | Solid `--line*` and `--accent-soft`, opaque windows. |
| **Animation speed** | `normal`, `calm` (animation durations doubled) or `off`. Windows' reduced-motion preference is respected. |
| **Size of new widgets** | The starting scale for new widgets, 0.5 to 3. |
The same settings from a terminal:
```powershell
umbractl general --corner-radius round --animation-speed calm
umbractl set-general --accent "#ff7a59" --light-text on --ui-font Consolas --font-scale 1.1 --border off --reduce-transparency on
```
## Themes
A theme restyles every widget at once: surfaces, lines, text, accent, up/down colors and corner radii. Switch in **Settings → Appearance**, or:
```powershell
umbractl themes # installed themes and the community catalog
umbractl install-theme ember # install from the catalog
umbractl theme ember # switch, live (`umbractl theme default` for Umbra Black)
umbractl remove-theme ember
```
"Umbra Black" is the built-in default. The catalog ships Ember, Glacier and Mono. Themes are **data only**: a list of named color and radius tokens with strict value checks, never code, so a theme can't load anything. Your own appearance settings (accent, corner radius, font) are applied on top of the theme.
Widgets that set `"themeable": false` in their manifest keep their own look. To make a theme, see [Build a theme](/umbra/docs/themes/build-a-theme/).
## Windows contrast themes
When Windows has a contrast theme on, Umbra maps the tokens to system colors and ignores themes and accents, so widgets stay readable. Widget authors can read about it in the [styling guide](/umbra/docs/widgets/styling/).
---
# Data, privacy and backups
> What Umbra stores and sends, the Data and privacy page, backup and restore, the trash, and safe mode.
## What Umbra stores
Everything lives in `%APPDATA%\Umbra` (or the `data` folder next to `Umbra.exe` in a [portable copy](/umbra/docs/internals/portable-mode/)). The environment variable `UMBRA_DATA_DIR` overrides the location.
| Path | Contents |
|---|---|
| `settings.json` | Settings, per-widget options, positions, layouts, hotkeys, active theme |
| `widgets\\` | Installed community and agent-written widgets |
| `data\.json` | What a widget saved with `umbra.store` (1 MB cap per widget) |
| `themes\\` | Installed themes |
| `approvals.json` | Which widget commands you approved |
| `trash\-\` | Widgets removed in Settings, kept 7 days for **Undo** |
| `umbra.log` | The log |
## What Umbra sends
Umbra collects no telemetry and has no account. Its own network traffic is limited to:
1. a daily check for a new release on GitHub (turn it off with `umbractl general --updates off`),
2. the widget and theme catalog when you open **Browse** or **Themes**,
3. requests that widgets make to hosts they declared in their `widget.json`.
A widget cannot reach anything it didn't declare; the app blocks the rest. See [Sandbox and permissions](/umbra/docs/widgets/sandbox/).
## The Data & privacy page
**Settings → Data & privacy** shows, for every widget:
- the hosts it can reach and the local commands it declares (and whether you approved them),
- how much data it has saved, with a **Delete data** button,
- recent blocked requests (a request to a host the widget didn't declare),
- how many times its renderer crashed.
It also has **Export** and **Import backup**, **Open data folder** and **Open log**, **Reset everything**, and **safe mode**. The same read-only report is `umbractl privacy [id]`.
## Backup and restore
```powershell
umbractl backup C:\Backups\umbra.json # settings, layouts, theme, hotkeys and widget data
umbractl restore C:\Backups\umbra.json # validated before anything is replaced
```
A backup **never includes command approvals**, so after a restore you approve widget commands again. The trash is not part of backups either.
## Removing widgets
- **Settings → Remove** moves the widget folder, its data and its settings (for every copy) to the trash for 7 days, with an **Undo** button on the toast. The trash is purged at startup after 7 days. (Undo does not bring back the working folders of `permissions.commands` runs.)
- `umbractl remove ` and the MCP `remove_widget` delete a widget and its data for good, with no undo.
## Safe mode
Safe mode turns community widgets off without deleting anything, so you can find a misbehaving one. Turn it on from **Data & privacy**, with `umbractl safe-mode on`, or start Umbra with `Umbra.exe --safe`. It isn't saved: the next normal start restores everything.
---
# Updates
> How Umbra updates itself, how widget and theme updates work, and why an update can wait for your approval.
## Updating Umbra
Umbra checks GitHub once a day for a new release. When one is found it downloads the installer in the background and verifies it, then shows a **dot on the tray icon**. Install it from the tray menu or **Settings → About**.
Installing closes Umbra, runs the installer silently with a small dark progress window, and starts the new version. After an update, **About** shows the release notes once.
```powershell
umbractl check-update # is a newer version out? (it never installs one)
umbractl general --updates off # stop the daily check
```
What Umbra will install is restricted: the installer must be an HTTPS download from this project's GitHub releases and named `UmbraSetup-.exe`. Automation can check for updates but can never install one. See [Updates and installer](/umbra/docs/internals/updates-installer/).
:::note
Portable copies don't update themselves. **About** shows a download link instead.
:::
## Updating widgets and themes
Installed community widgets show an **Update** button on **Browse** when the catalog has a newer version. To update everything:
```powershell
umbractl update --all
```
A failure doesn't stop the rest; failures are listed in the result.
### Updates that ask for more
An update never grants new access silently. Umbra compares the new `widget.json` with the installed one and, if the update adds **hosts, system readings, media, notifications or commands**, it waits:
- **Settings** shows a box listing exactly what's new, and you accept or decline.
- `umbractl install ` refuses until you repeat it with `--accept-permissions`.
- `umbractl update --all` skips such widgets and lists them, so you accept them one by one.
- The MCP server strips `--accept-permissions`, so an agent can't approve for you.
The widget's `changelog` (if it has one) is shown with the request.
## Version numbers
Umbra and its tools share one version, from `Directory.Build.props`. Widgets and themes have their own `version`, bumped on every change; that's how Browse knows to offer an update.
---
# Troubleshooting
> Find out why a widget misbehaves, read logs, use safe mode and diagnostics, and understand what Umbra does when a widget crashes.
## Start here
1. **Is the widget enabled and visible?** Check **My widgets**: enabled, not hidden, and not limited by a time range or "only on AC power". The tray tooltip shows if edit mode or safe mode is on. Widgets also hide while a fullscreen app is in front if that option is on.
2. **Read the log.** `umbractl logs 100` prints the last lines (widget load errors, blocked network requests, crashes). The file is `%APPDATA%\Umbra\umbra.log`, and **Data & privacy → Open log** opens it. For more detail, set **General → Log level** to *verbose* (`umbractl general --log-level verbose`).
3. **Check blocked requests.** If a widget shows no data, **Data & privacy** lists requests it made to hosts it didn't declare. A widget can only reach HTTPS hosts listed in its `widget.json`.
4. **Try safe mode.** `umbractl safe-mode on` (or `Umbra.exe --safe`) closes all community widgets without deleting anything. If the problem goes away, turn widgets back on one at a time.
## Reporting a bug
**Settings → About → Copy diagnostics** (or `umbractl diagnostics`) produces a Markdown block with the Umbra version, Windows build, WebView2 version, monitors with DPI, GPU and proxy state, enabled widgets with versions and the last 30 log lines with your user paths hidden. It contains no option values, no proxy address and no widget data. Paste it into an [issue](https://github.com/AmineChr54/umbra/issues/new/choose); the link on the About page pre-fills your version.
## Common problems
**A widget stopped working.** If a widget's renderer exits unexpectedly, Umbra reloads it automatically, up to 3 times in 10 minutes. After that you see a host-drawn **"This widget stopped working"** page with a **Reload** button instead of a blank window. A hung renderer is only logged. If the whole WebView2 browser process exits, Umbra recreates it. Data & privacy shows each widget's crash count. See [Crash recovery](/umbra/docs/internals/crash-recovery/).
**A hotkey does nothing.** `umbractl hotkeys` shows each hotkey's status. `failed` includes the reason, most often that another app already owns that combination.
**Umbra says it's already running.** Only one instance runs per user (a portable copy has its own). A second launch opens Settings in the running copy instead. If you want to run from source, quit the installed Umbra first.
**WebView2 is missing.** Umbra needs the WebView2 runtime, which ships with current Windows. On startup Umbra checks for it and tells you if it's missing; install the Evergreen runtime from Microsoft.
**Widgets show "Offline".** The little status dot means the last fetches failed. Check your network or proxy (**General → Advanced → Proxy**).
**Everything is broken after a change.** **Data & privacy → Reset everything** returns Umbra to a clean state, or restore a [backup](/umbra/docs/using/data-privacy-backups/).
## For widget developers
`umbractl reload` re-scans widget folders after editing, `umbractl capture out.png` shows exactly what the widget renders, and starting Umbra with `UMBRA_SIMULATE_OFFLINE=1` makes every host fetch fail so you can test the offline state. See [Testing with capture](/umbra/docs/widgets/testing/).
---
# Your first widget
> Scaffold, run, edit and screenshot a working widget in a few minutes, then see where to go next.
A widget is a folder with a `widget.json` and a web page. This walks through creating one, changing it and looking at the result. You need Umbra installed and a text editor; no build tools.
## 1. Scaffold it
```powershell
umbractl new my-widget
```
This writes a working widget into `%APPDATA%\Umbra\widgets\my-widget` and shows it on your desktop straight away. (Use `--name "My widget"` for a display name, or `--dir ` to scaffold somewhere else; widgets outside the community folder aren't picked up until you load them with `umbractl create `.)
You now have:
```
my-widget/
widget.json the manifest
index.html the page
style.css styles
main.js the code
```
## 2. Read the manifest
```json
{
"$schema": "https://raw.githubusercontent.com/AmineChr54/umbra/main/schemas/widget.schema.json",
"id": "my-widget",
"name": "my-widget",
"description": "Describe in one sentence why people want this widget.",
"author": "your-github-name",
"version": "0.1.0",
"entry": "index.html",
"width": 260,
"height": 120,
"permissions": { "hosts": [] },
"options": {
"greeting": { "label": "Greeting", "type": "text", "default": "Hello" }
}
}
```
`id` must equal the folder name. `width` and `height` are the widget's size in logical pixels. `permissions.hosts` is empty, so this widget can't reach the internet. `options` becomes a settings form on the widget's card in **My widgets**. The [manifest reference](/umbra/docs/widgets/manifest/) covers every field.
## 3. Read the page
`index.html` loads Umbra's stylesheet and SDK from the virtual host `umbra.local`, then your files:
```html
...
```
`umbra.css` gives you design tokens (colors, fonts, radii), and `umbra.js` gives you the global `umbra` object: options, refresh, data fetching, saved data and more. See [Page and lifecycle](/umbra/docs/widgets/page-and-lifecycle/).
## 4. Change it
Edit `main.js` or `style.css`, then tell Umbra to re-scan:
```powershell
umbractl reload
```
Change the option live without editing any file:
```powershell
umbractl set my-widget greeting "Good morning"
```
## 5. Fetch real data
To call an API, declare its host in `widget.json`, then use `umbra.fetchJson` inside `umbra.every`:
```json
"permissions": { "hosts": ["api.open-meteo.com"] }
```
```js
umbra.every(async () => {
const data = await umbra.fetchJson("https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t=temperature_2m");
document.getElementById("app").textContent = `${data.current.temperature_2m}°`;
umbra.rendered();
});
```
Requests to any host you didn't declare are blocked, and `fetchJson` rejects. See the [JavaScript API](/umbra/docs/widgets/javascript-api/).
## 6. Look at it
```powershell
umbractl capture my-widget shot.png
```
This saves a PNG of just that widget and nothing else on screen. Check it at other sizes with `umbractl configure my-widget --scale 2`. [Testing with capture](/umbra/docs/widgets/testing/) has the full loop.
## 7. Make it good, then publish
Follow the [design guidelines](/umbra/docs/widgets/design-guidelines/) (true black background, tokens instead of hard-coded colors, tabular numbers), add a `preview.png`, and [publish it](/umbra/docs/widgets/publishing/) by pull request so it shows up in everyone's Browse page.
:::tip[Prefer to describe it?]
Connect an AI agent with `claude mcp add umbra -- umbractl mcp` and ask for the widget you want. The agent reads this documentation, writes the files, captures a screenshot and iterates. See [MCP server](/umbra/docs/automate/mcp/).
:::
---
# widget.json
> Every field of a widget manifest, option types, permissions and the rules Umbra validates.
Every widget has a `widget.json` in its folder. Umbra validates it when the widget loads, when it's installed, and in CI for catalog widgets (`node scripts/catalog.mjs`). Add the `$schema` line and your editor validates and completes it as you type:
```json
"$schema": "https://raw.githubusercontent.com/AmineChr54/umbra/main/schemas/widget.schema.json"
```
## Example
```json
{
"$schema": "https://raw.githubusercontent.com/AmineChr54/umbra/main/schemas/widget.schema.json",
"id": "weather",
"name": "Weather",
"description": "Current temperature and conditions for one city.",
"author": "your-github-name",
"version": "1.0.0",
"entry": "index.html",
"preview": "preview.png",
"width": 300,
"height": 160,
"defaultPosition": { "x": 24, "y": 420 },
"permissions": { "hosts": ["api.open-meteo.com"] },
"options": {
"city": { "label": "City", "type": "text", "default": "Berlin", "hint": "Shown under the field" },
"units": { "label": "Units", "type": "select", "default": "c",
"choices": [{ "value": "c", "label": "Celsius" }, { "value": "f", "label": "Fahrenheit" }] },
"decimals": { "label": "Decimals", "type": "number", "default": 0, "min": 0, "max": 2, "step": 1 },
"compact": { "label": "Compact mode", "type": "toggle", "default": false }
}
}
```
## Fields
| Field | Rules |
|---|---|
| `id` | Equals the folder name. 2 to 40 characters: lowercase letters, digits and dashes, starting with a letter or digit (`^[a-z0-9][a-z0-9-]{1,39}$`). |
| `name`, `description`, `author` | Required, non-empty. |
| `version` | Required, like `1.2.3`. **Bump it on every change**: it's how users get an Update button. |
| `changelog` | Optional, up to 500 characters: what changed. Shown when an update asks for new access and carried in the catalog index. |
| `entry` | The page to open. Default `index.html`. |
| `preview` | Screenshot for Browse. Recommended: a 2x capture on a black background. |
| `icon` | Optional tab icon for [tab groups](/umbra/docs/using/copies-and-tab-groups/): a 64×64 PNG, light grey on transparent. |
| `width`, `height` | Integers 80 to 1200, in **logical** pixels. Umbra scales them for the display's DPI and the user's size setting. |
| `defaultPosition` | `{ "x", "y" }` from the top left of the primary work area, in logical pixels. Omit to start at the top right. |
| `themeable` | Default `true`. `false` keeps your own look and ignores the user's [theme](/umbra/docs/using/appearance/). |
| `options` | The settings form in **My widgets**, in this order. See below. |
| `permissions` | What the widget may reach. See below. |
## Options
| `type` | Extra fields | Value |
|---|---|---|
| `text` | `hint` | string |
| `number` | `min`, `max`, `step` | number |
| `select` | `choices`: a list of `{ "value", "label" }` (required) | the chosen `value` |
| `toggle` | none | boolean |
Every option has a `label` and a `default`. Read values in the page from `umbra.options`; they update live through `umbra.onSettings`. Users (and scripts) can change them with `umbractl set