Plugin format reference
Define portable skills and Farero commands, configuration, private keys, roles and Workflow templates.
Updated 2026-11-10
A package has a root plugin.json manifest and optional skills/<name>/SKILL.md files. The manifest requires the Agent Plugins 1.0 schema identifier and a portable name. Farero-specific declarations live under extensions["ai.farero"], whose current experimental version is "0.1". Its optional displayName supplies the title shown in Farero.
Package boundaries
Ship the complete runnable package. Installation copies and validates files; it does not install dependencies or execute setup scripts. Package paths stay within the archive or source folder. Links, traversal paths and nonportable filename collisions are refused.
A local folder is copied into an immutable revision. A GitHub source identifies a full commit. An HTTPS archive identifies both its URL and SHA-256. A directory source is verified against the installation’s trusted signing keys.
A command declaration
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "hello-plugin",
"version": "0.1.0",
"extensions": {
"ai.farero": {
"version": "0.1",
"config": {
"heading": {
"type": "string",
"default": "Hello",
"maxLength": 80
}
},
"commands": {
"hello": {
"description": "Print a greeting.",
"runtime": "node",
"entry": "./ai.farero/hello.mjs",
"workspace": "required",
"platforms": [
"darwin",
"win32",
"linux"
],
"inputs": {
"name": {
"type": "string",
"required": true,
"maxLength": 80
}
},
"argv": [
{
"config": "heading"
},
{
"input": "name"
}
],
"limits": {
"timeoutMs": 5000,
"outputBytes": 8192
},
"dataDestinations": []
}
}
}
}
}const [heading, name] = process.argv.slice(2)
process.stdout.write(`${heading}: ${name}\n`)
runtime is node. entry points to a file inside the package. workspace is required when the command needs the calling chat’s worktree, or none to use private scratch space. platforms lists darwin, win32 and/or linux; a declaration must still be checked on the platforms you distribute for.
argv is an array of literal strings or single input/config references. Each item becomes one argument, without shell parsing or interpolation. An optional value without a default omits its argument. Read package resources relative to the entry file, since the working directory may be a worktree.
limits.timeoutMs bounds execution time. limits.outputBytes bounds each of stdout and stderr. dataDestinations lists the destinations you send data to for the installation review; Farero does not enforce it as a network sandbox.
Typed inputs and saved configuration
inputs belongs to a command. config belongs to the extension and stores non-secret values. Both accept string, integer and boolean fields. Strings declare maxLength and can add minLength and enum. Integers declare minimum and maximum. Every type may declare required and a type-matching default.
A missing value receives its default when one exists. An empty string is a value; required alone does not forbid it. Use minLength when an empty string must be rejected. Numeric strings, out-of-range integers and unknown field names are refused rather than converted.
Private credentials
Declare each credential under credentials with an optional description, required and maxBytes. A command opts into a credential through stdin.credentials. Users enter the value under Keys in the app; they must not paste it into a chat, CLI option or non-secret config field.
{
"version": "0.1",
"credentials": {
"apiKey": {
"required": true,
"maxBytes": 8192
}
},
"commands": {
"search": {
"stdin": {
"credentials": [
"apiKey"
]
}
}
}
}A bound command receives one JSON document on stdin followed by EOF: {"version":1,"credentials":{"apiKey":"…"}}. Read it once and keep its contents out of stdout, stderr, exceptions and files that other processes can read. Treat logs from third-party libraries with the same care.
Skills and requirements
Place each skill in skills/<name>/SKILL.md with name and description frontmatter. A skill that needs commands declares them under extensions["ai.farero"].skills[<name>].requiresCommands. Optional delegation and browser requirements also belong there. Availability is evaluated per component and per calling chat.
Package instructions and skill files
The ai.farero extension accepts either instructions or instructionsFile for package-wide agent instructions. Use this to explain how a collection of skills works in Farero. The text must be nonempty and at most 20,000 characters; instructionsFile names a UTF-8 file inside the package. Declare only one of the two fields.
An agent calls plugin_guide with plugin to read those instructions and the skill catalog. Short collections also include their skill text. For a larger collection, skillsNote directs the agent to request one skill at a time.
{"plugin":"my-plugin","skill":"my-skill"}A skill read returns SKILL.md in instructions, its full length and nextOffset while text remains. Call again with offset set to nextOffset until the whole file has been read. max_chars chooses a page size from 1,000 to 40,000 characters; the default is 8,000.
The first page lists other files relative to the skill folder in files. Pass one of those paths as file to read it in text, using the same paging. The guide reads reviewed UTF-8 files up to 1 MiB and refuses paths outside the skill folder. Package instructions accompany the first page so an agent can apply them while reading unchanged upstream skills.
Roles and Workflow templates
roles is a map of package role names. A role can provide title, description, instructions or instructionsFile, readOnly, delegation, concurrent, a provider requirement and ordered models. Each model choice names model and may set effort and fast. requires can declare commands, browser and independentFrom role names.
Roles appear as package/role selectors. Compatible user model choices or bindings to local roles are stored separately from the package. They cannot weaken the package’s access or independence requirements.
workflows maps template names to a title, description, ordered roles and optional objective. The first role is the root. Users explicitly start templates through Farero’s managed Workflow system. Each run retains its package revision, saved configuration, template and resolved role choices.
Validation and automation
farero plugins validate ./hello-plugin --json
farero plugins pack ./hello-plugin --out ./hello-plugin.tgz --jsonValidation runs no package code and reports file or component diagnostics. Unknown portable metadata is a warning. A malformed supported Farero declaration is an error. Keep unsupported optional components visible with a reason rather than treating a platform declaration as proof of availability.
In JSON mode stdout contains one receipt and progress goes to stderr. Exit codes are 0 completed, 1 failed, 2 usage, 3 invalid package, 4 refused, 5 app unavailable, 6 accepted and pending, and 7 uncertain. App operations return an ID that automation can observe with inspect --operation. Reuse that ID to recover the original receipt after a lost response.
Use farero plugins --help for the installed CLI’s complete command and option syntax.