Configuration
The conceptual model — what config owns versus what the src/ conventions own — is in
Configuration model. This page is the field contract.
Top-level fields
Host-scoped extension keys (claude, codex, cursor, portable) are contributed by target
adapters through declaration merging on AgentBundleConfigExtensions. Extension values must be
strict finite JSON (AB4500), and host-specific values stay in their adapter rather than in
compiler core. The field-by-field list of every adapter-owned key is in
Host-scoped declarations.
Generated type definitions
The config is a TypeScript contract, not a runtime schema: defineConfig accepts an
AgentBundleConfig (or a factory returning one), and validateSource enforces the rules on this
page with structured diagnostics. The exact shapes below are generated from the package source
by TypeDoc on every documentation build, so they cannot drift from the published types.
plugin
package.json is authoritative for release identity. Declare the release version only there:
a plugin.version that disagrees with package.json reports the AB4008 warning, and a release
build with no version anywhere is refused with AB4013 rather than shipping the
0.0.0-dev.<short-revision> development fallback. The field remains only for compatibility and
will be removed under the normal breaking-change policy.
hooks
Keys are the seven canonical events: sessionStart, beforeTool, afterTool, stop,
agentStart, agentStop, workspaceOpen. A value is one entry, or an array of entries, each
either a module path or { handler, tools?, targets?, timeout?, args? }. How each canonical
event and tool selector lowers to a host-native event and matcher is the generated
Event and hook matrix.
The hook result contract is documented in full in Hooks. One
field is worth repeating because it is easy to get wrong: reason is a non-empty string that is
valid only when denying a beforeTool, stop, or agentStop hook, and denying one of those
without a reason fails.
output and runtime
output.distPath is the artifact output directory relative to the project root. The CLI
(build, prepack, dev) defaults it to artifact, because the CLI also runs the package build
and that owns dist/; the programmatic build() defaults to dist unless packageOutputs: true.
The per-invocation --output flag wins, but is subject to the same project-root
containment check; an output path that is absolute or external, has an invalid shape, or lands
in a reserved compiler namespace is unsupported (AB4707–AB4709).
runtime.node is a minimum Node.js version in major.minor[.patch] form. It can only raise the
default floor for generated executables, never lower it, and the selected floor is recorded as
runtime.node in the artifact manifest. The floor itself is described in
Configuration model.
payload
Keys are artifact-root destination directories — one safe path segment outside the compiler-owned namespaces — and values are already-built source directories. Payload trees are copied byte-for-byte and are opaque to the compiler, which cannot rewrite their internal sibling references, so stable names are the correctness contract. Integrity stays content-addressed through the artifact manifest.
evals
Accepts exactly three keys; anything else is rejected.
Provider credential material in the evals block is rejected outright
(EVAL_CREDENTIAL_REJECTED) — Agent Bundle reuses the host CLI's existing signed-in session. See
Security.
dev
Development-only settings that never become part of a built artifact.
tools
The single bundler escape hatch. Both fragments merge last-but-bounded into every bundler config
the framework synthesizes, and the artifact invariant assertions still run after the merge, so a
hatch value that breaks an artifact contract is a hard diagnostic rather than a silent override
(AB472x).
The hatch executes under two bundler engine copies: artifact scripts, MCP entries, hooks, and the
package build compile through Rslib's nested Rsbuild/Rspack, while MCP App views compile through
the workspace-pinned @rsbuild/core. Never construct plugins or perform instanceof checks
against an imported @rspack/core — use the utils argument passed to tools.rspack mutator
functions ((config, { rspack }) => ...), which always hands you the executing engine's own
rspack object.