Choose scope by ownership

QuestionUser scopeProject scope
Who owns the capability?The individual developerThe repository or team
Where is it stored?~/.autohand/extensions.autohand/extensions
Where is it discovered?Across workspacesOnly for the selected workspace
Typical examplesPersonal Git helpers, an individual's review agentRepository-specific test runner, release process, compliance audit
ReproducibilityMachine-dependentWorkspace-owned and easier to pin

Install at project scope with an explicit workspace path so the destination cannot be ambiguous:

autohand --path /work/acme-api extensions install ./acme.test-triage --scope project

Know the precedence rules

  1. Built-in tools, agents, skills, commands, providers, flags, and reserved keybindings cannot be replaced.
  2. Standalone persisted meta-tools and configured user/external agents remain ahead of extension contributions.
  3. User extensions load in deterministic id order.
  4. Project extensions load in deterministic id order.
  5. A project extension with the same id replaces the user extension as a whole package.
  6. A contribution name conflict rejects the conflicting package rather than selecting by filesystem order.

Use the same extension id at both scopes only when project scope is an intentional, complete override. Do not expect individual tools from the user version to merge with agents from the project version.

Separate installation trust from execution approval

Declarative installation is an explicit decision to store a validated package; it executes no package code. A package with runtime entrypoints requires the separate --trust code-execution decision. Declarative tool invocation remains a later permission decision, while trusted runtime code itself is not sandboxed.

PhaseSecurity controls
Read packageBounded UTF-8 files, strict JSON, duplicate-key rejection, contained real paths, no contribution symlinks
Validate contributionExact schemas, safe tool name and parameters, handler safety checks, agent format checks, conflict detection
Install declarative packageStaging, validation of staged content, atomic rename, separate state, no package code or dependency installer execution
Install runtime packageAll declarative checks plus explicit --trust; validation still never imports the entrypoint
Activate runtimeCompiled entrypoint registration is transactional; failure contributes nothing and appears in extensions doctor
Invoke toolShell escaping, tool filters, immutable security blacklist, permission manager, hooks, approval, events, accounting
Delegate agentActive registry resolution, allowlist filtering, normal nested authorization

Review a package before trusting it

  1. Read autohand.extension.json and confirm the id, version, repository, and every declared path.
  2. Read every tool handler. Check executables, network access, file mutation, revision semantics, and output bounds.
  3. Read every agent prompt, Agent Skill, and tool allowlist. Confirm each stays inside the package's stated purpose.
  4. If contributes.runtime is present, review every emitted JavaScript file and bundled dependency. Confirm registered commands, views, shortcuts, flags, hooks, providers, and policy match the README.
  5. Run validate --json before installation.
  6. Install into project scope or an isolated profile for the first evaluation.
  7. Exercise calls under normal permissions and test denial paths.

Validation is not a code review or sandbox. It proves the package satisfies the mechanical contract and rejects known unsafe shapes without importing runtime code. You must still decide whether every declared handler, prompt, skill, entrypoint, and bundled dependency is appropriate for your environment.

Operate changes atomically

Normal installation copies through a same-filesystem staging directory and validates the staged package. Existing content is moved aside only during the atomic replacement. State changes use temporary files and renames. Removal first moves the installed package to a tombstone before cleanup.

This prevents a partially copied directory from becoming active after interruption. It does not eliminate the need for a rollback plan: keep the previous immutable source version available and verify the new copied installation in a fresh process.

autohand extensions validate ./acme.release-assistant-1.2.0
autohand extensions install ./acme.release-assistant-1.2.0 --replace
autohand extensions show acme.release-assistant
autohand extensions doctor

Add --trust to the replacement command when the package declares runtime entrypoints. Trust is stored separately from package files, survives disable/enable, and disappears on removal.

Use disable as a reversible incident control

Disabling leaves the package installed and inspectable but removes all of its runtime contributions. Use it when investigating an unexpected command, conflict, or regression. It is faster and more evidence-preserving than deleting files manually.

autohand extensions disable acme.release-assistant
autohand extensions show acme.release-assistant
autohand extensions doctor

# After review
autohand extensions enable acme.release-assistant
# Or remove it
autohand extensions remove acme.release-assistant --yes

In an interactive non-bare session, the equivalent /extensions mutation refreshes the current registry. For final recovery proof, start a new process and confirm the package snapshot again.