Skip to content

Run your first component

Every act subcommand accepts the same three forms of reference: a local path, an HTTP(S) URL, or an OCI registry ref. We’ll use the published SQLite component at actpkg.dev/library/sqlite.

Terminal window
act info actpkg.dev/library/sqlite --tools

Prints the component’s metadata (name, version, description), its declared capabilities, and every tool it exposes.

Terminal window
mkdir -p /tmp/actdemo
act call actpkg.dev/library/sqlite query \
--args '{"sql": "SELECT sqlite_version()"}' \
--session-args '{"database_path": "/tmp/actdemo/app.sqlite"}' \
--allow 'fs=/tmp/actdemo/**'
[
{
"sqlite_version()": "3.51.3"
}
]

act call instantiates the component, runs one tool, prints the result, and exits.

Two things in that command are worth unpacking:

  • --session-args — sqlite is a stateful component: it holds an open database connection, so it exports session-provider and takes its connection parameters at session open rather than per call. On act call, this flag opens a session-of-1, runs the call, and closes it. Ask any component what it accepts with act session open-args-schema <component>.
  • --allow 'fs=…' — the component declares a wasi:filesystem capability, and nothing reaches the filesystem until you grant it. fs=/tmp/actdemo/** grants that directory read-write and nothing else; :ro would make it read-only. Note it covers the whole directory, not just the database file: SQLite also writes a .lock sidecar next to it. Grant too little and the audit trail tells you exactly what was refused — and which flag would grant it.
Terminal window
act run actpkg.dev/library/sqlite --mcp \
--session-args '{"database_path": "/tmp/actdemo/app.sqlite"}' \
--allow 'fs=/tmp/actdemo/**'

Exposes the component over MCP stdio. Plug into Claude Code, Claude Desktop, Cursor, or any MCP client. With --session-args the host pre-opens one session and hides the session machinery from the client entirely.

Rather than typing that command, put it in your MCP client’s config. In Claude Code that is .mcp.json at the root of the project:

{
"mcpServers": {
"sqlite": {
"command": "npx",
"args": [
"@actcore/act", "run", "actpkg.dev/library/sqlite", "--mcp",
"--session-args", "{\"database_path\": \"/tmp/actdemo/app.sqlite\"}",
"--allow", "fs=/tmp/actdemo/**"
]
}
}
}

Each flag is its own array element, and the JSON value passed to --session-args is a string, so its quotes are escaped. If you have act on $PATH, use "command": "act" and drop the leading "@actcore/act" argument.

The equivalent one-liner, if you would rather not edit the file by hand:

Terminal window
claude mcp add sqlite -- npx @actcore/act run actpkg.dev/library/sqlite --mcp \
--allow 'fs=/tmp/actdemo/**'

For a component you serve over HTTP instead, point the client at the endpoint:

{
"mcpServers": {
"sqlite": { "type": "http", "url": "http://[::1]:3000/mcp" }
}
}

.mcp.json lives in the repository, so the grant travels with the project. Everyone who opens it gets the same component at the same version with the same capability ceiling — rather than each developer running an npx tool with ambient access to their whole machine and hoping it behaves. A reviewer can read the diff and see exactly what a new tool is allowed to touch.

act cached it to ~/.cache/act/components/. Subsequent runs skip the network. act store list shows what’s cached, act store gc prunes it.

The SQLite component declares a wasi:filesystem capability. At runtime you must grant it — otherwise the component can open no files at all. The declaration is a ceiling: you can’t grant more than the component asked for, and the component can’t reach past what you granted.

The default policy mode is ask, so an interactive run prompts you on first access instead of requiring the flag up front. A headless run with no prompt channel degrades to deny — which is why scripted invocations like the ones above pass --allow explicitly. See Policy & sandbox.