Picture this: You sit down at your Mac with a coffee, planning to "quickly check a few emails." Next thing you know, it's 3 PM, your coffee has achieved room temperature, and you're wondering if you've entered some sort of time vortex. Sound familiar?
If you're nodding your head (and possibly rubbing your stiff neck), you're not alone. In our hyper-connected world, time has a sneaky way of slipping through our fingers like sand – or like that last slice of pizza when you're not paying attention.
That's why I built a session tracker that lives right in your Mac's menu bar. It's like having a gentle, persistent friend who reminds you to take breaks, tracks your work patterns, and occasionally judges your life choices (in the nicest possible way).
What Does This Digital Time Wizard Do?
Our session tracker is basically a sophisticated time-keeping ninja that:
Tracks Your Current Work Session - It knows when you start working and keeps a running timer
Detects Sleep/Wake Cycles - Smartly figures out when you've been away from your computer
Logs Daily Activity - Keeps a record of all your work sessions throughout the day
Sends Gentle Reminders - Politely suggests you take a break after an hour (because your eyes and back will thank you)
Shows Beautiful Stats - Displays your current session time and daily totals right in your menu bar
Think of it as a Fitbit for your productivity, but instead of counting steps, it's counting the minutes you spend glued to your screen.
The Magic Behind the Curtain
This isn't just any ordinary timer script – it's a surprisingly sophisticated piece of bash wizardry that handles all sorts of edge cases:
Smart Session Detection
The script doesn't just start counting from when you run it. It's smart enough to:
Detect when your Mac has been rebooted
Figure out when you've been away (sleeping, lunch break, or that inevitable YouTube rabbit hole)
Resume tracking seamlessly when you return
Intelligent Time Gap Detection
Here's where it gets clever: the script monitors for gaps in activity longer than 2 minutes. If it detects you've been away, it logs your previous session and starts a new one. It's like having a personal assistant who's really good at reading between the lines.
Cross-Reboot Persistence
Even if you restart your Mac, the script remembers your previous session and can estimate when it ended. It's like having a time-tracking elephant – it never forgets.
Setting Up Your New Digital Productivity Buddy
Ready to get this bad boy running on your Mac? Here's how to set it up:
Prerequisites
First, you'll need xbar (formerly BitBar), which is a fantastic tool that lets you put the output of any script in your Mac's menu bar:
brew install xbar
If you don't have Homebrew installed, grab it from brew.sh first.
Optional but Recommended: Better Notifications
For prettier notifications, install terminal-notifier:
brew install terminal-notifier
Don't worry if you skip this – the script will fall back to macOS's built-in notification system.
Installing the Script
- Create the xbar plugins directory (if it doesn't exist):
mkdir -p "~/Library/ApplicationSupport/xbar/plugins"
- Create the script file:
nano "~/Library/Application Support/xbar/plugins/current-session.1m.sh"
- Copy and paste the following code:
#!/bin/bash
export PATH="/usr/local/bin:/opt/homebrew/bin:$PATH"
SESSION_FILE="/tmp/current_session_start"
DAILY_LOG_FILE="/tmp/daily_activity_$(date +%Y%m%d)"
CURRENT_TIME=$(date +%s)
UPTIME_SECONDS=$(sysctl -n kern.boottime | awk '{print $4}' | sed 's/,//')
BOOT_TIME=$(date -r "$UPTIME_SECONDS" +%s 2>/dev/null || echo "$CURRENT_TIME")
if [ ! -f "$SESSION_FILE" ]; then
SESSION_START="$CURRENT_TIME"
SESSION_FILE_NEEDS_UPDATE=true
else
STORED_TIME=$(cat "$SESSION_FILE")
if ! [[ "$STORED_TIME" =~ ^[0-9]+$ ]] || [ "$STORED_TIME" -lt 1000000000 ] || [ "$STORED_TIME" -gt $((CURRENT_TIME + 86400)) ]; then
SESSION_START="$CURRENT_TIME"
SESSION_FILE_NEEDS_UPDATE=true
elif [ "$STORED_TIME" -lt "$BOOT_TIME" ]; then
SESSION_START="$CURRENT_TIME"
SESSION_FILE_NEEDS_UPDATE=true
else
LAST_CHECK_FILE="/tmp/last_session_check"
if [ -f "$LAST_CHECK_FILE" ]; then
LAST_CHECK=$(cat "$LAST_CHECK_FILE")
TIME_GAP=$((CURRENT_TIME - LAST_CHECK))
if [ "$TIME_GAP" -gt 120 ]; then
SESSION_START="$CURRENT_TIME"
SESSION_FILE_NEEDS_UPDATE=true
else
SESSION_START="$STORED_TIME"
SESSION_FILE_NEEDS_UPDATE=false
fi
else
SESSION_START="$STORED_TIME"
SESSION_FILE_NEEDS_UPDATE=false
fi
fi
fi
LAST_CHECK_FILE="/tmp/last_session_check"
NEW_SESSION_STARTED=false
if [ -f "$LAST_CHECK_FILE" ] && [ -f "$SESSION_FILE" ]; then
LAST_CHECK=$(cat "$LAST_CHECK_FILE")
PREV_SESSION_START=$(cat "$SESSION_FILE")
TIME_GAP=$((CURRENT_TIME - LAST_CHECK))
if [ "$TIME_GAP" -gt 120 ] && [ "$PREV_SESSION_START" -lt "$LAST_CHECK" ]; then
PREV_SESSION_DURATION=$((LAST_CHECK - PREV_SESSION_START))
if [ "$PREV_SESSION_DURATION" -gt 60 ]; then
echo "$PREV_SESSION_START $LAST_CHECK $PREV_SESSION_DURATION" >> "$DAILY_LOG_FILE"
fi
NEW_SESSION_STARTED=true
fi
elif [ ! -f "$LAST_CHECK_FILE" ] && [ -f "$SESSION_FILE" ]; then
PREV_SESSION_START=$(cat "$SESSION_FILE")
if [ "$PREV_SESSION_START" -lt "$BOOT_TIME" ]; then
PREV_SESSION_DURATION=$((BOOT_TIME - PREV_SESSION_START))
if [ "$PREV_SESSION_DURATION" -gt 60 ] && [ "$PREV_SESSION_DURATION" -lt 86400 ]; then
echo "$PREV_SESSION_START $BOOT_TIME $PREV_SESSION_DURATION" >> "$DAILY_LOG_FILE"
fi
fi
fi
if [ "$SESSION_FILE_NEEDS_UPDATE" = true ]; then
echo "$SESSION_START" > "$SESSION_FILE"
rm -f "/tmp/last_rest_notification"
fi
echo "$CURRENT_TIME" > "/tmp/last_session_check"
SESSION_DURATION=$((CURRENT_TIME - SESSION_START))
NOTIFICATION_FILE="/tmp/last_rest_notification"
if [ "$SESSION_DURATION" -gt 3600 ]; then
CURRENT_HOUR=$((SESSION_DURATION / 3600))
if [ -f "$NOTIFICATION_FILE" ]; then
LAST_NOTIFICATION_HOUR=$(cat "$NOTIFICATION_FILE")
else
LAST_NOTIFICATION_HOUR=0
fi
if [ "$CURRENT_HOUR" -gt "$LAST_NOTIFICATION_HOUR" ]; then
if command -v terminal-notifier >/dev/null 2>&1; then
terminal-notifier -title "Session Tracker" -subtitle "Time for a rest" -message "You've been working for ${CURRENT_HOUR} hour(s). Consider taking a break!" -sound funk -group "session-tracker"
else
osascript -e "display notification \"You've been working for ${CURRENT_HOUR} hour(s). Consider taking a break!\" with title \"Session Tracker\" subtitle \"Time for a rest\" sound name \"Glass\""
fi
echo "$CURRENT_HOUR" > "$NOTIFICATION_FILE"
fi
fi
TOTAL_TODAY=0
if [ -f "$DAILY_LOG_FILE" ]; then
while read -r start_time end_time duration; do
if [ -n "$duration" ] && [ "$duration" -gt 0 ]; then
TOTAL_TODAY=$((TOTAL_TODAY + duration))
fi
done < "$DAILY_LOG_FILE"
fi
TOTAL_TODAY=$((TOTAL_TODAY + SESSION_DURATION))
DURATION_HOURS=$((SESSION_DURATION / 3600))
DURATION_MINUTES=$(( (SESSION_DURATION % 3600) / 60 ))
DURATION_SECONDS=$((SESSION_DURATION % 60))
TOTAL_HOURS=$((TOTAL_TODAY / 3600))
TOTAL_MINUTES=$(( (TOTAL_TODAY % 3600) / 60 ))
if [ $DURATION_HOURS -gt 0 ]; then
DURATION_STRING="${DURATION_HOURS}h ${DURATION_MINUTES}m"
else
DURATION_STRING="${DURATION_MINUTES}m"
fi
if [ $TOTAL_HOURS -gt 0 ]; then
TOTAL_STRING="${TOTAL_HOURS}h ${TOTAL_MINUTES}m"
else
TOTAL_STRING="${TOTAL_MINUTES}m"
fi
if [ "$SESSION_DURATION" -gt 3600 ]; then
echo "⚠️ $DURATION_STRING | size=10"
else
echo "🕒 $DURATION_STRING | size=10"
fi
echo "---"
echo "📊 Current Session: $DURATION_STRING"
echo "📅 Today Total: $TOTAL_STRING"
if [ -f "$DAILY_LOG_FILE" ] && [ -s "$DAILY_LOG_FILE" ]; then
SESSION_COUNT=$(wc -l < "$DAILY_LOG_FILE")
echo "🔢 Sessions Today: $((SESSION_COUNT + 1))"
fi
if [ "$SESSION_DURATION" -gt 3600 ]; then
echo "---"
echo "⏰ Take a break! You've been working for over an hour | color=orange"
fi
- Make it executable:
chmod +x "~/Library/Application Support/xbar/plugins/current-session.1m.sh"
Start xbar and refresh:
Understanding the Code: A Gentle Journey Through Bash Land
Let's break down what this script does, step by step:
The Setup Phase
SESSION_FILE="/tmp/current_session_start"
DAILY_LOG_FILE="/tmp/daily_activity_$(date +%Y%m%d)"
We store our session data in temporary files. The daily log file includes the date, so each day gets its own log file. It's like having a new diary page for each day!
The Detective Work
UPTIME_SECONDS=$(sysctl -n kern.boottime | awk '{print $4}' | sed 's/,//')
BOOT_TIME=$(date -r "$UPTIME_SECONDS" +%s 2>/dev/null || echo "$CURRENT_TIME")
This is where we get all CSI about when your Mac was last booted. We use this to figure out if your session file is from before a reboot.
The Smart Session Logic
The script has several scenarios it handles:
First run ever: Creates a new session
File exists but invalid: Starts fresh (protects against corrupted data)
File is from before reboot: Starts a new session post-reboot
Checking for sleep gaps: If there's a gap > 2 minutes, it assumes you were away
The Notification System
if [ "$SESSION_DURATION" -gt 3600 ]; then
fi
After an hour of work, the script gently reminds you to take a break. It's like having a caring friend who's also really good at math.
What You'll See in Action
Once everything is running, you'll see:
The Beauty of Simplicity
What I love about this solution is that it's:
Lightweight: Uses minimal system resources
Unobtrusive: Sits quietly in your menu bar
Smart: Handles edge cases you didn't even think about
Customizable: Easy to modify for your specific needs
Customization Ideas
Want to make it your own? Here are some ideas:
Change the break reminder interval: Modify the 3600 seconds (1 hour) to whatever works for you
Add different notification sounds: Change the sound funk to sound glass, sound ping, etc.
Modify the time gap detection: Change the 120 seconds gap threshold
Add more detailed logging: Include timestamps, session names, or project tags
The Philosophical Side: Why This Matters
In our always-on world, this simple script serves a deeper purpose. It's not just about tracking time – it's about being mindful of how we spend our most precious resource. By making our work patterns visible, we can:
Recognize unhealthy patterns (like those 4-hour coding binges)
Celebrate productivity (look at all those completed sessions!)
Build better habits (those break reminders really do help)
Understand our rhythms (maybe you're most productive in the morning?)
Wrapping Up
Building this session tracker was a fun exercise in bash scripting and practical problem-solving. It started as a simple "how long have I been working?" question and evolved into a surprisingly sophisticated time-tracking system.
The best part? It's taught me to actually take breaks. Turns out, when your computer politely suggests you step away from the screen, you're more likely to listen than when your back is screaming at you.
So go ahead, give it a try! Your future self (and your neck) will thank you. And who knows? You might just discover that you're either more or less productive than you thought. Either way, at least you'll know for sure.