Skip to content

Instantly share code, notes, and snippets.

@pixelhandler
Last active March 4, 2026 18:22
Show Gist options
  • Select an option

  • Save pixelhandler/cf365027d26b856babcddb105b81fbc8 to your computer and use it in GitHub Desktop.

Select an option

Save pixelhandler/cf365027d26b856babcddb105b81fbc8 to your computer and use it in GitHub Desktop.
Priority Nudge — Claude CLI focus nudges on a 25/5 Pomodoro loop (macOS)

Priority Nudge

A macOS script that uses Claude CLI to read your daily log and send you periodic focus nudges as native notifications.

It runs on a 25/5 Pomodoro-style loop — nudge, wait 25 minutes, nudge, wait 5 minutes, repeat — from a configurable start time until your configured end-of-day.

How It Works

Each cycle, the script:

  1. Reads your daily markdown log file (e.g. ~/notes/2026-03-04.md)
  2. Sends the contents to Claude CLI with a prompt that prioritizes:
    • Meetings starting within the next 60 minutes
    • Highlighted items wrapped in ==double equals==
    • Fallback to the most important pending item
  3. Displays Claude's 2-line nudge as a macOS notification

Prerequisites

  • macOS (uses osascript for notifications)
  • Claude CLI installed and authenticated
  • A daily log file in markdown format, named by date (YYYY-MM-DD.md)

Configuration

All settings are configurable via environment variables. Defaults are shown below.

Variable Default Description
CLAUDE claude Path to the Claude CLI binary
LOG_DIR $HOME/notes Directory containing daily log files
TZ America/Los_Angeles Timezone for time display and scheduling
END_HOUR 15 Hour (24h) when the script stops (3 PM)
END_MIN 0 Minute when the script stops

Installation

1. Save the script

mkdir -p ~/.claude/scripts
curl -o ~/.claude/scripts/priority-nudge.sh \
  "RAW_GIST_URL/priority-nudge.sh"
chmod +x ~/.claude/scripts/priority-nudge.sh

Or copy priority-nudge.sh from this gist manually.

2. Create the log directory

mkdir -p ~/.claude/logs

3. Test it

bash ~/.claude/scripts/priority-nudge.sh --once

You should see a macOS notification with a focus nudge based on today's log. If the log file doesn't exist yet, Claude will tell you.

4. Set up automatic scheduling (optional)

To run the script automatically on weekday mornings, use the included launchd plist template.

Edit the plist:

Open com.user.claude-priority-nudge.plist and replace these placeholders:

Placeholder Replace with
__USERNAME__ Your macOS username (run whoami)
__SCRIPT_PATH__ Full path to priority-nudge.sh

Install it:

cp com.user.claude-priority-nudge.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.user.claude-priority-nudge.plist

Verify it loaded:

launchctl list | grep priority-nudge

5. Customize the schedule

The default schedule starts at 6:35 AM, Monday–Friday. Edit the StartCalendarInterval entries in the plist to change this. The Hour and Minute keys control when the loop begins each day. The script itself handles when to stop (via END_HOUR/END_MIN).

Uninstall

launchctl unload ~/Library/LaunchAgents/com.user.claude-priority-nudge.plist
rm ~/Library/LaunchAgents/com.user.claude-priority-nudge.plist
rm ~/.claude/scripts/priority-nudge.sh

Troubleshooting

  • No notification? Check System Settings > Notifications > Script Editor (or Terminal). Ensure notifications are allowed.
  • "Claude unavailable"? Make sure claude is in your PATH or set the CLAUDE env var to the full path.
  • macOS Focus/DND will suppress notifications. The nudge still logs to ~/.claude/logs/priority-nudge.log.
  • Check logs: tail -f ~/.claude/logs/priority-nudge.log and ~/.claude/logs/priority-nudge-stderr.log (if using launchd).

Daily Log Format

The script works with any markdown file, but nudges are best when your log uses bullet journal notation.

Log Template

  • Task
  • * Priority
  • Task complete
  • > Task migrated (moved forward)
  • < Task scheduled (moved to calendar)
  • Note
  • Event
  • ! Idea
  • ? Explore
  • = Sentiment

Bullet Points Key

Symbol Meaning
Task (to do)
Task (completed)
* Task (priority)
> Migrated (moved to another day)
< Scheduled (added to calendar)
~~struck~~ Cancelled / irrelevant
Event
Note / observation
! Inspiration / great idea
? Explore / research later
= Sentiment / feeling

Example Daily Log

## Meetings
- ○ 7:00 AM: Standup and Learnings
- ○ 9:30 AM: Jane / John
- ○ 12:30 PM: Lunch
- ○ 1:00 PM: AI Workflow Shareout

---

# Daily Log
- `>` [TASK-1](https://example.com/issue/TASK-1) Sync — PR ready, may escalate to L1
	- `-` In stand up Jane asked to ==move to Friday== for product review
- `` [TASK-2](https://example.com/issue/TASK-2) Export — awaiting repro info from John
	- `-` Demo of bug reproduction and fix
	- `-` Learned need to run same db for same seed and setup for main and bugfix branch
	- `√` John provided confirmation
	- `-` "it's related to duplicate names"
- `` [PR #42](https://example.com/pull/42) review for Jane — [TASK-3](https://example.com/issue/TASK-3) Index Page
- `` Start (hand off from Jane) [TASK-3](https://example.com/issue/TASK-3) Index Page

The script's prompt looks for:

  1. Meetings starting within 60 minutes (the event bullets)
  2. Focus items wrapped in ==double equals== (e.g. ==move to Friday==)
  3. Fallback to the most important pending task
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.user.claude-priority-nudge</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>__SCRIPT_PATH__</string>
</array>
<!-- Weekdays only: 1=Mon, 2=Tue, 3=Wed, 4=Thu, 5=Fri -->
<key>StartCalendarInterval</key>
<array>
<dict>
<key>Weekday</key><integer>1</integer>
<key>Hour</key><integer>6</integer>
<key>Minute</key><integer>35</integer>
</dict>
<dict>
<key>Weekday</key><integer>2</integer>
<key>Hour</key><integer>6</integer>
<key>Minute</key><integer>35</integer>
</dict>
<dict>
<key>Weekday</key><integer>3</integer>
<key>Hour</key><integer>6</integer>
<key>Minute</key><integer>35</integer>
</dict>
<dict>
<key>Weekday</key><integer>4</integer>
<key>Hour</key><integer>6</integer>
<key>Minute</key><integer>35</integer>
</dict>
<dict>
<key>Weekday</key><integer>5</integer>
<key>Hour</key><integer>6</integer>
<key>Minute</key><integer>35</integer>
</dict>
</array>
<key>StandardOutPath</key>
<string>/Users/__USERNAME__/.claude/logs/priority-nudge-stdout.log</string>
<key>StandardErrorPath</key>
<string>/Users/__USERNAME__/.claude/logs/priority-nudge-stderr.log</string>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
<key>HOME</key>
<string>/Users/__USERNAME__</string>
</dict>
</dict>
</plist>
#!/bin/bash
# Priority Nudge — 25/5 alternating Claude CLI focus nudges
# Runs from a configurable start time until END_HOUR:END_MIN, weekdays only
# See README.md for setup and configuration
set -euo pipefail
unset CLAUDECODE 2>/dev/null || true # Allow running from within Claude Code sessions
export TZ="${TZ:-America/Los_Angeles}"
CLAUDE="${CLAUDE:-claude}"
LOG_DIR="${LOG_DIR:-$HOME/notes}"
END_HOUR="${END_HOUR:-15}" # 3:00 PM
END_MIN="${END_MIN:-0}"
mkdir -p "$HOME/.claude/logs"
now_minutes() {
echo $(( $(date +%-H) * 60 + $(date +%-M) ))
}
past_end() {
[ "$(now_minutes)" -ge $(( END_HOUR * 60 + END_MIN )) ]
}
nudge() {
local today
today=$(date +%Y-%m-%d)
local log_file="$LOG_DIR/$today.md"
local time_now
time_now=$(date +"%I:%M %p %Z")
local prompt="It is $time_now. Read my daily log at $log_file.
Priority order for your nudge:
1. MEETINGS — if any meeting starts within the next 60 minutes, that is the top priority. Mention the meeting time and subject.
2. FOCUS — if no upcoming meeting, items wrapped in ==double equals== (e.g. ==next==) indicate my primary focus. Nudge me on those.
3. FALLBACK — if neither, pick the most important pending item.
Give me a 2-line nudge: (1) what I should focus on right now, (2) what's coming up next. Be concise and direct. Use plain text only — no markdown, no asterisks, no formatting symbols."
local output
output=$("$CLAUDE" -p "$prompt" --output-format text 2>/dev/null) || output="Claude unavailable"
# macOS notification (truncated to 200 chars for display)
local short="${output:0:200}"
osascript -e "display notification \"$short\" with title \"Priority Nudge\" subtitle \"$time_now\"" 2>/dev/null || true
# Also log to file
echo "[$time_now] $output" >> "$HOME/.claude/logs/priority-nudge.log"
}
# --once: run a single nudge and exit (skips time check and loop)
if [[ "${1:-}" == "--once" ]]; then
nudge
exit 0
fi
# Main loop: 25 min gap, run, 5 min gap, run, repeat
while true; do
past_end && exit 0
nudge
sleep $((25 * 60))
past_end && exit 0
nudge
sleep $((5 * 60))
done
@pixelhandler
Copy link
Author

Screenshot 2026-03-04 at 9 54 46 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment