feat(cli): Add taskless onboard subcommand for post-install rule discovery#20
Merged
Conversation
Add the add-onboard-command change: proposal, design doc, and five spec deltas covering a new cli-onboard capability plus modifications to cli-help, cli-init, cli-taskless-bootstrap, and skill-taskless. The change introduces a post-install onboarding flow: a thin CLI gate (taskless onboard with --force and --mark-complete) that delivers a conversational, agent-executed recipe for first-pass rule discovery. Tracks completion via a 3-state install.onboarded field that only the agent writes after explicit user confirmation. Widens the skill trigger to volunteer Taskless quietly when the user wants to add a rule and hasn't named another tool. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extend TasklessInstallManifest with an optional onboarded?: boolean field used to gate the upcoming taskless onboard recipe. The field is 3-state (absent / false / true); absent or false both mean "not yet onboarded" for gating purposes. Update writeInstallState to preserve any pre-existing install.onboarded across re-installs. Without this, taskless init or taskless update would silently wipe the flag because writeInstallState constructs a fresh TasklessInstallManifest from InstallState (which does not carry onboarded). Refs add-onboard-command (group 1). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add packages/cli/src/help/onboard.txt — the agent-facing recipe for the post-install rule discovery flow. Conversational by design: opens by asking the user which sources to scan (TODOs/FIXMEs, agent-memory files, PR review comments via gh, issue tracker via MCP, plus any sources the user names), probes tool availability before promising scans, filters for high-signal candidates (repeated patterns, cited docs, merge-blocking feedback), and synthesizes findings as a bullet list of <kebab-name>: <description> the user can materialize one by one via taskless help rule create. The final step is consent-gated: the agent asks explicitly before running taskless onboard --mark-complete, and the recipe warns against auto-marking on ambiguous responses. The Vite glob in commands/help.ts (../help/*.txt) picks up the new file with no plumbing change. Refs add-onboard-command (group 2). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two coupled changes:
1. Add taskless onboard subcommand. Three modes via flag combinations:
- default: bootstrap .taskless/, gate on install.onboarded === true
(refuse with --force hint), otherwise print the embedded onboard
recipe.
- --mark-complete: write install.onboarded = true, preserving all
other manifest state. Invoked by the host agent only after explicit
user confirmation per the recipe.
- --force --mark-complete: rejected with exit 1 and a clear error.
Telemetry: cli_onboard_recipe (with forced property),
cli_onboard_already_done, cli_onboard_marked_complete.
2. Migrate recipe-rendering substitution from ad-hoc {{KEY}} replaceAll
to sprintf-js named arguments (%(KEY)s). Centralizes the variable
table in renderRecipe with two flavors:
- System-resolved values (CLI_VERSION, INPUT_SCHEMA when present).
- Agent-fill markers (PACKAGE_MANAGER_DLX, rendered as
<package-manager-dlx>) so consuming agents can substitute at
execution time without recipe-specific conventions.
All 15 recipes migrated; commands/help.ts exports a new getRecipe()
so onboard.ts and the help command share the same render path.
User-visible diff: ci.txt previously rendered {{PACKAGE_MANAGER_DLX}};
now renders <package-manager-dlx>. The recipe prose is consistent with
the new marker.
Refs add-onboard-command (group 3 + 3a).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The existing help command iterates the subCommands map for the index table and computes intent telemetry from positional args, so adding onboard to subCommands and a description to the citty meta block was sufficient — no further help.ts changes needed. Refs add-onboard-command (group 4). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Print a one-line trailer after a successful taskless init (both wizard and --no-interactive paths) pointing the user at the new onboarding flow. The wording branches on whether the install plan included commands: - Targets that received commands (Claude Code, Cursor) also receive the Taskless skill, so the with-commands trailer mentions the slash command (/tskl onboard), the skill, and the bare `taskless onboard` CLI fallback. - Targets without commands (OpenCode, Codex, .agents/ fallback) only have the skill, so the no-commands trailer mentions the skill and the CLI fallback, and omits /tskl onboard entirely. The trailer is suppressed on cancel/failure: wizard cancellation returns before the trailer line, and any throw in the install path propagates past it. taskless update keeps its existing void-discard on runNonInteractive and does not print the trailer. Threads the new commandsInstalled flag through runNonInteractive's return value (init.ts) and via planTargets (wizard/index.ts) so both paths share the same getOnboardTrailer helper exported from commands/onboard.ts. Refs add-onboard-command (group 5). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…section
Update skills/taskless/SKILL.md to support proactive volunteering on
unspecified-tool rule requests:
- Description gains two new trigger phrases ('onboard with taskless',
'set up taskless for this project').
- Description replaces the prior blanket 'do NOT trigger on generic
ESLint/linting' carve-out with a named-tool-suppression clause:
trigger when the user wants to add/write/create a rule and has not
named a specific lint/format/static-analysis tool. Suppressing
examples (illustrative): eslint, ruff, biome, ast-grep.
- Body's Topics table gains an 'onboard' row pointing at
npx @taskless/cli help onboard.
- New ## Quiet suggestion section specifies the proactive trigger
behavior: a one-line offer rather than a full recipe, accept ->
fetch rule create, decline -> proceed without this skill, decline
is sticky within the conversation only (no persistent decline
state).
Constraint check: description is 945 chars (<= 1024 cap); body is
59 lines (<= 80 cap).
Refs add-onboard-command (group 6).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add packages/cli/test/onboard.test.ts with 7 e2e tests covering the new taskless onboard subcommand: - bootstrap + recipe print on first run - gate refusal when install.onboarded is true - --force overrides the gate and prints the recipe - --mark-complete writes the flag while preserving install.targets, install.installedAt, install.cliVersion, and unknown top-level fields like experimental - --mark-complete is byte-identical on second run (idempotent) - --force --mark-complete exits 1 with a clear error mentioning both flag names - taskless help onboard returns identical content to taskless onboard --force (recipe parity check) Extend init-no-interactive.test.ts with three trailer scenarios: - with commands (Claude Code detected): trailer mentions /tskl onboard, the Taskless skill, and `taskless onboard` - without commands (.agents/ fallback): trailer mentions the skill and CLI but not /tskl onboard - taskless update does not print the trailer Refresh help-extensions.test.ts to assert the new sprintf-js syntax: existing CLI_VERSION/INPUT_SCHEMA tests now also guard against the new %(KEY)s placeholder leaking through unrendered, and a new test covers PACKAGE_MANAGER_DLX rendering as the <package-manager-dlx> agent-fill marker. Net: 207 -> 218 passing tests. Refs add-onboard-command (group 7). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- .changeset/onboard-command.md: minor changeset for @taskless/cli covering the new onboard subcommand, the install.onboarded manifest field, the post-install trailer, the skill trigger expansion, and the sprintf-js recipe substitution refactor. Release tooling rolls it into the next minor. - packages/cli/README.md: new taskless onboard section documenting the three modes (default / --force / --mark-complete), the 3-state install.onboarded manifest field, the consent-only-via-agent rule, and the conditional trailer wording. Refs add-onboard-command (group 8). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Close two scenario gaps surfaced by /opsx:verify: - W3 (init trailer is informational, not gated on manifest): re-run init --no-interactive on top of an existing install.onboarded:true manifest. Assert the onboarding trailer still prints and that the onboarded flag survives the re-install (writeInstallState preservation path). - W4 (3-state onboarded semantics): seed install.onboarded:false and run taskless onboard. Assert the recipe is printed, not the gate notice — both absent and false must be treated as not-onboarded. Net: 209 -> 211 tests (10 onboard.test.ts + 4 trailer scenarios in init-no-interactive.test.ts). Refs add-onboard-command (verify follow-up). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add Skill(pr-writer) and Skill(pr-writer:*) to the project allow list so the pr-writer skill can run without prompting on each invocation. Picked up while opening the PR for add-onboard-command. Pure permission allowlist update — no behavior change to the codebase. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a post-install onboarding flow to the Taskless CLI and skill ecosystem so new users can discover high-signal starter rules from real repo signals, while also refactoring recipe rendering to a single sprintf-js–based interpolator shared across help and onboard.
Changes:
- Introduces
taskless onboard(with--forceand--mark-complete) plus a new embeddedhelp onboardrecipe and manifest flaginstall.onboarded. - Refactors recipe interpolation from
{{KEY}}placeholders to sprintf-js named args (%(KEY)s) and adds<package-manager-dlx>agent-fill rendering. - Adds a post-install “Next: … onboard” trailer to successful
taskless initpaths and expands the consolidatedtasklessskill triggers + routing guidance.
Reviewed changes
Copilot reviewed 39 out of 40 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| skills/taskless/SKILL.md | Expands trigger guidance and adds routing + “quiet suggestion” behavior for generic rule requests. |
| pnpm-lock.yaml | Locks new sprintf-js and @types/sprintf-js dependencies. |
| packages/cli/test/onboard.test.ts | Adds coverage for gating/force/mark-complete behaviors and recipe parity with help onboard. |
| packages/cli/test/init-no-interactive.test.ts | Asserts init trailer wording and onboarded-flag preservation on reinstall. |
| packages/cli/test/help-extensions.test.ts | Updates interpolation tests for new %(KEY)s syntax and <package-manager-dlx> rendering. |
| packages/cli/src/wizard/index.ts | Prints onboarding trailer after successful wizard installs. |
| packages/cli/src/install/state.ts | Preserves install.onboarded across reinstalls when writing install state. |
| packages/cli/src/index.ts | Registers the new onboard subcommand. |
| packages/cli/src/help/update.txt | Migrates recipe placeholders to %(CLI_VERSION)s. |
| packages/cli/src/help/rule.txt | Migrates header placeholder to %(CLI_VERSION)s. |
| packages/cli/src/help/rule-verify.txt | Migrates header placeholder to %(CLI_VERSION)s. |
| packages/cli/src/help/rule-meta.txt | Migrates header placeholder to %(CLI_VERSION)s. |
| packages/cli/src/help/rule-improve.txt | Migrates placeholders to %(CLI_VERSION)s / %(INPUT_SCHEMA)s. |
| packages/cli/src/help/rule-improve.anonymous.txt | Migrates header placeholder to %(CLI_VERSION)s. |
| packages/cli/src/help/rule-delete.txt | Migrates header placeholder to %(CLI_VERSION)s. |
| packages/cli/src/help/rule-create.txt | Migrates placeholders to %(CLI_VERSION)s / %(INPUT_SCHEMA)s. |
| packages/cli/src/help/rule-create.anonymous.txt | Migrates header placeholder to %(CLI_VERSION)s. |
| packages/cli/src/help/onboard.txt | Adds the new conversational onboarding recipe. |
| packages/cli/src/help/init.txt | Migrates header placeholder to %(CLI_VERSION)s. |
| packages/cli/src/help/info.txt | Migrates header placeholder to %(CLI_VERSION)s. |
| packages/cli/src/help/ci.txt | Migrates placeholders to sprintf-js and documents <package-manager-dlx> substitution. |
| packages/cli/src/help/check.txt | Migrates header placeholder to %(CLI_VERSION)s. |
| packages/cli/src/help/auth.txt | Migrates header placeholder to %(CLI_VERSION)s. |
| packages/cli/src/filesystem/migrate.ts | Extends manifest typing with install.onboarded?: boolean. |
| packages/cli/src/commands/onboard.ts | Implements taskless onboard, gating, mark-complete writes, telemetry, and shared trailer text. |
| packages/cli/src/commands/init.ts | Prints onboarding trailer after successful non-interactive init and threads commandsInstalled. |
| packages/cli/src/commands/help.ts | Switches recipe rendering to sprintf-js and exports getRecipe. |
| packages/cli/README.md | Documents the new taskless onboard command and semantics. |
| packages/cli/package.json | Adds sprintf-js and its types. |
| openspec/changes/add-onboard-command/tasks.md | Tracks implementation checklist for the OpenSpec change. |
| openspec/changes/add-onboard-command/specs/skill-taskless/spec.md | Specifies updated skill trigger and quiet-suggestion behavior requirements. |
| openspec/changes/add-onboard-command/specs/cli-taskless-bootstrap/spec.md | Specifies manifest schema + 3-state semantics for install.onboarded. |
| openspec/changes/add-onboard-command/specs/cli-onboard/spec.md | Specifies the onboard subcommand contract and telemetry. |
| openspec/changes/add-onboard-command/specs/cli-init/spec.md | Specifies init trailer behavior and wording rules. |
| openspec/changes/add-onboard-command/specs/cli-help/spec.md | Specifies sprintf-js placeholder conventions and onboard topic registration. |
| openspec/changes/add-onboard-command/proposal.md | Describes rationale/impact of the onboard feature and associated changes. |
| openspec/changes/add-onboard-command/design.md | Captures key design decisions and trade-offs. |
| openspec/changes/add-onboard-command/.openspec.yaml | Declares the OpenSpec change metadata. |
| .changeset/onboard-command.md | Declares a minor release for @taskless/cli including onboard + sprintf refactor. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)
packages/cli/src/help/rule.txt:7
rule.txtdoesn’t follow the canonical recipe section structure (it has## Subcommandsbut no## Preconditions,## Steps, or## Errors). Since this PR updates the help-file templating/spec to standardize sections, either add the missing sections here (even if brief) or explicitly document/encode an exception for “router” topics likerule.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Address Copilot review feedback on the add-onboard-command PR and
archive the OpenSpec change so the check-openspec-archived CI gate
passes.
Review feedback:
- M1: update the stale '{{INPUT_SCHEMA}}' comment above
TOPIC_INPUT_SCHEMAS in help.ts to reference the current
'%(INPUT_SCHEMA)s' sprintf-js syntax.
- M2: correct the proposal's 'No new runtime dependencies' bullet
(sprintf-js was added in support of the substitution refactor;
@types/sprintf-js is dev-only).
- L1: generalize writeInstallState to shallow-merge previous
install state with the newly computed install record, so any
sibling fields under install (today: onboarded; tomorrow: future
opt-in flags) survive re-installs without each one needing
bespoke preservation code.
Archive:
- Move openspec/changes/add-onboard-command/ to
openspec/changes/archive/2026-05-15-add-onboard-command/.
- Merge all 5 spec deltas into the live capability specs (cli-help,
cli-init, cli-onboard, cli-taskless-bootstrap, skill-taskless).
- Used --no-validate because the live cli-init spec has 3 pre-
existing requirements without SHALL/MUST keywords (req 17, 22,
23 — pre-date this change). They block strict re-validation
during merge but the deltas merge cleanly. Worth a follow-up
cleanup pass; out of scope here.
Side benefit: the live cli-help 'Help text files follow a
consistent format' requirement now uses prose instead of an
embedded fenced template (the prior fence confused the parser into
reporting zero scenarios). Resolves the S1 follow-up flagged by
/opsx:verify.
210 tests still pass; build clean.
Refs PR #20.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two PR review fixes:
- ci.txt: the GitHub Actions template's escape pattern
\${{ '{{ github.event_name }}' }} actually evaluates to the literal
string '{{ github.event_name }}' rather than the event-name context
value, so the diff-scan branch never fired in copy-pasted output.
Switch to standard \${{ github.event_name }} / \${{ github.base_ref }}.
This was a pre-existing bug surfaced by Copilot's review of the PR.
- cli-onboard spec: replace the placeholder 'TBD ... Update Purpose
after archive' with a real Purpose covering the subcommand surface
(default / --force / --mark-complete), manifest gating semantics,
recipe embedding, and telemetry.
Refs PR #20.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
thecodedrift
added a commit
that referenced
this pull request
May 16, 2026
Address Copilot review feedback on the add-onboard-command PR and
archive the OpenSpec change so the check-openspec-archived CI gate
passes.
Review feedback:
- M1: update the stale '{{INPUT_SCHEMA}}' comment above
TOPIC_INPUT_SCHEMAS in help.ts to reference the current
'%(INPUT_SCHEMA)s' sprintf-js syntax.
- M2: correct the proposal's 'No new runtime dependencies' bullet
(sprintf-js was added in support of the substitution refactor;
@types/sprintf-js is dev-only).
- L1: generalize writeInstallState to shallow-merge previous
install state with the newly computed install record, so any
sibling fields under install (today: onboarded; tomorrow: future
opt-in flags) survive re-installs without each one needing
bespoke preservation code.
Archive:
- Move openspec/changes/add-onboard-command/ to
openspec/changes/archive/2026-05-15-add-onboard-command/.
- Merge all 5 spec deltas into the live capability specs (cli-help,
cli-init, cli-onboard, cli-taskless-bootstrap, skill-taskless).
- Used --no-validate because the live cli-init spec has 3 pre-
existing requirements without SHALL/MUST keywords (req 17, 22,
23 — pre-date this change). They block strict re-validation
during merge but the deltas merge cleanly. Worth a follow-up
cleanup pass; out of scope here.
Side benefit: the live cli-help 'Help text files follow a
consistent format' requirement now uses prose instead of an
embedded fenced template (the prior fence confused the parser into
reporting zero scenarios). Resolves the S1 follow-up flagged by
/opsx:verify.
210 tests still pass; build clean.
Refs PR #20.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add a post-install discovery flow that helps a fresh Taskless user go from zero rules to a useful starter set. Implements the
add-onboard-commandOpenSpec change end-to-end (5 spec deltas: newcli-onboardcapability + modifications tocli-help,cli-init,cli-taskless-bootstrap, andskill-taskless).taskless initalready gets users installed — but until now there was no path between "installed" and "actively producing rules from real codebase signal." First-time users typically don't know what kinds of patterns Taskless is well-suited to capture, what sources to mine for candidates, or how to prioritize them. This change closes that gap.What's in the change
taskless onboardsubcommand with three modes: default prints an agent-facing recipe (refused if already complete),--forcere-runs regardless of state,--mark-completewritesinstall.onboarded: true. The recipe is conversational by design — it asks the user which sources to scan (codebase TODOs/FIXMEs, agent-memory files, recent PR comments viagh, issue tracker via MCP, plus user-suggested sources), probes tool availability before promising scans, filters for high-signal candidates (repeated patterns, cited docs, merge-blocking feedback), and outputs a bullet list of<kebab-name>: <description>the user can materialize one by one viataskless rule create.install.onboardedmanifest field (absent /false/true). Only the agent writes it, and only after explicit user confirmation per the recipe —taskless initnever touches it.writeInstallStatewas updated to preserve the flag across re-installs (otherwiseinit/updatewould silently clobber it).taskless init, prints a one-line trailer pointing the user at the new flow. Wording adapts to the install plan — when commands were installed (Claude Code, Cursor) the trailer mentions/tskl onboard, the Taskless skill, and the bare CLI; when no commands were installed (OpenCode, Codex,.agents/fallback) it mentions only the skill and the CLI.tasklessskill now also volunteers Taskless when the user asks to add/write/create a rule and has NOT named a specific lint/format/static-analysis tool. Suppressing examples (illustrative — any named tool of this kind suppresses):eslint,ruff,biome,ast-grep. Behavior on this trigger is a quiet single-line offer, not a full recipe; declines are sticky within the conversation only and never written to disk. This intentionally reverses a prior deliberate narrowing — see the design doc for the tradeoff.{{KEY}}replaceAllcalls tosprintf-jsnamed arguments. All 15 recipes migrated to%(KEY)ssyntax.PACKAGE_MANAGER_DLXjoinsCLI_VERSIONandINPUT_SCHEMAin the variable table as an explicit "agent-fill" marker rendered as<package-manager-dlx>(was previously left literal as{{PACKAGE_MANAGER_DLX}}— the new marker is more self-documenting).Where to focus review
--force --mark-completerejection and the manifest preservation in--mark-completemode are the spots to scrutinize.install.onboarded. Without this,taskless updateafter onboarding would silently wipe the flag.renderRecipenow uses sprintf-js. Worth confirming thePACKAGE_MANAGER_DLX → <package-manager-dlx>translation reads naturally in ci.txt.onboardedis a boolean (not a richer enum), and why the recipe is conversational (not a fixed phase script).Release
A minor changeset for
@taskless/cliis queued at .changeset/onboard-command.md. Release tooling rolls it into the next published version.Refs the
add-onboard-commandOpenSpec change.