CapaKit CLI Docs#
CapaKit CLI runs, tests, packages, and shares local-first AI app Kits.
Current alpha scope:
- macOS only.
- workload toolchains: Bun only.
Known limitations:
- macOS sandbox is currently too strict for some workloads, known not to work:
- Chromium: requires too many permissions, probably will support once added VM based sandbox backend.
Quick Start: macOS#
The public alpha currently targets macOS and Bun workloads.
Install#
Install CapaKit:
curl -fsSL https://capakit.com/install.sh | sh
The installer places capakit under ~/.capakit/bin by default and updates your shell profile unless
CAPAKIT_NO_MODIFY_PATH=1 is set.
Restart your shell if capakit is not found immediately:
capakit --version
Run a Kit#
Run the hello-world Kit from GitHub:
capakit run https://github.com/capakit/hello-world-demo-kit
CapaKit downloads the Kit, prepares the workload, starts the local runtime, and prints the local URLs you can open or call.
Keep the command running while you use the app. Press Ctrl-C to stop it.
Run as a Skill#
AI app Kits that expose MCP can be used as skills. CapaKit generates the provider-specific skill structure, including agent instructions and a command entrypoint for calling the Kit's MCP tools.
# Run the hello-world Kit as a Codex skill:
capakit run https://github.com/capakit/hello-world-demo-kit --global-skill codex
# Use another terminal to run the "hello-world" MCP tool
~/.codex/skills/hello-world/hello-world hello-world
> hello world
Supported skill providers:
- global skill installs: (
--global-skill <provider>)codex: installs in~/.codex/skills/<skill-name>/.claude: installs in~/.claude/skills/<skill-name>/
- "project" skill installs: (
--project-skill <provider> --project-root <project>)portable: installs in<project>/<skill-name>/claude: installs in<project>/.claude/skills/<skill-name>/.
Generated skill files are temporary and are removed when capakit run exits.
Edit a Local Kit#
Clone a Kit, test it, then run it:
git clone https://github.com/capakit/hello-world-demo-kit
cd hello-world-demo-kit
capakit test
capakit run
Use capakit exec [WORKLOAD] -- <COMMAND> to safely run workload commands like bun add <package>.
Where CapaKit Writes#
CapaKit uses these host paths:
~/.capakit/bin: default install location for thecapakitexecutable.~/.capakit: CapaKit home. Stores materialized package sources, runtime state and persistent secret stores.~/.cache/capakit: persistent build cache.<kit>/_state/: generated state for a local Kit.
Storage usage:
capakit storage status
capakit storage status --detailed
Working With Coding Agents#
CapaKit is designed to be used with coding agents. You do not need to know the full CLI before asking an agent to build
something. Tell the agent to use capakit to create or edit a CapaKit AI app Kit, then describe the app you want in
plain product terms.
Useful words to use:
- AI app Kit: a CapaKit project the agent can create, edit, test, run, and package.
- Web UI: a local browser app, usually for forms, dashboards, workflows, uploads, or visual output.
- Tool: a named action an AI assistant can call, such as
summarize_file,search_docs, orextract_invoice_fields. - MCP server: a set of tools exposed to AI assistants and coding agents.
- Skill: a tool app installed into an agent environment, such as a Codex skill.
The most important instruction is simple: ask the coding agent to use CapaKit. CapaKit provides agent instructions that the agent knows how to follow.
Prompting Agents#
Start with the outcome. Mention the user-facing surface only when you already know it.
Create a web app:
Use capakit to create a new AI app Kit called invoice-helper.
I want a web UI where I can upload invoice text and see extracted fields: vendor, date, total, and line items.
Please test it and leave clear run instructions.
Create tools for an assistant:
Use capakit to create an AI app Kit that works as an MCP server.
It should provide a tool named extract_invoice_fields that accepts invoice text and returns structured invoice fields.
Please make the tool description clear enough for an AI assistant to choose it correctly.
Modify an existing Kit:
This is an existing CapaKit AI app Kit.
Add a web UI for reviewing the results, keep the existing tools working, run the CapaKit tests, and update the README.
Glossary#
These terms appear throughout the docs. You do not need to memorize them before using CapaKit.
- AI app: the app you build, run, test, and share with CapaKit. It can be a web UI, assistant tools, or both.
- Kit: the project or package for one AI app. A Kit can be a local directory, a GitHub repository, or a
.capakitarchive. - Workload: one isolated code process inside a Kit, such as Bun code that serves a web UI or MCP tools.
- Tool: a named action an AI assistant can call, such as
search_docsorextract_invoice_fields. - Agent protocols: standard ways for assistants, agents, and apps to talk to each other.
- MCP: exposes tools and context that an assistant or coding agent can call.
- A2A: exposes an agent service with an agent card and callable skills.
- OpenAI-compatible: exposes a model-style API that existing OpenAI-compatible clients can call.
- Public path: the local path CapaKit exposes for a protocol surface, such as
/uifor a web UI or/mcpfor tools. - CapaKit runtime: the CapaKit process that orchestrates an AI app.
- Local models: AI models that run on your machine instead of a cloud API.
Security#
CapaKit treats Kits and their workloads as code that should run with explicit boundaries. The local runtime prepares the Kit, starts workload processes, routes requests between them, and limits what each workload can see or call according to the Kit manifest.
At a high level, the runtime isolation boundaries:
Kit
AI app package with host-exposed public paths
Workloads
Code processes that implement the app
Connected through an isolated workload service mesh
Workload
Sandboxed runtime process, such as `bun run start`
Access to its workload files and declared resources
Each workload full lifecycle is sandboxed from the host, including dependency installs such as bun install and runtime
commands such as bun run start.
Secrets#
CapaKit has two secret stores:
- Kit secrets: per-Kit secrets that are exposed only to configured workloads, not limited to CapaKit-managed integrations.
- Vault secrets: protected secrets that can be shared between Kits, safely used only with trusted CapaKit-managed integrations (Relays).
Secret values are not stored in capability.yml. The manifest declares the secret key, usage text, and which store it
belongs to. The value is provided by prompting the user when the Kit starts or via CLI in advance, if the secret value
is not already available.
Kit Secrets#
Kit secrets are for values a workload may need directly, such as an API key used by a Kit's own source code.
The secret values are stored in encrypted form in CapaKit home (~/.capakit).
Workloads do not receive any Kit secret automatically. A workload record in the manifest must list the secret in its exposed secrets. At runtime, the workload can resolve only those exposed secrets through the runtime workload SDK.
Important: Kit secrets are intentionally available to workload code that declares access. Treat any Kit that receives a Kit secret as code that can use that secret.
Vault Secrets#
Vault secrets are protected secrets stored in the global secret store under ~/.capakit. They are intended for trusted
CapaKit-managed integrations, such as secure exit nodes (Relays), rather than ordinary Kit source workloads.
Source workloads cannot expose vault secrets. If a workload is added with a vault secret, CapaKit rejects it; workload code can only use Kit secrets. This keeps the user's higher-trust vault separate from untrusted or semi-trusted Kit code.
Isolation#
CapaKit isolation is manifest-driven. The Kit declares what each workload may use, and the CapaKit runtime turns those declarations into sandbox policy.
Resources#
Workload resource access is explicit and granular:
- Environment:
- host environment is not inherited.
- CapaKit constructs workload and toolchain-specific env when starting it.
- Filesystem:
- by default workloads have access to:
- workload root
- isolated per-instance home/cache/tmp directories
- CapaKit-owned toolchain roots
- CapaKit-owned shared toolchain cache roots
- manifest-declared host mounts, granted to each workload as read-only or read-write
capakit execandcapakit run --mode sourcerun root Kit workloads from real source roots
- by default workloads have access to:
- Network:
- workloads communicate with other workloads through the CapaKit service mesh
- workload-to-workload access is limited to manifest-declared connections
- prepare commands default to full network access for dependency installation
- start commands default to no IP networking
- workload commands can override the default with
network: none,network: loopback, ornetwork: full
- Secrets:
- workload code can resolve only exposed Kit secrets
- Vault secrets are reserved for trusted CapaKit-managed integrations
- RPC:
- CapaKit service-mesh RPC links use mTLS with SPIFFE-style service identities
Run Modes#
CapaKit has two main local run modes:
- Source mode: runs root Kit workloads from local source roots.
- Managed mode: builds workload artifacts and runs from those artifacts.
Imported Kit dependencies use managed artifact execution by default.
Sandbox Backends#
CapaKit translates the same workload isolation model into different runtime backends.
macOS Seatbelt#
On macOS, CapaKit runs workload commands through a generated Seatbelt policy.
The generated policy:
- starts from default deny
- allowlists required system files, devices, runtime libraries, and process primitives
- allowlists only the workload roots, CapaKit toolchain/cache roots, runtime home/cache/tmp dirs, host mounts, and IPC paths needed by that workload
- grants host mounts according to the workload's read-only or read-write manifest grant
- exposes only constructed workload env; the host environment is not inherited
- gives prepare commands full network access by default
- gives start commands no IP networking by default
- allows commands to override the default with
network: none,network: loopback, ornetwork: full - enables Metal GPU access only when the workload declares the Metal GPU capability
Set CAPAKIT_DEBUG_SEATBELT_POLICY=1 to have CapaKit write the generated Seatbelt policy path to stderr for debugging.
Relays#
Relays are CapaKit-managed exit workloads for calling trusted external providers.
Instead of injecting secrets such as API keys into potentially vulnerable source workloads, Relay exit nodes are CapaKit-native trusted services that attach headers in transit and direct connections to preconfigured URLs.
The source workload talks to the Relay like any other workload. The workload SDK provides provider clients that are already routed through the Relay.
This gives the Kit a narrower trust shape:
- source workload code does not read the provider API key
- the provider key can live in the global vault secret store
- external provider access is represented as a workload connection in
capability.yml - the Relay is a CapaKit-managed runtime attachment, not arbitrary Kit source code
Relay workloads are relay-only. A workload cannot mix source runtime code and relay attachments.
Example:
vault_secrets:
- key: openai_api_key
usage: OpenAI API key
workloads:
app:
connections:
- openai-exit
endpoints:
- mcp
runtime:
source:
toolchain: bun
prepare:
command: bun install
start:
command: bun run src/index.ts
openai-exit:
endpoints:
- oaic
runtime:
attachments:
relays:
- kind: mesh_to_open_ai
endpoint: oaic
api_key_secret: openai_api_key
Related manifest section: Workloads.
In this example, app can call the openai-exit workload because it is listed under connections. The Relay resolves
openai_api_key from vault secrets and uses it only inside the managed Relay path.
Relays are not a general-purpose proxy. They are provider-specific adapters with explicit authentication behavior.
Providers#
CapaKit currently supports these Relay kinds:
mesh_to_open_ai- upstream host:
api.openai.com - auth header written by Relay:
Authorization: Bearer <api-key> - endpoint protocol:
oaic
- upstream host:
mesh_to_anthropic- upstream host:
api.anthropic.com - auth header written by Relay:
x-api-key: <api-key> - default Anthropic version header:
anthropic-version: 2023-06-01when the request does not set one - endpoint protocol:
http
- upstream host:
mesh_to_google_ai_studio- upstream host:
generativelanguage.googleapis.com - auth header written by Relay:
x-goog-api-key: <api-key> - endpoint protocol:
http
- upstream host:
The Relay strips caller-supplied provider auth headers before forwarding, then writes the configured provider auth header from the vault secret.
Kit Anatomy#
A Kit is the source or package for one CapaKit AI app.
The root file is capability.yml. It declares the app name, workloads, public paths, options, dependencies, host
mounts, secrets, and connection policy. Workload source code lives under workloads/<workload-name>/.
Kits can come from these sources:
- Local source directory:
- editable Kit root containing
capability.yml - works with
run,test,exec,kit package,kit clean,kit workloads, andkit secrets
- editable Kit root containing
- Local
.capakitarchive:- packaged Kit created by
capakit kit package - runnable with
capakit run - not editable, testable, or packageable in place
- packaged Kit created by
- GitHub repository URL:
- remote Kit source
- runnable with
capakit run - not editable, testable, or packageable in place
Examples:
capakit run .
capakit run ./hello-world.capakit
capakit run https://github.com/capakit/hello-world-demo-kit
When CapaKit runs a packaged or remote source, it materializes the Kit under CapaKit-managed storage. Edit the original source directory when you want to change the Kit.
Breakdown of Kit files:
AGENTS.md: Kit-local instructions for coding agents.capability.yml: required runtime manifest.capability-test.yml: optional test manifest forcapakit test.tests/: optional fixture directories used bycapakit test.workloads/<workload>/: workload source roots.README.md: user-facing usage notes for the Kit..gitignore: excludes generated state and dependency/build output._state/: generated local CapaKit state. (Do not edit it.)
AGENTS.md#
Points coding agents to capakit agents-md print.
capability.yml#
capability.yml is the source of truth for how the Kit runs. It declares the app name, options, workloads, public
paths, host mounts, secrets, dependencies, and workload-to-workload connection wiring.
Example: hello-world kit
version: '1'
name: hello-world
workloads:
hello:
endpoints:
- mcp
runtime:
source:
toolchain: bun
prepare:
command: bun install
start:
command: bun run src/index.ts
expose:
- path: /mcp
target: hello # -> workloads.hello
default_mcp: true # some CLI commands, such as run, do not need an explicit MCP endpoint
endpoints:
- mcp # points to the MCP endpoint -> workloads.hello.endpoints
Workloads#
Each workloads key names one addressable workload and maps to workloads/<name>/ for source workloads.
A workload entry can be a source runtime, a CapaKit-managed Relay runtime, an imported workload, or a set of runtime variants. Source workloads declare the protocol surfaces they serve, the runtime commands CapaKit should run, and the explicit resources they may use.
workloads:
app: # workload id
connections:
- tools # outbound peer connection
endpoints: # expose running services
- http
- mcp # shorthand format: `path: /mcp` and `protocol: mcp`
- protocol: mcp # extended format, can provide a custom path
path: /agent
config:
timeout_ms: 30000
mounts:
- uploads # mount that was declared in host_mounts
- mount_mid: cache
access: read_write
exposed_secrets:
- vendor_api_key # secret that was defined in kit_secrets
runtime:
source:
toolchain: bun
prepare:
command: bun install
network: full
hydrate:
command: bun run hydrate
env:
CACHE_MODE: warm
env_from_options:
MODEL_NAME: model # from top-level `options`
network: loopback # none | loopback | full
start:
command: bun run src/index.ts
env:
NODE_ENV: production
env_from_options:
APP_MODE: mode
network: none
capabilities:
gpu: metal
tools:
endpoints:
- mcp
runtime:
source:
toolchain: bun
prepare:
command: bun install
start:
command: bun run src/index.ts
Relay workloads are CapaKit-managed runtime attachments. They are useful for trusted provider exits, where the source workload should call a provider without reading the provider secret directly.
vault_secrets:
- key: openai_api_key
usage: OpenAI API key
workloads:
app:
connections:
- openai-exit
endpoints:
- mcp
runtime:
source:
toolchain: bun
prepare:
command: bun install
start:
command: bun run src/index.ts
openai-exit:
endpoints:
- oaic
runtime:
attachments:
relays:
- kind: mesh_to_open_ai
endpoint: oaic
api_key_secret: openai_api_key
Imported workloads point at a public path exposed by a dependency Kit. The importing Kit can connect to or expose the imported workload like any other workload.
dependencies:
shared-tools:
source:
package: https://github.com/capakit/shared-tools-kit
version: main
workloads:
shared-tools:
import:
dependency: shared-tools
exposed_path: /mcp
Variant workloads declare multiple runtime implementations under one workload id. Keep variants within the same trust shape: do not mix source variants and relay variants under one workload.
workloads:
model:
endpoints:
- oaic
variants:
default:
runtime:
source:
toolchain: bun
prepare:
command: bun install
start:
command: bun run src/local-model.ts
gpu:
runtime:
source:
toolchain: bun
prepare:
command: bun install
start:
command: bun run src/gpu-model.ts
capabilities:
gpu: metal
Common workload fields:
endpoints: protocol endpoints served by the workload. Supported endpoint protocols arehttp,mcp,a2a, andoaic.connections: workloads this workload may call through the CapaKit service mesh.mounts: Kit-level host mounts granted to this workload.exposed_secrets: Kit secrets this workload may resolve through the workload SDK.
Example Kits:
- hello-world-demo-kit capability.yml: minimal Bun MCP source workload.
- local-image-tagger-demo-kit capability.yml: source workload with HTTP and MCP endpoints, host mounts, and an imported local model dependency.
- llama-cpp-local-kit capability.yml:
source workload with
hydrate, host mounts, options, GPU capability, and MCP/OAIC endpoints.
Expose#
expose maps host-reachable paths to workload endpoints.
expose:
- path: /ui
target: app
endpoints:
- http
- path: /mcp
target: app
endpoints:
- mcp
default_mcp: true
Set exactly one default_mcp: true when the Kit exposes a primary MCP endpoint for capakit mcp or skill installs.
Example Kits:
- hello-world-demo-kit capability.yml:
exposes
/mcpas the default MCP endpoint. - local-image-tagger-demo-kit capability.yml:
exposes both
/mcpand/from the same workload.
Host Mounts#
Declare host mounts at the Kit level, then opt workloads into them:
host_mounts:
models:
usage: Local model files
access: read_only # read_only | read_write
workloads:
app:
mounts:
- models
Bind host paths at run, test, MCP, or exec time:
capakit run --mount models=~/.capakit/models
Mount access defaults to read_only. A workload can request narrower or equal access, but not broader access than the
top-level mount declaration allows.
Example Kits:
- local-image-tagger-demo-kit capability.yml: read-only image input mount plus read-write model cache mount.
- stable-diffusion-local-kit capability.yml: read-write model and binary cache mount used during hydration and runtime.
Dependencies#
Kit dependencies let one Kit import a public path exposed by another Kit. A dependency can come from any supported Kit source.
Dependency Kit:
expose:
- path: /mcp
target: tools
endpoints:
- mcp
Consumer Kit:
dependencies:
shared-tools:
source:
package: https://github.com/capakit/shared-tools-kit
version: main
workloads:
tools:
import:
dependency: shared-tools
exposed_path: /mcp
Use options, mount_bindings, and secret_bindings under a dependency when the dependency Kit requires configured
inputs from the parent Kit.
Example Kits:
- kids-storybook-creator-demo-kit capability.yml: imports both llama.cpp and stable-diffusion local Kits, passing options and mount bindings.
- realtime-voice-demo-kit capability.yml: imports llama.cpp and connects it to local ASR/TTS workloads.
Secrets#
kit_secrets are for values source workload code may use. A workload must list a Kit secret in exposed_secrets before
it can resolve the value.
vault_secrets are for trusted CapaKit-managed integrations such as Relays. Source workloads cannot expose vault
secrets.
kit_secrets:
- key: vendor_api_key
usage: Vendor lookup API key
workloads:
app:
exposed_secrets:
- vendor_api_key
Secret values are not stored in capability.yml.
Options#
options declares typed Kit inputs that can be reused elsewhere in the manifest. Options are useful when the same Kit
needs small configuration differences without editing workload code.
options:
model:
kind: enum
default: small
enum_values:
- small
- large
description: Model profile to use
cache_enabled:
kind: boolean
default: true
description: Enable workload cache behavior
gpu:
kind: enum
default: none
enum_values:
- none
- metal
description: Optional GPU capability
workloads:
app:
endpoints:
- mcp
runtime:
source:
toolchain: bun
prepare:
command: bun install
start:
command: bun run src/index.ts
env_from_options:
MODEL_PROFILE: model
CACHE_ENABLED: cache_enabled
model:
endpoints:
- oaic
runtime:
source:
toolchain: bun
prepare:
command: bun install
start:
command: bun run src/model.ts
capabilities:
gpu:
from_option: gpu
Option kinds are string, number, boolean, enum, and path. Enum options may declare enum_values.
Common option fields:
kind: required option type.default: optional default value. The value must matchkind.required: settruewhen the Kit must receive a value if no default is declared.enum_values: allowed values forkind: enum.description: user-facing helper text forcapakit kit infoand generated guidance.secret: metadata for display and guidance. Usekit_secretsorvault_secretsfor actual secret values.scope: optional display metadata, usuallypublicorinternal.
Options can be referenced from workload command env_from_options, dependency options, and option-backed capability
fields such as runtime.capabilities.gpu. If a manifest references an unset option, CapaKit rejects the Kit.
dependencies:
shared-tools:
source:
package: https://github.com/capakit/shared-tools-kit
version: main
options:
model:
from_option: model
cache_enabled: true
Example Kits:
- llama-cpp-local-kit capability.yml: model, hydration, context, thread, and GPU options wired into workload env and capabilities.
- stable-diffusion-local-kit capability.yml: model, backend, sampling, and hydration options wired into prepare/start commands.
- kids-storybook-creator-demo-kit capability.yml: parent Kit options passed through to dependency Kits and workload env.
capability-test.yml#
capability-test.yml is the test suite consumed by capakit test. Tests can call MCP tools, send HTTP requests, or run
exec preflight commands against prepared workload artifacts.
Example:
tests:
- id: extract-fields
test: extracts invoice fields
exposed_path: /mcp
tool: extract_invoice_fields
inputs:
text: "Invoice total: 42.00"
validations:
- $.total.eq(42)
- $.vendor.exists()
- id: ui-health
test: web UI returns health JSON
kind: http
target:
workload: app
endpoint: /http
request:
method: GET
path: /health
validations:
- $.ok.eq(true)
- id: typecheck
test: workload typechecks
kind: exec
workload: app
command: bun run build
validations:
- $.exit_code.eq(0)
Example test manifests:
- hello-world-demo-kit capability-test.yml: MCP structured result validation and exec typecheck.
- local-image-tagger-demo-kit capability-test.yml: MCP test with fixture-backed host mount input.
- stable-diffusion-local-kit capability-test.yml: HTTP test against a workload-local test endpoint plus exec typecheck.
- realtime-voice-demo-kit capability-test.yml: HTTP test covering multiple connected workloads and generated result assertions.
Test Cases#
tests may be a list of cases, or the file may contain a single case. Test kind is inferred when possible:
toolmeans MCP.commandmeans exec.- otherwise the case is HTTP.
MCP and HTTP tests can target an existing public exposed_path, or they can declare target.workload and
target.endpoint. Target-based tests create a temporary test expose for that case.
Exec tests run before live HTTP/MCP tests. They execute against prepared workload artifacts, so they check the managed runtime shape rather than only the source tree.
Fixtures#
Test fixtures live under tests/<test-id>/<mount-id>/. When a test runs, CapaKit auto-binds each fixture directory to
the matching declared host mount unless the same mount was explicitly passed with --mount.
Example:
tests/
extract-fields/
uploads/
invoice.txt
The id field controls the fixture directory name. Without id, CapaKit derives a slug from the test name.
Assertions#
Assertions are JSON-path expressions evaluated against the test result:
- MCP: the MCP tool result's
structuredContentorstructured_contentwhen present, otherwise the full MCP result. - HTTP: the parsed JSON response body.
- Exec: a CapaKit-generated result object for the completed preflight command.
MCP result value:
{
"total": 42,
"vendor": "ACME"
}
Generated MCP tools usually return structuredContent, so validations address the structured fields directly:
validations:
- $.total.eq(42)
- $.vendor.exists()
If a tool returns no structured content, validations run against the full MCP result object. For example:
{
"content": [
{
"type": "text",
"text": "done"
}
]
}
MCP tool results with isError or is_error are treated as failed tests before validations run.
HTTP result value:
{
"ok": true,
"items": [
{
"id": "invoice-1",
"total": 42
}
]
}
HTTP validations address the response JSON body:
validations:
- $.ok.eq(true)
- $.items.lenGte(1)
- $.items[0].total.eq(42)
The response body must be JSON. An empty response body is treated as null. HTTP responses with status 300 or higher
fail before validations run.
Exec result value:
{
"exit_code": 0,
"target_count": 1,
"targets": [
{
"workload": "app",
"variant": "default",
"artifact_root": "/path/to/prepared/artifact",
"command_root": "/path/to/command/root"
}
]
}
Exec validations address that generated object:
validations:
- $.exit_code.eq(0)
- $.target_count.eq(1)
- $.targets[0].workload.eq("app")
- $.targets[0].variant.eq("default")
Exec tests only produce a result object when the command exits successfully. A non-zero command exit fails the test before validations run.
Supported assertion operators:
$.field.exists()
$.field.notNull()
$.field.eq(value)
$.field.ne(value)
$.field.gte(number)
$.field.lte(number)
$.field.lenEq(count)
$.field.lenGte(count)
$.field.lenLte(count)
$.field.contains(value)
Expected values are parsed as JSON when possible. Otherwise they are treated as strings.
workloads/#
Each source workload lives in workloads/<workload-name>/. CapaKit treats each workload directory as its own source
root and sandbox boundary. Workloads can read their own files, declared mounts, runtime home/cache/tmp dirs, and
CapaKit toolchain paths; they cannot read sibling workload source by default.
Typical generated Bun workload:
workloads/app/
.gitignore
package.json
tsconfig.json
src/
index.ts
capakit_mcp.ts
HTTP UI workloads also include UI files and Vite config:
workloads/web/
package.json
vite.config.ts
src/
index.ts
capakit_http.ts
ui/
App.tsx
index.html
main.tsx
styles.css
Run workload commands through CapaKit:
capakit exec app -- bun install
capakit exec app -- bun test
capakit exec --all -- bun run build
capakit exec runs from the workload source root. File writes affect the local workload directory, but process
execution uses the CapaKit workload sandbox.
Bun Workloads#
The public alpha targets Bun workloads. Generated Bun workloads use @capakit/sdk and protocol-specific helpers:
- MCP:
@capakit/sdk/mcp - HTTP:
@capakit/sdkplus Hono/Vite/React scaffold - A2A:
@capakit/sdk/a2a - OpenAI-compatible:
@capakit/sdk/oaic
Generated Bun manifests use prepare.command: bun install. MCP, A2A, and OpenAI-compatible workloads usually start with
bun run src/index.ts; generated HTTP UI workloads start with bun run start.
README.md#
README.md is the user-facing guide for the Kit. Keep it specific to the app, not a copy of the CapaKit manual.
Useful README content:
- what the app does
- how to run it
- how to test it
- required mounts or secrets
- public paths or tools users should call
- screenshots for UI or visual-output Kits
- known limitations
Coding agents should update README.md when app behavior, setup, commands, secrets, mounts, or user-visible outputs
change.
CLI#
The capakit CLI utility is the runtime and toolkit for coding agents.
Use the CLI with -h or --help options to explore.
capakit --help
capakit --version
capakit <command> --help
Output Formats:
capakit defaults to human-readable text output.
Use --output json for commands that produce structured summaries or tables:
capakit kit info --output json
capakit kit workloads list --output json
capakit storage status --output json
Set the default output format with:
CAPAKIT_OUTPUT_FORMAT=json
Supported values are text and json. --output takes precedence over CAPAKIT_OUTPUT_FORMAT.
Runtime logs are separate from command output. For machine-readable logs, set:
CAPAKIT_LOG_FORMAT=json
Useful diagnostic controls:
--verbose: raise CapaKit log verbosity for the command.--log-details lineage|fields|all|none: include internal lineage and/or structured log fields.CAPAKIT_LOG_DETAILS=lineage|fields|all|none: default log detail mode.CAPAKIT_CLI_THEME=auto|dark|light|mono: override terminal log styling.
Workload SDKs#
Workload SDKs are used inside workload source code. They give a workload its CapaKit runtime context, expose protocol servers to the runtime, call connected workloads, resolve declared secrets, and inspect declared host mounts.
TypeScript SDK:
The public alpha uses the TypeScript SDK package @capakit/sdk from Bun
workloads.
Use the root module for runtime primitives:
import {
createRunnerSdk,
endpointPath,
hostMountMid,
secretMid,
workloadMid,
} from "@capakit/sdk";
Core SDK APIs:
createRunnerSdk(): creates the workload runtime SDK.sdk.start(): starts the workload's mounted protocol endpoints.sdk.stop(): stops mounted endpoints and SDK clients.sdk.mount(...): mounts an HTTP-style endpoint handler.sdk.workloads.endpoint(...): resolves a manifest-declared connected workload endpoint.sdk.secrets.resolve(secretMid("...")): resolves a Kit secret listed inexposed_secrets.sdk.mounts.get(hostMountMid("...")): reads a declared host mount binding.endpointPath,workloadMid,secretMid,hostMountMid: typed id helpers for SDK calls.
Minimal HTTP workload:
import { createRunnerSdk, endpointPath } from "@capakit/sdk";
const sdk = createRunnerSdk();
sdk.mount({
protocol: "http",
endpoint: endpointPath("/http"),
handler: async () =>
Response.json({
ok: true,
}),
});
await sdk.start();
Provider helpers live in protocol-specific modules:
@capakit/sdk/mcp:mountMcp,createMcpClient.@capakit/sdk/oaic:mountOaic,createOaicClient.@capakit/sdk/a2a:mountA2a,createA2aClient.@capakit/sdk/anthropic:createAnthropicClient.@capakit/sdk/google-ai-studio:createGoogleAiStudioClient.@capakit/sdk/websocket:connectWebSocket.
Minimal MCP workload:
import { createRunnerSdk } from "@capakit/sdk";
import { mountMcp } from "@capakit/sdk/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
const sdk = createRunnerSdk();
const server = new McpServer({
name: "hello",
version: "1.0.0",
});
mountMcp(sdk, {
endpoint: "/mcp",
server,
});
await sdk.start();
Calling a connected MCP workload:
import { createRunnerSdk, endpointPath, workloadMid } from "@capakit/sdk";
import { createMcpClient } from "@capakit/sdk/mcp";
const sdk = createRunnerSdk();
const tools = await createMcpClient(
sdk,
workloadMid("tools"),
endpointPath("/mcp"),
);
const result = await tools.callTool({
name: "lookup",
arguments: { query: "hello" },
});
The target workload must be listed in the caller's connections; CapaKit does not expose arbitrary sibling workloads
to source code.
Example Kits:
- hello-world-demo-kit: minimal Bun MCP workload.
- local-image-tagger-demo-kit: SDK usage with mounts, connected model dependency, HTTP, and MCP.
- llama-cpp-local-kit: OpenAI-compatible local model workload.
Registry#
The public registry is a catalog of example and reusable AI app Kits. The source of truth is
github.com/capakit/apps; the CLI reads the registry catalog from that repository.
Use it to discover the current public Kits:
capakit registry tags
capakit registry search --tag llama.cpp
capakit registry info llama-cpp-local
Support#
For runtime bugs, CLI failures, docs issues, or confusing behavior, open an issue in github.com/capakit/cli.
Include:
capakit --version- macOS version and CPU architecture
- the command you ran
- the Kit source, preferably a GitHub link when possible
- relevant error output or logs
Security Issues#
Do not open public GitHub issues for vulnerabilities or sensitive reports. Use the security contact flow on capakit.com/security.
Include the affected version, impact, reproduction steps, and whether the issue involves secrets, sandbox escape, network isolation, package integrity, or unauthorized workload access.