CtrlK
BlogDocsLog inGet started
Tessl Logo

tessleng/schedule-management

Create and migrate repo-defined Tessl schedules in a project's tessl.json. Turns a plain-language cadence into a validated schedules entry, and moves an existing UI/CLI schedule into version control.

90

0.94x
Quality

97%

Does it follow best practices?

Impact

94%

0.94x

Average score across 2 eval scenarios

SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

SKILL.mdskills/schedule-setup/

name:
schedule-setup
description:
Create a repo-defined schedule in a project's tessl.json from a plain-language description. Use when the user wants to schedule a skill to run on a recurring cadence ("run X every morning", "kick off the report nightly", "schedule this weekly"), set up a cron-driven launch run, or add a `schedules` block to tessl.json. The user describes the skill, cadence, and environment in plain words; this skill writes the correct cron, adds and validates the entry, and explains what happens on push. Not for one-off runs (use `tessl launch`) or for moving an existing UI/CLI schedule into the file (use schedule-migrate).

Set up a repo-defined schedule

Turn a plain-language request ("run the nightly report at 2am") into a valid schedules entry in the project's tessl.json, validate it, and tell the user what happens next.

A repo-defined schedule is a recurring launch run declared in tessl.json so it is reviewed and version-controlled next to the code it runs against. On push to the default branch, Tessl reads the file and creates the schedule.

Read the schedules block reference for the full field list and the cron reference before writing a cron.

Communication rules

  • Ask about one thing at a time. Do not ask for the skill, cadence, and environment in a single prompt.
  • Explain each concept in one or two plain sentences, right before the user needs it.
  • The user describes the cadence in plain language. You write the cron. Never ask the user for a cron expression.
  • Confirm the cron you derived in plain words ("that's every day at 02:00 UTC") so the user can catch a mistake.

1. Preflight

  • Work from the repository root, where tessl.json lives.
  • Confirm the file exists. If there is no tessl.json, the project is not a Tessl project yet; tell the user to run tessl init first and stop.
  • Read the current tessl.json. Note whether a schedules block already exists and what keys it holds, so a new entry does not collide with an existing key.
  • Check the current Tessl CLI surface with tessl schedule --help rather than assuming flags.

2. Gather what to schedule

Collect these one at a time. The three the file requires are the skill, the cadence, and the environment.

  • Skill: which skill runs on the schedule. It becomes the entry's skill field, in one of two forms:
    • A registry ref: workspace/plugin[@version][#skill] (e.g. tessleng/dark-factory-report, or acme/reports#weekly to pick one skill from a multi-skill plugin).
    • A repo-local plugin: file:path/to/plugin (e.g. file:tiles/dark-factory-report), relative to the repo root.
    • If the user names a plugin but not which skill, and the plugin has more than one skill, ask which skill.
  • Cadence: how often, in plain language. Convert it to a five-field cron yourself using the cron reference. Default the timezone to UTC. If the user gives a local time, ask which timezone (or use a timezone they have already stated) and set timezone to an IANA name (e.g. America/New_York).
  • Environment: the workspace environment whose variables each run gets. This is the environment name, not its id (a committed file names the environment; the id is resolved per workspace at apply time). If the user is unsure, list options with tessl env list --workspace <workspace> and let them pick.

Optional fields, only if the user raises them (see the schedules block reference for all of them): agent, model, baseBranch, snapshot, workdir, inputs, instructions, description.

3. Choose a schedule key

The key is the schedule's stable identity in the schedules map: a lowercase kebab-case slug (a-z, 0-9, single dashes), not a display label. Derive it from the job (e.g. nightly-sales-report). Renaming a key later is a delete-plus-create, so pick a durable one. It must not collide with an existing key in the block.

4. Write the entry

Add the entry under a top-level schedules object in tessl.json. Create the schedules object if it does not exist; otherwise add the key alongside the existing ones. Preserve the rest of the file. Do not reorder or drop other keys.

A minimal entry:

{
  "schedules": {
    "nightly-sales-report": {
      "skill": "file:tiles/dark-factory-report",
      "cron": "0 2 * * *",
      "environment": "dark-factory-report",
      "description": "Nightly sales report"
    }
  }
}

Rules that the validator enforces. Get them right the first time:

  • skill, cron, and environment are required.
  • The entry is strict: an unknown or misspelled field name is a hard error, not a silent ignore. Only use the fields listed in the reference.
  • cron is five fields and its tightest interval must be at least 5 minutes apart. A per-minute cron is rejected.
  • Keep JSON valid: quote every key and string, no trailing commas, no comments.

5. Validate

Run the check from the repo root:

tessl schedule validate

It reads tessl.json, validates the schedules block, and reports every problem against the key it belongs to. It exits non-zero when the block is invalid. Fix anything it reports and run it again until it passes.

validate checks the file only: shape, cron expressions, and the minimum interval. It does not confirm that the environment exists in the workspace, that the skill's tile is installable, or that the agent/model are in the catalogue. Those are checked when the file is applied. Tell the user this so a clean validate is not mistaken for a guarantee the schedule will fire.

6. Explain what happens next

Once validate passes, tell the user in plain language:

  1. Commit the tessl.json change and push it to the repo's default branch (usually main). Repo-defined schedules are reconciled only from the default branch. A push to a feature branch does nothing.
  2. On that push, Tessl's GitHub App reads tessl.json and creates the schedule. This needs the Tessl GitHub App installed on the repo and the repo-defined-schedules feature enabled for the workspace.
  3. The new schedule then appears in tessl schedule list and in the UI, and fires a launch run on its cron.

If the schedule does not appear after the push, the usual causes are: the push was not to the default branch, the named environment does not exist in the workspace, the feature is not enabled, or the workspace has reached the limit of 20 active schedules. The active-schedule cap is enforced at apply time and not reported by validate: the schedule is silently skipped, not rejected with an error. If nothing else explains a missing schedule, run tessl schedule list --json --limit 100 and count the active entries. Point the user at these causes rather than re-editing the file.

skills

README.md

tile.json