/schedule-add
Create a new scheduled task for recurring Claude Code execution (project)
> /plugin marketplace add jshchnz/claude-code-scheduler > /plugin install scheduler@claude-scheduler
How it fires
How this command gets triggered: by you, by Claude, or both.
- Fires itselfClaude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/schedule-add
Context preview
What this command does when you run it.
Create a new scheduled task for recurring Claude Code execution (project)
Command definition
schedule-add.mddescription: Create a new scheduled task for recurring Claude Code execution (project)
allowed-tools: Read, Write, Bash(cat:*), Bash(launchctl:*), Bash(crontab:*), Bash(schtasks:*)
Add Scheduled Task
Help the user create a new scheduled task with proper configuration.
Process
1. **Gather Task Information**
- Ask for a task name (required)
- Ask for description (optional)
- Ask for schedule - accept either:
- Cron expression (e.g., "0 9 * * 1-5")
- Natural language (e.g., "every weekday at 9am", "today at 3pm")
2. **Detect Schedule Type: One-Time vs Recurring**
**One-time indicators** (default to one-time):
- "today at 3pm"
- "tomorrow at noon"
- "next Tuesday at 2pm"
- "at 5:30 PM" (no recurring keyword)
- "January 15th at 9am"
**Recurring indicators**:
- "every day at 9am"
- "daily at 6pm"
- "weekly on Monday"
- "weekdays at 10am"
- "every 30 minutes"
- Explicit cron expression (e.g., "0 9 * * 1-5")
**Rule:** Unless "every", "daily", "weekly", "monthly", or similar recurring keywords are present, assume **one-time**.
3. **Configure Execution**
- Ask for the Claude command or prompt to execute
- Confirm working directory (default: current project)
- Ask if task needs autonomous execution (file edits, git operations, running commands)
- If yes: set `skipPermissions: true` and add `--dangerously-skip-permissions` flag
- If no (read-only analysis): omit the flag
- If task needs autonomous execution AND project is a git repo, ask about worktree isolation:
- If yes: set `worktree.enabled: true`
- Configure optional settings:
- `branchPrefix`: default "claude-task/"
- `remoteName`: default "origin"
4. **Validate and Confirm**
- For recurring: show cron expression and next 3 run times
- For one-time: show exact date/time
- Confirm with user before creating
5. **Create Task**
- Generate unique task ID
- For one-time: prefix ID with `once.`
- Register with native scheduler
macOS launchd Implementation
Recurring Task Plist
Filename: `com.claude.schedule.<id>.plist`
**IMPORTANT:**
- Do NOT use `<key>WorkingDirectory</key>` - it causes permission errors in background processes
- Do NOT use `~` in paths - launchd doesn't expand tilde. Use `$HOME` instead
- Use `cd` inside the bash command for working directory
<?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.claude.schedule.<id></string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>-c</string>
<string>cd "/path/to/project" && claude -p "your prompt" --dangerously-skip-permissions</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:$HOME/.local/bin</string>
</dict>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key><integer>10</integer>
<key>Minute</key><integer>0</integer>
</dict>
<key>StandardOutPath</key>
<string>$HOME/.claude/logs/<id>.log</string>
<key>StandardErrorPath</key>
<string>$HOME/.claude/logs/<id>.error.log</string>
<key>RunAtLoad</key>
<false/>
</dict>
</plist>One-Time Task Plist (Polling-Based, Self-Cleaning)
Filename: `com.claude.schedule.once.<id>.plist`
**IMPORTANT:**
- launchd's `StartCalendarInterval` with Month/Day creates a yearly recurring schedule, NOT one-time. Use polling instead
- Do NOT use `~` in paths - launchd doesn't expand tilde. Use `$HOME` instead
- Self-cleanup: delete plist with `rm` FIRST, then `launchctl bootout` (reverse order prevents race condition)
1. Calculate unix timestamp for target time: `date -j -f "%Y-%m-%d %H:%M" "2026-01-08 15:25" +%s` 2. Use `StartInterval: 60` to poll every minute 3. Use `RunAtLoad: true` to check immediately 4. Script compares timestamps, runs task, then self-cleans
<?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.claude.schedule.once.<id></string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>-c</string>
<string>TARGET=<unix_timestamp>; NOW=$(date +%s); if [ $NOW -ge $TARGET ]; then cd "/path/to/project" && claude -p "your prompt" --dangerously-skip-permissions >> "$HOME/.claude/logs/once.<id>.log" 2>&1; rm "$HOME/Library/LaunchAgents/com.claude.schedule.once.<id>.plist" 2>/dev/null; launchctl bootout gui/$(id -u)/com.claude.schedule.once.<id> 2>/dev/null; fi</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:$HOME/.local/bin</string>
</dict>
<key>StartInterval</key>
<integer>60</integer>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/claude-schedule-once.<id>.out</string>
<key>StandardErrorPath</key>
<string>/tmp/claude-schedule-once.<id>.err</string>
</dict>
</plist>**How it works:**
- Polls every 60 seconds AND checks immediately on load
- Compares current unix timestamp to target
- If time has passed: runs task, deletes plist, then unloads from launchd
- If time hasn't passed yet: exits silently, will retry in 60 seconds
- StandardOut/Error go to /tmp for debugging; main output is redirected to ~/.claude/logs/
Cron Quick Reference (for recurring tasks)
* * * * *
| | | | |
| | | | +-- Day of week (0-6, Sun=0)
| | | +---- Month (1-12)
| | +------ Day of month (1-31)
| +-------- Hour (0-23)
+---------- Minute (0-59)
**Common patterns:**
- `0 9 * * *` - Daily at 9:00 AM
- `0 9 * * 1-5` - Weekdays at 9:00 AM
-
Read more
description: Create a new scheduled task for recurring Claude Code execution (project) allowed-tools: Read, Write, Bash(cat:*), Bash(launchctl:*), Bash(crontab:*), Bash(schtasks:*)
Add Scheduled Task
Help the user create a new scheduled task with proper configuration.
Process
1. **Gather Task Information**
- Ask for a task name (required)
- Ask for description (optional)
- Ask for schedule - accept either:
- Cron expression (e.g., "0 9 * * 1-5")
- Natural language (e.g., "every weekday at 9am", "today at 3pm")
2. **Detect Schedule Type: One-Time vs Recurring**
**One-time indicators** (default to one-time):
- "today at 3pm"
- "tomorrow at noon"
- "next Tuesday at 2pm"
- "at 5:30 PM" (no recurring keyword)
- "January 15th at 9am"
**Recurring indicators**:
- "every day at 9am"
- "daily at 6pm"
- "weekly on Monday"
- "weekdays at 10am"
- "every 30 minutes"
- Explicit cron expression (e.g., "0 9 * * 1-5")
**Rule:** Unless "every", "daily", "weekly", "monthly", or similar recurring keywords are present, assume **one-time**.
3. **Configure Execution**
- Ask for the Claude command or prompt to execute
- Confirm working directory (default: current project)
- Ask if task needs autonomous execution (file edits, git operations, running commands)
- If yes: set `skipPermissions: true` and add `--dangerously-skip-permissions` flag
- If no (read-only analysis): omit the flag
- If task needs autonomous execution AND project is a git repo, ask about worktree isolation:
- If yes: set `worktree.enabled: true`
- Configure optional settings:
- `branchPrefix`: default "claude-task/"
- `remoteName`: default "origin"
4. **Validate and Confirm**
- For recurring: show cron expression and next 3 run times
- For one-time: show exact date/time
- Confirm with user before creating
5. **Create Task**
- Generate unique task ID
- For one-time: prefix ID with `once.`
- Register with native scheduler
macOS launchd Implementation
Recurring Task Plist
Filename: `com.claude.schedule.<id>.plist`
**IMPORTANT:**
- Do NOT use `<key>WorkingDirectory</key>` - it causes permission errors in background processes
- Do NOT use `~` in paths - launchd doesn't expand tilde. Use `$HOME` instead
- Use `cd` inside the bash command for working directory
<?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.claude.schedule.<id></string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>-c</string>
<string>cd "/path/to/project" && claude -p "your prompt" --dangerously-skip-permissions</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:$HOME/.local/bin</string>
</dict>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key><integer>10</integer>
<key>Minute</key><integer>0</integer>
</dict>
<key>StandardOutPath</key>
<string>$HOME/.claude/logs/<id>.log</string>
<key>StandardErrorPath</key>
<string>$HOME/.claude/logs/<id>.error.log</string>
<key>RunAtLoad</key>
<false/>
</dict>
</plist>One-Time Task Plist (Polling-Based, Self-Cleaning)
Filename: `com.claude.schedule.once.<id>.plist`
**IMPORTANT:**
- launchd's `StartCalendarInterval` with Month/Day creates a yearly recurring schedule, NOT one-time. Use polling instead
- Do NOT use `~` in paths - launchd doesn't expand tilde. Use `$HOME` instead
- Self-cleanup: delete plist with `rm` FIRST, then `launchctl bootout` (reverse order prevents race condition)
1. Calculate unix timestamp for target time: `date -j -f "%Y-%m-%d %H:%M" "2026-01-08 15:25" +%s` 2. Use `StartInterval: 60` to poll every minute 3. Use `RunAtLoad: true` to check immediately 4. Script compares timestamps, runs task, then self-cleans
<?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.claude.schedule.once.<id></string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>-c</string>
<string>TARGET=<unix_timestamp>; NOW=$(date +%s); if [ $NOW -ge $TARGET ]; then cd "/path/to/project" && claude -p "your prompt" --dangerously-skip-permissions >> "$HOME/.claude/logs/once.<id>.log" 2>&1; rm "$HOME/Library/LaunchAgents/com.claude.schedule.once.<id>.plist" 2>/dev/null; launchctl bootout gui/$(id -u)/com.claude.schedule.once.<id> 2>/dev/null; fi</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:$HOME/.local/bin</string>
</dict>
<key>StartInterval</key>
<integer>60</integer>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/claude-schedule-once.<id>.out</string>
<key>StandardErrorPath</key>
<string>/tmp/claude-schedule-once.<id>.err</string>
</dict>
</plist>**How it works:**
- Polls every 60 seconds AND checks immediately on load
- Compares current unix timestamp to target
- If time has passed: runs task, deletes plist, then unloads from launchd
- If time hasn't passed yet: exits silently, will retry in 60 seconds
- StandardOut/Error go to /tmp for debugging; main output is redirected to ~/.claude/logs/
Cron Quick Reference (for recurring tasks)
* * * * * | | | | | | | | | +-- Day of week (0-6, Sun=0) | | | +---- Month (1-12) | | +------ Day of month (1-31) | +-------- Hour (0-23) +---------- Minute (0-59)
**Common patterns:**
- `0 9 * * *` - Daily at 9:00 AM
- `0 9 * * 1-5` - Weekdays at 9:00 AM
-
Put Claude on autopilot. Schedule code reviews, security audits, and anything else - Claude Code runs them automatically, even while you sleep.
Repo: jshchnz/claude-code-scheduler
Other commands on scheduler.
- /schedule-history
View execution history for all scheduled tasks with interactive selection
Open command - /schedule-list
List all scheduled tasks with their status and next run times (project)
Open command - /schedule-logs
View execution logs for scheduled tasks
Open command - /schedule-remove
Remove a scheduled task by ID or name
Open command - /schedule-run
Manually run a scheduled task immediately
Open command - /schedule-status
Check the health and status of the scheduler system
Open command

