Sticky Notes
Floating scratch-pad notes that persist across sessions and app restarts. Each note is draggable, resizable, and color-coded. Notes live in a portal overlay above the main UI and are toggled from the toolbar.
What it is
Floating scratch-pad notes that persist across sessions and app restarts. Each note is draggable, resizable, and color-coded. Notes live in a portal overlay above the main UI and are toggled from the toolbar.
Where to find it
UI Surface
- Toolbar icon — the sticky-note icon in the top-right toolbar pill (visible when the feature is enabled in Settings → Features → "Enable Sticky Notes", default on). The icon lights up in accent color when notes are visible.
- First click — if no notes exist yet, the toolbar click creates the first one and shows the overlay. Subsequent clicks toggle visibility on/off. The overlay's open/closed state persists to
localStorageso it survives renderer reloads. - Note title bar — each note has a drag handle (grip icon) on the left and four buttons on the right: + (new note, offset from current), palette (6-color picker), – (minimize to a small chip), × (delete, behind a confirm).
- Closing the last note hides the overlay — deleting the final remaining note turns the overlay off (the toolbar icon un-highlights) rather than leaving an empty portal with no reachable "New note" button. The feature stays enabled; clicking the toolbar icon again brings the overlay back and mints a fresh note. The auto-close writes through the same
stickyNotesOverlayOpenpath as the toolbar toggle, so it survives a reload. - Content area — a textarea with auto-save (500ms debounce). Placeholder text ("Write something...") disappears on focus. Text and icon colors auto-adjust for contrast against the note's background color.
- Resize handle — three dots in the bottom-right corner; drag to resize (120–800px width, 100–800px height).
- Minimized state — collapses to a small 48×32 chip at the note's position. Drag to reposition; click (without dragging) to expand.
- Settings search — searchable as "sticky", "notes", "notepad", "scratchpad", "memo", "post-it", etc.
How it behaves
Scope
- Desktop-rendered, but CLI-reachable. Each note is an absolutely-positioned, draggable, resizable overlay widget keyed to on-screen pixel coordinates, so the overlay is desktop-bound — but the note DATA is not. The localhost CLI control server serves
GET /sticky-notes,POST /sticky-notes,PATCH /sticky-notes/:idandDELETE /sticky-notes/:id(src/main/services/cli/cli-server-sticky-notes-routes.ts), so an AI or automation can list, create, edit and delete notes. Each write emitsSTICKY_NOTES_CHANGED, which an open overlay picks up via the live-sync subscription — including an external delete that empties the list, which hides the overlay the same way closing the last note by hand does.
For agents
Architecture
Data Model
sticky_notes SQLite table (migration v172):
| Column | Type | Default | Notes |
|---|---|---|---|
id |
TEXT PK | UUID | |
content |
TEXT | '' |
Max 10,000 chars (Zod) |
position_x |
INTEGER | 100 | 0–10,000 |
position_y |
INTEGER | 100 | 0–10,000 |
width |
INTEGER | 240 | 120–800 |
height |
INTEGER | 200 | 100–800 |
color |
TEXT | #FFF9E6 |
Hex #RRGGBB |
is_minimized |
INTEGER | 0 | Boolean |
created_at |
TEXT | ISO timestamp | |
updated_at |
TEXT | ISO timestamp |
IPC Channels
| Channel | Schema | Response |
|---|---|---|
sticky-notes:list |
{} |
{ notes: StickyNote[] } |
sticky-notes:create |
content, positionX/Y, width/height, color (all optional) | { id: string } |
sticky-notes:update |
id + any updatable field |
{} |
sticky-notes:delete |
{ id } |
{} |
sticky-notes:changed |
Push event (no payload) | — |
Key Files
| Layer | File | Purpose |
|---|---|---|
| Migration | src/main/db/incremental-migrations.ts |
v172 CREATE TABLE sticky_notes |
| Queries | src/main/db/queries-sticky-notes.ts |
CRUD (list, create, update, delete) |
| IPC handlers | src/main/ipc/sticky-notes-handlers.ts |
Zod-validated wrapHandler + push |
| Shared types | src/shared/types.ts |
StickyNote interface, stickyNotesEnabled in AppSettings |
| Shared channels | src/shared/ipc-channels/ |
5 channel constants |
| Shared schemas | src/shared/ipc-schemas.ts |
Zod schemas for all 4 mutations |
| Store | src/renderer/src/stores/sticky-notes-store.ts |
Zustand store (load, toggleOpen, CRUD) |
| Widget | src/renderer/src/features/sticky-notes/StickyNoteWidget.tsx |
Individual note UI |
| Overlay | src/renderer/src/features/sticky-notes/StickyNotesOverlay.tsx |
Portal container |
| Settings | src/renderer/src/features/settings/sections/features/feature-rows.tsx |
Toggle row |
| Toolbar | src/renderer/src/features/toolbar/toolbar-items.ts |
Item definition |
| Toolbar render | src/renderer/src/features/toolbar/ToolbarPinnedItem.tsx |
Switch case |
| App wiring | src/renderer/src/App.tsx |
Lazy overlay + toolbar prop threading |
| Tests | tests/unit/db/queries/queries-sticky-notes.test.ts |
4 CRUD unit tests |
Color Contrast
The widget uses luminance-based color selection. isLightColor() computes perceived brightness via the ITU-R BT.601 formula. Light backgrounds get dark text (#1a1a1a), dark backgrounds get light text (#f5f5f5). All icons, placeholder text, resize dots, and the text cursor follow the same rule — no Tailwind CSS-var colors are used on the note surface.
Default Colors
Six pastel presets: yellow (#FFF9E6), blue (#E6F9FF), green (#E6FFE6), pink (#FFE6F0), purple (#F0E6FF), orange (#FFE6D5).
Related
- Scratchpads — the other note-taking surface in Omniscio: persistent notes that live in a pane and feed the global search, rather than notes that float over the window.
Last verified 2026-09-28