Skip to content

Agent skills install from the npm packages the project already has - #219

Open
wmadden-electric wants to merge 61 commits into
claude/kind-jennings-32a0e4from
claude/agent-skills-npm-packages-770857
Open

Agent skills install from the npm packages the project already has#219
wmadden-electric wants to merge 61 commits into
claude/kind-jennings-32a0e4from
claude/agent-skills-npm-packages-770857

Conversation

@wmadden-electric

@wmadden-electric wmadden-electric commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

In a project that has @prisma/orm-postgres installed, this now works — no network, no extra tooling:

$ prisma skills sync
Synced 1 skill.
  project  /work/my-app
  check    enabled

  Skill      Package               Version   Installed into
  prisma-8   @prisma/orm-postgres  8.1.0     .claude/skills, .cursor/skills, .agents/skills, .windsurf/skills

And after pnpm up @prisma/orm-postgres bumps the package but nobody re-runs sync, every prisma command appends one line to stderr:

Prisma agent skills are out of date (installed @prisma/orm-postgres 8.1.0, synced 8.0.0). Run: prisma skills sync

Base: this PR is stacked on #218 (claude/kind-jennings-32a0e4) and shows only its own diff; GitHub retargets it to main when #218 merges.

The decision

Agent skills now travel inside the npm packages they describe, and this PR adds the CLI half of that: prisma skills sync copies them into place, prisma skills list reports status, prisma init sets a project up once, and a staleness notice after every command keeps the copies from silently rotting.

An agent skill is a directory with a SKILL.md — instructions that teach a coding agent (Claude Code, Cursor, Codex, Windsurf) how to use a library. Each harness auto-indexes skills from a known project directory (.claude/skills/, .cursor/skills/, .agents/skills/, .windsurf/skills/); a skill anywhere else is invisible. So a skill is only useful if something copies it into those directories and keeps the copy matching the installed package version. Until now that something was prisma orm init shelling out to a third-party CLI that cloned our skills from GitHub at a ref named after the package version — a convention, not a guarantee — and nothing ever detected that the copies had gone stale.

How sync decides what to install

Sync resolves a hardcoded allowlist of four packages — @prisma/orm-postgres, @prisma/orm-sqlite, @prisma/orm-mongo, @prisma/composer — by name from the project root and each workspace member directory. It never scans node_modules: a skill is instructions an agent will follow, so a scanner would let any transitive dependency inject instructions into the agent. That invariant is stated (and marked permanent) at the allowlist declaration, and this PR's trust boundary is exactly the code's — the only skills installed come from packages the user deliberately installed.

Each shipped SKILL.md carries a version stamp in its frontmatter, under the Agent Skills spec's metadata map (custom top-level keys are not spec-defined):

metadata:
  library: "@prisma/orm-postgres"
  library_version: "8.1.0"

Sync compares the installed package's version against the stamp in each harness copy and re-copies on mismatch. Pruning removes only copies whose stamp names an allowlisted package that is no longer installed — a skill some other tool put there is never touched. The synced copies are ordinary files git tracks; sync removes the * ignore file an earlier revision wrote into its copies, but leaves any .gitignore a user authored in place. If two workspace members pin different versions of one package, the highest wins and sync warns. Yarn PnP works because all reads go through Node's resolution and fs layers (there is a test that fakes the PnP zip filesystem to prove it).

Sync refuses what it does not own. A target directory whose SKILL.md is unstamped, unreadable, or stamped by a non-allowlisted package — a hand-written skill colliding on name — is left byte-for-byte intact, reported in a refused array and a SKILLS.UNMANAGED_DIRECTORY diagnostic, and the summary line never claims "up to date" without naming it. A directory whose SKILL.md is genuinely absent (an interrupted copy) is repaired.

prisma init

prisma init initializes a repository for Prisma development, purely locally — no platform calls. Two steps, each with an opt-out (--no-postinstall, --no-skills), always exit 0, never prompts, idempotent:

  1. Adds "postinstall": "prisma skills sync || exit 0" to the current directory's package.json, so skills resync on every install and upgrade. A different existing postinstall script is never clobbered or chained — init reports it and tells the user what to append. BOM, CRLF, indentation, and trailing-newline style are preserved; an unreadable, unwritable, or malformed manifest is a diagnostic, not a failure.
  2. Runs the skills sync in-process at the discovered workspace root. A sync failure is a diagnostic on a successful init.

This is a new command reusing a retired name: #218 deleted the old compute-config wizard, and nothing from it returns. Sync itself still never touches package.json (a test pins byte-identity across a sync run) — writing the hook is exclusively the act of a user running init.

The prisma agent group is deleted

prisma agent install|update|status — the old installer that shelled out to npx skills@latest for the v6/v7 skills — is gone (operator ruling, 2026-08-21). The post-login tip that advertised it now offers prisma skills sync instead, only when installed packages actually have stale copies, and can no longer fail a login that already succeeded.

The staleness notice

It prints to stderr, after the command's own output, never changes the exit code, and is deliberately not TTY-dependent — its main reader is an agent running the CLI without one. Off switches: --quiet, --json / --format json, --version, PRISMA_SKILLS_CHECK=0, CI/GITHUB_ACTIONS, skills: { check: false } in prisma.config.ts (an explicit --config <path> is honored), a persistent opt-out written by prisma skills sync --disable (stored in .prisma/skills.json), and any skills command itself. Flag scanning stops at a bare --. The per-command cost is stat calls and small file reads; prisma.config.ts is only evaluated after staleness is already established. With the init-written postinstall as the primary trigger, the notice is the backstop for projects that never ran init or removed the script.

Pin and state dir find the project root

.prisma/local.json (the link pin) and the state dir are now discovered by walking up from the cwd to the nearest directory containing .prisma/ — a pure filesystem check, no config file is read — so a repo linked at its root works from apps/api/. Nearest wins deliberately: a subdirectory linked to a different project beats the root. Commands that rewrite or delete the pin operate on the file they found, not on the cwd. When no .prisma/ exists, behavior is unchanged.

The rename: CLI_NAME is now prisma

The published package (prisma) has installed a bin named prisma since 8.0.0-rc.3, but every string the CLI printed still said prisma-cli. This PR moves CLI_NAME, so help text, error guidance, and the notice above all name the binary users actually have. There is no compatibility layer: the CLI is pre-rc and owes old spellings nothing, so every producer of error guidance was fixed to emit the current commands directly, and the display-time rewriter that used to patch up legacy spellings (renameAppCopy and friends) was deleted rather than extended. fromLegacyCliError survives only as a structural converter (legacy error shape → CliError); it no longer rewrites or filters any copy. Deliberate survivals, so nobody "finishes" the rename by mistake: the @prisma/cli package's own bin and README, the update-check entrypoint matcher and cache directory, git@github.com:prisma/prisma-cli.git repo URLs, and the utm_source/utm_campaign sign-in tags.

Tests

90+ new tests: npm/pnpm/Yarn-PnP fixture projects, every sync/check state (stale, never-synced, in-sync, refused, opted out), the collision and unreadable-skill refusals (chmod-based), pruning on package removal, a two-member monorepo with the version-conflict warning, every off switch, init's full package.json edge-case matrix (foreign script, non-object scripts, BOM, CRLF, read-only file, missing manifest), a credential-free e2e driving the built binary through init twice, a readdir-count regression test bounding workspace-glob expansion, and the legacy-error mapper suite.

For other owners

  • The feedback client's user-agent changed from prisma-cli/<version> to prisma/<version> — wire-visible; whoever reads that dashboard should know.
  • isLikelyGlobalNpmEntrypoint (update-check) still matches only prisma-cli install paths, so a globally installed prisma gets the docs-link fallback instead of a concrete update command. Pre-existing, untouched here, newly conspicuous.
  • The browser login success page still shows a static npx skills add prisma/skills copy button — the last surface promoting the retired installer; its removal is pending an operator decision.
  • Init stops touching agent skills; the family-level prisma init owns skills setup prisma#30097 (orm init) drops its scaffold-time sync call per operator ruling — follow-up on that PR.

Merge order: #218 merges first (this PR is stacked on it), then this PR, then prisma/prisma#30096 (packaging) and prisma/composer#251's npm release — both ship skills only this CLI can read.

Alternatives considered

  • Keep fetching from GitHub via npx skills add (status quo): version matched by ref-name convention only, unmanaged copies, network access during init, and an unpinned third-party CLI in our init path.
  • Discover skills by scanning node_modules: prompt-injection by construction — any transitive dependency could plant instructions. Permanently rejected.
  • Symlinks into node_modules instead of copies: no node_modules under Yarn PnP, symlink creation needs elevation on Windows, and only Claude Code documents following symlinked skills. Version-stamped, checked, auto-resynced copies are a managed cache.
  • A line in AGENTS.md telling agents to run sync each session: rejected by the team — agents shouldn't carry maintenance duties.
  • A postinstall in our own packages: dependency lifecycle scripts are blocked by default in pnpm 10+, bun, and Deno. Permanently rejected.
  • Writing a postinstall from prisma orm init or from sync itself (the original design): rejected — a routine command silently editing your package.json, or re-adding a script you removed, is not acceptable. The operator's final ruling: the hook is written only by prisma init, a command whose whole point the user invokes deliberately; nothing automatic ever edits the manifest, and the staleness notice covers everyone else.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0ca6e80e-b6ed-49a3-9abf-1d5671aa0399

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-new Bot commented Aug 21, 2026

Copy link
Copy Markdown

Open in StackBlitz

npx https://pkg.pr.new/@prisma/cli@219
npx https://pkg.pr.new/@prisma/cli-engine@219

commit: 8842b4c

@wmadden-electric
wmadden-electric marked this pull request as ready for review August 21, 2026 11:00
@wmadden-electric wmadden-electric changed the title Add prisma skills sync/list and the skill staleness check Agent skills install from the npm packages the project already has Aug 21, 2026
Adds `prisma skills sync` and `prisma skills list`, and the staleness
check every other command runs.

Skills now travel inside the Prisma packages a project installs, so a
copy in a harness skill directory is current only when its
`library_version` stamp matches the version of the package it came
from. Sync resolves the allowlisted packages by name from the project
root and from each declared workspace member, copies each skill tree
into the four harness directories, and removes copies whose source
package is gone. It never scans node_modules — the allowlist states why
that is permanent.

The check lives in main.ts after dispatch: every mounted family runs
through that one call, so the ORM and Composer families need no copy of
it. It writes one stderr line, never changes the exit code, and is
silenced by --quiet, --json/--format json, PRISMA_SKILLS_CHECK=0, CI,
`skills: { check: false }` in prisma.config.ts, and
`skills sync --disable`.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Fixture projects in the layouts npm and pnpm produce, a workspace with
two members pinning different versions, and a Yarn PnP fixture that
patches Node's resolver and the filesystem module the way .pnp.cjs
does — so the tests fail if the sync ever builds a node_modules path
itself or reads through an API the PnP layer does not patch.

Covers every state a copy can be in (in sync, stale, never synced,
orphaned), pruning on package removal, leaving skills from other
packages alone, exit 0 whenever there is nothing to do, and each of the
check's off switches.

The fixtures clear NODE_PATH first: vitest points it at this
repository's pnpm store, which would otherwise make every fixture
project look like it had two allowlisted packages installed.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The staleness notice is not TTY-gated, which the update-notification
section would otherwise imply is the rule for advisory stderr lines, so
its own section says why and lists every way to silence it.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
`prisma --config <path> skills list` invokes the command that fixes
stale skills, so the check must recognise the group even when shared
flags come first. Also trims sync's help to the two examples the style
guide asks for.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
A `packages/**` workspace made member enumeration walk the whole
working tree — dist, coverage, .git, every source directory — and the
resolver was then pointed at each one, four package names at a time.
The staleness check runs that on every command, so an ordinary
workspace pattern cost roughly a second per invocation instead of the
milliseconds the design budgets.

The walk now stops at a directory holding a package.json, because that
directory is the member and everything below it is the package's own
contents, and it never enters a dot-directory. Only directories with a
package.json are returned, so `**` answers with packages rather than
with directories.

The new test counts directory reads rather than timing them: on a
workspace with two built members it reads `packages` and
`packages/group` and nothing else.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
`skills sync` printed `check: enabled` in a project whose
prisma.config.ts sets `skills: { check: false }`, contradicting
`skills list` and the check itself. It now needs the same config
section and combines it with the persisted opt-out the same way.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The Agent Skills spec defines no custom top-level frontmatter keys;
extensions live under `metadata`, a map of strings. Slices 1 and 4 are
stamping `metadata.library` and `metadata.library_version`, so the
reader follows them there and nowhere else. No fallback to the old
top-level spelling: nothing has shipped one, and accepting both would
let a skill claim a stamp the spec has no place for.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Operator decision: the published binary is `prisma`, so CLI_NAME — the
one place the user-facing name lives — now says `prisma`, and every
command string, notice, error next step, help line and sample output
follows it. `prisma-cli` survives only where it names something that
really is still called that: the `@prisma/cli` package's own bin (its
README and the update check's entrypoint detection), the update-check
cache directory, the repository URL, the sign-in campaign tag, and the
legacy error copy the service group rewrites.

That rewriting is why one behavioural change came with the rename:
`fromLegacyCliError` turned a legacy `nextSteps` line into a
run-command action only when it began `prisma-cli `, and dropped every
other line. Legacy builders written with the new spelling would have
lost their next steps, so the mapper now recognises both spellings and
renames `<name> app ` to `<name> service ` either way.

The feedback client's user-agent follows CLI_NAME too, so it now
reports `prisma/<version>`; it identifies this binary, and this binary
is called prisma.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
`/docs/orm/tools/prisma-cli` is the path that 308-redirects to the ORM
CLI reference, which is the whole reason the comment cites it. The
sweep matched it because the path was followed by a space, and
output-conventions.md kept the right spelling, so the two disagreed.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The mapper's current-spelling branch does have a producer —
`computeConfigErrorToCliError` writes `prisma service <command>` into
nextSteps, and `resolveComputeManagementContext` maps it — so removing
the branch fails two tests in service-compute-config. What it lacked
was a test that says so directly: those two fail for reasons that read
as compute-config behaviour.

These drive `renameAppCopy` and `fromLegacyCliError` with one spelling
each, and pin the asymmetry that makes this worth covering — a command
line the mapper does not recognise is dropped from nextActions rather
than passed through, so an unrecognised spelling costs the user their
next step with nothing to show for it.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Round-4 review fixes (S2-R3-1, S2-R3-2), committed at session halt;
suites not re-run. Includes drive project artifacts up to this point.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The branch's only cli-engine change was two doc-comment lines renamed in a prisma-cli -> prisma sweep. That trips the engine-version check because 0.2.0 is already published, and publishing the engine for comments is not worth it. Restore the file to origin/main byte-for-byte.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Both failures were in test fixtures, not production code — the skills library joins every path with path.join, which is correct on Windows.

skills-pnp: the fake PnP layer remapped virtual paths with a startsWith check against a forward-slash prefix, but on Windows path.join hands it backslash paths, so the remap missed and sync found no packages. The fixture now compares in forward-slash form.

skills-workspace-scan: the recorded readdir paths carry native separators, so the expected relative paths did not match on Windows. The assertion now normalizes separators before comparing; the set of directories it pins is unchanged.
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…eout flake

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…gacy mapping

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…s gone

The CLI is pre-rc with no legacy obligations, so error copy no longer passes through a rename layer.

Producers now write the commands a user types today: domain-guidance.ts says prisma service domain retry/show instead of prisma-cli app domain ..., and computeConfigErrorToCliError says Service target instead of App target (its command lines already said prisma service ...).

Deleted from service/errors.ts: renameAppCopy, toCurrentCommandLine, COMMAND_PREFIXES, LEGACY_CLI_NAME, and the prefix filter on nextSteps. fromLegacyCliError keeps only the structural conversion (flat code to SERVICE.<code>, fix to a user-choice action, each nextSteps line to a run-command action) and passes all copy through unchanged. Every producer feeding it emits prisma-prefixed command lines, so the filter had nothing left to drop.

Kept: portCommandString in project/errors.ts. It converts package-runner invocations (npx -y @prisma/cli@next auth login) into bin invocations for display, which is not spelling rewriting.

tests/service-legacy-errors.test.ts existed to pin the rewriter and is deleted; the compute-config and domain-wait tests already assert the direct producer strings and still pass unchanged.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…n edit

Each managed skill directory now gets a .gitignore containing * when sync copies the tree, so git ignores the copy without anyone editing the project's root .gitignore. The staleness stamp and the orphan scan only read SKILL.md, so the extra file changes neither; a test pins that a copy stays synced with it present.

Sync's next-step output now suggests the optional postinstall script (prisma skills sync || exit 0) the user can add to their root package.json themselves. Sync never writes package.json — a test pins the manifest byte-for-byte across a run — and the staleness notice covers projects that skip the script.

docs/product/output-conventions.md states the model: the notice is the mechanism, gitignoring is self-contained to the managed directories, and the postinstall is user-added. No other doc claimed otherwise.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The new base made resolveStateDir synchronous; the .prisma-directory anchor and compute-config fallback both walk the filesystem, so the function stays async and its two callers await it with the request signal.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
One retry command in project show and two test expectations still said prisma-cli; both sides' lines merged cleanly past the rename commit.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
@wmadden-electric
wmadden-electric force-pushed the claude/agent-skills-npm-packages-770857 branch from 8842b4c to 4350bb3 Compare August 21, 2026 15:32
@wmadden-electric
wmadden-electric changed the base branch from main to claude/kind-jennings-32a0e4 August 21, 2026 15:32
prisma init now writes the real postinstall hook, so the advisory next-action was dead weight.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Installed skills are ordinary files git can see. A resync removes the .gitignore older CLI versions wrote, because replaceTree rewrites the whole tree.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The old v6/v7 skills installer that shelled out to npx skills@latest is replaced by the skills group. The post-login tip now points at skills sync, driven by the same status read the skills commands use, and fires only when installed Prisma packages have out-of-date skill copies.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
A name collision with a hand-written skill, or with one stamped by a package outside the allowlist, used to parse as an absent target and get silently deleted and replaced. Such a directory is now reported as unmanaged: sync leaves it untouched and warns, and it no longer counts as out of date.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Read the persisted opt-out before any scan and skip the orphan scan on the notice path; validate the skills config section with its own validator; exempt --version like the update check; stop reading flags past a bare --; honor an explicit --config path when loading the config.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
A purely local repository setup: it writes "postinstall": "prisma skills sync || exit 0" into package.json (never touching a script the user wrote) and runs the skills sync through the same status/sync path as prisma skills sync, presented with the shared sync presentation. Every degraded outcome — no package.json, a foreign postinstall, a sync failure — is a diagnostic on a successful exit 0, and reruns report each step as already done. --no-postinstall and --no-skills skip one step each.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
An EACCES on the write and a non-object scripts value both become warn diagnostics on a zero exit, and a BOM or CRLF manifest survives the rewrite byte-compatibly.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
init now emits the unmanaged-directory diagnostics, and the shared sync presentation renders a refused table plus an up-to-date summary clause so neither sync nor list claims everything is current while a directory was refused.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…elf-heals

Unmanaged is reserved for an existing SKILL.md that is unstamped or foreign-stamped, and sync also removes the .gitignore an older CLI left inside a copy that is already current.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Its status read is guarded and skips the orphan scan the tip never reads.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Its readers and writers were deleted with the agent group; the parser ignores unknown keys, so an older state file still reads cleanly and an older CLI defaults the missing field to null.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…s read

readSkillsStatus accepts them as options so the ancestor walk and the opt-out file are not read twice on the path that does not exit early.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
output-conventions describes the refusal rule and the summary clause, command-principles adds skills and init to the preview scope, and init's help says the hook lands in the current directory while the skills land at the workspace root.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Closes INIT-R4-1 and INIT-R4-2: only ENOENT on the SKILL.md stat reads as absent, so an EACCES or ENOTDIR parent classifies unmanaged and sync declines instead of dying on the rm. The init sync-failure test now forces its failure with a read-only parent, since a file squatting on .claude is refused gracefully now.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant