Get started free
Build

Overview

intentic is a lean core plus extensions: a folder with a manifest that can extend the agent itself, not just the editor UI.

On this page(10 sections)

The whole lifecycle

Seven steps take an extension from an empty directory to a payout that renews, and not all are yours: Discover and Install happen on the other side of the listing. What you publish is only ever met as what somebody else installs.

What an extension is

A directory with an intentic-extension.json file at its root. That's the whole definition. The manifest names a publisher, a name, and the things the extension contributes; if it contributes UI, the directory also holds a prebuilt bundle exporting an activate() function.

Usually that directory is a git repository, because a repository is how an extension travels to somebody else's sandbox. It doesn't have to be: a directory inside your own sandbox is already an extension, which is what makes "ask the agent to build me one" a reasonable sentence.

intentic-extension.json
{
    "publisher": "acme",
    "name": "incidents",
    "version": "1.0.0",
    "category": "work",
    "icon": "exclamation-triangle",
    "engines": { "intentic": "^2.0.0" },
    "permissions": { "sandbox": ["GET /logs", "GET /logs/tail"] },
    "contributes": {
        "views": [{ "id": "incidents", "label": "Incidents", "surface": "rail", "badge": true }]
    }
}

Identity is derived, never declared: this extension is acme.incidents everywhere in the product, because that's what publisher and name say. There is no id field to contradict the one the install dialog showed you.

It extends the agent, not just the editor

This is the part that has no equivalent in a normal editor's plugin model, and it's the reason to build one. A sandbox is a whole machine: an agent, its tools, its credentials, its image. An extension can reach all of it.

The UI half

ContributesWhat it adds
viewsA tile in the left rail, a per-repo panel in the Workspace tree, or a tab on the Sandbox hub.
viewersA renderer for a file type: the host fetches the bytes, your component draws them.
documentsA per-directory page in the Workspace tree: an icon on the rows your provider can explain, opened as a tab.
commandsAn entry in the command palette, optionally with a global keyboard shortcut.
settingsTyped settings the host renders and stores for you, including secrets and env vars for the agent.
filesWhich workspace files back your view, so the daemon pushes you a refresh instead of you polling.

The agent and daemon half

ContributesWhat it adds
agentA directory of skills, subagents, hooks and MCP servers, loaded into the agent every turn.
binExecutables prepended to the agent's PATH, which is how you ship it a command-line tool.
capabilitiesA whole third-party integration as data: a card, a config form, env vars, and a cheatsheet.
processesA long-lived background process the daemon supervises, optionally on a tunneled preview URL.
listenerA realtime event source that can wake the agent, the way Discord and IMAP do.
environmentDockerfile layers baked into the sandbox image, so your tools are actually installed.

The backend half

An extension can also ship a backend: a manifest server entry naming a bundle of real server code. It runs beside the daemon, serves the extension's own route namespace behind the daemon's ordinary auth, and reaches the daemon's own routes only through a second declared allowlist. That is what lets an extension be a whole product: a client for somebody else's API, work that outlives the browser tab, while its reach stays a list the owner read and approved.

One format, any subset

Everything above ships in one envelope. There is no separate skill-pack format, theme format, connector format or app format: there is one manifest, and every part of it is optional. What you fill in is what your extension is:

You fill inWhat you've made
agent onlyA skill pack. No code runs anywhere; the agent learns something.
capabilities onlyA connector: a card, a config form, env vars and a cheatsheet: data, not code.
entry + viewsA UI extension, like an editor plugin.
processes + listenerA realtime gateway that wakes the agent, the way Discord and IMAP do.
entry + server + agent + binA whole product: its screen, its backend, its skills, its CLI.

One envelope because the things it groups succeed or fail together. A user installs a product: "deployments", "knowledge", "Reddit research": not a skill here, a view there and a background process somewhere third. One install is one identity, one trust decision, one on/off switch that unwires all of it, one row a marketplace can list and attribute. Split those across four package kinds and every one of those sentences needs four answers.

The grouping never taxes the small case: a manifest with one section filled in is complete, installs the same way, and shows the owner a one-line approval instead of a four-line one. And the parts that are portable stay portable. The agent contribution is a standard agent-plugin directory with skills, subagents, hooks and MCP servers that work in other harnesses unchanged, and a registry file is the same marketplace format those harnesses already read. The envelope wraps the standard; it doesn't fork it.

The one deliberate limit: an extension contributes cards and code, never privilege. The handlers that grant real power stays in the core. Examples include running the sandbox privileged, joining a private network and installing other extensions. A manifest that tries to name one fails to parse. Shared surfaces stay core too: the model picker, the terminal, the chat are things an extension asks the shell for, so every extension offers the same, current list instead of five worse copies of it.

What bounds an extension

Extension code runs in somebody's browser and somebody's sandbox. Official discovery adds exact-sha security review, while the install makes declared host integrations legible before approval. These are layered controls, not runtime isolation, and all of them constrain what you design as an author:

  • Code that comes from elsewhere is pinned to a commit. Installing takes a full 40-character commit sha, not a branch. The code you approved is the code that runs, and an update is an explicit, visible act, never something that happens under you. An extension you wrote in your own sandbox is pinned to nothing, for the same reason your own repositories aren't: there is no upstream that could change it behind your back, only files you can read.
  • The manifest is the host-integration surface. The install dialog shows exactly the declared contributions. Afterwards the host enforces them: a view, command, viewer, setting or process the approved manifest never declared is refused at runtime. That enforcement applies to host APIs, not ordinary browser globals.
  • Cooperative daemon calls are allowlisted. Each half declares the routes it calls through the extension API as "GET /logs"-style entries, in two lists because they run as different principals. Undeclared API calls are refused; this is not a claim that arbitrary browser or process code is confined to that list.
  • Official listings pass two automated security checks. Trivy checks the exact source for known dependency flaws, committed secrets and dangerous deployment configuration. An intentic agent then reads the complete tree without running author code, including browser egress, server/process/agent/bin/build surfaces, dependencies and source versus shipped artifacts. A finding, blocked or uninspectable audit fails closed, and both run identities are recorded against the repository, commit and optional subdirectory.

The extension API injects transport auth and secret settings round-trip as "still set" rather than their value. That reduces routine credential handling; it is not a secrecy boundary from browser code sharing the app realm, which is why the exact source is audited.

Verification & trust explains what those mechanics guarantee and what listed, verified and blocked mean. What they look like from the other side, at the moment somebody clicks install, is Install & manage extensions.

Everything first-party is an extension too

Most of the product you already use is extensions: over twenty-five of them. Activity, Automations, Memory, Knowledge, Deployments, Pipelines, the file viewers, the commit graph, the Discord, Slack, Telegram, WhatsApp and IMAP gateways, the Google Workspace connection, the connector catalog. They ship through the same @intentic/extension-api a third-party bundle compiles against, and a lint rule fails the build if one of them reaches into app internals instead.

That's a deliberate constraint rather than a boast: it means the public API is the API the product is built on, so it can't quietly rot into the second-class path.

How extensions reach a sandbox

  • Baked into the image: first-party ones are present in every sandbox and can be switched off, not removed.
  • Git-installed: everything else, as a sha-pinned clone into .intentic/extensions/, added from a repo URL or picked from a registry.
  • Written in the workspace: a directory under .intentic/workspace-extensions/, run straight from where it sits. No clone, no install step, no publishing: see Build an extension.

All three land in one list on Sandbox → Extensions, with one on/off switch each. Switching one off unwires it everywhere: no view, no command, no PATH entry, no connector card, no env var, no background process.

Type to search every page, in the docs and the API reference.