Skip to main content

Choose the right extension boundary

Orcacode implements both portable components of Agent Plugins 1.0: Agent Skills under skills/ and MCP servers declared by an optional root mcp.json. Version 1 starts only MCP entries with "type": "stdio". Orcacode also defines lifecycle hooks under its reverse-domain client extension namespace; those hooks are deliberately Orcacode-specific, not a third portable Agent Plugins component.
Standard boundary: Agent Plugins 1.0 standardizes Skills and MCP only. Its client-extension mechanism allows reverse-domain manifest data and directories but assigns them no portable behavior. Orcacode owns and documents io.github.okikorg.orcacode/; other clients may ignore it while continuing to load the portable package. Orcacode still does not start HTTP/SSE plugin transports, run setup scripts, provide a marketplace, or fetch remote packages.

Scaffold a package

plugin init writes source and configuration only and refuses to overwrite a non-empty target. Python requires 3.11 or newer and uses uv with the stable-major MCP Python SDK. TypeScript requires Node 20 or newer, the 1.x MCP TypeScript SDK, Vitest, and esbuild.
The aliases --py and --ts are equivalent. Each scaffold includes an intentionally empty, tracked skills/ directory; add standard skills/<name>/SKILL.md packages as needed. It also includes an empty io.github.okikorg.orcacode/hooks.json; leaving it empty adds no runtime hook work. Orcacode does not directly run a dependency installer. The generated Python MCP launch does run uv with its environment and cache under PLUGIN_DATA, so its first executable test or enabled start may resolve packages there. Run plugin test successfully while online before offline use, or pre-populate that managed uv environment explicitly. Generated manifests use the canonical Agent Plugins 1.0 schema URLs and every MCP entry declares "type": "stdio". A command is a bare executable; ${PLUGIN_ROOT} and ${PLUGIN_DATA} belong in arguments, environment values, or the working directory, not in command.

Validate, test, and register

Paths default to the current directory for validate, test, and install. plugin list reports saved state. Registering the same name and canonical path again is idempotent; the same name from a different path is rejected.

Manage and verify plugins in the TUI

Enter /plugin or /plugin list to open the shared filterable picker. Type to filter, use arrow keys to move, press enter to toggle the selected registration, or press space to reveal actions. Typed forms mirror every CLI command and relative paths resolve from the TUI workspace. The picker deliberately separates saved from live state. live · 1 tool · 1 skill · 2 hooks means all three capability groups are active. restart to load means enablement is saved for the next launch. off next run means current components remain until exit. Use /skills and /mcp for read-only component detail; hook counts remain under /plugin because hooks are lifecycle behavior rather than model-callable tools. At interactive startup, enabled plugin MCP servers connect in the background. The TUI remains usable, but their tools may be unavailable until initialization completes. Connections run up to four at a time, with a 30-second timeout per server.
Process boundary: /plugin test executes bounded MCP and hook probes but does not make those components available to the current agent. Install or enable changes become active only after restarting Orcacode.

Add Orcacode lifecycle hooks

Place the client-owned configuration at io.github.okikorg.orcacode/hooks.json. The document is closed and versioned: {"version":1,"hooks":{...}}. Supported event keys are on_agent_start, before_model, after_model, before_tool, after_tool, on_error, and on_agent_end. Streaming model_delta and native around_tool continuation hooks are intentionally unavailable to subprocess hooks.
Each entry accepts command, optional string-array args, string-map env, cwd, and timeout_ms from 1 through 30000. The default is 5000 ms. Orcacode sends one JSON object containing version, event, plugin, and event-specific payload to stdin. Observation hooks return no stdout or {}. A before_tool hook may return {"decision":"continue"}, {"decision":"deny","reason":"..."}, or {"decision":"rewrite","arguments":{...}}. An after_tool hook may return replacement output and is_error fields.
Failure policy: Invalid output, non-zero exit, timeout, or launch failure from deterministic hooks stops the current agent run; Orcacode never silently bypasses a declared policy hook. on_error and on_agent_end are best-effort terminal observers because the native lifecycle cannot propagate failures from them. Hooks apply to interactive, headless, and spawned subagent execution.

Treat every plugin as local executable code

plugin.json, mcp.json, and hook configuration are visible package data. Never put passwords, API keys, bearer tokens, or private configuration in them. Orcacode clears the ambient environment for plugin children, preserves a small set of runtime essentials, and overlays declared environment values plus its reserved paths. This reduces accidental secret inheritance; it is not a sandbox. Children retain the operating-system permissions of the user running Orcacode, so review source and dependencies before enabling a plugin.
Stdio contract: Reserve stdout for MCP or hook protocol output. Send diagnostics to stderr. Hook output is capped at 1 MiB and input at 2 MiB.
Orcacode resolves PLUGIN_DATA beneath $ORCA_CONFIG_DIR/plugin-data/<plugin-name>/ immediately before an enabled executable component starts. Use it for runtime environments, caches, artifacts, checkpoints, audit logs, and durable state. On Unix, Orcacode creates and re-enforces this directory at mode 0700. On non-Unix systems, protection relies on the containing configuration-tree and user-profile ACL. Make tools and hooks bounded and idempotent where practical. Prefer small, stable JSON schemas. Large binary values belong in contained artifact files, with paths and metadata returned through MCP instead of embedding payloads in JSON.

Model reinforcement-learning runtimes with handles

A stateful simulator or training runtime should expose separate tools such as create, reset, step, and close. create returns an opaque handle; later calls accept that handle instead of trying to serialize an environment, tensor store, worker, or native runtime object. Check cancellation between expensive phases and before committing checkpoint state. Keep caches, checkpoints, replay buffers, and recoverable handle metadata under PLUGIN_DATA. Default to one MCP server per plugin so handles share one supervised process and one lifecycle; split servers only when genuine process isolation or incompatible runtimes require it.