Wayland-native, markdown-based desktop sticky notes for Linux.
Waynote keeps quick, glanceable notes on the desktop layer of your tiling
compositor. Notes are plain .md files — hackable, version-controllable, and
friendly to Obsidian and AI agents: edit a note from any editor and it refreshes
live on screen.
Note
Waynote is v0.1.0 — young, but functional. The full feature set works; the interactive paths (drag/resize, click-to-edit, checkboxes, image paste, tray) have had limited real-world testing, so expect the occasional rough edge. Issues and feedback are welcome.
Existing sticky-note apps target X11 desktop environments, hide your notes in a private database, and don't speak markdown. Waynote is built for Wayland power users instead:
- Lives on the desktop layer via
wlr-layer-shell— send notes behind your windows or bring them to the front, show/hide all, recolour them, lock one read-only, move it to another monitor, and pin the ones that stay. - Plain markdown files. Each note is a
.mdfile with a small YAML frontmatter (id, color, pinned, locked, tags). Render is faithful — six distinct heading levels, bold/italic/strikethrough, inline code and code blocks, blockquotes, nested and ordered lists, links, task checkboxes (struck through when done), and inline images — across seven paper colours, withCtrl+B/Ctrl+I/Ctrl+Kshortcuts while editing. - Agent- and sync-friendly. External edits (your editor, a script, an AI agent, Syncthing) are reconciled live, with conflict copies instead of silent overwrites. Content stays clean for git: volatile geometry is stored separately from the notes.
- A single Rust binary, hackable and easy to install.
Waynote needs a compositor that implements wlr-layer-shell:
- ✅ Supported: Hyprland, Sway, river, Wayfire, niri, KDE/KWin, COSMIC.
- ❌ Not supported: GNOME/Mutter (no layer-shell), X11, macOS, Windows.
The quickest path on Arch and derivatives — two packages are available, pick one:
yay -S waynote-bin # prebuilt binary, no compilation
yay -S waynote # builds from sourceEither one installs the waynote binary, a desktop entry, the tray icon, and a
(disabled) systemd user unit, and pulls in the gtk4 and gtk4-layer-shell
runtime dependencies automatically. Nothing else to do — skip to
Running the app.
You'll need a wlr-layer-shell compositor (see
Compatibility), Rust
(stable), and the GTK 4 + gtk4-layer-shell development libraries. On Arch:
sudo pacman -S gtk4 gtk4-layer-shell rustThen build, and install the desktop entry, tray icon, and systemd unit into your home directory:
git clone https://github.com/mryll/waynote.git
cd waynote
cargo build --release
./target/release/waynote install-user-assets # desktop entry, tray icon, systemd unitwaynote # or, from a source checkout: cargo runLoads notes from $XDG_DATA_HOME/waynote/notes/ (typically
~/.local/share/waynote/notes/). Notes are plain .md files — drop any
conforming markdown file in that directory and it appears on the desktop within
seconds.
waynote # run the app
waynote new [<monitor>] # create a new note (optionally on a monitor, e.g. DP-2)
waynote show-all | hide-all | toggle # show / hide all notes (forwards to the app)
waynote doctor # run diagnostics (D-Bus, SNI tray, paths)
waynote install-user-assets # install icon, .desktop, and systemd unit
waynote autostart on|off|status # toggle the systemd user autostart
waynote --render-demo # open the markdown render demo window (dev)The CLI verbs forward to the already-running instance (starting it if needed), so
bind them in your compositor — the same idea on any wlr-layer-shell WM.
Hyprland (~/.config/hypr/hyprland.conf):
bind = SUPER, N, exec, waynote new
bind = SUPER SHIFT, H, exec, waynote hide-all
bind = SUPER SHIFT, S, exec, waynote show-all
bind = SUPER SHIFT, T, exec, waynote toggle # hide all, or show all if any are hiddenSway (~/.config/sway/config):
bindsym $mod+n exec waynote new
bindsym $mod+Shift+h exec waynote hide-all
bindsym $mod+Shift+s exec waynote show-all
bindsym $mod+Shift+t exec waynote toggle
Tip
On Wayland an app can't know which monitor has focus, so a new note lands on the monitor under the pointer, else the last-used one, else the primary. To force the note onto the focused monitor, pass it explicitly — your compositor knows it:
# Hyprland
bind = SUPER, N, exec, waynote new "$(hyprctl activeworkspace -j | jq -r .monitor)"# Sway
bindsym $mod+n exec waynote new "$(swaymsg -t get_workspaces | jq -r '.[]|select(.focused).output')"
Any other action — arrange, or per-note ones like set-color, toggle-lock,
move-to-monitor — is available over D-Bus:
gapplication action dev.mryll.waynote arrangeWaynote opens one layer-shell surface per (monitor × layer) —
front = Layer::Top, desktop = Layer::Background — each hosting a stationary
canvas. The Wayland input region is limited to the note rectangles, so the rest
of the surface stays click-through. Notes are data models: moving a note across
monitors or layers recreates its view in the target surface rather than
reparenting widgets, which avoids ghost frames.
src/
main.rs # app entry point + CLI routing
app/
controller.rs # central state: notes, watcher, tray, actions
presenter.rs # places note cards onto surfaces
tray.rs # SNI tray item (ksni)
core/
markdown.rs # pulldown-cmark → IR
note.rs # note domain model
reconcile.rs # diff-and-reconcile for file-watcher changes
platform/
render.rs # GTK TextBuffer renderer (markdown IR → widgets)
watcher.rs # inotify file watcher + debounce
paths.rs # XDG path resolution
doctor.rs # diagnostics
surfaces.rs # layer-shell surfaces
The design follows Vertical Slice Architecture — user actions are slices, while filesystem, surfaces, tray, and markdown render are shared platform modules — keeping domain logic unit-testable without a display.
Waynote 0.1.0 is feature-complete: notes on the Wayland desktop with faithful markdown rendering, persistence with live file-watching and conflict copies, per-note colour / lock / layer / move-to-monitor controls, a system-tray item, image paste, and autostart. Verified live on Hyprland and Sway.
Planned next: broader compositor verification, optional tags and filters, and distro packaging beyond the AUR.
- Design — product behavior, persistence model, architecture, and scope
- Repaint contract — the validated redraw and input-region sequence, and its caveats
