What is Tide?
Tide is a macOS scheduler for AI agents — run Claude Code, GitHub Copilot, and Gemini tasks on a recurring interval via launchd, with a terminal UI to manage runs, logs, and notifications.
Why this exists
AI coding assistants don't have a persistent scheduler — any built-in scheduling only fires while the app is open. The moment you close it, all scheduled tasks stop.
Tide solves this by delegating execution to macOS launchd (~/Library/LaunchAgents). Jobs fire on schedule regardless of whether any app is open.
Use cases
- Daily standup summaries (git log, open PRs, ticket status)
- Recurring code generation or analysis tasks
- Automated health checks that report back to you
- Any "run a prompt on a schedule" scenario where you need it to keep running unattended
How it works
Tide has two distinct layers:
launchd (scheduling)
└─ tide.sh → agent-runner.js
├─ claude-code: @anthropic-ai/claude-agent-sdk
├─ copilot: @github/copilot-sdk
├─ gemini: ai-sdk-provider-gemini-cli + Vercel AI SDK
├─ streams output to ~/.tide/tasks/<id>/runs/<runId>/output.log
└─ writes run.json, notifications, rotates logs, prunes old runs
TUI (src/) — reads ~/.tide/, never writes to launchd except on create/enable/disable/delete- launchd owns the schedule. Each task is a plist in
~/Library/LaunchAgents/. launchd firestide.sh <id>on your configured interval. - tide.sh is a thin shim. It reads the
profilefrom the task's.mdfile and hands off toagent-runner.js. Forclaude-codeprofiles withtshauth, it wraps execution intsh awsto inject AWS credentials. - agent-runner.js owns the full run lifecycle: PID overlap detection, jitter, calling the agent plugin, streaming tokens to
output.login real time, writingrun.json, sending notifications, rotating logs, and pruning old runs. - The TUI polls
~/.tide/on an interval and callslaunchctl printper task to get live status. It only writes to launchd when you create, enable, disable, or delete a task.
Limitations
macOS only
Tide uses launchd and macOS-specific APIs (launchctl, osascript for notifications). It will not run on Linux or Windows.
Interval-only scheduling
Tide only supports interval-based schedules (every N minutes, hours, etc.). Calendar-based scheduling ("run at 9am daily") is not supported — see ADR-0001 for why.
Sleep and wake behaviour
launchd catches up missed StartInterval jobs on wake — if the interval elapsed while your Mac was asleep, the task fires once immediately on wake. This means tasks can fire at unpredictable clock times after a long sleep. A per-task jitter (0–min(interval/4, 300) seconds, assigned at creation) spreads tasks out so they don't all pile up on the same wake.