-
Notifications
You must be signed in to change notification settings - Fork 1
docs(skills): add ask skill with references for progressive disclosure #94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| --- | ||
| name: ask | ||
| description: Fetch version-accurate library documentation, source trees, and producer-shipped skills so the agent works against the exact version installed in the project, not training-data guesses. Use this skill whenever the user needs docs for a dependency, wants to read a library's real source, asks "how does X work internally", needs to pin reading to a specific version or ref, mentions ask docs / ask src / ask skills, or any task that would benefit from a library's actual README / source / skill files over recalled knowledge — even when they don't explicitly name the "ask" CLI. Preferred over inferring API shape from memory whenever accuracy matters. | ||
| allowed-tools: Bash(ask:*) | ||
| --- | ||
|
|
||
| # Version-Accurate Docs & Source with `ask` | ||
|
|
||
| `ask` resolves the version from the project's lockfile | ||
| (`bun.lock → package-lock.json → pnpm-lock.yaml → yarn.lock → package.json` | ||
| range fallback), fetches docs or source once, caches them globally at | ||
| `~/.ask/` (override via `ASK_HOME`), and prints absolute paths to stdout so | ||
| the commands compose naturally in shell substitutions. Progress / errors go | ||
| to stderr, paths go to stdout — safe for `$(ask …)`. | ||
|
|
||
| ## Core Pattern | ||
|
|
||
| ```bash | ||
| # Docs — one candidate path per line | ||
| cat "$(ask docs zod | head -n1)"/README.md | ||
| rg "parseAsync" $(ask docs zod) | ||
|
|
||
| # Source — single absolute path to the checkout root | ||
| rg "ZodError" $(ask src zod) | ||
| fd -e test.ts . $(ask src zod) | ||
|
|
||
| # Producer-shipped skills — one /skills/ dir per line | ||
| ls $(ask skills vercel/ai) | ||
| ``` | ||
|
|
||
| `ask docs` emits candidate documentation directories (publish-time | ||
| `dist/docs` first, then any subdirectory whose basename matches `/doc/i` | ||
| up to depth 4, falling back to the checkout root when nothing matches). | ||
| `ask src` emits exactly one path: the checkout root. Both auto-fetch on | ||
| cache miss; pass `--no-fetch` to fail fast (exit 1) on miss instead. | ||
|
|
||
| ## Spec Grammar | ||
|
|
||
| ``` | ||
| zod # bare → npm ecosystem (resolved via lockfile) | ||
| npm:next # explicit ecosystem | ||
| npm:@mastra/client-js # scoped package | ||
| facebook/react # owner/repo → github:facebook/react@main | ||
| github:vercel/next.js@v14.2.3 # pinned tag | ||
| github:owner/repo@main # pinned branch | ||
| ``` | ||
|
|
||
| - For `npm:` specs (and bare names), the version comes from the project's | ||
| lockfile. Append `@version` to pin explicitly: `zod@3.22.0`, | ||
| `npm:next@14.2.3`. | ||
| - For `github:` specs, `@<ref>` pins a tag or branch. Bare `owner/repo` | ||
| (no `@ref`) defaults to `main`. | ||
| - Any ref works with these one-shot reading commands — branches, tags, | ||
| or mutable refs like `main` / `master` are all accepted, since | ||
| nothing is persisted. | ||
|
|
||
| ## One-Shot Reading Commands | ||
|
|
||
| | Command | Output | Use when | | ||
| |---------|--------|----------| | ||
| | `ask docs <spec> [--no-fetch]` | Candidate doc dirs, one per line | You want README / guides / handwritten docs at the installed version | | ||
| | `ask src <spec> [--no-fetch]` | Checkout root, single line | You need to read real source, search all files, follow implementations | | ||
| | `ask skills <spec>` (= `ask skills list`) | `/skills/` dirs, one per line | The library ships its own Claude / Cursor / OpenCode skills | | ||
|
|
||
| All three share `ensureCheckout`, so the cached path is reused across | ||
| commands — calling `ask docs`, then `ask src`, then `ask skills list` on | ||
| the same spec fetches once. | ||
|
|
||
| ## When You Need More | ||
|
|
||
| Lazy-load these references only when the situation calls for them: | ||
|
|
||
| - **Managing the cache** — disk pressure, stale entries, `--kind` / | ||
| `--older-than` filters, legacy v1 layout cleanup → | ||
| [`references/cache.md`](references/cache.md). | ||
| - **Project-level declarative workflow** — `ask.json`, `ask install`, | ||
| `ask add`, `ask remove`, `ask list`, auto-regenerated `AGENTS.md` and | ||
| per-library `.claude/skills/<name>-docs/SKILL.md` → | ||
| [`references/declarative-workflow.md`](references/declarative-workflow.md). | ||
| - **Vendoring producer skills into this project** — `ask skills install`, | ||
| `--force`, `--agent claude,cursor,opencode,codex`, `ask skills remove | ||
| --ignore-missing` → | ||
| [`references/skills-vendoring.md`](references/skills-vendoring.md). | ||
|
|
||
| ## When to Reach for `ask` | ||
|
|
||
| Reach for it when: | ||
|
|
||
| - The installed version matters — otherwise the agent risks fabricating | ||
| API shape from an outdated training snapshot. | ||
| - The answer lives in source, not types — edge cases, error paths, | ||
| internal helpers, behavior that isn't documented anywhere else. | ||
| - A library may ship its own skills — `ask skills list <spec>` discovers | ||
| producer-side `skills/` directories without touching the project. | ||
|
|
||
| Skip it when TypeScript / LSP / intellisense can answer the question, or | ||
| when the user has already pointed at a specific file path. | ||
|
|
||
| ## Why This Exists | ||
|
|
||
| Training data ages; lockfiles don't. `ask` bridges the two by pinning | ||
| every read to the version the project actually runs, so generated code | ||
| reflects reality instead of last year's docs. The `$(ask …)` idiom is | ||
| the main ergonomic: it turns a cached path into a first-class argument | ||
| to `rg`, `cat`, `fd`, or any tool that accepts a path — no extra API to | ||
| learn. | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| # Cache Management (`ask cache`) | ||
|
|
||
| Read this when disk is filling up, a cached entry is stale, or you need | ||
| to inspect what `ask` has fetched. The global store lives at `~/.ask/` | ||
| by default; set `ASK_HOME` to relocate it. Every `ask install` writes | ||
| `<askHome>/STORE_VERSION` (currently `"2"`) as a layout marker. | ||
|
|
||
| ## Store Layout (v2) | ||
|
|
||
| ``` | ||
| <askHome>/ | ||
| ├── npm/<pkg>@<version>/ # npm tarball extractions | ||
| ├── github/<host>/<owner>/<repo>/<ref>/ # github shallow clones (PM-unified) | ||
| ├── web/<sha256-of-url>/ # crawled doc sites | ||
| ├── llms-txt/<sha256>@<version>/ # llms.txt imports | ||
| ├── STORE_VERSION # "2" | ||
| └── .quarantine/<ts>-<uuid>/ # corrupt entries, preserved for inspection | ||
| ``` | ||
|
|
||
| `host` is currently always `github.com` — the segment exists so | ||
| `gitlab.com` / `bitbucket.org` can slot in without a migration. | ||
|
|
||
| ## `ask cache ls [--kind <kind>]` | ||
|
|
||
| List every entry in the store with its size. | ||
|
|
||
| ```bash | ||
| ask cache ls # everything | ||
| ask cache ls --kind npm # filter: npm | github | web | llms-txt | ||
| ``` | ||
|
|
||
| Entries print as `<kind>/<key> <size>`. Total size is summarized at | ||
| the end. If a legacy (pre-v2) `github/db` or `github/checkouts` | ||
| directory exists, its entries are tagged with a `(legacy) ` prefix in | ||
| the key — that's the signal to run `ask cache clean --legacy`. | ||
|
|
||
| ## `ask cache gc [--dry-run] [--older-than <duration>]` | ||
|
|
||
| Remove entries that no project references anymore. `gc` discovers | ||
| references by walking `$HOME` (or each path in `ASK_GC_SCAN_ROOTS`, | ||
| colon-separated) for `.ask/resolved.json` files and treating the | ||
| entries listed there as roots. | ||
|
|
||
| ```bash | ||
| ask cache gc # remove all unreferenced | ||
| ask cache gc --dry-run # preview only, no deletion | ||
| ask cache gc --older-than 30d # also require age > 30 days | ||
| ask cache gc --older-than 12h # supports d / h / m / s | ||
| ASK_GC_SCAN_ROOTS=/repos:/work ask cache gc # restrict scan | ||
| ``` | ||
|
|
||
| Always try `--dry-run` first when `ASK_GC_SCAN_ROOTS` is unset — the | ||
| default `$HOME` scan may miss project directories stored elsewhere, | ||
| which would mark still-used entries as unreferenced. | ||
|
|
||
| ## `ask cache clean --legacy` | ||
|
|
||
| Remove the pre-v2 github store layout. The flag is required; calling | ||
| `ask cache clean` without it exits with a reminder. | ||
|
|
||
| ```bash | ||
| ask cache clean --legacy | ||
| ``` | ||
|
|
||
| Deletes: | ||
| - `<askHome>/github/db/` (bare-clone DB from the old shared layout) | ||
| - `<askHome>/github/checkouts/` (per-ref worktrees from the old layout) | ||
|
|
||
| The v2 layout (`<askHome>/github/<host>/<owner>/<repo>/<ref>/`) is | ||
| untouched. Safe to run anytime; it's a no-op when no legacy dirs exist. | ||
|
|
||
| ## Environment Variables | ||
|
|
||
| | Variable | Purpose | Default | | ||
| |-----------------------|--------------------------------------------|----------------| | ||
| | `ASK_HOME` | Override the global store root | `~/.ask` | | ||
| | `ASK_GC_SCAN_ROOTS` | Colon-separated scan roots for `cache gc` | `$HOME` | | ||
|
|
||
| Both are read at invocation time — set them inline or export per shell. | ||
|
|
||
| ## Troubleshooting Tips | ||
|
|
||
| - "Corrupted store entry … quarantined to …" — `ask install` moved a | ||
| tamper/missing-stamp entry into `.quarantine/`. Re-run the install; | ||
| the fresh fetch replaces it. Delete the quarantine dir manually once | ||
| you've inspected it. | ||
| - `ask docs <spec>` prints nothing — the checkout exists but has no | ||
| `/doc/i` subdirs AND the walker can't see the root. Try | ||
| `ask src <spec>` and `ls $(ask src <spec>)` to confirm the checkout | ||
| is populated. | ||
| - `gc` removed an entry you still needed — either the project wasn't | ||
| inside `ASK_GC_SCAN_ROOTS`, or `.ask/resolved.json` was missing / | ||
| out of date. Re-run `ask install` in the project to rebuild both. |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| # Declarative Workflow (`ask.json` + `ask install`) | ||
|
|
||
| Read this when the user wants a checked-in list of libraries the | ||
| project's agents should reference, or wants `AGENTS.md` auto-regenerated | ||
| with lazy `ask src` / `ask docs` pointers. The one-shot reading | ||
| commands (`ask docs` / `ask src` / `ask skills list`) don't persist | ||
| anything; this flow does. | ||
|
|
||
| `ask install` is **lazy-first**: it resolves versions and writes | ||
| `AGENTS.md` plus a per-library `.claude/skills/<name>-docs/SKILL.md` | ||
| that tells agents to invoke `ask src <spec>` / `ask docs <spec>` on | ||
| demand. No documentation is downloaded during `install` — fetching | ||
| happens the first time an agent calls `ask docs` / `ask src`. | ||
|
|
||
| ## What Gets Written | ||
|
|
||
| - `ask.json` — the declarative input. Array of spec strings. Checked | ||
| into git; edited by `ask add` / `ask remove` (or by hand). | ||
| - `AGENTS.md` — block between `<!-- BEGIN:ask-docs-auto-generated -->` | ||
| and `<!-- END:ask-docs-auto-generated -->` maintained by `ask`. | ||
| - `.claude/skills/<name>-docs/SKILL.md` — one skill per declared | ||
| library, each delegating to `ask docs <spec>` / `ask src <spec>`. | ||
| - Ignore files (`.gitignore`, `.prettierignore`, etc.) — patched via | ||
| `# ask:start … # ask:end` marker blocks. Don't hand-edit inside | ||
| those markers; `install` / `remove` overwrite them. | ||
|
|
||
| ## `ask install` | ||
|
|
||
| Reads `ask.json`, resolves each spec to a concrete version, regenerates | ||
| per-library skills, and rewrites the `AGENTS.md` block. | ||
|
|
||
| ```bash | ||
| ask install | ||
| ``` | ||
|
|
||
| Per-entry behavior: | ||
|
|
||
| 1. **Version resolution** | ||
| - `npm:` specs → read lockfile chain | ||
| `bun.lock → package-lock.json → pnpm-lock.yaml → yarn.lock → | ||
| package.json` (range fallback). Missing from every lockfile ⇒ | ||
| entry skipped with a warning. | ||
| - `github:` specs → the ref encoded in the spec | ||
| (`github:vercel/next.js@v14.2.3`). No lockfile lookup. | ||
| - Explicit `@version` on any spec wins over lockfile resolution. | ||
| 2. **Skill generation** — writes `.claude/skills/<name>-docs/SKILL.md`. | ||
| 3. **AGENTS.md regeneration** — rewrites the auto-generated block | ||
| with every resolved library. | ||
|
|
||
| `postinstall`-friendly: per-entry failures emit a warning; the overall | ||
| exit code is always 0, so an unresolvable entry doesn't break | ||
| `bun install`. | ||
|
|
||
| ## `ask add <spec>` / `ask add` (interactive) | ||
|
|
||
| Appends to `ask.json`, then runs install for just that entry. | ||
|
|
||
| ```bash | ||
| ask add npm:next | ||
| ask add npm:@mastra/client-js | ||
| ask add github:vercel/next.js@v14.2.3 | ||
| ask add facebook/react # bare owner/repo → github:facebook/react | ||
| ask add # interactive picker | ||
| ``` | ||
|
|
||
| Bare names without `:` or `/` (e.g. `ask add zod`) are rejected with a | ||
| hint listing the two valid forms. Note the asymmetry: the one-shot | ||
| `ask docs zod` DOES accept bare names — only `ask add` is strict | ||
| because the spec is persisted. | ||
|
|
||
| ## `ask remove <name>` | ||
|
|
||
| Removes from `ask.json`, deletes the generated skill, re-runs install | ||
| to regenerate `AGENTS.md`. | ||
|
|
||
| ```bash | ||
| ask remove next | ||
| ask remove @mastra/client-js | ||
| ask remove npm:next # also accepts the full spec | ||
| ``` | ||
|
|
||
| The `name` match is tried against the full spec, the spec body, and | ||
| the derived library slug — so the unscoped name, the full spec, or the | ||
| scoped package name all work. | ||
|
|
||
| ## `ask list [--json]` | ||
|
|
||
| Prints declared libraries with their resolved versions. Unresolved | ||
| entries (declared in `ask.json` but missing from every lockfile) show | ||
| `version: unresolved` so drift is visible. | ||
|
|
||
| ```bash | ||
| ask list | ||
| ask list --json | jq '.entries[] | select(.version == "unresolved")' | ||
| ``` | ||
|
|
||
| JSON shape (`ListModelSchema`): `{ "entries": [...], "conflicts": | ||
| [...], "warnings": [...] }`. Each entry has `name`, `version`, | ||
| `format`, `source`, `location`, plus optional `itemCount` / `skills`. | ||
|
|
||
| ## `ask.json` Shape | ||
|
|
||
| Strict array of ecosystem-prefixed spec strings — schema is | ||
| `z.array(z.string().regex(/^[a-z][a-z0-9+-]*:.+$/))` with `.strict()`. | ||
| Object entries are rejected. | ||
|
|
||
| ```json | ||
| { | ||
| "libraries": [ | ||
| "npm:next", | ||
| "npm:@mastra/client-js", | ||
| "npm:zod@3.22.0", | ||
| "github:vercel/next.js@v14.2.3", | ||
| "github:vercel/ai@v5.0.0" | ||
| ] | ||
| } | ||
| ``` | ||
|
|
||
| - `npm:` specs: append `@<version>` to pin, otherwise the lockfile | ||
| decides. | ||
| - `github:` specs: append `@<ref>` to encode the version inside the | ||
| spec string. `github:` without a ref defaults to `latest` in the | ||
| generated output. | ||
| - No separate `ref`, `source`, or `docsPath` keys. Per-library | ||
| `docsPath` comes from the ASK Registry when `ask docs` / `ask src` | ||
| actually fetch, not from `ask.json`. | ||
|
|
||
| ## Intent-Format and Resolved-Cache Notes | ||
|
|
||
| Prior versions of `ask` had a `.ask/resolved.json` lockfile, a | ||
| `<!-- intent-skills:start -->` block in `AGENTS.md` for | ||
| TanStack-intent packages, and a `--allow-mutable-ref` flag. In the | ||
| current lazy-first architecture `ask install` does not write | ||
| `.ask/resolved.json` and does not populate intent blocks; the | ||
| underlying code modules still exist but are not wired into the | ||
| install path. Treat the docs, source, and skills commands as the | ||
| supported surface, and `ask.json` as a strict spec-string array. |
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3: "nothing is persisted" is misleading: one-shot commands do persist fetched data in the global ASK cache. Clarify that only project declarative state is not persisted.
Prompt for AI agents