---
title: "Extension Scopes, Security, and Lifecycle"
source: https://docs.autohand.ai/guides/extensions/scopes-security-lifecycle
---

# Scopes, security, and lifecycle

Treat an extension as an installed capability with an owner, a trust decision, an active scope, and a reversible lifecycle—not as a folder copied into a hidden directory.

## Choose scope by ownership

| Question | User scope | Project scope |
|---|---|---|
| Who owns the capability? | The individual developer | The repository or team |
| Where is it stored? | ~/.autohand/extensions | .autohand/extensions |
| Where is it discovered? | Across workspaces | Only for the selected workspace |
| Typical examples | Personal Git helpers, an individual's review agent | Repository-specific test runner, release process, compliance audit |
| Reproducibility | Machine-dependent | Workspace-owned and easier to pin |

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

``` bash
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.

| Phase | Security controls |
|---|---|
| Read package | Bounded UTF-8 files, strict JSON, duplicate-key rejection, contained real paths, no contribution symlinks |
| Validate contribution | Exact schemas, safe tool name and parameters, handler safety checks, agent format checks, conflict detection |
| Install declarative package | Staging, validation of staged content, atomic rename, separate state, no package code or dependency installer execution |
| Install runtime package | All declarative checks plus explicit --trust; validation still never imports the entrypoint |
| Activate runtime | Compiled entrypoint registration is transactional; failure contributes nothing and appears in extensions doctor |
| Invoke tool | Shell escaping, tool filters, immutable security blacklist, permission manager, hooks, approval, events, accounting |
| Delegate agent | Active 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.

``` bash
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.

``` bash
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.