Skip to content
Back to skills

Scheduler Skill

ASecurity

Schedule recurring prompts (monitoring, reporting, watching) for the CURRENT shadok-ai channel — with an optional deterministic "check" that runs WITHOUT the LLM so routine "nothing to report" runs cost ZERO tokens. Use whenever the user asks to monitor / report / watch / alert on something on a recurring basis (every N minutes, hourly, daily, each morning…).

  • 10 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 1, 2026
ai-agentspythonrustgoshellbashnodeapi

Works with

  • api

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned September 1, 2026

npx -y skills add shadok-ai/shadok-ai --skill scheduler-skill --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Scheduler Skill?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Scheduler Skill
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/shadok-ai-scheduler-skill/badge)](https://www.skillsdirectory.com/skills/shadok-ai-scheduler-skill)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: shadok-scheduler
description: Schedule recurring prompts (monitoring, reporting, watching) for the CURRENT shadok-ai channel — with an optional deterministic "check" that runs WITHOUT the LLM so routine "nothing to report" runs cost ZERO tokens. Use whenever the user asks to monitor / report / watch / alert on something on a recurring basis (every N minutes, hourly, daily, each morning…).
---

# shadok-scheduler

Turn a natural-language request like *"watch the Google Ads budget every morning
and alert me when a cap is exceeded"* into a token-efficient scheduled job on
**this channel**.

Only works inside a shadok-ai channel — it needs `SHADOK_SESSION_ID` and
`SHADOK_PORT` in the env (set automatically). If they're missing, tell the user
this must be run from inside a shadok-ai session.

## The token-efficient pattern — DO THIS

Never schedule a bare LLM prompt for monitoring: it burns tokens every run even
when nothing changed. Instead, split detection (free) from wording (rare):

1. **Write a check script** that prints **nothing** when everything is fine, and a
   short line **only** when there is something to report (a threshold crossed, an
   error, a meaningful change). Prefer reusing existing skill scripts (e.g.
   `~/.claude/skills/google-ads/scripts/…`) for the data. Save it somewhere
   durable (a skill's `scripts/` dir). Test it once: it should be silent on a
   normal day.
2. **Register a cron** with that check plus a short alert prompt. The server runs
   the check on schedule (0 tokens); the agent is woken **only** when the check
   prints something, and receives that output prepended to the prompt.

Result: quiet days cost nothing; the LLM is spent only to word a real alert.

For pure reporting where you WANT output every run (e.g. a daily figures digest),
omit the check — the prompt runs every time.

### What a check can see — secrets and cwd

A check does **not** run inside this agent's process. The server runs it with
`sh -c`, in the CHANNEL's directory, with the secrets of the channel's
**profile** injected as environment variables.

So reference a secret by name (`$MY_API_KEY`) and trust it: never hardcode a
value into a check script, and never try to source a shell profile to get one.

The sharp edge is the other direction. A channel with **no profile**, or a
profile that doesn't list that name, gets **nothing** — the variable is simply
absent, and you find out at 6am rather than now. A name that isn't in the vault
is skipped just as silently. Your own shell having the key proves nothing about
the guard's.

`schedule.mjs env` prints exactly what a guard gets here. Run it before writing a
check that needs a secret.

## Commands

```
node scripts/schedule.mjs add --schedule <spec> --prompt "<text>" [--check "<shell command>"] [--tz <zone>]
node scripts/schedule.mjs list
node scripts/schedule.mjs del <id>
node scripts/schedule.mjs tz [<zone>|-]
node scripts/schedule.mjs env
```

`<spec>`: `every:30m` · `every:2h` · `daily:09:00` · `once:2026-08-25T08:42`.

### One-shot — a reminder on a given date

`once:<YYYY-MM-DDTHH:MM>` fires **exactly once**, then the schedule is left in
the list disabled and marked `(fired)` — so you can see it ran, and delete it
when you want.

Use it whenever the user asks to be reminded or warned **on a date** ("warn Alex
on the 25th", "remind me on Monday morning"). Do NOT reach for the harness's own
one-shot scheduler for that: it lives in the agent's process and dies with it,
whereas this one is on disk and survives a restart, an auto-update, and a
container recreate.

Two behaviours worth knowing:

- A date already in the past is **refused**, not silently accepted.
- A slot missed while the server was down still fires **late**, at the next
  tick. A reminder arriving late beats a reminder that vanished — the prompt
  carries its own date, so say in it what it is about and when it was for.

```
node scripts/schedule.mjs add \
  --schedule once:2026-08-25T08:42 \
  --prompt "REMINDER — Alex is back today. Two documents have been stuck in generation since 18/08: …"
```

### Timezone — read this before scheduling a `daily` or a `once`

A `daily` runs at that wall-clock time **in a timezone**, and the default is
whatever the SERVER's machine is set to. On a machine running in UTC,
`daily:09:00` fires at 11:00 for someone in Paris — silently.

- `schedule.mjs tz` prints the timezone `daily` schedules actually use.
- `schedule.mjs tz Europe/Paris` pins it for every `daily` on this instance,
  including the ones already scheduled (they're realigned immediately).
- `--tz Europe/Paris` on `add` pins one schedule only.

When the user names an hour and you're not sure the server sits in their
timezone, check with `tz` first — `list` shows the zone next to each schedule.
An interval (`every:30m`) is a duration, so it has no timezone.

A `once` date is read in that same timezone at CREATION and stored as an
absolute instant. Changing the instance timezone afterwards realigns the
`daily` schedules but **not** a `once` — its instant was already arbitrated.
So check `tz` BEFORE scheduling a dated reminder, not after.

### Example — guarded monitoring (near-zero tokens)

```
node scripts/schedule.mjs add \
  --schedule daily:09:00 \
  --check "python3 $HOME/.claude/skills/google-ads/scripts/check_budget.py" \
  --prompt "The monitoring detected a Google Ads budget anomaly. Write a clear, actionable alert for the team."
```

### Example — plain recurring report (runs every time)

```
node scripts/schedule.mjs add --schedule daily:18:00 \
  --prompt "Review the day on the account and post a short summary."
```

After creating a schedule, confirm to the user in plain language: what it watches,
when it runs, and that quiet runs won't cost tokens (if a check was set).

## Authenticating a direct API call

The commands above do this for you. If you call the cockpit's API yourself, send
your session key — it is in your environment and it does not expire:

```bash
curl -sS -H "x-shadok-session-key: $SHADOK_SESSION_KEY" \
  "http://127.0.0.1:$SHADOK_PORT/channels"
```

`$SHADOK_AUTH` (a cookie) is still accepted, but it was frozen into your
environment at spawn and expires after a week, so never rely on it alone. A
`401` means that header is missing — or that you were started before this
existed, in which case nothing you hold can authenticate any more and only a
human can fix it: ask them for *Reload agent* on your ⋯ menu.

Files in this skill

  • SKILL.md6.4 KB
  • scripts/schedule.mjs11 KB
  • test/fake-cockpit.mjs1.2 KB
  • test/schedule.test.mjs7.8 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.