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
97%
Does it follow best practices?
Impact
94%
0.94xAverage score across 2 eval scenarios
Low
Low-risk findings worth noting
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.
tessl.json lives.tessl.json, the project is not a
Tessl project yet; tell the user to run tessl init first and stop.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.tessl schedule --help rather than
assuming flags.Collect these one at a time. The three the file requires are the skill, the cadence, and the environment.
skill
field, in one of two forms:
workspace/plugin[@version][#skill] (e.g.
tessleng/dark-factory-report, or acme/reports#weekly to pick one skill
from a multi-skill plugin).file:path/to/plugin (e.g.
file:tiles/dark-factory-report), relative to the repo root.timezone to an IANA name (e.g.
America/New_York).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.
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.
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.cron is five fields and its tightest interval must be at least 5
minutes apart. A per-minute cron is rejected.Run the check from the repo root:
tessl schedule validateIt 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.
Once validate passes, tell the user in plain language:
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.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.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.