feat(cli): add ask skills namespace (list/install/remove)#87
Merged
Conversation
Parallels findDocLikePaths with a /skill/i regex so ask skills can surface producer-side skill directories shipped by libraries. Task: T001
encodeSpecKey rewrites / and : as __ so the spec triple (ecosystem, name, version) becomes a flat, grep-friendly directory name. @ is preserved to keep scoped npm packages human-readable. Task: T002
lock.ts: .ask/skills-lock.json schema + atomic IO (readLock, upsertEntry, removeEntry, writeLockAtomic) that backs remove/reinstall determinism. agent-detect.ts: detectAgents + resolveAgentNames covering Claude Code, Cursor, OpenCode, Codex. AGENTS.md alone is not an install target. Tasks: T003, T004
- runSkillsList + skillsListCmd mirror ask docs using findSkillLikePaths. - vendorSkills copies producer-side skill dirs into .ask/skills/<specKey>/ via a staging dir + atomic rename. removeVendorDir wipes the tree. - linkSkill creates relative POSIX symlinks, refuses to overwrite real dirs without --force, and is a no-op when the same link already exists. unlinkIfOwned only unlinks symlinks whose target matches the vendored path, protecting user-authored skills. - ignore-files.ts now marks .ask/skills/ and .ask/skills-lock.json as vendored in .gitignore, .prettierignore, sonar-project.properties, and .markdownlintignore. Tasks: T005, T006, T007, T008
Implements the install/remove orchestration and wires the new skills namespace into the ask CLI. - runSkillsInstall: resolve via ensureCheckout → walk via findSkillLikePaths → filter each /skill/i parent via ^skills?$/i → enumerate children as individual skills → vendor → detect agents → prompt if >1 → symlink → update .ask/skills-lock.json → patch ignore files. Supports --force, --agent CSV, --no-fetch. - runSkillsRemove: reverse via the lock file. Only unlinks symlinks whose target matches the vendored path so user-authored skills are never touched. - skillsCmd: citty parent that registers list/install/remove and short-circuits `ask skills <spec>` to the list behaviour. - Wired into main subCommands alongside src/docs/cache. - Integration test covers happy-path install, idempotent re-install, remove teardown, missing-entry error, and no-agent-detected error. - Registration test asserts the four subcommand surfaces and their flag shapes. - README gets an 'ask skills' section under CLI usage documenting the vendored + symlinked install model and the v1 POSIX-only caveat. Tasks: T009, T010, T011, T012, T013
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
…nly projects Review flagged an Important issue (PR #87 validation): manageIgnoreFiles early-returned when ask.json was absent, so a user who ran only 'ask skills install' without any 'ask docs' state never had .ask/skills/ or .ask/skills-lock.json added to .gitignore. That violated FR-11 and AC-6 and would have quietly committed vendored bytes. - Replace the ask.json-only gate in manageIgnoreFiles with a new hasAskOptIn() that also accepts a .ask/skills-lock.json or .ask/skills/ presence signal. Either entry point (docs or skills) now qualifies as opt-in. - Add integration regression test covering the skills-only path without ask.json. It asserts .gitignore picks up both .ask/skills/ and .ask/skills-lock.json after the first runSkillsInstall — the exact shape that would have caught the original bug.
Deploying ask-registry with
|
| Latest commit: |
038c926
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://02bcafc6.ask-registry.pages.dev |
| Branch Preview URL: | https://amondnet-solar-boysenberry.ask-registry.pages.dev |
amondnet
marked this pull request as ready for review
April 14, 2026 15:59
16 tasks
Contributor
There was a problem hiding this comment.
No issues found across 29 files
Requires human review: Significant new feature (1900+ lines) adding filesystem mutations, symlinking logic, and lock file management; requires human validation of the architectural implementation.
Architecture diagram
sequenceDiagram
participant User as CLI User
participant CLI as Skills Command Logic
participant Res as Resolver (ensureCheckout)
participant FS as Local Filesystem (.ask/)
participant Agents as Agent Dirs (.claude, .cursor, etc)
Note over User,Agents: NEW: ask skills install [spec] Flow
User->>CLI: ask skills install <spec>
CLI->>Res: resolve and fetch spec
alt Cache Miss & --no-fetch
Res-->>CLI: NoCacheError
CLI-->>User: Exit 1
else Success
Res-->>CLI: checkout directory path
end
CLI->>CLI: NEW: findSkillLikePaths(checkout)
CLI->>CLI: NEW: detectAgents(projectDir)
alt Multiple Agents Found
CLI->>User: consola.prompt (multiselect)
User-->>CLI: selected agents (e.g., claude, cursor)
else Zero Agents Found
CLI-->>User: Error: No agents detected
end
rect rgb(240, 240, 240)
Note over CLI,FS: Atomic Vendoring
CLI->>FS: NEW: vendorSkills()
FS->>FS: Create .ask/skills/<spec-key>/.tmp
FS->>FS: Copy source skills to .tmp
FS->>FS: Rename .tmp to canonical path
end
loop For each Skill and Selected Agent
CLI->>Agents: NEW: linkSkill()
Agents->>Agents: Create relative POSIX symlink to .ask/skills/
end
CLI->>FS: NEW: writeLockAtomic(.ask/skills-lock.json)
CLI->>FS: CHANGED: manageIgnoreFiles()
Note right of FS: Patches .gitignore, .prettierignore, etc.
CLI-->>User: Success Summary
Note over User,Agents: NEW: ask skills remove [spec] Flow
User->>CLI: ask skills remove <spec>
CLI->>FS: readLock()
FS-->>CLI: Lock entries (spec, skills, agents)
loop For each recorded Symlink in Lock
CLI->>Agents: NEW: unlinkIfOwned()
Note right of Agents: Only unlinks if target matches vendor path
end
CLI->>FS: NEW: removeVendorDir()
CLI->>FS: writeLockAtomic() (remove entry)
CLI-->>User: Success message
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.
Summary
Introduces
ask skills— a sibling namespace toask docsthat surfaces and installs producer-side skills (agent-facing instruction bundles) shipped by libraries under a top-levelskills/directory.ask skills <spec>/ask skills list <spec>— prints candidate skill paths (one per line) fromnode_modules/<pkg>/and the cached GitHub checkout.ask skills install <spec>— vendors each discovered skill into.ask/skills/<spec-key>/<skill-name>/and creates relative POSIX symlinks into every selected coding-agent directory (.claude/skills/,.cursor/skills/,.opencode/skills/,.codex/skills/). Detects agents automatically; prompts viaconsola.promptmultiselect when >1 is present. Supports--agent,--force,--no-fetch.ask skills remove <spec>— reverses install deterministically via.ask/skills-lock.json; only unlinks symlinks whose target matches the vendored path.The lock file is the single source of truth for removal so user-authored skills are never touched. Re-install is idempotent. Ignore markers in
.gitignore,.prettierignore,sonar-project.properties, and.markdownlintignorenow cover.ask/skills/and.ask/skills-lock.jsonvia the existing# ask:start ... # ask:endblock.Refs #86
Scope
packages/cli/src/commands/find-skill-paths.tspackages/cli/src/skills/{spec-key,lock,agent-detect,vendor,symlinks}.tspackages/cli/src/commands/skills/{index,list,install,remove}.tspackages/cli/src/index.tspackages/cli/src/ignore-files.tsTest plan
list(mocked ensureCheckout).claude/skills/main.subCommandsask skills install github:...@v...in a project with.claude/+.cursor/Design notes
.ask/skills/<key>/vendored copy; avoids byte duplication and keeps versions in sync..ask/skills/<spec-key>/<name>/layout: name collisions between libraries resolve via the spec-key namespace;removeis a singlerm -rf.<spec-key>encoding:/and:→__,@kept. Grep-friendly, reversible.See the full plan at
.please/docs/tracks/active/ask-skills-command-20260414/plan.md.Summary by cubic
Adds a new
ask skillsCLI namespace to list, install, and remove producer-side skills from libraries. Skills are vendored into.ask/skills/, symlinked into detected agents, and tracked via a lock file; also fixes ignore patching for skills-only projects. Aligns with Linear #86.New Features
ask skills [list] <spec>prints candidate skill paths fromnode_modules/<pkg>/and the cached checkout.ask skills install <spec>vendors into.ask/skills/<spec-key>/<skill-name>/and symlinks into detected agents (.claude/skills/,.cursor/skills/,.opencode/skills/,.codex/skills/). Supports--agent,--force,--no-fetch.ask skills remove <spec>reverses install via.ask/skills-lock.json; only unlinks symlinks that point to the vendored target.ask skills <spec>is shorthand forskills list..ask/skills/and.ask/skills-lock.json. Uses relative POSIX symlinks; Windows junction fallback deferred.Bug Fixes
.ask/skills/or.ask/skills-lock.jsonexists,.gitignoreand friends are patched even without anask.json, preventing vendored skills from being committed.Written for commit 038c926. Summary will update on new commits.
Verification Checklist
bun run --cwd packages/cli lint— zero errorsbun run --cwd packages/cli test— 67/67 skills tests passask skills install github:...@v...against a project with both.claude/and.cursor/markers