Skip to content
Development
Skill

/headless-cron-creator

Generate headless Claude Code cron jobs with safety.

From plugin
vexjoy-agent
44964 skills198 agents12 commands83 hooks

Claude Code

$ npx -y skills add notque/vexjoy-agent --skill headless-cron-creator --agent claude-code

SKILL.md

headless-cron-creator.SKILL.md
name: headless-cron-creator
promoted_to: deploy
description: "Generate headless Claude Code cron jobs with safety."
user-invocable: false
argument-hint: "<name> <schedule> <prompt>"
agent: python-general-engineer
allowed-tools:
  - Read
  - Write
  - Bash
  - Edit
  - Glob
  - Grep
routing:
  triggers:
    - "create cron job"
    - "scheduled task"
    - "headless agent"
    - "background automation"
    - "recurring agent"
  category: process
  pairs_with:
    - deploy

Headless Cron Creator Skill

Generate headless Claude Code cron jobs from a task description and schedule. Creates a wrapper script with safety mechanisms (lockfile, budget cap, dry-run default, logging) and installs crontab entries. All crontab mutations go through `scripts/crontab-manager.py`, which writes to temp files and creates timestamped backups in `~/.claude/crontab-backups/` before every change -- never pipe directly to `crontab -` because a mid-stream pipe failure wipes the entire crontab.

Instructions

Phase 1: PARSE

Extract job parameters from the user's request.

**Required parameters**:

  • **name** -- short kebab-case identifier (e.g., `reddit-automod`, `feed-health-check`)
  • **prompt** -- what Claude should do each run (natural language)
  • **schedule** -- cron expression or human-readable interval

**Optional parameters** (with defaults):

  • **workdir** -- where to `cd` before running (default: current repo root)
  • **budget** -- max USD per run (default: `2.00`; user may override)
  • **allowed-tools** -- which tools the headless session can use (default: `Bash Read`; user may override)
  • **logdir** -- where to store logs (default: `{workdir}/cron-logs/{name}`)

**Human-readable schedule conversion** -- use off-minutes (7, 23, 47) instead of `:00`/`:30` because every cron job on the system fires at round minutes, creating load spikes:

| Human Input | Cron Expression | |-------------|----------------| | every 12 hours | `7 */12 * * *` | | twice daily | `7 8,20 * * *` | | hourly | `23 * * * *` | | daily at 6am | `7 6 * * *` | | weekly on sunday | `7 9 * * 0` | | every 30 minutes | `*/30 * * * *` |

**Gate**: All required parameters extracted. Proceed to Phase 2.

Phase 2: GENERATE

Create the wrapper script using `crontab-manager.py generate-wrapper`. Embed the prompt via bash heredoc to avoid escaping issues.

python3 ~/.claude/scripts/crontab-manager.py generate-wrapper \
  --name "{name}" \
  --prompt "{prompt}" \
  --schedule "{schedule}" \
  --workdir "{workdir}" \
  --budget "{budget}" \
  --allowed-tools "{allowed_tools}"

Review the generated script. Verify it contains:

  • [ ] `set -euo pipefail`
  • [ ] `flock` lockfile -- prevents concurrent runs of the same job
  • [ ] `--permission-mode auto` -- never use `--dangerously-skip-permissions` (auto is sufficient) or `--bare` (breaks OAuth/keychain auth)
  • [ ] `--max-budget-usd` -- caps spend per run (default 2.00 USD)
  • [ ] `--no-session-persistence`
  • [ ] `--allowedTools`
  • [ ] `tee` to per-run timestamped log file
  • [ ] Dry-run/execute toggle -- scripts do nothing destructive without `--execute`
  • [ ] Exit code propagation via `PIPESTATUS[0]`

Do not use the `CronCreate` tool -- it is session-scoped (dies when the session ends, auto-expires after 7 days). Use system `crontab` via `crontab-manager.py` instead.

**Gate**: Script generated and reviewed. Proceed to Phase 3.

Phase 3: VALIDATE

Verify the generated script meets cron best practices.

1. Run the script in dry-run mode:

   bash -n scripts/{name}-cron.sh  # syntax check

2. Check the script by hand (no auditor skill exists):

  • [ ] Error handling (`set -e`)
  • [ ] Lock file (`flock`)
  • [ ] Logging (`tee`, `LOG_DIR`)
  • [ ] Working directory (absolute `cd`)
  • [ ] PATH awareness (absolute path to `claude` -- cron has minimal PATH, so all commands must use absolute paths)
  • [ ] Cleanup on exit (lock release)

**Gate**: All checks pass. Proceed to Phase 4.

Phase 4: INSTALL

Install the crontab entry. Every entry gets a `# claude-cron: <tag>` marker so `crontab-manager.py` can identify and manage only its own entries without touching non-Claude crontab lines. All paths in the crontab entry must be absolute because cron has minimal PATH.

1. Show the proposed entry:

   python3 ~/.claude/scripts/crontab-manager.py add \
     --tag "{name}" \
     --schedule "{schedule}" \
     --command "{absolute_script_path} --execute >> {logdir}/cron.log 2>&1" \
     --dry-run

2. **Ask the user for confirmation** before installing. Never install without explicit approval.

3. If confirmed:

   python3 ~/.claude/scripts/crontab-manager.py add \
     --tag "{name}" \
     --schedule "{schedule}" \
     --command "{absolute_script_path} --execute >> {logdir}/cron.log 2>&1"

4. Verify:

   python3 ~/.claude/scripts/crontab-manager.py verify --tag "{name}"

**Gate**: Entry installed and verified. Proceed to Phase 5.

Phase 5: REPORT

Summarize the created cron job and print the exact commands to test and manage it.

Output:

  • Script path
  • Cron schedule (human-readable + expression)
  • Log directory
  • Budget per run
  • Tag for management
  • Commands for future management:
  python3 ~/.claude/scripts/crontab-manager.py list          # see all claude cron jobs
  python3 ~/.claude/scripts/crontab-manager.py verify --tag {name}  # health check
  python3 ~/.claude/scripts/crontab-manager.py remove --tag {name}   # uninstall

To modify an existing wrapper script, regenerate it with `--force` rather than editing in place.

Error Handling

Error: "tag already exists"

Cause: A cron entry with this tag is already installed. Solution: Either `remove --tag {name}` first, or choose a different name.

Error: "claude: command not found" in cron

Cause: Cron has minimal PATH; `claude` isn't in it. Solution: `generate-wrapper` resolves the absolute path to `claude` at generation time. If th

Read more
@notque
Ships withvexjoy-agent

Essays and writing behind this toolkit live at vexjoy.com. VexJoy Agent connects plain-English requests to specialist agents, skills, and workflows. /do selects the knowledge and tools needed for your task.

44964 skills198 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
449
Star history of notque/vexjoy-agent on GitHub, a chart by star-history.com

Other skills on vexjoy-agent.

assessment

assessment

Assessment: read-only inspection, codebase overview, value analysis, health checks, ADR consultation, decision analysis,…

@notque@notqueInstall Skill
business-ops

business-ops

Business operations: strategy, technology, growth, competitive intelligence, support, finance, HR, legal, operations, sales,…

@notque@notqueInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills12d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react3d252k
@facebook@facebookInstall Skill

Questions about headless-cron-creator.

Which coding agents can use headless-cron-creator?
headless-cron-creator installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.