Extension helper API reference
Look up the inputs, fixed identities, build callbacks, Snapshot relationships, and failure behavior of every specific defineX helper.
Import the helpers and Vector types on this page from @evilkiwi/vector. Each helper captures an extension identity when called. Most helpers also store a synchronous build(context) callback. Root helpers receive the no-config Context; builder methods receive their builder-bound Context<RuntimeConfig, Computed>. The callback returns the exported build type, which excludes identity fields supplied by Vector. defineSkill() can instead capture one External Skill descriptor.
The remaining host fields are owned by the OpenCode 2 packages pinned in Vector’s package manifest. Use those declarations and Vector’s exported build types instead of copying host shapes.
Omit a callback-built extension
Every domain-specific Build alias on this page accepts optional Vector metadata under $vector. Set $vector.disabled to exactly true to omit that extension from the candidate Snapshot:
import { defineCommand } from '@evilkiwi/vector';
export const review = defineCommand({
name: 'review',
build: ({ cwd }) => ({
template: 'Review this change.',
$vector: { disabled: cwd.endsWith('/readonly') },
}),
});
Every selected callback still runs once. Vector checks the returned metadata after the callback, omits the extension before Snapshot preflight only when $vector.disabled === true, and strips $vector from every included host value. Omission does not cascade to dependent entries. Existing Snapshot checks reject a default or materialized extension that references an omitted entry.
This metadata applies to agents, commands, catalog providers, models, integrations, integration methods, MCP servers, references, Inline Skills, tools, and websearch providers. External Skills use descriptors rather than callbacks and do not accept $vector. It also does not apply to defineVector(), computeContext, Instruction Files, or default selectors.
Host-native states remain distinct. MCP disabled registers an inactive server, catalog provider activation controls host activation, and model enabled controls host model availability. None of these fields omits its extension; use $vector.disabled for omission.
Agent, catalog, and model helpers
| Helper | Fixed identity fields | Extension Plan field | Build result | Snapshot checks |
|---|---|---|---|---|
defineAgent() |
id |
agents |
AgentBuild |
Agent IDs are unique; defaultAgent names an agent in the Snapshot. |
defineCatalogProvider() |
id |
catalogProviders |
CatalogProviderBuild |
Provider IDs are unique. |
defineModel() |
id, providerID |
models |
ModelBuild |
Provider/model keys are unique and the provider exists in the Snapshot. |
defaultModel must name an enabled model whose provider is present and enabled in the Snapshot. It cannot select a variant because the pinned host setter accepts only a provider and model.
declare function defineAgent(definition: { id: string; build(context: Context): AgentBuild }): AgentDefinition;
declare function defineCatalogProvider(definition: {
id: string;
build(context: Context): CatalogProviderBuild;
}): CatalogProviderDefinition;
declare function defineModel(definition: {
id: string;
providerID: string;
build(context: Context): ModelBuild;
}): ModelDefinition;
Command, skill, and reference helpers
| Helper | Fixed identity fields | Extension Plan field | Build result | Snapshot checks |
|---|---|---|---|---|
defineCommand() |
name |
commands |
CommandBuild |
Command names are unique; an optional agent names an agent in the Snapshot. |
defineSkill() |
id |
skills |
SkillBuild or one External Skill descriptor |
Skill IDs are unique. |
defineReference() |
name |
references |
ReferenceBuild |
Reference names are unique. |
declare function defineCommand(definition: { name: string; build(context: Context): CommandBuild }): CommandDefinition;
declare function defineSkill(
definition:
| {
id: string;
build(context: Context): SkillBuild;
external?: never;
}
| {
id: string;
build?: never;
external:
| { type: 'local'; path: string }
| {
type: 'managed';
manager: 'skills';
source: string;
ref?: string;
sync?: 'when-missing' | 'always';
};
},
): SkillDefinition;
declare function defineReference(definition: {
name: string;
build(context: Context): ReferenceBuild;
}): ReferenceDefinition;
An Inline Skill uses { id, build } and keeps the existing synchronous behavior. A Local Skill and Managed Skill use { id, external }; build and external are mutually exclusive, and each definition resolves one skill.
Local Skills
external.path names the exact skill directory. Use an absolute path or a path beginning with ~/. Other relative forms fail activation. Vector expands ~/, resolves symlinks, validates the canonical directory, and uses its canonical SKILL.md file path as the skill location.
import { defineSkill } from '@evilkiwi/vector';
export const review = defineSkill({
id: 'review',
external: { type: 'local', path: '~/team-skills/review' },
});
Managed Skills
The managed descriptor uses the exact skills manager. source accepts GitHub owner/repo, credential-free remote Git and HTTP(S) sources supported by the manager, including GitLab repositories without .git, HTTPS skills.sh, direct skill files, and archives. GitHub shorthand normalizes to GitHub. Local paths, file: sources, URL credentials or query parameters, embedded #ref, and embedded @skill selectors fail activation. Ambient SSH authentication remains available for SSH sources.
Pass a Git ref through the separate ref field only for a remote Git source. The manager does not apply refs to skills.sh, direct skill files, or archive downloads, so Vector rejects those combinations. Vector always passes the definition id as the selected skill. sync defaults to when-missing; always requests a mutating update on every activation.
import { defineSkill } from '@evilkiwi/vector';
export const review = defineSkill({
id: 'review',
external: {
type: 'managed',
manager: 'skills',
source: 'acme/team-skills',
ref: 'main',
sync: 'when-missing',
},
});
Managed Skills use a user cache shared across plugins and projects. A valid when-missing entry bypasses manager execution. Missing or invalid entries repair under a per-skill lock. Concurrent waiters consume the preceding attempt’s success or failure without repeating remote work, while a later independent always activation performs a new staged update. Any External Skill failure prevents all host transform registration. Vector does not expose a general installer or CLI, prune the cache, watch sources, or promise reader-atomic replacement.
The manager may sanitize its installed directory name. Vector requires exactly one staged skill directory, renames it to the exact definition id, and then applies canonical basename and frontmatter validation. This preserves IDs with uppercase letters, spaces, or Unicode without adding broader Agent Skills naming rules.
External Skill files
The canonical directory basename and parsed frontmatter name must both exactly equal the definition id. description is required and must be a non-empty string. Vector preserves the Markdown body and uses the canonical absolute SKILL.md file path as the location.
Top-level slash accepts a boolean. Namespaced metadata values override it: opencode/slash and opencode/autoinvoke accept booleans or trimmed, case-insensitive true and false strings. Top-level autoinvoke is ignored, as are other unknown fields. Vector does not apply broader Agent Skills naming or length rules.
Web search helper
declare function defineWebSearchProvider(definition: {
id: string;
build(context: Context): WebSearchProviderBuild;
}): WebSearchProviderDefinition;
Select the result in ExtensionPlan.webSearchProviders. IDs are unique. A non-false defaultWebSearchProvider names one of these providers. A provider execute() callback may return results directly or by promise.
Integration helpers
declare function defineIntegration(definition: {
id: string;
build(context: Context): IntegrationBuild;
}): IntegrationDefinition;
Select the result in ExtensionPlan.integrations. Integration IDs are unique.
defineIntegrationMethod() accepts four method variants:
type |
Additional fixed field | Build result member |
|---|---|---|
oauth |
id |
OAuth member of IntegrationMethodDefinition |
command |
id |
Command member of IntegrationMethodDefinition |
key |
None | Key member of IntegrationMethodDefinition |
env |
None | Environment member of IntegrationMethodDefinition |
Every method also fixes integrationID. Select it in ExtensionPlan.integrationMethods. The target integration must exist in the same Snapshot, and each integration/type/method identity must be unique. OAuth authorization, completion, and refresh callbacks may return credentials directly or by promise.
MCP server helper
declare function defineMCPServer(definition: {
name: string;
build(context: Context): MCPServerBuild;
}): MCPServerDefinition;
Select the result in ExtensionPlan.mcpServers. MCP server names are unique.
Tool helper
declare function defineTool<
Input extends Tool.ValueSchema = Tool.ValueSchema,
Output extends Tool.ValueSchema | undefined = Tool.ValueSchema | undefined,
>(definition: {
name: string;
build(context: Context): ToolBuild<Input, Output>;
}): ToolDefinition<Record<never, never>, Input, Output>;
Select the result in ExtensionPlan.tools. The name is normalized by replacing characters outside letters, digits, _, and - with _. The normalized value starts with an ASCII letter and contains at most 64 characters. A name that cannot meet that contract throws synchronously. Namespace segments are provider-safe. Direct tool name execute is reserved when CodeMode is explicitly disabled. Duplicate exposed names fail preflight.
Tool execute() receives validated input and ToolExecutionContext, including sessionID, agent, messageID, id, and async progress(update). It may return a result directly or by promise.
Builder-bound helpers
createVectorBuilder() returns the same specific helpers bound to inferred Runtime Configuration and computed Context types. These methods do not declare their own Runtime Configuration generic. defineTool() retains its Input and Output generics. Root helpers remain available as no-config, no-computed-context helpers. See defineVector(), createVectorBuilder(), and Context.