diff --git a/.changeset/skill-unchained-commands.md b/.changeset/skill-unchained-commands.md new file mode 100644 index 00000000..58080d79 --- /dev/null +++ b/.changeset/skill-unchained-commands.md @@ -0,0 +1,5 @@ +--- +"@taskless/cli": patch +--- + +The installed Taskless skill now tells agents to run each Taskless command as its own shell call, with nothing chained around it. An agent that wrote `echo ======` between two commands lost the second one in zsh, which treats the separator as an error and drops the rest of the line, so `detect` was skipped without anything reporting it. diff --git a/packages/cli/test/installed-documentation.test.ts b/packages/cli/test/installed-documentation.test.ts index f62c70c6..c2f2eb19 100644 --- a/packages/cli/test/installed-documentation.test.ts +++ b/packages/cli/test/installed-documentation.test.ts @@ -167,6 +167,20 @@ describe("this repository's own installed Taskless docs", () => { expect(skill).toContain("earlier in this session"); }); + it("tells an agent to run each Taskless command on its own", async () => { + // An agent chained `agent route; echo ======; detect --json`. zsh read + // `======` as equals expansion and dropped the rest of the line, so + // `detect` never ran and nothing said so. Losing this guidance in a + // rewrite fails just as quietly, so it is pinned. + const skill = await readFile( + resolve(repositoryRoot, "skills", "taskless", "SKILL.md"), + "utf8" + ); + expect(skill).toContain("as its own shell call"); + expect(skill).toContain("Do not chain it with other commands"); + expect(skill).toContain("nothing says so"); + }); + it("preflights the CLI and scopes a blocked one to the exact invocation", async () => { // A harness may refuse a download-and-run command. Without a preflight // the refusal lands on the first command that does work, after any diff --git a/skills/taskless/SKILL.md b/skills/taskless/SKILL.md index 26bbefd1..be3741f8 100644 --- a/skills/taskless/SKILL.md +++ b/skills/taskless/SKILL.md @@ -150,6 +150,16 @@ earlier in this session is not a substitute for fetching it again, even for the same topic. Start each Taskless task with `%(TASKLESS_CLI)s agent ` and follow the copy it returns. +## Run each Taskless command on its own + +Run every `%(TASKLESS_CLI)s` command as its own shell call, exactly as +written. Do not chain it with other commands, and add no separators, pipes, +or redirections around it. The commands Taskless hands you run the same in +bash, zsh, and fish; the glue around them does not. An `echo ======` between +two commands is an error in zsh, which drops the rest of the line, so the +second command never runs and nothing says so. A chain also reports only its +last command's exit code, and `check` uses its exit code to report results. + ## --anonymous Any rule/check command accepts `--anonymous` to skip the Taskless API and