obsidian-daily-qs
Omarchy Quattro bar widget for today's Obsidian daily note todos: view open items, add new checkboxes, and toggle them from a bar panel.
<img width="1108" height="1472" alt="preview" src="https://github.com/user-attachments/assets/91530fad-7796-4dfe-aebb-4eb24683d2b8" />Requirements
- Omarchy Quattro (Quickshell-based shell) on Linux
- An Obsidian vault with the Daily notes core plugin configured
- A supported architecture: x86_64 or aarch64 (arm64)
- Vault path via the
vaultPathbar setting orOBSIDIAN_VAULT_ROOTfor the graphical session — see Set the vault path
Daily note location and date format are read from .obsidian/daily-notes.json (folder, format, optional template), relative to the vault root. An optional archive location can be configured via the archiveFolder bar setting — see Archived notes.
Architecture
- Rust backend (
obsidian-daily-qs): resolves today's note, parses markdown checkboxes, adds/toggles items, streams JSON snapshots. Released as per-architecture static musl binaries (linux-x86_64,linux-aarch64). - QML frontend (
omarchy/):bar-widgetwith a details panel. Left-click opens the panel. Architecture detection runs once at startup viauname -m.
obsidian-daily-qs watch ──(JSON lines)──▶ BarWidget ─▶ Panel
obsidian-daily-qs add|toggle ──(JSON line)──▶ BarWidget
Install
omarchy plugin add https://github.com/LucaNerlich/obsidian-daily-qs.git --enable
Update / remove:
omarchy plugin update luca.obsidian-daily
omarchy plugin remove luca.obsidian-daily
If the bar still shows an error right after an update, run omarchy restart shell once. Omarchy hot-reloads plugin QML in place; a full shell restart is the reliable way to drop a stale in-memory widget (for example after the 1.7 backend rename).
The plugin bundles statically linked musl builds of its backend for x86_64 and aarch64 (omarchy/bin/obsidian-daily-qs-<arch>), plus an unsuffixed omarchy/bin/obsidian-daily-qs shim that execs the matching arch binary (so a hot-reloaded pre-1.7 widget keeps working). The widget prefers the arch-specific ELF via uname -m. If that cannot start, it tries obsidian-daily-qs on PATH once (cargo install --path .); if both fail, it latches to an error state instead of restarting forever. On unsupported architectures the bar shows ⚠ arch with a tooltip explaining the problem.
Set the vault path
Prefer the bar setting (no Hyprland env needed):
omarchy bar set luca.obsidian-daily vaultPath '/home/you/Documents/notizen'
Or set it from the panel when the widget shows the setup empty state.
The backend also accepts --vault <path> and still reads OBSIDIAN_VAULT_ROOT when vaultPath is empty. The Omarchy shell runs as a child of Hyprland, so an export in ~/.bashrc does not reach it unless you also set the graphical session env:
Option A — Hyprland env (per-session, applies without logging out):
-- ~/.config/hypr/hyprland.lua
hl.env("OBSIDIAN_VAULT_ROOT", "/home/you/Documents/notizen")
hyprctl reload && omarchy restart shell
Option B — systemd user environment (applies at next login):
# ~/.config/environment.d/obsidian-vault.conf
OBSIDIAN_VAULT_ROOT=/home/you/Documents/notizen
Archived notes
If you move old daily notes out of the live daily-notes folder (for example
into dailies/_archive/2026/), tell the widget where they went via the
archiveFolder bar setting:
omarchy bar set luca.obsidian-daily archiveFolder 'dailies/_archive/YYYY'
- The value is a folder pattern relative to the vault root, using the same
moment-style tokens as the note format (
YYYY,YY,MMMM,MMM,MM,M,dddd,ddd,DD,D). The formatted note file name is appended, so withformat: "YYYY-MM-DD"the example above resolves2026-08-20todailies/_archive/2026/2026-08-20.md. - The live path always wins: when a note exists in both places the live one is used, and new notes are always created in the live folder.
- Archived days are fully usable: the week strip shows their open/done counts, and toggling, adding, editing, indenting, undo and open-in-Obsidian all work on the archived note in place.
- Leaving the setting empty keeps the default behavior of only looking in the live daily-notes folder.
- The backend also accepts the pattern directly as
--archive-folderfor CLI use, e.g.obsidian-daily-qs status --date 2026-08-19 --archive-folder 'dailies/_archive/YYYY'.
Usage
- Bar: Obsidian mark + done/total for today. Left-click opens the panel; middle/right-click opens the note in Obsidian.
- Panel:
- List todos; click a row (or move the keyboard cursor) to select it, click its checkbox or press Enter/Space to toggle. Hover a truncated row to see the full text.
- Sort order is file order by default, so new todos append to the bottom.
Cycle newest-first / uncompleted-first / alphabetical with the sort button next to
Hide done, or set
sortOrder(default,newest,openFirst,alphabetical). Parent-child hierarchy is preserved in every order. - Nested todos render indented; Shift+Enter adds under the selected row.
- New items go under the configured
insertHeading(ortodoHeadingwheninsertHeadingis empty). When both are empty, the built-inTasks/Todossection is used, falling back to the first todo list (usually at the top). Spacing is copied from that list, or from recent daily notes when starting a new one. - Right-click a row to delete it or move it to tomorrow (children included). Hovering (or selecting) a row also reveals an inline ✕ delete button.
eedits,xdeletes,[/]outdent/indent,uundoes the last mutation (undoing a defer restores both days; a tomorrow note created by the defer is deleted again).- Week strip jumps between days; ◀ / ● / ▶ also navigate.
- Search:
/; open-only toggle; carry over; open in Obsidian. Carry over shows on today when a previous daily note still holds open todos — it uses the most recent such note within the last 30 days (weekend/vacation gaps), nearest first; repeat to drain older backlog. Opening a missing day creates its note from the configured daily-note template.
- Settings (
omarchy bar set luca.obsidian-daily …):vaultPath,archiveFolder,openOnly,sortOrder,todoHeading,insertHeading,hideWhenDone,hideWhenEmpty.
omarchy bar set luca.obsidian-daily openOnly true
omarchy bar set luca.obsidian-daily sortOrder newest
omarchy bar set luca.obsidian-daily todoHeading Todos
omarchy bar set luca.obsidian-daily insertHeading Inbox
todoHeading filters which todos the bar and panel show. insertHeading
names the markdown heading new todos are added under (e.g. Inbox); when
empty it follows todoHeading, and when both are empty new todos use the
built-in Tasks/Todos placement. Missing headings fall back silently, so
existing notes keep their behavior.
CLI
export OBSIDIAN_VAULT_ROOT="/path/to/vault"
# or: obsidian-daily-qs --vault /path/to/vault …
obsidian-daily-qs status
obsidian-daily-qs status --date 2026-08-19 --heading Todos
obsidian-daily-qs watch
obsidian-daily-qs add --text "Ship plugin"
obsidian-daily-qs add --text "Inbox item" --heading Inbox
obsidian-daily-qs add --text "Nested" --under-line 12
# Widget path: pass sensitive fields on stdin so they never appear in argv
printf '%s' '{"text":"Ship plugin"}' | obsidian-daily-qs add --stdin
obsidian-daily-qs toggle --line 12
obsidian-daily-qs edit --line 12 --text "Renamed" --expect-text "Old"
printf '%s' '{"text":"Renamed","expectText":"Old"}' | obsidian-daily-qs edit --line 12 --stdin
obsidian-daily-qs delete --line 12
obsidian-daily-qs defer --line 12
obsidian-daily-qs defer --line 12 --heading Inbox
obsidian-daily-qs indent --line 12
obsidian-daily-qs outdent --line 12
obsidian-daily-qs undo
obsidian-daily-qs week
obsidian-daily-qs carry-over
obsidian-daily-qs carry-over --heading Inbox
obsidian-daily-qs open
Development
cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
cargo test --all-targets
node omarchy/model.test.mjs
omarchy plugin validate .
qmllint -I "$OMARCHY_PATH/shell" omarchy/BarWidget.qml omarchy/Panel.qml
make bundle rebuilds the musl backends for x86_64 and aarch64 into omarchy/bin/ (Linux). make verify-bundle is the marketplace gate. Any edit under src/, Cargo.toml, Cargo.lock, or rust-toolchain.toml requires a fresh make bundle in the same change.
Releasing
- Bump
Cargo.toml,Cargo.lock,manifest.json, andCHANGELOG.md. - Run
make bundlethenmake verify-bundleon Linux. - Open a PR; wait for the marketplace bundle CI job to be green.
- Merge, then tag
vX.Y.Zmatching the crate version.
License
Apache-2.0.