feat: configure agent skills via sanity init and add sanity skills commands#1124
feat: configure agent skills via sanity init and add sanity skills commands#1124jwoods02 wants to merge 6 commits into
sanity init and add sanity skills commands#1124Conversation
Co-authored-by: Jonah Snider <jonah@jonahsnider.com>
…t-out Skills install is now part of the default `sanity init` flow: no yes/no prompt, times it post-scaffold so the install lands in the new project dir, and runs project-wide for every detected editor with a `skillsCliAgent` mapping. - New `--no-skills` flag mirroring `--no-mcp`, with matching `skillsMode` plumbing alongside `mcpMode`. Both share env / non-interactive gating so e2e / UI tests don't shell out to `npx skills add`. - Editor detection is shared between MCP and skills and only runs when at least one of the two is active. - `installSkills()` in initAction wraps the call in a defensive try/catch so init never fails on a scaffolded project even if `setupSkills` violates its no-throw contract. - Dropped the `fs.mkdir` workaround from `setupSkills` — the scaffolded project directory always exists by the time we run. - `'prompt'` mode and `promptForSkillsSetup` helper are kept in `setupSkills` for a future `sanity skills add` command.
Adds `skills` to @sanity/cli dependencies and resolves the bundled bin via `import.meta.resolve` so init runs the version we ship rather than paying the `npx -y` registry lookup at runtime. Also passes `--project` to `skills add` explicitly instead of relying on the CLI's cwd-based scope auto-detect.
- `sanity skills add` installs Sanity agent skills into the current project for detected AI editors. Same code path as the post-init install: interactive prompt when TTY, auto when not. New `explicit` flag on `setupSkills` surfaces a hint when no eligible editors are detected so the command isn't silent. - `sanity skills update` refreshes any installed project skill whose `skills-lock.json` source points at a Sanity-owned GitHub org (currently `sanity-io` and `sanity-labs`), leaving foreign skills untouched. Runs the upstream `skills update` codepath rather than re-copying via `add`, so it's hash-checked and fast. Plumbed through oclif as a new `skills` topic; `check-topic-aliases.ts` updated to allowlist it.
|
Claude finished @jwoods02's task in 4m 44s —— View job Review
Issues1. Next.js +
Fix: use async function installSkills(cwd: string): Promise<void> { /* ... */ }
// ...
if (initNext) {
await initNextJs({ ..., workDir })
await installSkills(workDir) // ← match where initNextJs wrote files
...
}
// later
await installSkills(outputPath) // studio/app branch2. The diff replaces HTTP-level
The coverage report reflects this: 3. Out-of-scope test infra change
4. Drive-by un-export of
Minor
Changeset
Test coverage
· Branch: |
📦 Bundle Stats —
|
| Metric | Value | vs main (cd110e7) |
|---|---|---|
| Internal (raw) | 2.1 KB | - |
| Internal (gzip) | 799 B | - |
| Bundled (raw) | 10.97 MB | -98 B, -0.0% |
| Bundled (gzip) | 2.06 MB | -24 B, -0.0% |
| Import time | 812ms | +2ms, +0.3% |
bin:sanity
| Metric | Value | vs main (cd110e7) |
|---|---|---|
| Internal (raw) | 1023 B | - |
| Internal (gzip) | 486 B | - |
| Bundled (raw) | 9.84 MB | - |
| Bundled (gzip) | 1.77 MB | - |
| Import time | 1.91s | +7ms, +0.4% |
🗺️ View treemap · Artifacts
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
📦 Bundle Stats — @sanity/cli-core
Compared against main (cd110e7c)
| Metric | Value | vs main (cd110e7) |
|---|---|---|
| Internal (raw) | 96.3 KB | -723 B, -0.7% |
| Internal (gzip) | 22.7 KB | -44 B, -0.2% |
| Bundled (raw) | 21.61 MB | -723 B, -0.0% |
| Bundled (gzip) | 3.42 MB | -65 B, -0.0% |
| Import time | 776ms | +1ms, +0.2% |
🗺️ View treemap · Artifacts
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
📦 Bundle Stats — create-sanity
Compared against main (cd110e7c)
| Metric | Value | vs main (cd110e7) |
|---|---|---|
| Internal (raw) | 908 B | - |
| Internal (gzip) | 483 B | - |
| Bundled (raw) | 931 B | - |
| Bundled (gzip) | 491 B | - |
| Import time | ❌ ChildProcess denied: node | - |
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
sanity init and add sanity skills topicsanity init and add sanity skills commands
- Mention the new `sanity skills add` / `sanity skills update` commands in the changeset. - Drop the stale `npx skills add` reference in the init flow comment. - Soften the `skills update` no-op message so it reads correctly whether the lockfile is missing or only contains non-Sanity skills.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit ec5d6cc. Configure here.
Coverage Delta
Comparing 14 changed files against main @ Overall Coverage
|
…tion `fileURLToPath` returns backslash-separated paths on Windows, so the regex needs `[\\/]` instead of a literal `/` to match on both platforms.
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|

Description
Set up Sanity agent skills for AI editors as part of
sanity init, and add a newsanity skillstopic for managing them in existing projects.Both these wrap the
npx skillspackage, added as a dependancy to the CLIsanity initOnce the project has scaffolded, skills are installed into the new project directory for every detected AI editor. The install is automatic and project scoped — no extra prompt during init — to keep the flow short. Opt out with
--no-skills.--no-mcpand--no-skillsare independent flags. They map tomcpMode/skillsModeand gate only their own setup, so--no-mcpdoes not silently opt the user out of skills (or vice versa).--no-mcp --no-skillsshort-circuits detection entirely.setupSkillscan never abort an otherwise-successfulsanity init.sanity skills addInstalls Sanity agent skills into the current project for detected AI editors. Same underlying code path as the post-init install, with a few command-specific behaviours:
sanity skills updateRefreshes installed project skills to their latest published version. Only updates skills whose
skills-lock.jsonsourcepoints at a Sanity-owned GitHub org (sanity-ioorsanity-labs) — foreign skills (anything the user added themselves) are left untouched.skills updatecodepath, so updates are hash-checked and fast.skillsCLI actually writes: theorg/reposhorthand it normalises HTTP(S) inputs to, and the rawgit@github.com:org/repo.gitSSH form it keeps when the user passed an SSH URL.skillsis bundled as a dependencyThe bundled
skillsCLI is added as a direct dependency of@sanity/cliand resolved viaimport.meta.resolve('skills/bin/cli.mjs', import.meta.url). Renovate keeps it pinned.Trade-off: ~430 KB unpacked in the
@sanity/clipackage, no other tree growth (yamlwas already ours). In return:npxcold-start latency on everysanity init.--projectis passed explicitly toskills addrather than relying on the CLI's cwd-based scope auto-detect, so behaviour is consistent regardless of where the user runssanity init.What to review
initApp/initStudio/initNextJs. Worth a sanity check that all three flows reach the install reliably.isSanityOwnedSourceinrunSkillsUpdate.ts— the two matched lockfile shapes are what I observed in the bundledskillsdist. If you've seen other shapes in the wild, flag them.--no-skills/--no-mcpmatrix onsanity init— covered byinit.command.test.ts, but the combinatorics are worth a glance.setupSkillskeeps a'prompt'mode that is only used bysanity skills addtoday. Fine as-is, but flag if you'd rather inline it.Testing
Unit
setupSkills: skip mode, no eligible editors, install, dedup, error paths.runSkillsUpdate: Sanity-owned source matching across lockfile shapes, no-op when nothing matches.sanity skills add/sanity skills update: command-level mocks for telemetry and error paths.sanity initmocks updated to cover the new skills step;--no-mcp/--no-skillsmatrix tests added.Manual
sanity init— skills install fires after scaffold.sanity init --no-skills— MCP still runs, skills doesn't.sanity init --no-mcp— skills still runs, MCP doesn't.sanity init --no-mcp --no-skills— neither runs, editor detection skipped.sanity skills addinside a scaffolded project.sanity skills updateafter editing a Sanity-owned skill inskills-lock.json.Note
Low Risk
Low risk: only updates a unit test assertion to accept Windows path separators; runtime behavior is unchanged.
Overview
Adjusts the
setupSkillsunit test to validateSKILLS_BIN_PATHusing a path-separator-agnostic regex (skills[\\/]bin[\\/]cli\.mjs), making the test pass on both POSIX and Windows environments.Reviewed by Cursor Bugbot for commit 3bea22c. Bugbot is set up for automated code reviews on this repo. Configure here.