Extensions

How the tree grows.

Every capability beyond the seed is an extension. AI modes, MCP tools, HTML rendering, billing, fitness coaching, backup, gateway channels. Install what you need. Remove what you don't. Build your own.

The Contract

Every extension has two files. A manifest that declares what it needs and what it provides. An index that exports an init function. The kernel reads the manifest first, calls init second.

manifest.js

needs: models, services, other extensions (with semver constraints).optional: graceful degradation if missing.provides: CLI commands, env vars, energy actions, session types, indexes. The loader reads the manifest before calling any code. Unmet needs = extension skipped, logged, and the land boots without it.

init(core)

The entry point. Receives the core services bundle. Can return any combination of:router (HTTP routes at /api/v1),tools (MCP tools for the AI),jobs (background tasks),pageRouter (pages at /),exports (for other extensions to import). Registers hooks, modes, orchestrators, socket handlers, auth strategies through core.

The Loader

At boot, the loader brings every extension online in the right order. Dependencies are resolved automatically. A topological sort guarantees that if extension B depends on extension A, A loads first.

1

Discover

Scan extensions/ for directories with manifest.js. Skip disabled extensions (configurable via .config, env, or file). Validate manifest fields. Check required env vars.

2

Resolve

Check needs: models, services, other extensions with semver constraints. Topological sort so dependencies load first. Extensions with unmet requirements are skipped. The rest proceed.

3

Initialize

Call init(core) with the scoped services bundle. Extensions register modes, hooks, tools, socket handlers. They return routes, tools, jobs, and exports. Each extension receives only the services it declared.

4

Wire

Mount routes at /api/v1. Register MCP tools with ownership tracking. Mount page routes. Start background jobs. Run schema migrations. Ensure extension indexes. Sync state to .extensions system node.

Five Registries

Same pattern across all five. Extensions register. The kernel resolves. Failure falls back to the kernel, never to silence.

HooksLifecycle event handlers. 26 kernel hooks. Extensions fire their own with extName:hookName convention. before hooks cancel. after hooks react. Sequential hooks build on each other.
ModesAI conversation modes. How the AI thinks at each position. Extensions register modes during init(). The kernel resolves which mode fires based on position, intent, and per-node overrides.
OrchestratorsConversation flow replacements. The entire chat/place/query pipeline is an orchestrator. Replace it and you control every AI interaction on the land.
Socket HandlersWebSocket event handlers. Extensions add real-time features without touching the kernel's websocket code. The dashboard, recent-roots, and notification extensions all use this.
Auth StrategiesAuthentication methods. JWT is built-in. API keys, share tokens, public access are all extensions that register auth strategies. The kernel tries each one in order.

Spatial Scoping

Position determines capability. Block an extension at a node and it loses all power at that node and every descendant. Tools disappear. Hooks stop firing. Modes don't resolve. Metadata writes are refused.

Blocked

metadata.extensions.blocked = ["shell", "solana"] on any node. Inherits to all descendants. The extension is invisible at that position. No tools. No hooks. No modes. No metadata writes. As if it doesn't exist.

Restricted

metadata.extensions.restricted = { "solana": "read" }. The extension keeps its read-only tools. Write tools are filtered out. Hooks still fire. Metadata reads work. A middle ground between full access and blocked.

A health tree blocks the shell extension. A finance branch restricts scripts to read-only. Navigate somewhere and the capability surface changes. The tree reshapes around where you stand.

How Extensions Talk to Each Other

Extensions are decoupled. They never import each other directly. Three patterns for communication.

Hooks

Pub/sub. Extension A fires core.hooks.run("a:afterProcess", data). Extension B listens with core.hooks.register("a:afterProcess", handler, "b"). Neither imports the other. The kernel is the bus.

Exports

Direct call. Extension A returns exports: { doSomething } from init. Extension B calls getExtension("a")?.exports?.doSomething(). Dynamic import with try/catch. Graceful if A isn't installed.

Metadata

Shared state on nodes. Extension A writes metadata.a. Extension B reads metadata.a via getExtMeta. The node is the shared memory. The Map is the address space.

An Operating System Is Just Extensions Working Together

The seed doesn't ship an operating system. It ships the kernel that operating systems are built from. An OS emerges when enough extensions depend on each other that a coherent experience forms. AI modes, a conversation orchestrator, a data layer, metering, an interface, external channels. Each one independent. Together they form something whole.

Swap any of them and you get a different OS. A medical OS with triage and diagnosis modes. A coding OS with architect and review modes. A research OS with citation and synthesis modes.

TreeOS is the first operating system built on the seed. It ships 25+ extensions that work together. But it is one interpretation. The seed grows whatever you plant.

Browse ExtensionsThe Seed

Start Building

Check out extensions built so far at horizon.treeos.ai and publish your own to start growing. Every extension is a piece contributed toward the future of AI infrastructure. There are many things to be built off the kernel.

Open code. Open doors. Resilient. Decentralized. This was designed to be held back by no one. We can work together on this.

The Horizon at horizon.treeos.ai is one place to discover lands and share extensions. Anyone can host their own Horizon. Lands connect peer to peer. The Horizon is just discovery. But building together in one place is how communities grow.