Skip to content

dortort/claude-code-scheduler

Repository files navigation

Scheduler logo

@dortort/scheduler

CI License: MIT Node.js >= 18 TypeScript

Schedule recurring and one-time AI tasks with Claude Code — powered by native OS schedulers (launchd / crontab).

Features

Scheduling

  • Natural language — "every weekday at 9am", "daily at 5pm", "every Monday at 10am"
  • Cron expressions — standard 5-field cron syntax with full validation
  • One-time tasks — schedule a task to run once at a specific time

Execution

  • Worktree isolation — run tasks in isolated git worktrees to avoid interfering with your working copy
  • Shared executor — single Node.js executor for all tasks, reading config at runtime (no per-task wrapper scripts)
  • Run-to-run memory — optional context injection from previous output so recurring tasks focus on new/changed items

Operations

  • Execution history — JSONL-based history with filtering by status, task, and project
  • Log management — stdout/stderr capture with rotation and cleanup
  • Security built-in — env blocklist, sensitive file detection, shell escaping, trust boundary enforcement

Requirements

  • Node.js >= 18
  • Claude Code CLI (claude)
  • macOS (launchd) or Linux (crontab)

Quick Start

claude plugin install @dortort/scheduler

Then in any Claude Code session:

"Schedule a daily code review at 9am"

The plugin handles cron setup, OS scheduler registration, and worktree isolation automatically.

Or for local development:

claude --plugin-dir /path/to/claude-code-scheduler

Commands

Command Description
/scheduler:add Add a new scheduled task (NL or cron)
/scheduler:list List all configured tasks with status
/scheduler:edit Modify a task's schedule, command, or settings
/scheduler:remove Remove a task by ID or name
/scheduler:enable Enable a disabled task
/scheduler:disable Disable a task without removing it
/scheduler:status Health check for the scheduling system
/scheduler:run Manually trigger a task
/scheduler:logs View stdout/stderr logs for a task
/scheduler:history View execution history with filters

Architecture

The plugin is organized as a set of focused modules:

src/
  types.ts              Zod schemas, task factory, validation
  config.ts             Config load/save/merge with trust boundaries
  index.ts              Public API re-exports
  cli/
    executor.ts         Shared task executor (direct + worktree modes)
    index.ts            CLI entry point (add, remove, update, sync, init, migrate)
    platform.ts         Platform-aware OS scheduler registration
    commands/            CLI subcommands (add, remove, update, sync, init, migrate)
  cron/
    parser.ts           Cron validation, NL-to-cron, next runs
    humanizer.ts        Cron-to-human-readable, date/duration formatting
  logs/
    index.ts            Log dir management, rotation, cleanup
  history/
    index.ts            JSONL execution history, querying, cleanup
  vcs/
    index.ts            Git worktree lifecycle, sensitive file detection
  schedulers/
    base.ts             Shared scheduler utilities
    darwin.ts           macOS launchd plist generation
    linux.ts            Linux crontab management with markers
    index.ts            Platform detection factory
  utils/
    shell.ts            Shell escaping, input sanitization
    exec.ts             Thin child_process wrapper with DI

Configuration

Tasks are stored in JSON config files:

  • Global: ~/.claude/schedules.json — your personal tasks
  • Project: <project>/.claude/schedules.json — shared team tasks

Global config takes precedence on ID collision. Project configs cannot set skipPermissions.


Development

npm install
npm test            # Unit/integration tests
npm run test:e2e    # E2E tests via Claude CLI subprocess (~9 min)
npm run lint        # ESLint with typescript-eslint
npm run typecheck   # Type checking only
npm run build       # TypeScript compilation
npm run test:coverage  # Tests with coverage report

CI runs automatically on every push and PR to main (lint, typecheck, test on Node 18+22, build).

Testing

The test suite has two tiers:

  • Unit/Integration (npm test) — fast tests covering library functions with no external dependencies.
  • E2E (npm run test:e2e) — subprocess tests that invoke each plugin command through claude --plugin-dir. Requires the claude CLI to be installed and takes ~9 minutes. Skipped automatically if the CLI is not available. E2E tests use temp directories with fixture data and assert on output patterns (not exact strings) to handle Claude's non-deterministic phrasing.

Releasing

Publishing is automated via GitHub Actions when a GitHub Release is created. The release workflow requires:

  • An npm environment configured in the repository settings
  • An NPM_TOKEN secret with publish access

Branch Protection (Recommended)

Enable branch protection on main requiring these status checks to pass:

  • Lint
  • Typecheck
  • Test (Node 18)
  • Test (Node 22)
  • Build

Contributing

  1. Fork the repo and create a feature branch from main
  2. Install dependencies: npm install
  3. Make your changes — the project uses TypeScript in strict mode with ESLint
  4. Run checks before submitting:
    npm run lint        # ESLint
    npm run typecheck   # TypeScript
    npm test            # Unit/integration tests
    npm run build       # Compilation
  5. Open a pull request against main

See Also


License

MIT

About

Schedule recurring AI tasks with Claude Code using cron and natural language

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors