Protected ReadonlyclientsProtected ReadonlydirectoryProtected ReadonlyhashContent hash per root, keyed on a stat signature, so drift detection skips unchanged files.
Protected ReadonlyloggerProtected ReadonlymanifestProtectednotifyProtected ReadonlystagedProtectedstagingDisambiguates two staging directories created within the same millisecond.
ProtectedsubscriptionProtected ReadonlytarballProtectedwatchingProtectedchooseThe last segment of the identifier while no other installed plugin has claimed it, and the directory name otherwise. First come, first served, and recorded rather than derived: a plugin installed later must never rename the skills of one that is already there, and an update of this plugin must not rename its own.
ProtectedclaimedQualifiers of every managed plugin other than exceptDirectory, read from the markers alone -
listInstalledPlugins would walk every tree and hash it just to answer this.
The data directory is created here and never removed on update: the specification makes creating it a MUST before any plugin subprocess launches, and requires its contents to survive an update.
ProtectedcomputeReuses the cached hash while size and mtime of every hash-relevant file are unchanged, so an unchanged root is walked once and never re-read.
ProtectedcomputeRead straight from disk, without consulting the drift cache.
ProtecteddescribeFailures are isolated at the narrowest boundary the specification defines: an invalid
plugin.json leaves the directory without components, an invalid mcp.json only disables MCP,
and a single invalid server or skill is skipped.
ProtecteddiscoverImmediate children of skills/ only, never recursive. A directory without a SKILL.md is simply
not a skill and is not reported.
the names sorted, so a card rendered from this does not reshuffle between scans.
Dispose this object.
Protectedensure@parcel/watcher reports bare directory deletions reliably across platforms; fs.watch does not.
ProtectedexistsProtectedfindThe marker is the only evidence of ownership there is, so this scans for it.
ProtectedinitProtectedisWrites only the provenance marker, touching no file the plugin owns. Only the canonical directory name may be adopted: every other operation derives its target from the plugin identifier, so adopting another name would let an update create a second directory beside the adopted one.
Ends in launching a subprocess exactly like commit, so it carries the same obligations.
ProtectednotifyProtectedpluginProtectedpluginA sibling tree of the plugin roots, so plugin data is never part of a content hash and survives replacing the root.
Protectedpluginsprotected so a product can override it; deliberately not a preference.
ProtectedprepareA subprocess cannot create its own cwd, and the manifest reader never touches the filesystem,
so the ${PLUGIN_DATA}-rooted ones are created here. A cwd under the plugin root ships with
the plugin: inventing it would hide a broken plugin. Best-effort, so one bad server does not
fail the install.
ProtectedreadProtectedreadReports rather than throws: a bad manifest on disk shows the plugin without components.
ProtectedreadAn absent mcp.json is not an error. One that is not a regular file, or resolves outside the
plugin root, invalidates the MCP component type without touching the others.
ProtectedreadDot-prefixed entries are skipped at every level, matching computeContentHash - which is
what excludes our own .registry.json.
ProtectedreadProtectedreadProtectedreasonProtectedresolvesTrue when target's fully resolved path stays inside the resolved root.
ProtectedscheduleA hash mismatch is reported rather than thrown - the user decides - while a missing or invalid
plugin.json throws. The staging directory is removed again if anything fails, so a partial
download never survives.
ProtectedstatProtectedstopProtectedsweepSame-process failures always clean their own staging directory; this handles the crash case.
Only directories carrying our provenance marker are removed: one without it may be the user's. Deleting the data directory is permitted on uninstall, unlike on update.
Protectedwrite
Performs all Agent Plugin filesystem and network work: the plugins root lives outside the browser FileService sandbox.
Installing is two-phase so that a content-hash mismatch is an explicit user decision rather than something discovered after the plugin is already in place: stage downloads and verifies without touching the final location, and the frontend then commits or discards. Registering the resolved components is the frontend's job, after commit returns.