Fix Focus App High CPU Usage on macOS

Problem

The Focus app (com.ftustudio.focustime) - a Pomodoro timer - consumes ~50% CPU constantly, even when idle.

Root Cause

Stack sampling revealed the app redraws its menu bar icon at an excessive rate (~60 times/second) instead of once per second:

414 samples: -[NSStatusItem _updateReplicantsUnlessMenuIsTracking:]
400 samples: -[NSStatusItem _updateReplicant:]
218 samples: -[NSStatusItem _redrawReplicantSnapshot:sourceView:]

Each tick triggers expensive bitmap capture, CALayer rendering, and compositing for a simple countdown timer that only needs 1 update/second.

Solution

Since the app is sandboxed with hardened runtime (no dylib injection possible) and the developer is unresponsive, we use a duty-cycle throttler that pauses/resumes the process.

Install

# Create throttle script
mkdir -p ~/.local/bin
cat > ~/.local/bin/throttle-focus << 'EOF'
#!/usr/bin/env python3
"""Throttle Focus app to reduce CPU usage using duty-cycle approach."""
import subprocess
import signal
import sys
import time

TARGET = "Focus"
RUN_SEC = 0.05    # Run for 50ms
PAUSE_SEC = 0.95  # Pause for 950ms (~5% duty cycle)

def get_pid():
    try:
        result = subprocess.run(["pgrep", "-x", TARGET], capture_output=True, text=True)
        pids = result.stdout.strip().split('\n')
        return int(pids[0]) if pids[0] else None
    except:
        return None

def send_signal(pid, sig):
    try:
        subprocess.run(["kill", f"-{sig}", str(pid)], capture_output=True)
    except:
        pass

current_pid = None

def cleanup(signum=None, frame=None):
    if current_pid:
        send_signal(current_pid, "CONT")
    print("\nThrottling stopped.")
    sys.exit(0)

signal.signal(signal.SIGINT, cleanup)
signal.signal(signal.SIGTERM, cleanup)

print(f"Throttling {TARGET} (run {RUN_SEC*1000:.0f}ms / pause {PAUSE_SEC*1000:.0f}ms)")
print("Press Ctrl+C to stop")

while True:
    pid = get_pid()
    if not pid:
        print(f"Waiting for {TARGET} to start...")
        time.sleep(2)
        continue

    current_pid = pid
    send_signal(pid, "CONT")
    time.sleep(RUN_SEC)
    send_signal(pid, "STOP")
    time.sleep(PAUSE_SEC)
EOF
chmod +x ~/.local/bin/throttle-focus

# Create Launch Agent for auto-start
cat > ~/Library/LaunchAgents/com.local.throttle-focus.plist << 'EOF'
<?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.local.throttle-focus</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/python3</string>
        <string>/Users/hao/.local/bin/throttle-focus</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>StandardOutPath</key>
    <string>/tmp/throttle-focus.log</string>
    <key>StandardErrorPath</key>
    <string>/tmp/throttle-focus.log</string>
</dict>
</plist>
EOF

# Load the agent
launchctl load ~/Library/LaunchAgents/com.local.throttle-focus.plist

Management Commands

# Stop throttling
launchctl unload ~/Library/LaunchAgents/com.local.throttle-focus.plist

# Resume throttling
launchctl load ~/Library/LaunchAgents/com.local.throttle-focus.plist

# Check status
launchctl list | grep throttle

# View logs
cat /tmp/throttle-focus.log

# Uninstall completely
launchctl unload ~/Library/LaunchAgents/com.local.throttle-focus.plist
rm ~/Library/LaunchAgents/com.local.throttle-focus.plist
rm ~/.local/bin/throttle-focus

Results

Metric Before After
CPU Usage ~48% ~2%
Menu bar updates ~60/sec 1/sec

The timer still functions correctly - it just updates once per second instead of continuously.