Skip to content

extension.toml

Every extension is a folder with an extension.toml at its root. Core, the node and the apps all read the same file, and none of them takes one that breaks a rule on this page.

[extension]
id = "tickets"
name = "Tickets"
version = "0.2.0"
publisher = "acme"
summary = "Open, update and close tickets from a thread."
platforms = ["macos-arm64", "linux-x86_64"]
[run]
command = ["python", "-m", "tickets"]
runtime = "python3.12"
[permissions]
network = true
secrets = ["tickets.key"]
[[commands]]
kind = "tickets.open"
title = "Open a ticket"
params = { type = "object", required = ["title"], properties = { title = { type = "string" } } }
[[tools]]
name = "tickets_open"
command = "tickets.open"
description = "Open a ticket in the team's tracker, with this title."
returns = "result"

Extensions explains how they’re installed and used. The tables below are in the order they usually appear.

Required. What it is.

Field Default Meaning
id required Lowercase letters, digits and _, 2 to 32 characters, starting with a letter. It prefixes every command, tool and event name, and names the repo: pointman-<id>.
name required What people see, up to 60 characters
version required A semantic version: 0.2.0, 1.0.0-beta.1
publisher required Who publishes it, as an id like acme
summary required One line, up to 200 characters
node ">=0.1,<1" The node versions it works with, as a range
platforms [] Where it runs: macos-arm64, macos-x86_64, linux-x86_64, linux-arm64, windows-x86_64. Required when it has [run].

The process the node starts for it, from the package’s folder. Leave it out for a behaviour, or for a service that runs in core rather than on a node. Commands, tools, events, an MCP server, session hooks and credentials all need it.

Field Meaning
command The argv to run, such as ["python", "-m", "tickets"]. For a compiled one, ["bin/<id>", …].
runtime python3.12 (or another python3.x): the node makes an environment from the package’s lockfile. Or binary, for a compiled extension (below).

Compiled extensions (runtime = "binary") ship one build per platform. Each release on GitHub carries one asset per platform in platforms, named <id>-<version>-<platform>.tar.gz, with the extension’s files at its top, the same extension.toml, and the program at bin/<id>. Core refuses a release that’s missing one, and each node fetches the build for its own platform. The node runs bin/<id> from the package’s folder, never a program of that name on your PATH.

Paths whose presence means a machine could use it, per platform: macos, linux, windows. The apps use them to suggest machines (“Installed on studio; add it for the agents there?”). They’re suggestions only.

[detect]
macos = ["/Applications/Blender.app"]
linux = ["/usr/bin/blender"]

What it may touch on the machine. The node holds it to these.

Field Default Meaning
network false It reaches the network
gpu false It uses the GPU
drives_apps [] Other apps on the machine it controls, such as DaVinci Resolve
secrets [] Vault secrets it may use, by name, or every name under a prefix: rota.*
folders [] Folders it reads or writes beyond its own work folder

A JSON Schema (type = "object") for its settings on each machine. The apps draw it as a form, and a machine’s own values go in its agent.toml under [extension_settings.<id>]. Every default must fit its own schema.

[settings]
type = "object"
[settings.properties.threshold]
type = "integer"
minimum = 50
maximum = 100
default = 90
description = "Move new runs off an account once either window is this full (%)"

Work agents can ask a machine for, with run_on_machine or a tool below.

Field Default Meaning
kind required <id>.<verb>, such as tickets.open
title required What people see, up to 60 characters
params required A JSON Schema (type = "object") for its parameters, checked before anything runs
lane none Commands that share a lane run one at a time on a node, such as gpu
cancellable false It can be stopped while it runs
resumable false It saves checkpoints and carries on after the node restarts
ready_when none One field of its status that must be true before core sends it work
outputs [] What it makes, so the apps know how to show it: image, video, sequence, model, page, audio, document, progress

MCP tools for agents, each one making a request of a command. The command’s params are the tool’s input.

Field Default Meaning
name required <id>_<what it does>, such as tickets_open
command required One of its own command kinds
description required What agents are told it does, up to 1,000 characters
returns "accepted" accepted: the request’s id at once. result: wait for the result.

Status it reports to core while it runs.

Field Meaning
name <id>.<noun>, such as tickets.queue
description What it holds

File types it knows, so the apps can preview them and the Mac can open them.

Field Default Meaning
extensions required Like [".blend"]
open_with none The app a Mac opens them in
preview none One of its commands, which makes something every app can show

An MCP server it brings. The node signs in to it with OAuth and makes the calls, and agents’ sessions reach it through the node. An agent gets it with /agent.

Field Default Meaning
url required The server’s Streamable HTTP address
scopes [] OAuth scopes to ask for. None: what the server says.
instructions none What sessions are told about it, if the server says nothing, up to 2,000 characters

Links to its service that the apps draw as pills. See Links as pills.

Field Meaning
kind The service’s name for it, such as page
match What the link looks like, with {placeholders}: https://pages.example.com/@{owner}/{page}
show What the pill shows, in order: title, repo, number, sha, state, checks, lines

Makes it a behaviour: guidance for agents, with no process, added to the wake prompt of each agent it’s switched on for. A behaviour has no [run], [[links]] or [[files]]. See Behaviours.

Field Default Meaning
skill "SKILL.md" The file with the guidance, frontmatter first
clients all three The clients it’s written for: claude, codex, gemini
files [] Other files or folders in the package that agents read when a task needs them, named in the skill by relative path

Hooks into the agent runs its node starts: it’s asked before each run what to add to the run’s environment, and told how the run ended and how its account’s limits stood. Rota picks each run’s account this way.

Field Default Meaning
clients ["claude"] The clients whose runs it hears about
env required The environment variables it may set on a run, such as CLAUDE_CODE_OAUTH_TOKEN. The node drops any other. PATH, HOME and the node’s own variables can’t be set.

Something it needs from a person, such as an API key, drawn by the apps as a form. See Give an extension what it needs.

Field Default Meaning
id required What it is, within the extension
title required What the apps call it, up to 80 characters
help none Where to get the value, up to 400 characters
item required The vault item it’s kept as: <id>.<name>, or <id>.{label} to ask for a label. [permissions] secrets must cover it.
value any text A regular expression the whole value must match
placeholder none A hint in the empty field
needed 1 How many the apps ask for
sign_in false true: it signs the account in itself, and the apps offer Sign in