Standalone CLI helpers on $PATH, used across my desktop. Part of the
quantumfate desktop, alongside the
hypr compositor config and the
quickshell UI.
Most are small ,name.sh wrappers invoked from Hyprland keybinds. A few
integrate with the shared state / UI:
-
bin/qfs— "quantumfate shell": wraps the Quickshell IPC surface (qfs theme cycle,qfs window rename "...",qfs show, …). Zsh completion_qfslives in the quickshell repo'scompletions/. -
bin/dofus_swap.py— Dofus auto turn-swap detector. Reads its roster from the shared team source of truth ($XDG_STATE_HOME/dofus/team.json), the same file the Quickshell UI edits, so team changes take effect live. (Querying that team store from the shell is done withdofus-team, which lives in the quickshell repo'sscripts/.) -
bin/obsidian_vault.py+bin/,obsidian-cli-wrapper.sh— Obsidian Zettelkasten bootstrap: scans~/Documents/Obsidian/Main, infers the missingidx/meta_idxindex-note chain for a topic, creates notes via Templater, and keeps a tag-structure store ($XDG_STATE_HOME/obsidian/tags.json, plus a GPG-encrypted.gpgcopy). The vault is the source of truth; the store is a projection. Full reference: quickshelldocs/obsidian-vault-manifest.md.,obsidian-cli-wrapper.sh status # vault/store state ,obsidian-cli-wrapper.sh create atomic "Some Title" --tag Topic/Sub ,obsidian-cli-wrapper.sh ensure-topic Topic/Sub --dry-run # plan index notes -
bin/obsidian_linear_sync.py+bin/obsidian-linear-sync— one-way mirror of Linear into the same vault. Projects, milestones and issues become index notes underProjects/, so the index-notes plugin renders the hierarchy; sub-issues are filed under their parent. Linear is the source of truth and nothing is ever deleted. The API key is read from Proton Pass at runtime (Productivity/linear.app/api_key); a locked vault notifies and exits. Runs every five minutes fromobsidian-linear-sync.timer, deployed by theobsidian_linearrole in system-config.Because tags are derived from Linear's naming, a rename moves a whole subtree. The previous hierarchy is kept in
$XDG_STATE_HOME/obsidian/linear.jsonso the next run can diff it and rename the old tag prefix wherever it appears — including on notes the sync never created.obsidian-linear-sync # dry run obsidian-linear-sync --apply # sync now obsidian-linear-sync --project lance.nvim --apply obsidian-linear-sync --apply --force # rewrite managed blocks regardless -
bin/,scene-apply.sh+bin/,mood-bg.sh— the mood-mode enforcement seam (LEO-238).,scene-apply.sh [mode]is spawned detached by the shell whenever the active focus mood changes and brings user-unit background work in line with it: it stops the units the contract (etc/scene-managed.json) maps to the mood's reachable scenes and deferred/prevented background tasks, and hands back whatever the previous mood stopped. Units on the contract'sprotectedlist are never touched; stops go through systemd (SIGTERM + the unit'sTimeoutStopSec, never SIGKILL);gracefulentries are only requested and logged. Every decision lands in$XDG_STATE_HOME/scene-policy/log.jsonl, the feed for the scene-policy logging workspace (LEO-241).--dry-runprints the plan without touching systemd.,mood-bg.sh <task>is the dispatch-time gate for a task's timer: it asks the shell (focus bg <task>) and exits 0 to run, 2 to defer, 3 to prevent — the same verdict the mood panel shows.,scene-apply.sh game # gated manual run (the shell triggers this anyway) ,scene-apply.sh --dry-run # show the plan, touch nothing ,mood-bg.sh obsidian # timer gate → 0 | 2 | 3The contract ships from this repo because the actor ships here (the desktop's delivery rule: each repo delivers its own role/data; quickshell never reads
etc/scene-managed.json— it asks the same policy Focus reads).
How the shared state + IPC bridges work: quickshell/ARCHITECTURE.md.