npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hasna/skills

v0.10.83

Published

Skills library for AI coding agents

Readme

@hasna/skills

Skills library for AI coding agents — discover, pin, and run reusable capabilities through the Skills CLI and MCP server. Registers with Claude, Codewith, Codex, OpenCode and Cursor, and works with any MCP host.

npm License

Install The CLI

bun install -g @hasna/skills

Requires Bun 1.3+.

Private skill catalogs

The public package provides the CLI, API, SDK, hooks, and runtime. A skill's instructions and executable bundle belong to the organization that publishes them. API reads require authentication and use that organization's catalog, including tag filters, versions, and downloads. An empty account starts empty; neither a repository checkout nor files on the server machine supply defaults. Server startup and upgrades never import a bundled catalog.

Each operator can use their own compatible server and storage. S3 is optional: the server supports durable SQLite or PostgreSQL and database-backed bundles when no S3 bucket is configured. Publishing through an authenticated account does not publish to GitHub or npm. Keep private source documents and executable payloads outside public software repositories.

Quick Start

bun install -g @hasna/skills
skills login

skills login opens your browser to sign in to https://skills.md and stores an API key for this machine in ~/.hasna/skills/config/credentials (owner-only), together with the server it belongs to. On a terminal it then offers to register Skills with your coding agents (skills setup agents). Check who you are with skills whoami.

skills logout signs out the active profile. It deletes the key that skills login stored, then revokes it on the server that issued it when login minted it (a key you added with --api-key is only deleted, unless you pass --revoke). It exits 0 only when you are signed out. It exits non-zero, naming the reason, when revocation did not complete or is not supported (it then says where to revoke the key by hand), when another credential is still active (an environment variable, the Keychain or another selected profile, which it never changes), when the profile holds a credential skills login did not store (left in place), or when the local deletion failed.

  • No browser on this machine: skills login --device prints a code to approve on another device, then skills login --poll finishes the same sign-in.
  • An API key you already have: printenv MY_SKILLS_KEY | skills login --api-key reads it from stdin, verifies it and stores it. Nothing is echoed.
  • An email code instead of the browser: skills login --email [email protected]. Interactive code input is masked. For an agent or headless terminal, first request a code with skills login --email [email protected] --json, then send the fresh code through stdin to skills login --email [email protected] --code-stdin --json. This finishes the same sign-in without requesting another code. Keep the code out of shell commands, arguments and logs.
  • Running skills in a terminal opens the interactive browser. It also works signed out and has the same account commands: /login, /logout, /whoami.

Your own server

The software is open source and every command works against your own compatible Skills server. Sign in to it with skills login --url https://skills.example.com; the URL is stored with the key, so later commands use that server without flags. HASNA_SKILLS_API_URL selects a server for one shell. skills setup --api-url <origin> records a server without signing in.

Fleet stations

Stations provisioned with a fleet key keep using the internal gateway https://api.hasna.com/skills; versioned requests use /skills/v1. A key with no recorded URL (the Keychain item, HASNA_SKILLS_API_KEY alone, or an older credentials file) always stays on that gateway and is never sent anywhere else. The gateway has no interactive login service, so on such a station skills login says so and sends nothing. A stored gateway credential or vault reference is preserved even with --url. Use a separate credential profile for customer sign-in: skills --profile skillsmd login. Later product commands use that profile too, for example skills --profile skillsmd whoami --json; fleet commands keep their original configuration. Obtain a workspace API key through your administrator's provisioning process and configure it using the credential resolution below. Check the selected identity and available capabilities before syncing:

skills whoami --json
skills capabilities --json

A workspace administrator creates a shared profile selecting published skills by exact version and SHA-256 digest. Consumers sync that profile into a verified Skills cache, then load instructions through the CLI. Replace default with your assigned profile; these examples assume it selects [email protected]:

skills list --json
skills profiles show default --json
skills sync --selection-profile default --json
skills install [email protected] --selection-profile default --json
skills load [email protected] --selection-profile default
skills context 'Use $pdf-generate to create a PDF' --selection-profile default --json

# Preview retirement, then archive ordinary copies and vendor discovery files.
skills migrate native --include-unmanaged --include-vendor --json
skills migrate native --include-unmanaged --include-vendor --apply --json

# Preview the available adapters, then install one bridge plus hooks per agent.
skills hook agents --json
skills hook install --selection-profile default --json
skills hook install --selection-profile default --apply --json

--include-vendor resolves configured plugin discovery, so it needs a reviewed --discovery-inputs file when a configured plugin declares hooks. Without it, skills migrate native --include-unmanaged archives user and project copies only. Migration never archives Codex system skills (.codex/skills/.system), even with --include-vendor. Codex refreshes its OpenAI marketplace plugin caches on its own; retire those copies with a Codex [[skills.config]] rule (name = "<plugin>:<skill>" or the exact path of the SKILL.md, with enabled = false) rather than by archiving. The live Codex prompt hook accepts a name rule only for a copy with no Hasna marker, its remote install receipt, a refresh-safe plugin and no rule that enables it. Other checks (skills hook install reusing a saved review, skills hook trust) do not accept a hand-added name rule; for them, and for system skills, run skills hook install --agent codex --discovery-inputs <file> --apply with a fresh discovery review (no --discovery-inputs on an automatic binding; add a fresh --codex-native-catalog <file> for a plugin Skills has enrolled), which writes and records the disables. Run the same refresh after editing config.toml when the binding's recorded configuration witness counts the edit: on automatic bindings, after removing a rule that enables skills, and on reviewed bindings whose witness counts disable rows. A NATIVE_SKILL_DRIFT refusal names the step for each copy it lists, including that follow-up.

Without --agent, hook installation selects configured or detected consumers: existing managed bridge bindings, provider-specific home configuration, or an installed native CLI found through PATH. Detection reads metadata and never executes a native CLI. A provider-specific directory also identifies a GUI consumer without a CLI, such as Cursor. Shared .agents/skills or Claude configuration alone does not identify another provider. No detected consumers is an error; use --agent <agent> to configure a new consumer explicitly.

Every selected adapter still validates its configuration and prerequisites; errors never silently drop a detected consumer. Explicit --agent all selects all maintained adapters and requires every adapter's discovery capability, including Sumi's installed read-only sumi-paths command. Sumi is selected by its managed binding, native sumi or sumi-paths executable, existing legacy provider home or ~/.config/sumi configuration, a Sumi directory beneath XDG_CONFIG_HOME, or any set SUMI_HOME, SUMI_CONFIG_DIR, SUMI_CONFIG or SUMI_CONFIG_CONTENT selector (even empty or malformed). It then uses the unchanged Sumi path protocol and fails closed on unsupported configuration or a missing helper. Generic XDG configuration alone does not select Sumi; its provider directory must be present. Relative XDG paths resolve against the working directory, and home shorthand expands as in the native path protocol. Dangling or inaccessible provider roots never silently drop Sumi. Provider-defined roots outside these published presence locations cannot be detected without a binding, selector or executable; specify --agent sumi for that case. This is a detection limit, not proof that Sumi is absent.

Native migration includes the current directory, every ancestor, and the global agent directories. Use --project /path/to/project to include another project and its ancestors. This matches the prompt hook's project discovery, including skills inherited from a parent workspace. Preview the JSON inventory before applying it; archived copies retain recovery receipts. A drift refusal reports the affected paths without printing their skill documents.

Claude hook installation sets syncClaudeAiSkills: false in user settings to stop account skill synchronization from recreating native copies. The prompt hook checks that setting. Vendor migration also inventories ~/.claude/plugins/synced/ and archives its skill documents while preserving other plugin files. Whole-plugin synchronization remains unchanged because synced plugins can also provide hooks, MCP servers, and language servers. A later plugin download that restores a skill document will trigger another drift refusal and require review.

A patched Codex that enforces an exact native host-path allowlist reports its effective policy to the Skills SessionStart and UserPromptSubmit hooks as native_skill_policy. The guard's adapter parses that envelope strictly (capability host-path-allowlist-v1, restricted mode, non-host sources disabled, the sole allowed path equal to the Skills bridge document, a lowercase SHA-256 effectiveConfigDigest, the consumer's processId, session_id, and turn_id on UserPromptSubmit only), re-verifies the bridge document on every hook, walks the hook's real parent chain to find the claimed consumer, binds its start time and the digest of its executable to the reviewed digests stored under bridge.codexNativePolicy.executableDigests in the managed policy (an absent set refuses; Linux has no reviewed digest by default, so the adapter refuses there unless an operator pins one after its own review; only the file's identity to digest mapping is cached, in agent-hooks/codex-native-policy-executable-cache.json). The Skills data directory is the operator trust root: the managed policy and the cache file must be regular files reached through no symlink, owned by the current user or root and writable by neither group nor world, or the adapter fails closed; a writer with the same uid is outside this boundary. The adapter then requires the authenticated channel binding of the native hook-policy peer contract (native-hook-policy-peer-v1): Codex passes the read end of a per-hook socketpair in CODEX_NATIVE_SKILL_POLICY_FD; the hook forwards it as fd 3 to the qualified ancestor's own executable, debug verify-hook-policy --fd 3 --expected-process-id <pid> --input-sha256 <raw stdin SHA-256>, which sends a fresh challenge, verifies the actual writer and prints one native-hook-policy-peer-v1 attestation that must name that pid, that raw stdin digest and exactly the emitted policy; it runs once per invocation and is never cached. The managed trust default is empty, so no envelope is accepted until an operator records reviewed executable digests; with none, the helper is never run, and the hook's remaining deadline bounds both the first-use executable hash and the helper. Operators bind those digests through the package, never by editing the policy by hand:

skills hook trust-native --platform darwin-arm64 --digest <sha256> --expected-policy-sha256 <sha256> --json
skills hook trust-native --platform darwin-arm64 --digest <sha256> --expected-policy-sha256 <sha256> --apply --json

Preview comes first and writes nothing. Each --digest must be the SHA-256 of an independently verified final native artifact, taken from its own review, never from a fetch; the command accepts digests only from its arguments. --apply requires the exact current policy SHA-256, re-checks it immediately before the atomic 0600 replace, preserves the pre-change bytes in the usual migration backup and reads the backup and the result back before it reports; it sets exactly the given set for that one platform and preserves every other field (values identical; the file is re-serialized with the package formatter). A pre-existing group- or world-writable data directory (for example 0775) refuses both this command and the adapter until its mode is corrected. Inertness rests on that authenticated restricted policy; plugin classification proves nothing by itself and only narrows the scope to installed-plugin documents under ~/.codex/plugins/cache that the verified policy cannot load. Those are checked before any hash or helper run, and the acceptance is recorded at agent-hooks/codex-native-policy-acceptance.json; user, repository and project copies still refuse, and format or digest checks never prove the runtime policy on their own.

A Codex plugin refresh can deposit a new vendor skill in ~/.codex/plugins/cache (for example openai-curated-remote/sites/1.0.2-remix-b.1/skills/sites-remix). Skill payloads still reach agents only through the Skills CLI, so an enabled vendor copy keeps blocking the Codex prompt hook. Retire it by disabling it in ~/.codex/config.toml. The plugin-qualified name survives later version directories, so prefer it:

[[skills.config]]
name = "sites:sites-remix"
enabled = false

An exact path = ".../sites/1.0.2-remix-b.1/skills/sites-remix/SKILL.md" rule also works, but only for that version. On the live Codex prompt hook only, a copy is then exempt when every condition holds:

  • it is package-classified plugin content in openai-bundled, openai-curated or openai-curated-remote (exact names), with Codex's remote install receipt for the remote marketplace;
  • it carries no Skills or Hasna marker;
  • every cached version of its plugin passes the vendor refresh check described below for membership changes, so the plugin can load nothing that the inventory and this rule do not account for, and no version is a link;
  • a [[skills.config]] rule names its exact path or its plugin-qualified name with enabled = false, and no matching rule enables it.

A whole-plugin [plugins."sites@openai-curated-remote"] enabled = false table is not enough on its own: remote state can enable a locally disabled remote plugin, and a cache copy carries no proof that its plugin source is configuration-controlled, so the copy keeps blocking until a path or name rule retires it. This exemption only adds to the guard's existing ones; every copy that the guard already accepts, such as an exact-path disable in any plugin-cache marketplace or a reviewed plugin control, stays accepted on the live hook. Once the hook tolerates one of the witness changes below, a state the strict guard refuses outright, plugin-cache copies are exempt only through this vendor rule.

Instead of editing by hand, skills hook native-catalog followed by skills hook install --agent codex --codex-native-catalog <file> --apply writes the same rules through the guarded install path.

The hook also tolerates, with a visible systemMessage warning, only the discovery-witness changes such a refresh provably makes:

  • appended vendor disable rules or vendor plugin disables in config.toml, accepted when removing exactly those entries or restoring a formerly enabled vendor flag reproduces the reviewed digest. Candidates are tried smallest edit first, at most 128; with a typed settings witness that covers any change to up to two of at most eight vendor plugin tables. A change beyond the bound refuses;
  • directory membership changes under an allowlisted vendor marketplace that passes the vendor refresh check: every plugin version has exactly one manifest, .codex-plugin/plugin.json, alone in its directory, whose keys are only name, version, description, author, homepage, repository, license, keywords, interface, skills (the default ./skills/ only) and apps. So hooks in any form, commands, agents, extensions, MCP servers and unknown keys refuse. There is no hooks, commands or agents directory, no hooks.json or .mcp.json (names compared without regard to case), no root, .claude-plugin or .cursor-plugin manifest, no link and no SKILL.md below a dot-named or node_modules directory, or nested in another skill. One exception keeps today's vendor plugins working: every current OpenAI vendor plugin declares its connector as apps = "./.app.json", so exactly that declaration is allowed when .app.json is a regular file of at most 1 MiB, strict UTF-8, that passes the same connector validation reviewed plugin controls use (one apps object; app entries with only id, category and required, of the right types; no duplicate keys). Any other connector path, a file that fails that validation, or the file without the declaration refuses.

Every other copy and change still refuses with NATIVE_SKILL_DRIFT, including:

  • user, project, .system and Hasna-marketplace copies that the guard does not already exempt;
  • an enabled vendor copy whose plugin is only disabled by a whole-plugin table;
  • capability-control changes and whole-cache membership changes;
  • plugin activation, including a vendor plugin gaining enabled = true;
  • missing coverage and changed roots;
  • every install, trust, migrate and sync check.

Native hook invocations must use their installed adapter's selection profile. An old client command or environment override naming another profile refuses before synchronization or context loading. Review the hook installation and restart the native client to load its current commands. Explicit skills load, skills context, and skills sync commands can still select other profiles.

Reinstalling hooks without --command or --selection-profile preserves each agent's existing executable and profile independently, including when using --agent all. New agents use skills and default. Either explicit flag overrides that choice for the requested agents. The policy's shared default profile changes only when --selection-profile is supplied; older managed agents without a per-agent profile retain that shared default.

The hook install --include-vendor option is retained for compatibility with older scripts. Hook planning always inventories and disables discovered vendor system skills; use migrate native --include-vendor when retiring their discovery files.

Restart the agent after applying the hooks. In Codex, review and grant normal trust to the installed hook definitions before starting a new session. Then request a selected skill in a prompt, for example Use $pdf-generate to create a PDF. The hooks supply instructions; executing the skill remains a separate explicit action.

For Codex 0.153.0, 0.154.0, and 0.155.0, the normal installed Skills CLI can plan native trust for its three exact managed hook definitions:

skills hook trust --agent codex --json
skills hook trust --agent codex --apply --plan-digest <reviewed-plan-digest> --json

Review the commands, current hashes, and existing trust/enable state in the plan. Apply refuses if the plan, package, declarations, or configuration changed. The plan preserves the native CODEX_HOME choice. When unset, Codex uses the lexical ~/.codex path; an explicit CODEX_HOME resolves canonically. Only the home root and an explicitly admitted canonical root-alias target are accepted. Those views have separate hook identities even when they reach the same files; enrolling one preserves the other's trust entries. Keep the same CODEX_HOME choice for enrollment and the consuming agent. It enrolls the current exact definitions, including reviewed modified hooks, and preserves unrelated trust, settings, and comments. A private journal keeps the pre-write configuration; a failed write or verification requires journal reconciliation before retry. Unsupported versions or configuration layouts refuse without a configuration write. Enrollment uses a short-lived native app-server and makes hooks eligible for new Codex processes. Existing sessions retain their own configuration; use their native hook controls to refresh them.

When an explicit discovery review includes the full Codex configuration file, the exact native trust writes change that file's byte hash. Enrollment verifies those writes and completes its journal with bindingRefreshRequired: true. This reports native trust eligibility only: ordinary managed context remains blocked, and the discovery policy is unchanged. Review the current full file again and plan skills hook install --agent codex --discovery-inputs <review> --command <same-absolute-command> --json. Verify that the plan changes only the discovery policy, then repeat with --apply. Keep the same command and native home. The ordinary bridge must then pass, and a fresh skills hook trust --agent codex --json must report zero planned changes and bindingRefreshRequired: false. Verify context in a new native session after these checks; an enrollment receipt does not prove context was consumed.

If an interrupted journal's policy later changed only in reviewed Claude discovery roots/sources, skills hook trust reconcile --agent codex --journal <path> --review-claude-discovery <evidence-reference> --json can preview that specific recovery. Supply all five package provenance flags shown by skills hook trust reconcile --help for the current running Skills release. The old absolute hook command remains bound to its original package bytes; recovery reads that package as evidence without executing it. Review the full policy hashes, exact discovery additions/removals, journal, current package, configuration and complete native inventory in the private preview. Repeat the same command with --recovery-plan-digest <reviewed-digest> to record the receipt. Any unreviewed change refuses. This mode preserves the policy and native configuration and cannot be combined with --supersede-binding.

If another reviewed producer appended a user hook after the interrupted write, add --review-native-hook-additions <private-review.json>. This is a separate explicit review; a producer receipt alone never authorizes recovery. The review must be an absolute, owner-only regular file with these exact fields:

  • version: 1, kind: "native-hook-additions", a nonempty reason, and a producerEvidence reference to the independently reviewed producer operation.
  • journalIntentSha256, policySha256, configCurrentSha256, and hooksCurrentSha256 pin the complete current inputs and immutable intent.
  • producerBefore contains configPath, configSha256, hooksPath, and hooksSha256. These owner-only backup files must reproduce exactly the completed original trust write and the original hook declarations.
  • additions contains one or more { event, nativeHook } records. event is UserPromptSubmit, SessionStart, or SubagentStart. nativeHook contains exactly the native inventory fields key, eventName, handlerType, command, matcher, timeoutSec, async, statusMessage, additionalContextLimit, sourcePath, source, pluginId, isManaged, currentHash, enabled, and trustStatus.

Only appended single-command groups from the same user hook file are supported: no matcher, asynchronous handler, custom status/context limit, plugin source, duplicate command, replacement or reordering. The added hooks must already be enabled and trusted in the actual native inventory. Every original hook and unrelated configuration byte remains verified. Combine this flag with --review-claude-discovery only when that independent policy transition is also present. The package provenance flags, private preview, exact --recovery-plan-digest, and subsequent explicit binding refresh are still required. Reconciliation writes only its journal receipt.

When updating the Codex binding afterward, Skills replaces its single hook group in place so neighboring hooks retain their native indexes and trust identities. Ambiguous duplicate or mixed Skills groups refuse installation.

Each supported agent gets one small skills-cli native skill containing CLI instructions, without a copied catalogue. Claude's native Skill tool admits that bridge after other copies are retired. Prompt guards verify the owned bridge bytes, required native configuration, and discovered home/project skill paths before loading context. A missing or changed bridge, newly discovered copy, stale plugin registration, or incomplete scan reports repair guidance and refuses loading. Most adapters also block the prompt; Hermes has the native non-blocking prompt-hook limitation described below. These are checks on configured native discovery, not an operating-system restriction on arbitrary file reads.

Agent policies support up to 1 MiB of serialized UTF-8 JSON, with bounded agent and discovery collections (2,048 sources and 512 roots per agent). Installation validates the complete resulting policy before writing configuration or backups; the same limits apply when reading and guarding native context. A rejected plan leaves the previous policy intact.

Sumi uses its native V2 plugin API, independently of OpenCode. Its managed plugins/skills-cli.js plugin validates prompt admission and adds selected instructions to transient request context. Real native session IDs and parent IDs bind exact inherited pins; native agent definitions are not Hasna identities. Prompt matching uses the native prompt-admission event. Request context restores verified loaded Skills and never treats model history, attachments or compaction checkpoints as a new owner prompt. The complete native model context is unchanged; the hook's input limits and native/integrity refusals remain strict. Adapter refusals retain only fixed reason codes, never child diagnostic prose. Both older managed plugin forms remain recognized for a reviewed hook-install upgrade. Native payload tool calls and prompt attachments are refused except for the skills-cli bridge. The supported configuration resolver honors SUMI_CONFIG_DIR, XDG_CONFIG_HOME and SUMI_HOME without performing native home adoption.

Sumi integration refuses unresolved JSONC, inline/additional config, remote or relative skill sources, flat Markdown skills and foreign plugin packages. Resolve or review these sources before applying integration. The adapter was checked against Sumi 0.2.52. That release watches plugin sources for hot reload; installation alone does not prove an existing session adopted the plugin. Verify actual prompt consumption on each target after installation.

Hermes 0.20.5 uses pre_llm_call to add selected context and pre_tool_call with fail_closed: true and a small owned supervisor to guard tool calls. The supervisor maps Skills child failures, timeouts and missing/invalid directives to the native explicit block response and exit code 2. Installation edits config.yaml while preserving unrelated values/comments and creates the native .no-bundled-skills opt-out marker to prevent bundled payloads from reappearing. The supervisor stays in the Skills data directory and its bytes/command are checked before native loading. Installation leaves the native shell-hook allowlist unchanged: approve the two exact managed event/command pairs through Hermes normal hook trust and restart. The adapter refuses unreviewed installed plugin sources and custom Hermes homes/profiles, user-specific tilde expansion, and TERMINAL_CWD overrides. Nonempty HERMES_BUNDLED_PLUGINS and HERMES_BUNDLED_SKILLS overrides are also refused during discovery and hook checks; unset them to use the reviewed default source paths. Custom bundle locations need a dedicated discovery adapter. Retire native payloads before use. Legacy skills-cli.md files can shadow the bridge and must also be preserved and retired before proceeding. Only skill_view(name: "skills-cli") is allowed natively; author payloads with Skills CLI commands. Hermes itself fails open on pre_llm_call errors. A returned refusal is visible context, and the trusted pre-tool guard blocks drift and native skill fallback; this is not a claim that Hermes can prevent every model call after a failed prompt hook or guarantee refusal if the native host/supervisor itself dies. Arbitrary project/plugin paths still require a discovery audit.

Reviewed discovery can also bind directories: [{ path, sha256 }] alongside its full source-file hashes. The public SDK's captureDiscoveryDirectories(paths) captures recursive, sorted path/type membership without reading plugin payloads. Include every directory the reviewed loader scans, including plugin version selection parents and Python entrypoint discovery directories. Membership hashes detect added, removed or changed file types; keep source hashes for reviewed bytes. Missing directories bind as sha256: null. Symlinks and special nodes refuse. The bounds are 64 roots, 20,000 total entries, 8 MiB of path/type metadata and 64 levels of recursion. Capture and checks require stable directory identities; quiesce source writers for installation because these checks are not atomic with a later native import.

For full binary or source-byte coverage, use the public SDK's captureDiscoveryByteSources(paths) and retain its explicit hashMode: "bytes" on each source witness. It hashes the exact file bytes, including invalid UTF-8, with limits of 64 MiB per file and 256 MiB across one capture or verification. Missing files bind as sha256: null; symlinks, special files and changing file identities refuse. Raw witnesses cannot use configuration field projections. Existing witnesses without hashMode retain their original UTF-8 decoding contract and 16 MiB file limit; they are not silently converted into byte hashes. Directory membership and file bytes are separate witnesses. Neither substitutes for reviewing the actual executable, import paths or loader behavior.

For reviewed Claude user settings, captureClaudeSettings(canonicalSettingsPath) emits an opt-in claude-settings-v1 witness. It permits a fixed set of typed terminal display preferences and recognized built-in model selections to change while binding hooks, permissions, native skill protections, plugins, marketplaces, environment and every unknown field. Provider mappings, custom model values and instruction settings remain bound. Replace the settings source in an explicitly reviewed discovery input, then use the normal skills hook install --discovery-inputs <file> plan/apply flow; existing raw witnesses are never automatically converted or refreshed. See settings witness scope and migration.

For an explicitly reviewed launcher or interpreter reached through symlinks, use captureDiscoveryPathSources(paths) and retain hashMode: "path-bytes". Its digest binds the canonical input, directory identities, each link's identity and target, and the resolved regular file's identity and exact bytes. Relative link targets resolve component by component, including .. after an alias. Missing targets also receive a digest that binds the path leading to their absence. Retargeting to identical bytes, replacing a link or an ancestor, or changing a file's metadata requires a fresh review. Unrelated sibling writes do not change directory identity witnesses.

Path witnesses share the 64 MiB file and 256 MiB aggregate byte limits. Each path allows at most 40 links, 256 traversal steps and 64 KiB of metadata; one capture or verification permits 8 MiB of path metadata. Special nodes, cycles, oversized inputs and changes during capture refuse. Native hook checks repeat the witness verification; this does not make a later native execution atomic with external writers. Keep source writers quiescent during activation. Use bytes mode for configuration that hook installation will replace: path witnesses cannot predict the future identity of a planned write. Existing raw byte and directory witnesses still refuse links. Older clients reject the new mode; upgrade the CLI before installing a policy that uses it.

Hermes requires directory witnesses, including when upgrading an older policy. For an automatic bridge with no runtime installed, rerun normal skills hook install to review and apply the new bindings. Existing native trust is preserved. Reviewed Hermes installations need fresh source and directory coverage in their --discovery-inputs file. Other agents may add directory witnesses to their reviewed bindings without changing existing source-only reviews.

Hook installation preserves unrelated configuration, hooks, and plugin assets. For Codex it sets skills.bundled.enabled = false in user configuration, preserving the skills-cli bridge and disabling discovered native skill paths. This prevents supported Codex clients from installing or loading their bundled .system skills. The setting and its discovery witness are enrolled in the same configuration transaction; existing installations must rerun skills hook install. Missing or re-enabled bundled protection fails skills hook check before context loads. Ordinary [skills.bundled] and legacy [[skills.config]] tables are supported; inline or dotted target definitions that require rewriting refuse before changes. Convert those definitions to ordinary tables while preserving their values, then rerun installation. The control has been verified with Codex 0.153.0, 0.153.4 and 0.154.0; this is not a claim that every older build supports it. Use a client that supports skills.bundled.enabled; Skills does not infer support from version text or silently substitute path-only protection. Existing exact system-skill trees can remain only with their hash-bound disabled paths; migration preserves these package files. A client that restores or changes packaged skills requires a fresh inventory and disable plan. Native exports are refused while managed CLI loading is active. Migration preserves ordinary skill directories in private archives; --include-unmanaged includes user-authored copies, and --include-vendor retires vendor SKILL.md discovery files while preserving shared scripts and assets. Archive receipts and configuration backups live under the Skills data directory.

After vendor documents are archived, inventory still scans their retained asset directories for newly introduced skills. Vendor container traversal allows 32 directory levels; the ordinary native-root limit remains unchanged. Each inventory is bounded to 20,000 discovery entries and 4 MiB of UTF-8 path metadata before directory entries are retained or sorted. Unsupported special files and unsafe directory links are refused.

Codex 0.162.1 loads SKILL.md files below node_modules inside its skill roots, so Codex inventory and the prompt guard walk node_modules in ~/.codex/skills, ~/.agents/skills, each project's .codex/skills and .agents/skills and configured plugin skill roots. In ~/.codex/plugins/cache they walk it only where it can lie in a plugin skill root: below a version's default skills directory or a manifest-declared skills path, or as a marketplace, plugin or version directory named node_modules; an unreadable manifest walks every node_modules in its version. Dot-named directories such as node_modules/.pnpm, a plugin version's own dependencies and any node_modules outside a skill root stay unscanned, because Codex does not load them; other agents' roots keep skipping node_modules. Depth limits are unchanged: Codex reads six directory levels below a root, and an ordinary root records a skill four levels down and refuses anything deeper.

Native archives persist a version 2 recovery journal before moving payloads; migrate native --json --apply returns its receiptPath. The journal records every source, archive path, expected hash, and move status, then marks successful completion. Interrupted operations can be inspected against that durable intent. On failure, recovery restores verified archives only when the original path is still absent. It preserves occupied paths or unverified archives, records that they require recovery, and continues compensating other unchanged entries. Keep native agents and other skill writers stopped throughout migration and recovery: portable directory rename cannot atomically reserve an absent target. Vendor file restoration uses an exclusive hard link to preserve concurrent files. Do not retry an interrupted operation until its journal and both paths have been reconciled; a failed final journal write may leave the earlier durable intent.

For a reviewed migration that must retire one exact native copy, pass --target-manifest <file>. The JSON manifest uses schema hasna.skills-native-migration-targets.v1 and binds each target to an agent, an existing absolute projectRoot, a normalized project-relative path, and the complete directory treeSha256. Exact-target mode refuses broad selector flags, protected or vendor entries, missing or ambiguous paths, symlinks, digest drift, and writes a manifest digest into the recovery journal. Every inventory entry outside the manifest remains untouched.

skills hook agents --json reports the supported adapters and coverage limits. Claude and Codex have lifecycle context hooks; Gemini uses BeforeAgent, and OpenCode uses its awaited message plugin. Cursor receives selected context at session start and gates later prompt submission; its prompt hook does not inject context on the supported installed path. Other inventoried clients do not automatically gain a working prompt adapter.

Gemini's BeforeAgent prompt can include the Skills policy emitted at session start. The hook excludes that exact leading policy from skill selection, so it does not displace the user's requested skill. Other hook context and user text remain part of the selection input.

Gemini discovery also covers the installed @google/gemini-cli package and its bundled builtin skills. skills hook install finds the package through the gemini command on its PATH and records the resolved executable and its realpath target in the managed policy (bridge.discoveryExecutables.gemini). Later checks always verify that recorded path, and also look gemini up on the caller's PATH, because what PATH resolves is what that process would run:

  • If PATH resolves a gemini whose realpath differs from the recorded target, that runtime shadows the reviewed one, and the check refuses with NATIVE_SKILL_DRIFT, naming both targets. Another launcher for the same target is not a shadow.
  • If PATH resolves no gemini at all (a narrower PATH such as env -i PATH=/usr/bin:/bin or a launchd unit), the recorded path is the only witness, so a Claude hook update or a Gemini hook still verifies the reviewed runtime.
  • A changed recorded target, package or builtin set refuses with NATIVE_SKILL_DRIFT.
  • When the recorded executable no longer resolves, or a policy written before this record cannot find gemini on the caller's PATH, and nothing else in the reviewed discovery changed, the refusal is DISCOVERY_ROOT_UNRESOLVED, naming the agent and the command. That is an environment gap rather than drift, and it still blocks. Any other change is still NATIVE_SKILL_DRIFT.

An install treats a recorded executable that no longer resolves as no record. Run skills hook install from the reviewing environment to record or refresh the path. The SDK exports DISCOVERY_ROOT_UNRESOLVED and isDiscoveryRootUnresolved for callers that classify refusals.

Known local plugin registrations are resolved automatically. Plugins with instruction-injecting hooks, unresolved runtime registrations, unsupported legacy command formats, and higher-precedence project discovery settings need separate review; a cache-only scan does not establish complete coverage. The advanced --discovery-inputs <file> option on hook installation and migration accepts reviewed active roots and full source-file SHA-256 witnesses. Its version-1 document has an agents array; each entry names agent, absolute roots, sources (path and sha256, or null for an absent file), and pluginHooks: "reviewed-no-skill-injection". Include the agent configuration and every input establishing the active roots and plugin-hook behavior. A changed witness requires a new review. This option does not add support for an unknown native file format or make unreviewed plugin behavior safe. Managed system configuration, process-specific overrides, and alternate agent home directories are outside automatic coverage and require their own integration review before declaring a station migrated.

The pluginHooks attestation is the reviewer's point-in-time statement; Skills does not inspect hook behavior. When a Claude .claude-plugin/plugin.json is listed as a plain byte witness (hashMode omitted or "bytes") with a non-null sha256, Skills also requires plain byte witnesses for that plugin's hooks/hooks.json (when present) and any string hooks target in the manifest. A manifest listed as claude-plugin-manifest-v1 (the form Skills writes into the stored policy) or as path-bytes triggers no such requirement. A source that the absent-retired-claude-version rule retains (see discovery-binding) is stored exactly as listed: Skills does not project its manifest, require its hook files or convert its marker, because the file no longer exists. The version-root .orphaned_at timestamp that Claude rewrites at startup is bound by presence only, as claude-plugin-orphaned-at-v1, and is still strictly validated; see the full scope. For plugins outside receipt-backed admission (a claude-plugin-registry witness, see the discovery transition contract), other plugin files such as hook modules, bin/ files and package.json are bound only if the review lists them (a reviewed directories membership witness detects only added or removed files, not content changes), and the review is not checked against the roots registered in ~/.claude/plugins/installed_plugins.json. Later checks re-hash the stored sources, and drift makes the Skills hooks refuse with NATIVE_SKILL_DRIFT; this detects a change but does not stop plugin code from running. A process running as the same user can rewrite the plugin files and the managed policy, so the witness is a tripwire, not a security boundary. See the full scope. A stronger witness for plugins outside receipt-backed admission is planned and not yet implemented.

Captured review catalogs are immutable evidence, while configuration and plugin files remain live discovery inputs. To retain a captured Codex native catalog, explicitly add reviewArtifacts to its Codex entry in --discovery-inputs:

"reviewArtifacts": [{
  "kind": "codex-native-catalog",
  "path": "/absolute/private/reviewed-catalog.json",
  "sha256": "<exact original file SHA-256>"
}]

The same path and digest must already be a full byte witness in sources. The normal read-only install plan validates the catalog using its owning schema; apply retains its exact bytes privately under the resolved Skills data directory at agent-discovery/artifacts/<sha256>/catalog.json before changing the policy. The stored witness includes the original path, byte digest and projected catalog digest. Later hooks verify the retained bytes and permissions, so removal of the original scratch copy cannot break discovery. Live native roots, configuration, plugin files and trust still require their original witnesses; retention does not refresh or exempt them. No artifact is inferred from a filename.

For an existing reviewed policy, plan one exact legacy witness migration:

skills hook retain-review-artifact --kind codex-native-catalog \
  --source /absolute/private/reviewed-catalog.json \
  --expected-policy-sha256 <current-policy-byte-sha256> \
  --expected-source-sha256 <original-reviewed-byte-sha256> --json

Run from the same reviewed project directory; add --apply to execute that guarded transaction. It requires the original bytes to exist and all current bridge, discovery and trust checks to pass. Missing originals need exact recovery first; this command never captures a replacement catalog or rehashes a changed source. Apply preserves and reads back the old policy, leaves the original source and session pins intact, and records retention lineage in the transaction receipt. Existing sources without an explicit declaration keep their live-path semantics. Immutable files left by a compensated transaction are retained and may be reused only after exact verification.

When hook install omits --discovery-inputs, it reuses an existing reviewed binding only after rechecking its sources, directory membership, configuration coverage, managed bridge and native trust. Unchanged reviews need no new input file; drift still requires a fresh explicit review. Explicit discovery inputs take precedence, including when their agents array omits a previously reviewed agent. The default --agent all still includes every supported adapter.

That recheck has two halves, and only one of them gates reuse. BINDING CUSTODY — the same managed bridge, home, alias set, agent, command/profile binding and reviewed discovery — must hold before a saved review is reused, or the plan refuses and names a fresh explicit review. Bridge PROTECTION — the native plugin bytes, the permission and hook rules and the bundled-skill switches — is written by the same plan, so it is asserted in full after the writes instead of gating the repair that fixes it; a plan that does not repair it is refused before the receipt is written. Hermes native shell-hook trust is the exception: it is the user's own consent and no Skills write creates it, so it stays a pre-write condition. One implementation serves both halves, so they cannot drift apart.

Because that recheck includes the managed bridge, hook install cannot reuse a saved review on a host whose bridge has since broken, and in that form it cannot repair its own precondition. It refuses and names the reachable form, skills hook install --agent <agent> --discovery-inputs <review> --apply, which skips the retained-review precheck and rebuilds the bridge from the review in the same transaction. A reviewed binding always carries a whole-file witness for the agent configuration beside its projected fields, so unchanged projected fields do not excuse a change outside them: a fresh explicit discovery review, not a witness refresh, is the supported route.

For reviewed Claude plugins, skills integration plugin plan, admit and resolve provide a command-source admission boundary before native discovery. Original packages and migrated skill/command prompts remain in private versioned Skills storage. Native projections retain ordinary components, and a typed receipt permits only verified registry/cache transitions. See plugin admission for the package, review and runtime contracts; these commands do not change live agent registrations or settings.

The read-only skills hook review-claude-candidate check requires its reviewed discovery inputs to bind the user settings, both project settings files and both plugin registries. A project .claude/settings.json or .claude/settings.local.json that the review omits is exempt only when no other expected source shares its path and it is either absent, or present with exact preimage bytes that parse strictly as one JSON object (strict UTF-8, no byte-order mark, comments, trailing content or duplicate keys) and carry only allowlisted settings: permissions with allow, deny, ask and defaultMode, plus outputStyle, model, theme, effortLevel, verbose and spinnerTipsEnabled. Any discovery key (enabledPlugins, extraKnownMarketplaces, additionalMarketplaces, skillOverrides), env, hooks, permissions.additionalDirectories or unknown key keeps the file required. The allowlist is a reviewed list of settings, not a proof that Claude cannot discover anything from the file. This admits the permissions-only ~/.claude/settings.local.json that Claude writes when it saves a permission rule. Each exempt file is re-checked against its exact preimage until the result; user settings and the registries are never exempt. See prospective Claude candidate review.

If your home .claude or .codex directory intentionally links to another directory within your home, add --allow-root-aliases to hook installation and native migration. The plan records and rechecks the exact link and target; links inside skill contents or configuration files remain refused.

On macOS, the OS-owned /var, /tmp and /etc aliases into /private are accepted only while their exact targets and protected parent directories verify. The protection check refuses extended ACLs and unavailable native ACL inspection. Inventory reports canonical paths and deduplicates their alias spellings. This does not permit other root-owned links or user-controlled ancestor links.

Cooperating installers can use the root package's planClaudeStopHookUpdate({ expectedSettingsSha256, replacement }), then applyAgentIntegration(plan), to write an explicitly authorized Claude settings replacement changing only hooks.Stop, together with every existing discovery witness for that file. Every other field and hook must retain the same value; this includes discovery configuration and display/model preferences. The caller must authorize its own exact change; this API does not grant approval to change another owner's hooks. It checks the current native bridge, inventory, policy, executable witnesses and root aliases, preserves each witness mode, and verifies the consumer guard after applying. A concurrent edit or pre-existing drift refuses renewal. Failed post-write checks compensate only unchanged writes, retaining private backups. A null plan means no Skills policy exists; malformed or untrusted policy throws instead. This local integration operation requires no hosted credential, does not reload an existing agent, and cannot adopt a stale policy after another installer has already changed settings. Settings and policy are separate files: this is a guarded sequence with compensation, not a cross-file atomic commit. A concurrent hook can fail closed during installation. A successful update does not reload an existing session.

Legacy full-file settings witnesses remain strict until explicitly upgraded:

skills hook rebind-settings --agent codex \
  --reviewed-preimage /private/preserved/config.toml \
  --expected-policy-sha256 <current-policy-sha256> \
  --expected-settings-sha256 <current-settings-sha256> --json

For Sumi, use --agent sumi and the exact preserved sumi.json. A fresh review can capture skills hook witness --kind sumi-settings-v1 --path <absolute-sumi.json> --json and include that witness in its discovery inputs. The versioned witness permits JSON whitespace and changes to $schema, username, experimental.statusline and experimental.compact_tools only. All other fields, unknown controls, nested plugin options, permission-map order and array order remain protected. Foreign plugin source witnesses and the explicit hook review remain required. Missing preserved bytes require a fresh review; the runtime never upgrades a stale review automatically.

The Sumi plugin emits a fixed SkillsHookRefusal error with the own data property skillsHookRefusal: { version: 1, code: "SKILLS_HOOK_REFUSED" }. Its remediation is fixed; child stderr and arbitrary hook reasons are never copied into the error. A compatible Sumi adapter can present this refusal without turning it into an untyped server error. Regenerate the managed plugin with the normal guarded skills hook install --agent sumi flow after updating Skills.

The plan proves the preserved original matches every witness being replaced, permits only the documented non-discovery differences, and labels the replacement witness (the JSON receipt lists them under replacedWitnesses). --apply preserves and reads back the original policy before writing, and never writes the native configuration. Claude upgrades to claude-settings-v3, or to claude-settings-v4 with --claude-witness-version 4; Codex uses codex-settings-v2, which also replaces the narrower automatic plugins/marketplaces/skills projection of the same file once the preserved original is proved to explain it. That projection is order-sensitive, so it keeps failing after Codex re-serializes the file it owns.

Existing codex-settings-v1 witnesses retain their original verifier. New reviews use skills hook witness --kind codex-settings-v2 --path <config.toml> --json. The guarded rebind accepts a raw or v1 witness only when the exact preserved configuration proves its original digest and any automatic projection. Without that preimage, capture a fresh native catalog and explicitly review all discovery inputs before installing a v2 binding; runtime never adopts drift automatically.

The Codex v2 witness binds the whole configuration apart from native-owned state that is not a discovery input: the hooks.state trust ledger Codex rewrites when it trusts a hook, table order and other serialization-only differences, retired [[skills.config]] entries that explicitly disable one skill, and model, model_reasoning_effort and model_verbosity at the root or in [profiles.*]. Every hook declaration, provider mapping, plugin, skill source or enablement, project-trust entry, environment setting and unknown field stays bound, and a malformed inference selection refuses instead of being adopted. Runtime hooks never silently upgrade a witness.

A supported Codex native skill and installed-plugin receipt can be captured through the package-owned client into a new private file, then reviewed and passed to hook install with --codex-native-catalog <file>:

skills hook native-catalog --cwd /absolute/project --output /private/catalog.json --json
skills hook install --agent codex --codex-native-catalog /private/catalog.json --json

Codex 0.159.2, 0.160.0, 0.160.1 and 0.161.0 have measured qualified-name catalog support. Native transport, capture and review use one capability registry of exact releases. Unmeasured releases, including 0.160.2 and 0.161.1, refuse until the native catalog/name-denial and hook-dispatch acceptance tests pass; an RPC handshake alone does not establish those semantics. Admitting a release does not admit its corpus: the transport still requires the existing native corpus admission (see docs/codex-corpus-writers.md).

Upstream Codex builds that lack corpus-admission-inspect, such as 0.160.0 and 0.162.1, use an interim fallback instead: an exclusive Skills-owned lock at <realpath(dirname(codex home))>/.hasna/skills/codex-corpus-locks/, outside the Codex home and independent of data-root overrides, recorded as nativeAdmission: "unavailable" with the probe record in every receipt. The probe record identifies the selected executable file (for npm installs, the launcher script), not the vendor binary it starts. Its guarantee is weaker. Upstream Codex's own refresh writes are not coordinated with that lock, only Skills writers exclude each other, and preimage checks refuse only the races they detect. For a project-level .codex, or a symlinked ~/.codex, the lock lives under the target's parent, such as <project>/.hasna/skills/codex-corpus-locks/; ignore that folder there. Probes run with a fresh, Skills-created CODEX_HOME in <Skills data root>/codex-probe-homes/, removed after each probe. The fallback is retired in the first release after the Harnesses enrollment/inspect route is live for that build line.

The capture refuses an existing output file, writes mode 0600, verifies the exact bytes, and reports only version, directory, count, file path and SHA-256, plus the admission record when the interim fallback applies. Its safe catalog shape is {version,cwd,skills,plugins}; skills have {name,path,enabled,pluginId} and plugins have {id,name,installed,enabled,localVersion}. Older reviewed catalogs without plugins remain valid for skills present in skills/list. The installer matches the native qualified name against bounded frontmatter and the owning plugin manifest. If Codex omits a skill from skills/list because its exact path is already disabled, the installer derives that identity only when the exact installed and enabled plugin row matches the cache marketplace, manifest name and local version. It preserves path disables and adds exact qualified name disables. For a newly named remote materialization omitted from the native list, use --codex-skill-denials <file> together with a fresh native catalog and explicit --discovery-inputs. The denial file is an array of exact {name,path,sha256} document reviews. The discovery review must also bind the current full plugin manifest and each declared app/MCP control file. This plans only exact false path/name rules; it requires the real installed remote identity and receipt, rejects conflicting enables, and rechecks consulted files and configuration before application. It never synthesizes a native catalog row or enables a capability.

A wholly absent remote skills-only parent with retained qualified-name denies keeps its reviewed fingerprints. A returning parent must satisfy the same identity and capability checks. App/MCP declarations and active hooks do not receive this absence exception; the saved review must explicitly establish the skills-only role. The planner can also retain an already body-free historical remote version whose capabilities match the reviewed disabled identity. It records bounded membership rows matching their original directory fingerprints. Only exact reviewed inactive roots or wholly absent disabled skills-only parents are projected out; surviving versions, receipts and unrelated members stay bound. Direct user hook references, returning skill bodies and capability changes still refuse. Older directory witnesses without this projection need a fresh review; their historical hashes are never silently weakened. Updating the binary preserves existing policy and does not enroll this proof. Preview skills hook install with fresh --discovery-inputs and the genuine --codex-native-catalog, then apply the same reviewed inputs with --apply. Preserve the exact policy/configuration/hook preimages and compare them before application. The apply invocation replans and checks its observed preconditions; the preview is not an apply token. Keep typed V3 settings witnesses, existing disables, command/profile choices and session pins unchanged. A retired Claude cache version may likewise remain absent only while unchanged native settings and registrations select a different extant, witnessed user version. Individual missing files, current registered roots, aliases and registration changes still refuse; historical source hashes and typed settings witnesses remain intact. An explicit Claude discovery review must cover every registered active cache manifest, skill root and hook source. Installation refuses an incomplete review that covers only an older cache, before retirement of that cache can break prompt delivery. Hook behavior still requires the existing no-skill-injection review.

For a Codex 0.160.0, 0.160.1 or 0.161.0 remote refresh omitted by an existing qualified-name disable, a fresh native catalog and discovery review can plan the new exact path disable in the same transaction. The remote installation receipt, namespace and capability controls must match; conflicting enable rules, unknown names and ambiguous materializations refuse. Changed plugin capability controls require a fresh native catalog even when a new discovery review is supplied. Known skill identities remain disabled across versioned plugin cache relocation, even when their disabled bodies change. Unknown names, conflicting enables, changed plugin controls, native hooks and unsupported name syntax still refuse. Only manifest version metadata may vary. Reviewed app declarations use the implicit .app.json or explicit ./.app.json, with a bounded apps map containing connector id, optional category, and optional boolean required. The entire canonical app file and its presence stay bound; it preserves existing connector availability and native capability hints. Changed or unknown app fields, custom references, native hooks, commands and unsupported MCP controls refuse. Referenced own-root ./.mcp.json declarations may preserve local stdio servers with Codex's typed tool, approval, timeout and environment metadata. Their complete fingerprints and presence remain bound; review never executes commands or resolves environment values. Name controls suppress Skills, not every plugin capability. A Codex 0.160 catalog may also prove a nonremote plugin is installed but disabled. With an exact current path deny and explicit witnessed plugin disable, its cache can remain inert across versions; re-enable, ambiguous identity, conflicting controls and unsafe paths refuse. This does not approve its hook declarations. Remote-controlled, missing or unknown source identities do not qualify.

The catalog retains local source paths separately from installed cache identities. When a reviewed discovery witness binds a positively mapped installation input, runtime checks omit that input from plugin skill loading. Default home/project roots and installed caches are still checked, and migration inventory remains complete. Overlapping, linked, missing or contradictory mappings refuse. No prompt hook starts an app server to obtain this receipt: native startup can maintain caches. The explicit capture starts and closes only its own bounded native client; it does not reload an existing agent session. Neither a receipt nor a config write proves an existing session adopted new rules; use the actual native session's supported acceptance path separately.

At session start, the hook authenticates and refreshes the profile. Prompt hooks select complete skill instructions from that verified cache using explicit $skill references, profile keywords, paths and always-required selections. A session retains its loaded selections; compaction restores loaded instructions, and subagents inherit the parent's selection. Instructions that exceed the context budget produce an explicit skills load command. A hook never executes a skill. Cached use is explicit and expires after 24 hours. When a session receipt expires, the hook authenticates the current profile. If every loaded selection still has identical metadata and bundle digest, it archives the old receipt and advances that session to the current profile under an exact receipt precondition. Unloaded selections may be added or removed. If renewal is refused because the same profile moved on (a loaded selection changed or disappeared, or another pinned selection's policy, membership or lifecycle changed), the managed hook applies the explicit reconciliation planner and applier below to the authenticated current revision: it archives the old receipt, retains unchanged loaded bundles, retires changed or removed ones and delivers context for the prompt. The first hook context that succeeds and reaches the agent afterwards names each retired loaded skill once and how to reload its replacement; earlier instructions from those skills must not be relied on. Identity, integrity and receipt failures, an unavailable authority and anything the planner refuses keep their refusal; session write-lock contention keeps SESSION_WRITE_BUSY. A session created from a project lock (.skills/selection.lock.json) records that lock in its receipt and is never migrated automatically, whatever directory it