Taskless v0.12.0: Revisions, Restores, and Rollbacks

Jakob Heuser, CTO

0.12.0 moves the CLI onto version 2 of the Taskless rule API. Every rule Taskless issues now has its own id and its own history, and check makes sure the rule it runs is the one we issued. If one changes, three new commands put it back.

Please upgrade soon. Once the service raises its minimum version, 0.11.x can no longer generate rules or verify runtime rules.

npx @taskless/cli

This release also carries everything we announced for 0.11.3. That version never reached npm, so if you're on 0.11.2, the rule id renames, Vale 3.22.0 and the .vale.ini schema from that post all arrive with this upgrade.

check verifies every issued rule

When you're logged in, check compares every file of every issued rule against what Taskless issued. Before 0.12.0 that only covered runtime rules. Now it covers ast-grep and Vale rules too.

An edited issued rule doesn't run, whatever its engine. For ast-grep and Vale rules the run also fails, naming each file that was changed, removed or added. A copy of an issued rule under a new id gets the same treatment: the copy doesn't run, and the failure names the rule it came from.

Rules you wrote yourself are unaffected. So are runs that are logged out, use --anonymous, or pass --dangerously-run-scripts, where nothing is checked, same as before.

check also stops rewriting your rules. 0.11.x tried to repair a changed runtime rule in the middle of a run. 0.12.0 reports the change and tells you which command to run.

Rules generated by 0.11.x or earlier came from the v1 API, so 0.12.0 treats them as rules you wrote. Your ast-grep and Vale rules keep running. Runtime rules need to be regenerated.

Restore, roll back, and list revisions

Three commands recover a rule that changed:

taskless rule restore no-eval
taskless rule revisions no-eval
taskless rule rollback no-eval <revisionId>

rule restore puts a rule back to its current revision. rule revisions lists a rule's recent revisions and marks the current one, so you can pick one without opening the dashboard. rule rollback makes an earlier revision current. Restore and rollback verify every file before they write it.

rule revisions works on every plan. Restore and rollback need a plan that includes rule recovery. On a plan without it, check gives you the git log and git restore steps for the rule's directory, so you're never sent to a command the service will refuse.

check says when it didn't verify

A CI job without a token used to run its ast-grep and Vale rules unverified and say nothing about it. Now check prints one notice whenever it ran rules without verifying them, along with the fix: auth login, a TASKLESS_TOKEN in CI, dropping --anonymous, the specific problem with your GitHub origin, or the GitHub App install steps. The exit code doesn't change. Under --json it's an entry in notices.

One exit code does change. When the service withholds a runtime rule because your organization's plan doesn't include runtime rules, check now exits 1 instead of printing a notice and exiting 0. The output names the withheld rules and links to the upgrade page, and --json carries an entitlement object. If a CI job starts failing for this reason, the rules stopped running, and the fix is your plan.

Rule generation rides out a flaky network

rule create and rule improve used to give up on the first network error while waiting for a generation request. They now retry a network failure, 408, 429 or 5xx on the next 15 second poll, and only fail after eight in a row.

If a command does give up, the request may still finish on the service. The message gives you the request id and the command to pick it back up:

taskless rule create --resume <requestId>

Errors from the rule service got clearer at the same time. A network failure names its cause, such as getaddrinfo ENOTFOUND, where it used to say fetch failed, and it tells you whether retrying will help. check stopped calling a rejected request an outage. A --from request file with a problem names each failing field, the resolved path, or the JSON parser's position.

Logging in works when your token goes bad

taskless auth login used to refuse to run if a token was already saved, even a revoked or expired one, which made it a dead end for the very error that recommends it. It now checks the saved token with the service and replaces it if it's no longer valid. Every "authentication was rejected" message names the command to run. When the token comes from TASKLESS_TOKEN, the messages say so, since changing that variable is the only fix.

Setup also no longer asks you to log in. Local ast-grep and Vale rules run without an account, and the commands that need one still say so.

Vale 3.23.0

The bundled Vale moves from 3.22.0 to 3.23.0. A Vale rule over code comments now reads less:

  • Comments addressed to a tool, like //nolint, # noqa and eslint-disable, aren't linted.
  • A Python docstring's :param: fields aren't linted.
  • Kotlin (.kt, .kts) is comment-aware. It used to be linted as one block of prose.

Findings in those places go away and nothing new appears. Separately, a standalone scope: doc(h2) now lints the heading's own text, where before it matched nothing.

Upgrading

The first run after you upgrade migrates your .taskless/, so commit what it rewrites. On top of the 0.11.3 migrations, it tidies a .taskless/ that an earlier migration left half done: test files still in .taskless/sg/rule-tests/ move into their rule's .tests/, and the empty directory goes away.

The upgrade also finds any package.json pin of @taskless/cli or @taskless/cli-nightly that would run an older CLI, including pins in workspace packages and in scripts, and offers the version to move it to. Scripts, CI and git hooks run that pin, and an older CLI refuses a .taskless/ that a newer one migrated. It never edits package.json itself.

If you read the CLI's JSON output, two fields changed:

  • rule create --json prints requestId where it printed ruleId. The old field always held the request id. The ids of the rules it wrote are in rules, and those are what rule improve takes.
  • info --json moves the list of agent harnesses (Claude Code, Codex, Cursor, OpenCode) from tools to harnesses. tools now lists gh, git and jq from your PATH.

Also in this release

  • taskless share prints a QR code for taskless.io, for when you're showing Taskless to someone in person.
  • Installing the CLI downloads a lot less. The libraries the build already bundles moved to devDependencies, so tsx is the only runtime dependency left, plus the platform's ast-grep and Vale binaries.
  • Every command the CLI tells you to run now begins with the launcher you used, so you can paste it as shown even when taskless isn't on your PATH.
  • Onboarding finishes by offering to wire check into your CI and into a pre-commit hook, and asks about marking itself complete as a separate question.
  • -d <path> works before a subcommand, as in taskless -d . info. It used to fail with "Unknown command".
  • When .taskless/.env.local.json is tracked by git, the warning gives you the steps to untrack it and, if you pushed it, to replace the token.
  • Every --help opens with a line telling an agent to run init before installing or updating, which installs the skill and recipes that keep its sessions consistent.

The full changelog is on taskless/cli#407.

Getting it

npx @taskless/cli