add create-scheduled-task skill, update plugin registries
New skill for creating/managing headless Claude scheduled tasks on systemd timers. Plugin blocklist and marketplace files updated. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e76527a0a0
commit
0617a0a499
@ -1,5 +1,5 @@
|
||||
{
|
||||
"fetchedAt": "2026-02-28T18:10:38.336Z",
|
||||
"fetchedAt": "2026-03-01T05:51:34.878Z",
|
||||
"plugins": [
|
||||
{
|
||||
"plugin": "code-review@claude-plugins-official",
|
||||
|
||||
@ -13,6 +13,6 @@
|
||||
"repo": "anthropics/claude-code"
|
||||
},
|
||||
"installLocation": "/home/cal/.claude/plugins/marketplaces/claude-code-plugins",
|
||||
"lastUpdated": "2026-02-28T18:11:46.614Z"
|
||||
"lastUpdated": "2026-03-01T06:14:11.879Z"
|
||||
}
|
||||
}
|
||||
256
skills/create-scheduled-task/SKILL.md
Normal file
256
skills/create-scheduled-task/SKILL.md
Normal file
@ -0,0 +1,256 @@
|
||||
---
|
||||
name: create-scheduled-task
|
||||
description: Create, manage, or debug headless Claude scheduled tasks that run on systemd timers. USE WHEN user says "create a scheduled task", "add a cron job for Claude", "schedule a task", "new scheduled task", "manage scheduled tasks", or wants Claude to do something automatically on a timer.
|
||||
---
|
||||
|
||||
# Create Scheduled Task
|
||||
|
||||
## When to Activate This Skill
|
||||
- "Create a scheduled task for X"
|
||||
- "Schedule Claude to do X every day"
|
||||
- "Add a new automated task"
|
||||
- "Debug a scheduled task"
|
||||
- "List scheduled tasks"
|
||||
- "Manage scheduled tasks"
|
||||
|
||||
## System Overview
|
||||
|
||||
Headless Claude Code sessions triggered by systemd timers. Each task has its own prompt, MCP config, settings, and timer.
|
||||
|
||||
```
|
||||
~/.config/claude-scheduled/
|
||||
├── runner.sh # Universal task runner (DO NOT MODIFY)
|
||||
├── disabled # Touch this file to globally disable all tasks
|
||||
├── logs -> ~/.local/share/... # Symlink to log directory
|
||||
└── tasks/
|
||||
└── <task-name>/
|
||||
├── prompt.md # What Claude should do
|
||||
├── settings.json # Model, budget, tools, working dir
|
||||
└── mcp.json # MCP servers this task needs (optional)
|
||||
|
||||
~/.config/systemd/user/
|
||||
├── claude-scheduled@.service # Template unit (DO NOT MODIFY)
|
||||
└── claude-scheduled@<task-name>.timer # One per task
|
||||
```
|
||||
|
||||
## Creating a New Task
|
||||
|
||||
### Step 1: Create the task directory
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.config/claude-scheduled/tasks/<task-name>
|
||||
mkdir -p ~/.local/share/claude-scheduled/logs/<task-name>
|
||||
```
|
||||
|
||||
### Step 2: Write the prompt (`prompt.md`)
|
||||
|
||||
Write a clear, structured prompt that tells Claude exactly what to do. Include:
|
||||
- Specific instructions (repos to check, files to read, etc.)
|
||||
- Desired output format (structured text or JSON)
|
||||
- Any cognitive-memory operations (recall context, store results)
|
||||
|
||||
**Guidelines:**
|
||||
- Be explicit — headless Claude has no user to ask for clarification
|
||||
- Specify output format so results are parseable in logs
|
||||
- Keep prompts focused on a single concern
|
||||
|
||||
### Step 3: Write settings (`settings.json`)
|
||||
|
||||
```json
|
||||
{
|
||||
"model": "sonnet",
|
||||
"effort": "medium",
|
||||
"max_budget_usd": 0.75,
|
||||
"allowed_tools": "<space-separated tool list>",
|
||||
"graph": "default",
|
||||
"working_dir": "/mnt/NV2/Development/claude-home",
|
||||
"timeout_seconds": 300
|
||||
}
|
||||
```
|
||||
|
||||
**Settings reference:**
|
||||
|
||||
| Field | Default | Description |
|
||||
|-------|---------|-------------|
|
||||
| `model` | `sonnet` | Model alias or full ID. Use `sonnet` for cost efficiency. |
|
||||
| `effort` | `medium` | `low`, `medium`, or `high`. Controls reasoning depth. |
|
||||
| `max_budget_usd` | `0.25` | Per-session cost ceiling. Typical triage run: ~$0.20. |
|
||||
| `allowed_tools` | `Read(*) Glob(*) Grep(*)` | Space-separated tool allowlist. Principle of least privilege. |
|
||||
| `graph` | `default` | Cognitive-memory graph for storing results. |
|
||||
| `working_dir` | `/mnt/NV2/Development/claude-home` | `cd` here before running. Loads that project's CLAUDE.md. |
|
||||
| `timeout_seconds` | `300` | Hard timeout. 300s (5 min) is usually sufficient. |
|
||||
|
||||
**Common tool allowlists by task type:**
|
||||
|
||||
Read-only triage (Gitea + memory):
|
||||
```
|
||||
mcp__gitea-mcp__list_repo_issues mcp__gitea-mcp__get_issue_by_index mcp__gitea-mcp__list_repo_labels mcp__gitea-mcp__list_repo_pull_requests mcp__cognitive-memory__memory_recall mcp__cognitive-memory__memory_search mcp__cognitive-memory__memory_store mcp__cognitive-memory__memory_episode
|
||||
```
|
||||
|
||||
Code analysis (read-only):
|
||||
```
|
||||
Read(*) Glob(*) Grep(*)
|
||||
```
|
||||
|
||||
Memory maintenance:
|
||||
```
|
||||
mcp__cognitive-memory__memory_recall mcp__cognitive-memory__memory_search mcp__cognitive-memory__memory_store mcp__cognitive-memory__memory_relate mcp__cognitive-memory__memory_reflect mcp__cognitive-memory__memory_episode
|
||||
```
|
||||
|
||||
### Step 4: Write MCP config (`mcp.json`) — if needed
|
||||
|
||||
Only include MCP servers the task actually needs. Use `--strict-mcp-config` (runner does this automatically when mcp.json exists).
|
||||
|
||||
**Available MCP server configs to copy from:**
|
||||
|
||||
Gitea:
|
||||
```json
|
||||
{
|
||||
"gitea-mcp": {
|
||||
"type": "stdio",
|
||||
"command": "/home/cal/.local/bin/gitea-mcp",
|
||||
"args": ["-t", "stdio", "-host", "https://git.manticorum.com"],
|
||||
"env": {
|
||||
"GITEA_ACCESS_TOKEN": "<token from ~/.claude.json>"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Cognitive Memory:
|
||||
```json
|
||||
{
|
||||
"cognitive-memory": {
|
||||
"command": "python3",
|
||||
"type": "stdio",
|
||||
"args": ["/mnt/NV2/Development/cognitive-memory/mcp_server.py"],
|
||||
"env": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
n8n:
|
||||
```json
|
||||
{
|
||||
"n8n-mcp": {
|
||||
"command": "npx",
|
||||
"type": "stdio",
|
||||
"args": ["n8n-mcp"],
|
||||
"env": {
|
||||
"MCP_MODE": "stdio",
|
||||
"N8N_API_URL": "http://10.10.0.210:5678",
|
||||
"N8N_API_KEY": "<token from ~/.claude/.mcp-full.json>"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Wrap in `{"mcpServers": { ... }}` structure.
|
||||
|
||||
### Step 5: Create the systemd timer
|
||||
|
||||
Create `~/.config/systemd/user/claude-scheduled@<task-name>.timer`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Claude Scheduled Task Timer: <task-name>
|
||||
|
||||
[Timer]
|
||||
OnCalendar=<schedule>
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
```
|
||||
|
||||
**Common OnCalendar expressions:**
|
||||
|
||||
| Schedule | Expression |
|
||||
|----------|------------|
|
||||
| Daily at 9am | `*-*-* 09:00:00` |
|
||||
| Every 6 hours | `*-*-* 00/6:00:00` |
|
||||
| Weekdays at 8am | `Mon..Fri *-*-* 08:00:00` |
|
||||
| Weekly Sunday 3am | `Sun *-*-* 03:00:00` |
|
||||
| Monthly 1st at midnight | `*-*-01 00:00:00` |
|
||||
|
||||
`Persistent=true` means if the machine was off during a scheduled run, it catches up on next boot.
|
||||
|
||||
### Step 6: Enable the timer
|
||||
|
||||
```bash
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable --now claude-scheduled@<task-name>.timer
|
||||
```
|
||||
|
||||
## Managing Tasks
|
||||
|
||||
### List all scheduled tasks
|
||||
```bash
|
||||
systemctl --user list-timers 'claude-scheduled*'
|
||||
```
|
||||
|
||||
### Manual test run
|
||||
```bash
|
||||
~/.config/claude-scheduled/runner.sh <task-name>
|
||||
```
|
||||
|
||||
### Check logs
|
||||
```bash
|
||||
# Latest log
|
||||
ls -t ~/.local/share/claude-scheduled/logs/<task-name>/ | head -1 | xargs -I{} cat ~/.local/share/claude-scheduled/logs/<task-name>/{}
|
||||
|
||||
# Via journalctl (if triggered by systemd)
|
||||
journalctl --user -u claude-scheduled@<task-name>.service --since today
|
||||
```
|
||||
|
||||
### Disable a single task
|
||||
```bash
|
||||
systemctl --user disable --now claude-scheduled@<task-name>.timer
|
||||
```
|
||||
|
||||
### Disable ALL tasks (kill switch)
|
||||
```bash
|
||||
touch ~/.config/claude-scheduled/disabled
|
||||
# To re-enable:
|
||||
rm ~/.config/claude-scheduled/disabled
|
||||
```
|
||||
|
||||
### Check task run history
|
||||
```bash
|
||||
ls -lt ~/.local/share/claude-scheduled/logs/<task-name>/
|
||||
```
|
||||
|
||||
## Existing Tasks
|
||||
|
||||
| Task | Schedule | Budget | Description |
|
||||
|------|----------|--------|-------------|
|
||||
| `backlog-triage` | Daily 09:00 | $0.75 | Scan Gitea issues across repos, prioritize, suggest focus |
|
||||
|
||||
## How the Runner Works
|
||||
|
||||
`runner.sh` is the universal executor. For each task it:
|
||||
|
||||
1. Reads `settings.json` for model, budget, tools, working dir
|
||||
2. Reads `prompt.md` as the Claude prompt
|
||||
3. Invokes `claude -p` with `--strict-mcp-config`, `--allowedTools`, `--no-session-persistence`, `--output-format json`
|
||||
4. Unsets `CLAUDECODE` env var to allow nested sessions
|
||||
5. Logs full output to `~/.local/share/claude-scheduled/logs/<task>/`
|
||||
6. Stores a summary to cognitive-memory as a workflow + episode
|
||||
7. Rotates logs (keeps last 30 per task)
|
||||
|
||||
**The runner does NOT need modification to add new tasks** — just add files under `tasks/` and a timer.
|
||||
|
||||
## Key Constraints
|
||||
|
||||
- **Read-only by default**: Tasks should use `--allowedTools` to restrict to only what they need. No Bash, no Edit unless explicitly required.
|
||||
- **Cost ceiling**: `max_budget_usd` is a hard limit per session. Typical Sonnet run with MCP tools: $0.15–0.30.
|
||||
- **OAuth auth**: Uses Cal's Claude Max subscription via OAuth. No API key needed.
|
||||
- **Nested sessions**: The runner unsets `CLAUDECODE` so it works from within a Claude session or from systemd.
|
||||
- **Log retention**: 30 logs per task, oldest auto-deleted.
|
||||
|
||||
## Reference Files
|
||||
|
||||
- Runner: `~/.config/claude-scheduled/runner.sh`
|
||||
- Template service: `~/.config/systemd/user/claude-scheduled@.service`
|
||||
- Example task: `~/.config/claude-scheduled/tasks/backlog-triage/`
|
||||
- Gitea issue: [claude-home#2](https://git.manticorum.com/cal/claude-home/issues/2)
|
||||
Loading…
Reference in New Issue
Block a user