Configuration model
agent-bundle.config.ts at the project root is the whole declarative surface. It is one small
flat object holding project identity, target selection, and the policy no route file can own.
Everything structural — which Skills exist, which MCP routes exist, which scripts ship — comes
from the src/ conventions unless you override it here.
defineConfig is an identity helper: it exists to type the object, not to transform it.
Project identity
plugin names the plugin as hosts will see it:
package.json is authoritative for release identity. A declared plugin.version that disagrees
with it reports the AB4008 warning, and a release build with no version anywhere is refused
outright (AB4013) rather than packaging the development fallback. Plugin code reads its own
identity from agent-bundle/meta instead of a hand-maintained version module.
Targets
targets selects the artifact layouts the build emits:
The portable standard packages only Skills and MCP servers, so rules, commands, and hooks are honestly unavailable on that target rather than silently dropped. Claude Code consumes the standard only through CLI translation, which is why its dedicated target remains necessary.
The full surface
Host-scoped extension keys — claude, codex, cursor, portable — are contributed by the target
adapters through declaration merging, so a host-specific value stays in its own adapter instead
of leaking into compiler core. Ordinary projects need no extension key at all.
Host-scoped declarations
Every host key is optional and every field inside it is optional. claude and codex extend
the shared AgentBundleHostConfig, whose single field nativeHooks names a project-authored,
target-native hook document (hooks.json) the adapter validates and merges beside the compiled
hooks. The adapter-owned fields are:
Everything else about a Cursor plugin is derived from the cross-host model. The host capability tables in the host reference record which of these surfaces each pinned host version actually honours.
Two Claude Code surfaces deserve a closer look because their contracts are narrower than their names suggest:
claude.lspServers— emitted as a plugin-root.lsp.jsonby theclaudetarget and the Claude half ofplugin. Path tokens expand only incommand,args,env, andworkspaceFolder. agent-bundle does not include the language-server binary; install it separately so the declared command is available onPATH. Codex, Cursor, and the portable format do not receive this configuration.claude.settings— emitted as a plugin-rootsettings.jsonthat Claude Code applies when the plugin is enabled. The pinned contract supports onlyagentandsubagentStatusLine, and any other key is rejected rather than shipped as a default Claude Code would silently ignore. No path tokens are expanded here, becausesettings.jsonis absent from the host's placeholder-substitution table. Declaringagentalso raises a warning while the pluginagents/component is deferred: the referenced agent has to reach the plugin root some other way, such as a prebuilt payload.
Runtime floor
Generated executables target Node.js 22.12 or newer by default. runtime.node raises that floor
— it can never be lowered — and the selected floor is recorded as runtime.node in the artifact
manifest.
JSX means rendering
Structure lives in config and conventions; JSX appears only where something is rendered. An
executable route is one async default Server Component that does the work and returns Agent.*
nodes, and it calls await agent() only when it needs host, session, actor, workspace,
capability, or state context. There is no public execute/render split, and a plain .ts
route is never wrapped in React behavior.
Authorable surfaces
- Skills — Markdown Skills, their resources, and rendered Skill sources.
- Hooks — the seven canonical lifecycle events and tool selectors.
- MCP servers and Apps — generated route servers, handwritten stdio entries, and browser Apps.
- Scripts and assets — artifact scripts and static files.
- Package entries —
bin,lib, the routed CLI, and the bundler escape hatch.