One Tree, Three Interfaces

CLI. AI. Browser. Same data.

Install an extension and it adds tools the AI can call, commands the CLI shows, and pages the browser renders. All from one package. Uninstall it and all three vanish together. Block it at a branch and the AI loses the tool, the CLI loses the command, and the browser loses the page. At that position. Same tree. Same rules. Three interfaces that always agree.

Why This Matters

Most platforms have a frontend team and a backend team and they disagree about what the UI should show. The frontend checks permissions its own way. The backend checks a different way. They drift. Buttons appear that lead to 404s. Links show for features that aren't installed. Admin panels display options the user can't actually use.

TreeOS doesn't have this problem. The same extension that registers an AI tool also registers the UI that displays it. The same spatial scoping that determines whether the AI can use a tool at a position determines whether the browser shows it. Install the solana extension and the wallet link appears on every node's values page. Block solana on a Journal tree and the wallet link vanishes there. Not because of a CSS rule. Because the kernel filtered it using the same resolution chain that filtered the AI's tools.

One extension. One init(). Backend logic, AI tools, CLI commands, and browser UI. All deployed together. All scoped together. All removed together. The frontend is not a separate app. It's a view into the same tree the AI sees.

?html

Every API endpoint returns JSON by default. Add ?html to the query string and the same endpoint returns a rendered HTML page instead. Same data. Same auth. Same URL. Different format.

# JSON (for CLI, AI, extensions, integrations)
GET /api/v1/node/abc-123
→ { "status": "ok", "data": { "name": "Fitness", "type": "goal", "children": [...] } }

# HTML (for browsers)
GET /api/v1/node/abc-123?html
→ <html>... rendered page with the same node data ...</html>

The kernel serves JSON. The html-rendering extension intercepts ?html requests and wraps the same data in a visual interface. Remove html-rendering and the API still works. The HTML layer is optional. The data layer is the truth.

Three Ways In

CLI

Terminal native. cd, ls, chat, note, tree. The fastest way to navigate and build. Extension commands appear automatically. Power users live here.

treeos cd Fitness
treeos chat "add back day"
treeos tree

AI

The AI sees the same tree you see. It reads nodes, notes, metadata. It calls tools via MCP. It writes notes, creates nodes, changes statuses. When you chat, the AI is reading and writing the same data the CLI and browser show.

[Position]
User: tabor
Tree: Fitness (abc-123)
Current node: Push Day

Browser

The HTML rendering extension wraps API data in a visual interface. Navigate trees, read notes, view values, manage extensions. Every page is the same API call with ?html appended. What the browser shows is what the CLI returns is what the AI reads.

/api/v1/node/abc-123?html
/api/v1/root/abc-123?html
/dashboard

Dynamic HTML

The HTML pages are server-rendered. No React. No build step. No client-side framework. Template strings that read from the database and return HTML. Fast, lightweight, works everywhere. The same Node.js process that runs the AI serves the pages.

Pages are assembled from render functions. Each function takes data and returns HTML. Extensions register their own render functions. The html-rendering extension provides the layout. TreeOS extensions provide the pages. Third-party extensions add their own.

// Extension registers a page
const treeos = getExtension("treeos-base");
treeos?.exports?.registerSlot("node-detail", "my-ext", (ctx) => {
  const data = getExtMeta(ctx.node, "my-ext");
  return `<div class="my-ext-panel">${data.summary}</div>`;
});

// The node detail page resolves all registered slots:
const extraHtml = resolveSlots("node-detail", { node, user });
// → includes my-ext's panel if my-ext is installed
// → excludes it if my-ext is blocked at this position

UI Slots

Pages don't know which extensions are installed. They define slots. Extensions register fragments for those slots. The page resolves whatever's registered. Same pattern as hooks, modes, and tools. Extensions register. The resolver filters.

user-profileThe user profile page. Extensions add energy badges, tier labels, wallet links.
node-detailThe node detail view. Extensions add values panels, schedule widgets, script editors.
tree-overviewThe tree root page. Extensions add understanding summaries, cascade status, health indicators.
welcome-statsThe landing page stats row. Extensions add custom metrics.
land-adminThe /land admin page. Extensions add their own management sections.
nav-sidebarThe navigation sidebar. Extensions add quick links, recent items, bookmarks.

Spatial scoping applies to slots. Navigate to a Finance tree where solana is allowed: the wallet link appears. Navigate to a Journal tree where solana is blocked: the wallet link is gone. Same extension installed on the land. Different position, different UI. The page doesn't decide. The slot resolver uses the same spatial scoping that filters the AI's tools. What the AI can do, the browser shows. What the AI can't, the browser hides.

Building TreeOS Apps

A TreeOS app is just an extension that registers pages, tools, modes, and slots. The tree is the database. The AI is the backend logic. The HTML is the frontend. The CLI is the power user interface. All four access the same data through the same API.

Fitness App

The fitness extension registers: two AI modes (coach and log), one route (/root/:rootId/fitness), one CLI command (fitness), and HTML slots for the node detail page (workout values, set tracking). Users interact through chat, CLI, or browser. Same tree.

Your App

Create an extension. Register modes for how the AI thinks about your domain. Register tools for what the AI can do. Register routes for your API. Register slots for your UI fragments. Register CLI commands for power users. The tree holds the data. Everything else is a view into it.

Developer reference covers everything: manifest, init, hooks, modes, tools, routes, slots, CLI commands.

The tree is the single source of truth. The CLI reads it. The AI reads it. The browser renders it. None of them own the data. The tree does. When you type treeos note "bench 135x10", the AI sees it. When the AI creates a node, the browser shows it. When you edit in the browser, the CLI reflects it. One tree. Three interfaces. Zero divergence.

Start BuildingExtensionsGuide