# Extending lean-ctx — one decision, one trust model lean-ctx can be extended in several ways. They look similar from the outside (they all "add capabilities"), but each targets a different job and a different trust model. This guide is the **single entry point**: pick the right mechanism in one decision, then follow its dedicated guide. > TL;DR — building a **tool or integration** (in any language)? Build an > [**Addon**](addons.md). Everything else is for a narrower job below. ## Pick your extension type ```mermaid flowchart TD Q0{What are you adding?} Q0 -->|Data: knowledge, graph, patterns to share/sell| PACK[ctxpkg Pack] Q0 -->|A tool / integration callable by the agent| ADDON[Addon · flagship] Q0 -->|An external context source feeding search/knowledge| PROV[Context Provider] Q0 -->|In-process compression / compute| WASM[WASM Extension] Q0 -->|Deep in-process build on the engine, in Rust| SDK[Embedding SDK] Q0 -->|A reusable config bundle| PERSONA[Persona / Policy Pack] Q0 -->|Local hooks on agent lifecycle events| PLUGIN[Plugin] ``` - **Share or sell *data*** (knowledge, graph edges, session, patterns, gotchas) → [**ctxpkg Pack**](publishing-packages.md) - **A *tool / integration* the agent can call** (any language, via MCP) → [**Addon**](addons.md) — the flagship path - **An external *context source*** (issues, tickets, DB rows, a REST API, another MCP server's resources) that should flow into search + knowledge → [**Context Provider**](../contracts/provider-framework-contract-v1.md) - **In-process compression / compute** → **WASM Extension** ([WASM ABI](../contracts/wasm-abi-v1.md)) - **Deep, in-process build on the engine, in Rust** → [**Embedding SDK**](embed-sdk.md) (`lean-ctx-sdk`) - **A reusable configuration bundle** → [**Persona**](../contracts/persona-spec-v1.md) / [**Policy Pack**](policy-packs.md) - **Local hooks on agent lifecycle events** (pre/post tool, plus local tools) → **Plugin** ([extension trust](../contracts/extension-trust-v1.md)) ## The mechanisms at a glance | Mechanism | Job | Lives where | Distribution | Trust model | |---|---|---|---|---| | **Addon** | Expose **tools** to the agent | External MCP server (stdio/http) | Registry (`lean-ctx addon`) | Declared `[capabilities]` → per-addon OS sandbox + env scrub + install consent | | **Context Provider** | Feed an external **data source** into the pipeline | `[providers.*]` / `~/.config/lean-ctx/providers/` | Config (+ tokens) | Token-scoped; data redacted on ingest | | **Plugin** | **Hooks** on lifecycle events + local tools | Local subprocess | Local install | `[trust]` permissions → env scrub + cwd jail + timeout | | **WASM Extension** | In-process **compressor/provider** | Sandboxed WASM in the engine | Extension registry | WASM sandbox (no ambient host access) | | **ctxpkg Pack** | Ship/sell **data** | Signed archive | Hosted registry (`lean-ctx pack`) | Ed25519 signing + publisher identity | | **Persona / Policy Pack** | Reusable **config** | TOML bundle | File / registry | Inherits engine config trust (global-only floors) | | [**Embedding SDK**](embed-sdk.md) | **In-process** build in Rust | Your binary links the crate | crates.io | Runs in your process — you own the trust boundary | ## Resolving the common overlaps Four mechanisms can all involve "an external MCP server" or "extra tools", which is the usual source of confusion. Disambiguation: ### Addon vs `[[gateway.servers]]` Same runtime, two layers. `[[gateway.servers]]` is the **raw config primitive**: a downstream MCP server the gateway aggregates. An **Addon** is the **packaged, distributable, capability-governed** form of exactly that — a `lean-ctx-addon.toml` manifest + registry entry + install consent + per-addon sandbox. `lean-ctx addon add` *writes* a `[[gateway.servers]]` entry for you and records the granted capabilities. Hand-editing `[[gateway.servers]]` is the escape hatch; an Addon is the supported, shareable artifact. ### Addon vs `[providers.mcp_bridges.]` Both connect to an external MCP server, but for **opposite purposes**: - **Addon** exposes the server's **tools** so the agent can *call* them (`ctx_tools find` / `call`). Use it for *actions*. - **MCP Bridge** (a Context Provider) pulls the server's **resources** into the consolidation pipeline — BM25 index, graph, knowledge, session — so they become *context* (searchable via `ctx_semantic_search`, recallable via `ctx_knowledge`). Use it for *data*. If you want the agent to *do something*, build an Addon. If you want lean-ctx to *know something*, configure a Provider/MCP Bridge. > The line is softer than it used to be: an Addon's output can **also** flow into > the consolidation pipeline when you enable the gateway's deep-integration flags > (`index_output`, and category adapters), so a tool's results become searchable > + graphable too. The split is now about intent (a callable *action* vs a > standing *data source*), not capability — see > [Why an addon goes deeper](addons.md#why-an-addon-goes-deeper-than-a-passthrough). ### Addon vs Plugin - **Addon** = an MCP server whose **tools** plug into the gateway. Cross-language (anything that speaks MCP), distributed via the registry. This is the path for third-party tools/integrations. - **Plugin** = a local subprocess that runs on **lifecycle hooks** (pre/post tool call, etc.) and may register a few local manifest tools. Use it to *react to* agent activity locally, not to ship a distributable tool. ## Naming: `@ns/name` Distributable artifacts (Addons and Packs) use a namespaced identity so the same short name from two authors never collides: ``` @/ ``` - `` is your registry namespace (your verified publisher handle or org). - `` is the artifact slug — lowercase `[a-z0-9-]`, no leading/trailing dash. - The bare `` (no `@ns/`) refers to a built-in/first-party entry. Examples: `@dastholo/lean-md`, `@acme/jira-tools`, `@acme/payments-knowledge`. Local-only mechanisms (Plugins, Providers, Personas) are addressed by their local id and are not namespaced. ## Start building (scaffolds) Each executable mechanism has a one-command scaffold so you start from a valid, secure-by-default artifact: | You want | Command | Then | |----------|---------|------| | An addon (tool/integration) | `lean-ctx addon init [name] [--http]` | `lean-ctx addon audit ./lean-ctx-addon.toml` → `addon add ./…` | | A config provider (REST source) | `lean-ctx provider init ` | edit `.lean-ctx/providers/.toml`; auto-discovered | Validate before you publish: `lean-ctx addon audit` runs the capability + malware gate on a single manifest, and `lean-ctx addon registry validate [path]` runs the full security + quality bar over a registry file (the dry-run CI uses). ## One trust model All executable extensions converge on **declared, least-privilege capabilities** rather than ambient trust: - **Addons** declare `[capabilities]` (`network`, `filesystem`, `env`, `exec`). The declaration drives a **per-addon OS sandbox** (`sandbox-exec` on macOS, `bwrap` on Linux) for `network` + `filesystem` — inherited by any child process — plus an **environment allowlist** at the single gateway spawn point, so host secrets never reach a child unless the addon lists the variable name. `exec` is a **declared + audited** capability (disclosure, not OS-enforced — child processes are already bound by the inherited net/fs sandbox). You see exactly what you grant at install. See [`addon-manifest-v1`](../contracts/addon-manifest-v1.md). - **Plugins** declare `[trust]` permissions (`network`, `fs_write`, `env_passthrough`) and share the same environment allowlist; subprocesses get a scrubbed env + cwd jail + per-call timeout. - **WASM Extensions** run in a WASM sandbox with no ambient host access. - **Packs** carry no executable code; they are Ed25519-signed and bound to a publisher identity. Secure-by-default: an Addon that declares a `[capabilities]` block but omits a field gets the most restrictive value (no network, read-only filesystem, scrubbed env). An Addon with no block keeps the legacy global `addons.sandbox` behaviour. ## See also - [Addons — community extensions](addons.md) (flagship; build & publish) - [Publishing context packages](publishing-packages.md) - [Context policy packs](policy-packs.md) - [Provider framework contract](../contracts/provider-framework-contract-v1.md) - [Addon manifest contract](../contracts/addon-manifest-v1.md)