Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .changeset/agent-ok-preflight.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
"@taskless/cli": patch
---

New `taskless agent ok` topic: it prints one line confirming the CLI can run, through the invocation it was launched with, and does nothing else. The Taskless skill and the `/tskl` command now run it once per session before any other Taskless command, so a harness that blocks download-and-run commands (Claude Code's auto mode, for one) stops the agent before it starts work rather than partway through. On a blocked command the agent now names the exact command to the user, offers three ways forward (an allow rule for exactly that invocation, approval through the agent's permissions command such as `/permissions`, or approving every Taskless command by hand in chat), and never proposes an allow rule that wildcards the package name or version.
New `taskless agent ok` topic: it prints one line confirming the CLI can run, through the invocation it was launched with, and does nothing else. The Taskless skill now runs it once per session before any other Taskless command, so a harness that blocks download-and-run commands (Claude Code's auto mode, for one) stops the agent before it starts work rather than partway through. On a blocked command the agent names the exact command in one message and offers three ways forward: it adds an allow rule for exactly that invocation (handing the user the change when the harness blocks the agent's own edit), the user approves it through their agent's permissions command such as `/permissions`, or the user approves every Taskless command by hand in chat. It never proposes an allow rule that wildcards the package name or version, and never asks what the user wants while blocked. A request that names no task, such as "let's use taskless", goes straight to onboarding, so its one question is the only one the user sees.
7 changes: 7 additions & 0 deletions .changeset/remove-tskl-command.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@taskless/cli": minor
---

The `/tskl` slash command is removed. `taskless init` no longer installs it, and upgrading removes the copies an earlier install wrote, from `.taskless/commands/` and from each tool's `commands/tskl/`. Other files in a tool's `commands/` directory are left alone.

What to do: ask your agent in plain language instead, such as "set up taskless" or "add taskless to CI". The Taskless skill picks that up the same way `/tskl` did. The `init --json` envelope drops `commandsInstalled` and each target's `writtenCommands`, and keeps `removedCommands`, which is where the removal shows up.
3 changes: 1 addition & 2 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@
},
"homepage": "https://taskless.io",
"repository": "https://github.com/taskless/cli",
"license": "MIT",
"commands": "./commands/tskl/"
"license": "MIT"
}
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ node_modules/
/.taskless/skills/
/.taskless/commands/
/.claude/skills/taskless/
/.claude/commands/tskl/

# Vale platform-package tarballs (npm pack output from vale-prepare.cjs)
.vale-dist/
Expand Down
1 change: 0 additions & 1 deletion .taskless/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ npx @taskless/cli@latest check
- `taskless.json` - Version manifest / migration state
- `.env.local.json` - Local authentication credentials (git-ignored)
- `skills/` - Canonical Taskless skill content; tool directories hold thin stubs that delegate here (managed by Taskless)
- `commands/` - Canonical Taskless command content (managed by Taskless)

Every rule is one directory, `rules/<engine>/<id>/`, holding
everything that defines it. Its test cases sit inside it as
Expand Down
14 changes: 3 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ Includes a CLI that works with agentic systems (and humans too) at @taskless/cli
```
skills/
taskless/SKILL.md # Single consolidated router skill
commands/
tskl/tskl.md # Single /tskl router command
packages/
cli/ # @taskless/cli, recipes live in cli/src/agent/
scripts/
Expand All @@ -20,13 +18,7 @@ scripts/

## Skill

Starting in v0.7, Taskless ships a **single consolidated skill** (`taskless`) plus a single `/tskl` slash command. The skill body is a small router; per-task instructions live behind `npx @taskless/cli agent <topic>` and are fetched on demand.

| Skill | Command | Description |
| ---------- | ------------- | ------------------------------------------------------ |
| `taskless` | `/tskl <ask>` | Router for any Taskless action (create rule, improve, |
| | | delete, check, auth, CI). Fetches the canonical recipe |
| | | for the user's intent and follows it. |
Taskless ships a **single consolidated skill** (`taskless`). The skill body is a small router; per-task instructions live behind `npx @taskless/cli agent <topic>` and are fetched on demand. It handles any Taskless action (create rule, improve, delete, check, auth, CI) by fetching the canonical recipe for the user's intent and following it.

Available `taskless agent` topics: `route`, `create-sg-rule`, `create-vale-rule`, `create-runtime-rule`, `create-remote-rule`, `improve-rule`, `delete-rule`, `check`, `auth`, `ci`, `info`, `init`, `update`. Run `taskless agent` with no topic for the index. Append `--anonymous` for the local-only flow on improve.

Expand Down Expand Up @@ -129,10 +121,10 @@ In v0.7+, new agent-facing instructions are added as **recipes**, not skills. To
1. Create `packages/cli/src/agent/<topic>.txt` following the canonical template (Goal / Preconditions / Steps / Input schema / Errors / See Also).
2. Use `{{CLI_VERSION}}` and `{{INPUT_SCHEMA}}` placeholders for runtime interpolation.
3. For topics with a substantively different local-only flow, add `<topic>.anonymous.txt`. The `agent` command's variant lookup is automatic.
4. Update the topic table in `skills/taskless/SKILL.md` and `commands/tskl/tskl.md` so agents can discover the new topic.
4. Update the topic table in `skills/taskless/SKILL.md` so agents can discover the new topic.

### Distribution channels

- **`taskless init`**: CLI installs the consolidated skill to `.claude/skills/taskless/` and the command to `.claude/commands/tskl/`
- **`taskless init`**: CLI installs the consolidated skill to `.taskless/skills/taskless/` and a reference stub to `.claude/skills/taskless/`
- **Claude Code Plugin Marketplace**: `.claude-plugin/marketplace.json` and `plugin.json`
- **Vercel Skills CLI**: `npx skills add` discovers skills from `skills/` directory
59 changes: 0 additions & 59 deletions commands/tskl/tskl.md

This file was deleted.

5 changes: 2 additions & 3 deletions dotagents.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,8 @@ repository carries a `.claude-plugin/plugin.json`, and `add` checks a source for
plugins first: when it finds one, the source is plugin-only. So that command
adds a plugin named `taskless` with `path = "."`, which vendors the entire
repository (including `packages/`, `example/`, and the lockfile) into
`.agents/plugins/taskless/`. What it ships is the Taskless skill and the `tskl`
command, which is the right way to get those, and it is not a route to
`iterate-pr`.
`.agents/plugins/taskless/`. What it ships is the Taskless skill, which is the
right way to get that, and it is not a route to `iterate-pr`.

To take the development skills, declare them with an explicit `path`. One skill:

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
## Why

A real session of "let's use taskless" took four user turns to reach onboarding's one question:

1. Auto mode blocked `agent ok`. The agent offered three remedies, then also asked what the user wanted Taskless to do.
2. The user picked "I add an allow rule". Auto mode refused the agent's write to `.claude/settings.local.json`, so the agent handed the user a one-line command that made the change. That worked.
3. Once the preflight passed, the agent surveyed the install and offered a menu of topics.
4. The user said "set it up", and only then did onboarding ask its question.

The goal is one approval, if one is needed, and then onboarding's single question. The two "what next?" questions repeat a request the user already made. The fallback in step 2 is worth keeping: the agent knows what its harness accepts, and the skill cannot.

The `tskl` slash command carried a second copy of the same routing and preflight guidance, kept in step with the skill by hand, and it is overhead now that a plain request reaches the skill.

## What Changes

- On a blocked command, the agent sends one message naming the command and offers three remedies: it adds the exact-invocation allow rule, and hands the user the change if the harness blocks its edit; the user approves it through their agent's permissions command (in Claude Code, `/permissions` with `Bash(<invocation>:*)`); or the user approves every Taskless command manually in chat.
- The blocked message does not ask what the user wants. Their request stands, and the agent carries it out once unblocked.
- Once `agent ok` passes, the agent goes straight to the request, without surveying the install or offering a menu.
- A request that names no task ("use", "try", or "set up" Taskless) routes to `agent onboard`, whose question is the only one asked.
- **BREAKING** The `tskl` slash command is removed. `init` stops installing it. An upgrade removes the command an older install recorded in the manifest, from the canonical store and from each tool directory, along with any empty `tskl/` directory. A symlinked `tskl/` directory is unlinked rather than deleted through. The `init --json` envelope drops `commandsInstalled` and `writtenCommands`.

## Delivery shape

**Single PR.** The skill edits and the command removal touch the same guidance, and the removal is only coherent with the skill carrying all of it. Most of the diff is deletion: the command source, its stub builder, and tests for both.

## Capabilities

### Modified Capabilities

- `skill-taskless`: the blocked-preflight remedies, routing for a request that names no task, and the command mapping removed.
- `cli-init`: no command is installed, and an upgrade removes the retired one.
- `cli-agent`: the invocation requirement no longer names the command file.
- `skills`: no `commandName` metadata, no commands directory, and the plugin declares no commands.
- `infrastructure`: the hand-authored command requirement is removed.

## Impact

- `skills/taskless/SKILL.md`: preflight and routing. The body stays within its 150-line cap.
- `commands/tskl/` deleted. `.claude-plugin/plugin.json` no longer declares commands.
- `packages/cli/src/install/`, `commands/init.ts`, `wizard/index.ts`: command writing removed; removal of recorded commands kept.
- `agent/init.md` (topic v6), the `0001` README template, and `.taskless/README.md`.
- READMEs and `dotagents.md`.
- Tests across the install suite.
- Changesets: `agent-ok-preflight` corrected in place (still unreleased); `remove-tskl-command` added as `minor`, since users of `/tskl` must change how they ask.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
## MODIFIED Requirements

### Requirement: Recipes name the CLI by its full invocation

Every instruction in shipped agent-facing content that tells a reader to run the Taskless CLI SHALL name the CLI by the invocation the build resolves for the reader, followed by the subcommand and its arguments — never by a hand-written one. Two mechanisms deliver that, because the content travels by two different paths:

- Recipe sources under `packages/cli/src/agent/` SHALL express the CLI as `%(TASKLESS_CLI)s`, which the recipe renderer substitutes at render time.
- `skills/taskless/SKILL.md` is not rendered through the recipe renderer, so it SHALL carry the canonical `npx @taskless/cli` string, which `applyCliInvocation` rewrites to the build target's invocation when the content is emitted.

Content SHALL NOT name the CLI as a bare `taskless` binary, because it is not installed on `PATH` for the overwhelming majority of readers. A recipe source SHALL NOT hardcode a launcher-and-package string such as `npx @taskless/cli` either, because that is the fact `%(TASKLESS_CLI)s` exists to hold in one place — the string is canonical only in the file above, where it is the rewrite anchor rather than a hardcoding. Prose that mentions the product, a config filename, or a directory (`taskless.config`, `.taskless/`) is unaffected — the requirement is about executable instructions.

An automated check SHALL fail when a bare `` `taskless <subcommand>` `` invocation, or a hardcoded `npx @taskless/cli`, appears in a recipe source, so the normalization cannot silently regress as recipes are edited. The check SHALL read the subcommand names from the CLI's own registry rather than restating them, so a newly added subcommand is covered without a second edit. It does not extend to `skills/taskless/SKILL.md`, whose rewrite anchor is the very string it flags and which quote invocations as example user utterances.

#### Scenario: A recipe instructs the reader to run a subcommand

- **WHEN** a recipe tells the reader to fetch another topic
- **THEN** the source SHALL read `%(TASKLESS_CLI)s agent <topic>` rather than `taskless agent <topic>` or `npx @taskless/cli agent <topic>`

#### Scenario: A regression is reintroduced

- **WHEN** a recipe source is edited to contain a bare `` `taskless check` ``-style invocation
- **THEN** the automated check SHALL fail and name the offending file and line

#### Scenario: Non-prod builds rewrite every invocation, not some of them

- **WHEN** a `nightly` or `self` build renders any recipe
- **THEN** every CLI invocation in the rendered text SHALL name that build's own invocation, with no occurrence left naming the released `@taskless/cli`

#### Scenario: Cross-reference checking survives the normalization

- **WHEN** the check that recipe cross-references cite only topics that resolve is run
- **THEN** it SHALL operate on rendered recipe text, where the invocation is a stable literal, rather than on source text where it is a placeholder
- **AND** it SHALL anchor on the invocation the running build actually renders, so the check does not pass vacuously under a `nightly`, `dev`, or `self` build whose rendered invocation names neither `taskless` nor `@taskless/cli`
- **AND** it SHALL fail when it finds no cross-reference at all, since an empty result is otherwise indistinguishable from every reference resolving
Loading
Loading