Skip to content

Repository files navigation

Priority

A keyboard-first macOS menu bar app for working Checkvist lists fast. Quick navigation, priority and due workflows, focus timers, a kanban board, an honest daily log, and a command line that reaches the same data.



Priority lives in the menu bar and is built to be driven without the mouse. Checkvist owns your tasks; Priority adds the things Checkvist has no representation for — priority ranking, start dates, recurrence, focus sessions, daily habits, and a record of what actually happened each day.

It works offline. It works from the terminal. And it exposes the whole surface to an AI assistant over MCP.

Contents

Install

  1. Download the latest .dmg from Releases.
  2. Drag Priority.app into Applications.
  3. Right-click it once and choose Open.

The build is signed with a development certificate rather than a Developer ID, so Gatekeeper will ask the first time. If it refuses outright:

xattr -cr /Applications/Priority.app

Or build it yourself — see Build from source.

First run

Open Preferences with Cmd+,:

Step What
1 Checkvist username and remote API key (from checkvist.com/auth/profile)
2 The checklist/list ID to work in
3 Global hotkey to toggle the popover
4 Quick-add hotkey, and whether it targets the list root or a specific parent
5 Day rollover hour — when your day starts, default 04:00
6 Obsidian inbox folder (optional)
7 MCP integration (optional)
8 Launch at login

Onboarding boxes guide the Checkvist, Obsidian and Google Calendar setup. Each one is dismissable, and the app stays usable offline-first without any of them.

Keyboard flow

Navigation

Key Action
j / Next task
k / Previous task
l / Enter subtasks
h / Exit to parent
Ctrl+← / Ctrl+→ Cycle root view
q All view
w Due view
e Tags view
r Priority view
t Kanban view
y Matrix view
Shift+T Daily view
Esc Cancel input / close popover

Task actions

Key Action
Space Complete
Shift+Space Invalidate ("won't do")
Enter Add sibling
Shift+Enter / Tab Add child
Shift+Tab Unindent
Shift+A Quick-add at the configured location
Cmd+↑ / Cmd+↓ Move task
19 Scoped priority rank, within the parent
Hyper+1Hyper+9 Absolute priority rank (Ctrl+Cmd+Option+Shift)
= Send to priority back
- Clear scoped priority
Hyper+- Clear absolute priority
' Start a focus session on the selected task, from any view

Kanban

Key Action
h / Previous column
l / Next column
Cmd+← / Cmd+→ Move task between columns
f Show this task in the All view, entering its subtasks if it has any

Dailies

Key Action
j / k Move through the checklist
Space Tick / un-tick
Return Add a daily — stays open, so a whole routine can be typed in one go
Cmd+↑ / Cmd+↓ Reorder
Esc Close the add field

Integrations

Key Action
o Open the selected task in Obsidian
O Open in a new Obsidian window
gc Add to Google Calendar

Command palette

Open with :, ; or Cmd+K. Most commands accept several spellings — unrepeat, no repeat, remove repeat and clear repeat all do the same thing.

Family Commands
Status done, undone, invalidate, delete, undo
Due due <value>, clear due
Start date start <value>, edit start, clear start
Repeat repeat <rule>, repeat daily, repeat every <n> <unit>, clear repeat
Tags tag <name>, untag <name>
Priority priority <1-9>, priority back, clear priority
Matrix matrix <quadrant>, importance <value>, urgency <value>
Kanban kanban left / right, kanban move left / right, kanban enter, kanban exit, kanban show in all, kanban focus mode
View list <name>, tab <name>, cycle tab next / prev, cycle filter next / prev, toggle children, toggle subtree, toggle context, toggle hide future
Timer focus mode, toggle timer, pause timer
Obsidian sync obsidian, open obsidian new window, link / create / clear obsidian folder, choose obsidian inbox
Calendar sync google calendar, open google calendar
MCP mcp guide, mcp config, copy mcp config, refresh mcp path
App preferences, search, quick add, refresh lists, upload offline tasks

Due values understand natural language and times: due today 14:30, due tomorrow 9am, due next week, due 4pm fri, due next monday morning. The time words morning, noon, afternoon, evening, midnight, eod and cob all resolve to configurable named times.

Views

View Key What it shows
All q The full tree
Due w Due and overdue, soonest first
Tags e Grouped by tag
Priority r Your ranked queue
Kanban t Configurable columns, filtered by tag or scoped to subtasks
Matrix y Eisenhower quadrants by importance and urgency
Daily Shift+T Dailies, the chart, and what you finished

Kanban cards show the task text with tags stripped, a P1P9 priority badge, the due date with overdue/today highlighting, inline tags, and a subtask count. Columns are configured in Preferences and reorder by drag.

The dock row

A narrow strip along the bottom of the popover, in every view. Right to left:

Button Does
⚙︎ Gear Preferences
↻ Refresh Re-fetch from Checkvist, with a spinner while it runs
↕ Resize Reveal the drag strip
▁▃▅ Graph Show/hide the Daily chart — Daily view only

Each root view remembers its own height. The Daily view stacks a checklist, a chart and a completions list where the All view is a single list, so one shared height would be wrong for one of them at all times. Drag the strip to set a height; double-click it to go back to sizing from the content.

Heights are clamped to 240–900pt on write and on read at launch, so a stored value can never put the strip out of reach. If one somehow does:

defaults delete uk.co.maybeitsadam.priority panelHeightOverridesByRootView

Hiding the graph shortens the panel by exactly the chart's height, which turns the Daily view into a compact checklist on days you're only ticking things off.

Daily log

The Daily view (Shift+T) answers "what did I get done, and how does today compare?"

Dailies

Recurring things you intend to do — habits, not tasks — sitting at the top of the view as a checklist.

  • They reset at every rollover and never go overdue. Miss one and it's a gap in the history: nothing to clear, nothing to reschedule. That's the whole reason they aren't Checkvist tasks with a repeat daily rule — a recurring task goes overdue and starts competing with real deadlines.
  • They're local. Stored in ~/Library/Application Support/Priority/dailies.json, so "brush teeth" never clutters your project lists or syncs to other Checkvist clients. Ticking one is instant and works offline.
  • Ticks land in the same log as task completions, so they count towards the chart and appear in the Obsidian note.
  • Schedules and archiving live in Preferences → Plugins → Daily Log — every day, or specific weekdays. Removing a daily archives it, so past days keep their record instead of showing an orphaned id.

What the day records

  • Recording is always on and always local. Completions, reopens, invalidations, finished focus sessions and the day's plan are appended to ~/Library/Application Support/Priority/daylog.jsonl — one JSON object per line, so it stays readable with tail, and a torn write costs one event rather than the file.
  • Checkvist owns current state, the log owns history, Obsidian owns the archive. Nothing syncs backwards, so there is no conflict resolution anywhere in this.
  • The day's plan is derived, not authored. At the first popover open after your rollover hour, whatever is due, overdue or starting that day is snapshotted. That's what "N left" measures against — you never plan a day by hand.
  • Deferring is not slipping. Pushing a due date forward is recorded distinctly from letting a task rot, so the view doesn't nag about a decision you made deliberately.
  • The day starts at your rollover hour, not midnight (default 04:00), so a session finishing at 01:30 counts towards the day it belonged to.
  • No backfill. History starts the day you first run this build. The chart is drawn from day one regardless — a flat run of days is a true statement about a history that has just started — with a "collecting since" line underneath until the window fills.

Obsidian daily notes

In Preferences → Plugins → Daily Log, point Priority at your dailies folder and set the note naming to match your vault (yyyy-MM-dd by default; a subfolder pattern like yyyy/MM nests them). The preview line shows exactly which note today's block would land in. Then switch on "Write days into Obsidian daily notes", which stays disabled until a folder is chosen.

Once a day closes, its block is spliced into that day's note:

<!-- priority:begin -->
## Log

**5 done** · **2/3 dailies** · **1h 40m focused** · 2 of 7 planned left

_Dailies:_
- [x] Read
- [x] Walk
- [ ] Stretch

- [x] Ship the DMG
- [x] Review the sync PR

_Unfinished:_
- [ ] Write release notes
<!-- priority:end -->

Only the text between the markers is ever touched, and rewriting a day replaces its own block rather than stacking a second one. Creating missing notes is off by default, so the plugin can't beat a Templater or Daily Notes template to the file — turn it on only if nothing else builds your dailies.

Command line

priority is a Rust CLI covering the same ground: your lists, your dailies, your day log. It talks to the Checkvist API directly and reads Priority's local files off disk, so it works whether or not the app is running — and its writes take the same flock(2) the app does, so both can be open at once.

Run it with no arguments and it opens a terminal UI with the same tabs as the app, and the same keys to reach them:

 All q │ Due w │ Tags e │ Priority r │ Kanban t │ Matrix y │ Daily d
┌ All ───────────────────────────────────────────────────────────────┐
│▎[ ] Ship v0.4                                                      │
│   [ ] Draft the release notes  #work                               │
│   [x] Tag the commit                                               │
│ [ ] Buy milk  #home                                                │
└────────────────────────────────────────────────────────────────────┘
 j/k move · l/h in-out · space done · a add · ? help · esc quit

Or drive it by subcommand:

./scripts/install_cli.sh     # release build + a symlink onto your PATH
priority auth login

priority                     # the terminal UI
priority tasks
priority add Draft the release notes --due friday
priority search -q report --due-before 2026-09-01
priority daily add Read for twenty minutes --weekdays mon,wed,fri
priority log --days 7
priority --json dailies | jq '.dailies[] | select(.done | not)'

Its credentials are its own, in ~/.config/priority/config.json at mode 0600 — separate from the app's login-keychain item, so neither depends on how the other was built or signed. The dailies, log and metadata commands need no credentials at all.

Every command is one of the MCP tools under a friendlier name, and the same binary serves them over MCP with priority --mcp-server.

Full guide: docs/cli.md

MCP server

Priority exposes 19 MCP tools so an AI assistant can work with your lists directly — thirteen that reach the Checkvist API, and six for the local state Checkvist has no representation for (day log, dailies, priority ranks and recurrence).

Set it up from Preferences → Plugins → Native MCP Integration. It detects Claude Code, Claude Desktop, Cursor, Windsurf, VS Code and Zed, and adds Priority to the one you pick in a single click, preserving any servers already in that client's config.

There are three interchangeable implementations — the one embedded in the app, a dependency-free Python fallback script, and the Rust CLI. A client may be pointed at any of them, so scripts/mcp_parity_check.py drives all three against a fixture and a stub API and diffs their tool lists, their answers, the files they leave on disk, and the HTTP requests they make.

Full guide: docs/mcp-server.md

Plugins

Every external integration is a plugin behind a protocol.

Built in: NativeCheckvistSyncPlugin, NativeObsidianIntegrationPlugin, NativeGoogleCalendarIntegrationPlugin, NativeMCPIntegrationPlugin, NativeDailyLogPlugin, OfflineTaskSyncPlugin.

To install your own, open Preferences → Plugins and click Install Plugin (folder, .zip, or .priority-plugin), or drop a plugin folder into ~/Library/Application Support/Priority/Plugins and hit Reload.

Built-in plugins are fully functional; user-installed plugins are manifest-driven (settings, metadata, lifecycle) and prepared for runtime capability wiring.

Authoring guide: docs/plugins.md

Build from source

Requirements: macOS 15.6+, Xcode 17+, and Rust for the CLI.

git clone https://github.com/MaybeItsSoftware/priority.git
cd priority

# The app
xcodebuild -project 'Priority.xcodeproj' -scheme 'Priority' -configuration Debug -destination 'platform=macOS' build

# Headless logic (303 tests)
swift test

# The CLI (48 tests)
cargo test --manifest-path cli/Cargo.toml

# All three MCP servers agree
cargo build --release --manifest-path cli/Cargo.toml
python3 scripts/mcp_parity_check.py

# Build + launch Debug, or produce a release DMG
./scripts/run.sh
./scripts/build_dmg.sh <version>

Layout

Path What
Priority/ The macOS app. CoreLogic/ is pure, headless, UI-free logic.
Priority/Plugins/ Integration plugins, one folder each, behind protocols
cli/ The Rust CLI crate — shares no source with the Swift side
scripts/ Build, install, the Python MCP fallback, and the parity check
docs/ CLI · MCP · plugins · state ownership

The same source tree is compiled by two build systems: the Xcode project builds the app, and Package.swift exposes PriorityCore, PriorityPlugins and PriorityAppLogic as SPM libraries so the headless logic can be tested without the app shell. Adding or moving a file often means updating Package.swift too — see CLAUDE.md.

Where your data lives

Path What
~/Library/Application Support/Priority/ Dailies, day log, task cache, installed plugins
~/Library/Preferences/uk.co.maybeitsadam.priority.plist Settings, priority ranks, recurrence rules, start dates
Login keychain, service uk.co.maybeitsadam.priority The app's Checkvist remote key
~/.config/priority/config.json The CLI's own credentials, mode 0600

Nothing is sent anywhere except Checkvist, and Google Calendar or Obsidian if you enable them.

Upgrading from Bar Tasker? Everything is carried across automatically on first launch — preferences, dailies, the day log and your keychain item. The old locations are copied rather than moved, so they stay on disk until you delete them.

License

MIT

About

A keyboard-first macOS menu bar app for managing tasks quickly with flexible integrations

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages