Manifest reference
Docs/Extend/Manifest reference

Manifest reference

Edit on GitHub
docs-site/extend/manifest.md

Every extension has an orrery.toml at its root. It is the contract: what the extension provides, what it asks for, and how it runs. Nothing outside it is available at runtime.

[extension]
api     = "orrery-ext/1"
name    = "buildgraph"
version = "1.2.0"
runtime = "node"

[provides]
tools = ["impacted", "deps"]

[requires]
read  = ["$WORKSPACE/**"]
spawn = ["java"]
net   = false

[listing]
homepage = "https://example.com/buildgraph"
image    = "docs/card.png"

[extension]

KeyRequiredMeaning
apiYesThe extension API major, "orrery-ext/1". Another major is refused at load.
nameYesThe extension id: the namespace of every tool it provides.
versionYesIts own semver version.
runtimeYesnative, wasm, node, python, process or none. none starts no process: see Declared extensions. Another name is looked up among the runtimes an extension registered.
residentNotrue keeps its process running for the whole session, so it is never parked. Default false. [extensions.<id>] resident in config overrides it. Costs one process while the session lasts (Show things: placements).

An older spelling, with api and runtime at the top level and id instead of name under [extension], is also accepted.

[provides]

Lists of names. Each tool becomes <name>.<tool>.

KeyContributes
toolsCallable tools.
providersModel providers.
agentsRole agents.
workflowsMulti-step orchestrations.
interceptorsHooks around a call.
lifecycleSession start and stop handlers.
gradersEval verdicts.
commandsCLI subcommands.
viewsLoop event to surface bindings.
renderersDeprecated, and unused: an extension never draws. Still accepted, so no manifest stops loading, and orrery install warns that it is ignored. Use [[provides.elements]] with a fallback, or place a surface with ui.show (Show things: placements).
skillsPrompt-level capabilities.
mcpMCP servers exposed as tools.

Singletons, one string each. Exactly one extension may hold each; a second claim is a load error:

KeyReplaces
memoryThe memory backend.
sessionThe session store.
permissionsThe permission decision point.
routerModel routing.

Tables, for UI packages (see Clients):

  • [[provides.clients]]: id, label, role (human, machine or named), entry, draws, fixtures.
  • [[provides.elements]]: id, props (a JSON schema path), fallback, fixture.
  • [[provides.placements]]: id, placement (band, pane.left, pane.right or footer), title, and optionally component and data. The host draws each one in its loading state before the extension is up, and the extension fills it with ui.show under the same id (Show things: placements). With component, the host fills it itself (below).
  • [[provides.components]]: a structure over the catalog, by name (below).

And one table of tables, [provides.actions.<name>]: what a button in a declared component does (below).

[[provides.components]]

A component is a structure over the catalog orrery/1 and the JSON Schema of its data (Show things: components).

[[provides.components]]
name    = "ci"
summary = "The last CI run: its status, what failed, and buttons to explain or rerun it"
file    = "ci.json"
schema  = { type = "object", properties = { failed = { type = "integer", default = 0 } } }
KeyRequiredMeaning
nameYesUnique in this manifest. ui.show {component} and a placement's component use it, as <name> or <ext>.<name>. Only this extension may show it: another extension, or the agent, sends an inline structure instead.
summaryYesOne line on what it shows, for people and the agent's tool search.
structureOne of the twoThe structure, inline, as a TOML table.
fileOne of the twoA JSON file next to orrery.toml holding the structure. One that fails to read or parse refuses the component, naming the file and the JSON error's line and column.
schemaNoA JSON Schema object for its data. Its defaults fill missing data, and every update is checked against it.

Placement component and data

[[provides.placements]]
id        = "ci"
placement = "pane.right"
title     = "CI"
component = "ci"                         # a [[provides.components]] name
data      = { file = ".ci/status.json" } # or "$session", "$cost", "$git", "$tasks"
  • component names a component this manifest declares. The host shows it at session start and keeps its data current.
  • data is a workspace file ({ file = "…" }, relative to the workspace) or a value the host holds. With no data, the schema's defaults alone fill it.
  • A file source needs [requires] read covering the file.

[provides.actions.<name>]

What a pressed button, a chosen row or a submitted form in a declared component does. Exactly one key:

[provides.actions.explain]
send = "Explain why CI failed, from .ci/status.json"   # a message to the agent, as the extension's

[provides.actions.rerun]
command = "/ci rerun ${value}"                         # an extension's slash command; ${value} = the chosen row's key
KeyDoes
sendSends the text to the agent as the extension's message, never as the person's. Needs "run.send" = true under [requires].
commandRuns the slash command, starting with /. Only commands that installed extensions' tools register; never the client's built-ins (/model, /theme).

${value} in either is replaced by the value that came with the action: a string as is (a row's key, a path), an object or a list as compact JSON (a form's values), nothing when there is none. It is text only, never a shell: a command still goes through the command registry. A value over 4 KiB is refused; send a key or a path instead (Actions). A code extension gets its actions as ui/event instead and needs no [provides.actions] (Show things: placements).

[requires]

What the extension asks for, by aspect. Each key takes true (the whole aspect), false (nothing) or a list of names or patterns:

KeyAsks for
read · writePaths, such as "$WORKSPACE/**".
spawnPrograms it may start, such as "git".
netHosts it may reach.
credsNamed credentials.
mem.read · mem.writeMemory scopes.

Install shows these requests and you grant or deny each. A denied request disables only the tools that need it.

[grants]

What a client package is handed beyond [requires]:

[grants]
client = ["draw", "consent", "tty"]   # also: handoff
GrantLets it
drawReceive frames and send intents.
consentAnswer a consent prompt.
ttyBe handed the terminal.
handoffMove a session to another machine.

[process]

Required for runtime = "process":

[process]
command  = "bin/my-ext"     # relative to the extension's folder, or on PATH
args     = ["--stdio"]
protocol = "orrery-ext/1"
env      = { RUST_LOG = "warn" }

Declared extensions: runtime = "none"

An extension with runtime = "none" has no process and no code. The host shows its placements as components, feeds their data, and runs their actions. The whole guide is Show things: components.

It may provide only what the host draws or runs itself: [[provides.components]], [[provides.placements]], [provides.actions], [[provides.keys]], [[provides.elements]] and skills. Anything else (tools, providers, a client) is refused at load, naming what needs code. A [process] table is refused too.

[listing]

Optional. Only the extension gallery reads it.

KeyMeaning
imageA card image: an https:// URL or a path inside the package.
homepageThe project's page, https:// only.

Limits

  • Components, placements and actions are checked at load: a name declared twice, a structure given both inline and as a file (or neither), a schema that is not an object, a placement naming an undeclared component or a host value that does not exist, data without component, an action with both or neither of send and command, and a command not starting with / are each refused, naming the key and the fix.
  • A placement whose data file [requires] read does not cover is refused at load, with the read line to add.
  • The structure itself is checked against the catalog when the session starts, not by orrery ext test. A refused one is drawn as its refusal, in its placement.
  • A structure file is read once, at session start. A change to it shows in the next session.
  • An action a structure names but [provides.actions] lacks is found only when it is pressed: a notice names the table to add.
  • [provides.actions] is read only for runtime = "none". A code extension's actions go to its own process.

Errors

A manifest that does not load names its file and what to write instead. Check one without a session:

orrery ext test ./my-extension