Aleph
Concepts

Extension System

How Aleph discovers, registers, loads, and reloads plugin components while sharing the Skill and MCP backends.

Aleph has two related meanings for Extension:

  • The user-facing Hub concept: one Extension with kind Skill, Plugin, or Mcp.
  • The src/extension/ plugin host: the runtime and registry that load plugin components.

The Hub façade routes by kind. The plugin host does not replace SkillSystem or McpManager; it integrates with them.

Architecture

ExtensionManager
├── DiscoveryManager
├── AdapterRegistry
├── PluginRegistry
├── PluginLoader
├── shared SkillSystem
├── HookExecutor
├── ServiceManager
└── ExtensionWatcher

The manager's startup path is:

scan scopes
  → parse and normalize a manifest
  → validate the candidate
  → resolve duplicate origins
  → register static capabilities
  → load Static, MCP, or WASM runtime
  → publish skills and agents
  → synchronize plugin MCP servers

The process-wide SkillSystem receives plugin skill roots, so plugin skills and filesystem skills share source precedence, snapshots, prompt XML, skill_read, status, and lifecycle operations.

Manifest adapters

The preferred format is .claude-plugin/plugin.toml, followed by the read-compatible .claude-plugin/plugin.json. aleph.plugin.toml remains a deprecated compatibility format and emits a warning. The adapter registry also accepts supported Codex and Cursor layouts and a final auto-discovery adapter.

Auto-discovery recognizes skills/, agents/, commands/, hooks/hooks.json, hooks.json, and .mcp.json. A directory containing one of these components can be treated as a static plugin without a manifest.

Unified capability registration

CapabilityDeclaration has six production variants:

pub enum CapabilityDeclaration {
    Tool(ToolRegistration),
    Hook(HookRegistration),
    Service(ServiceRegistration),
    Skill(SkillRegistration),
    Agent(AgentRegistration),
    McpServer(McpServerConfig),
}

The registrar validates ownership, classifies the declaration tier, and dispatches it to the matching registry. Tools, hooks, and skills are core; agents are important; services and MCP servers are pluggable. Command Markdown is stored as a command-type skill.

The PluginRegistry tracks plugins and their registered tools, hooks, services, skills, and agents. It keeps qualified keys such as plugin:diagnostics:check alongside short compatibility names. Registration does not grant a plugin permission to bypass tool execution policy.

Runtime integration

Plugin kindHost
StaticMarkdown components are registered without executable code
MCP.mcp.json is translated to namespaced transient MCP servers
WASMExtism loads the module and calls declared exports

An MCP plugin server ID is plugin:<plugin-id>/<server-name>. The MCP manager owns process health and tool discovery. The extension manager's synchronization is idempotent and non-fatal when no live MCP handle is attached, such as in CLI or test paths.

WASM tool discovery is based on the plugin registration path. The module can register declarations through the WASM registrar; it is not documented as a Node.js IPC runtime.

Hooks and services

Hooks are executed through the shared HookExecutor:

  • interceptor hooks run in priority order and can alter or stop a protected operation.
  • observer hooks run without becoming a blocking decision point.
  • The allowed kind depends on the event fire site.
  • A matcher is evaluated against tool_name only.

Runtime inventory exposes the resolved kind, priority, actions, consent state, and whether the hook is reachable. Hook output is capped at 64 KiB and hook timeouts at 300 seconds.

Background services require the plugin background permission and both a start and stop handler. Service lifecycle is coordinated during load, enable, disable, uninstall, hot reload, and daemon shutdown.

Discovery precedence

Scope directories are checked high to low:

agent > local > project > user

Duplicate plugin IDs are resolved by origin priority:

config > workspace > global > bundled

The active record is loaded; overridden records remain visible for diagnostics. A .disabled marker prevents a directory from becoming a candidate.

Lifecycle safety

ExtensionManager::load_all is protected by a load guard. The manager also tracks active plugin tool snapshots and a monotonic revision so the tool registry can refresh without rebuilding unrelated parts of the loop. Concurrent reload calls are serialized.

Unloading a plugin performs runtime cleanup before deleting files. For MCP plugins, transient servers are removed from the live manager so processes and tools do not survive the plugin lifecycle. Malformed plugin results are returned as errors rather than being reported as successful service results.

Relationship with the Hub

The Hub catalog is implemented in src/hub/ and persists catalog entries in hub_catalog.db. It supplies an InstallSpec and routes a selected Plugin entry to the marketplace installer. The extension host then discovers and loads the installed plugin.

The Hub is the catalog and trust boundary. This module is the plugin runtime and registration boundary. Neither module creates a multi-provider catalog model, and plugin manifests do not declare model providers through a plugin-provider section.

Code locations

  • src/extension/mod.rs — manager and shared subsystem wiring
  • src/extension/manifest/ — adapters and normalized manifests
  • src/extension/discovery/ — candidates, scopes, and conflict resolution
  • src/extension/capability.rs — declarations and tiers
  • src/extension/registrar/ — registration dispatch
  • src/extension/registry/ — component registry
  • src/extension/loader.rs — runtime loader
  • src/extension/hooks/ — hook executor and consent
  • src/extension/watcher.rs — change detection and reload
  • src/hub/ — user-facing catalog and install router

On this page