Skip to content

Integrations

Choose the integration direction first:

GoalInterfaceWhat runs where
Let a coding agent run a complete review or scanDirect CLIThe agent launches the local CLI with your configured model runtime
Let an external agent launch workflows or call selected target toolsMCP serverThe client chooses operations; workflow assessments use the selected engine’s provider
Give 0 tools from another MCP serverMCP client configuration0 connects operator-configured local or remote servers
Install a third-party toolHackstore pluginsEnabled JavaScript runs as a local child process, not in a sandbox
Let the model author executable toolsSelf-extensionGenerated TypeScript runs in disposable Docker or smolvm guests

Local tools and BYOK workflows do not require a cloud account. The website describes the product organization; the command and runtime sources linked below define these integration contracts.

A coding agent with shell access can invoke the CLI directly, without an MCP adapter. Install 0 where that agent runs, configure a supported model provider, and set the working directory explicitly:

Terminal window
0 review /absolute/path/to/repo --format json > review.json
0 scan --target https://target.example.com --scope /absolute/path/to/scope.json --format json > scan.json

The CLI’s inference is separate from the coding agent’s own model session; an agent subscription is not automatically a credential for every runtime. Inspect the command’s exit status and saved report, not just the last line of stdout. Findings can be leads or unconfirmed results: use the reported evidence and verification workflow rather than treating a successful CLI invocation as proof of exploitability. Keep fix application a separate, operator-reviewed step; see Scan Workflows.

For CI, use GitHub CI. For template discovery and managed workflow execution from an external agent, use the MCP workflow tools below. Individual target tools remain available for direct interaction.

The MCP server (0 mcp-server) exposes selected tools through the Model Context Protocol over stdio. --workflows selects template discovery, workflow authoring, and run lifecycle operations. Without it, the default remains the existing live-target tools. An explicit --tools list selects exactly those tools, including a mixture of workflow and live tools.

Use an MCP client that can launch local stdio servers. Client configuration formats differ; the examples use the common mcpServers shape.

Sources: mcp-server.ts, workflow-runtime.ts.

Local-target MCP stdio requires an explicitly selected host-local execution profile. The SmolVM CLI bridge supports batch commands but cannot forward the bidirectional stdio MCP transport; startup fails before booting a VM or reading provider credentials. The configured execution profile remains unchanged. Use 0 workflow commands for isolated execution. If the operator intends host execution, they can explicitly choose 0 workbench disable; this changes the sandbox boundary and must not be performed automatically by a connecting agent. Model provider configuration remains a separate prerequisite for assessments.

To connect to a registered remote engine, use 0 mcp-server --workflows --backend production --backends-config /absolute/path/to/backends.json. This host runs only the network transport; the engine supplies its workspace, scope, execution profile and model connection. Do not pass local --workspace, --scope or --db-path flags. The engine must advertise workflow-engine support. Remote clients detach on disconnect; engine runs persist until completion or explicit cancellation. list_runs lists the web engine’s retained runs. Foreground 0 workflow run ... --backend production explicitly cancels on SIGINT. Cancellation responses include cancellationAcknowledged: true when the controller accepts the request. The run remains active until executor cleanup finishes; only then does its status become cancelled.

Terminal window
# Authorized local source root
0 mcp-server --workflows --workspace /absolute/path/to/repo
# Authorized live targets; run from the project where scope is enabled
0 plugin enable scope
0 mcp-server --workflows --scope /absolute/path/to/scope.json \
--target https://target.example.com

--workspace authorizes local source targets inside that root, including canonical path checks. Live workflow targets require an explicit scope file and the project’s enabled scope plugin. --target optionally fixes the only accepted target. Supplying live-tool flags does not authorize arbitrary local source access; source workflows need --workspace.

ToolPurpose
list_templates / get_templateRead versioned templates and compatible target types
list_workflows / get_workflowRead saved definitions and their revisions
list_runsRead retained runs on the selected engine
save_workflowValidate and save a definition with optional expectedRevision
start_runStart one template or saved workflow with target inputs; return the run ID
get_runRead the owned run’s status, step outcomes, and retained events
get_run_resultsPage through findings and retained assessment results
cancel_runRequest cancellation of an execution on the selected engine

For example, call start_run with:

{
"templateId": "repository-review",
"revision": 1,
"target": "/absolute/path/to/repo",
"idempotencyKey": "review-request-1"
}

Select exactly one templateId or workflowId; saved workflow launches require revision. Optional timeCapMs and costCapUsd narrow run limits. get_run_results accepts runId, a numeric cursor, and limit from 1 to 100. A retry with the same owner-scoped idempotency key and request returns the same run. Changing that request while reusing the key is rejected.

The external agent chooses what to run using its own model. Assessments inside 0 require 0’s separately configured model provider. Discovery and individual target tools do not create an internal assessment model session. Workflows execute sequential typed steps through the shared runner. Templates select supported assessment, verification, fix, research, or deep review operations. Missing executor prerequisites fail before launch; a template label does not imply a specialized backend is available.

start_run.inputs is a JSON object, bounded to 32 KiB, containing the selected operation’s evidence references and options. Finding operations accept an existing findingId, findingPath, or structured finding; fix workflows require an explicit testCommand, and verification selects a supported runner such as local, smolvm, docker, or qemu. Backend-specific options must match the executor contract. Input data and saved definitions never grant filesystem access, runner availability, credentials, or apply permission.

Apply steps require both the operator-configured host flag --allow-apply and an explicit start_run.allowApply: true. The host must also have an authorized source workspace. Fix proposal remains separate from application; publication is not implied by either permission.

An embedded stdio host runs the same engine services as the browser. Closing that host ends its execution lifetime. To use an already running web engine, attach the MCP transport and optionally select an existing browser session:

Terminal window
0 mcp-server --workflows \
--engine-url http://127.0.0.1:3000 --engine-token-env ENGINE_TOKEN \
--session SESSION_ID

ENGINE_TOKEN holds the engine’s configured bearer credential; its value never appears in CLI arguments or client reports. Direct connections use HTTPS, or HTTP on loopback for a local engine or SSH tunnel. --backend production uses a trusted registered connection instead. Engine attachment requires no local workspace, scope, model, or target executor setup.

CLI and MCP workflow clients also discover a running local web engine that owns the selected control database and workspace. Private metadata holds its identity and transport credential; these are not copied to browser descriptors or tool reports. Failed authentication or a changed live engine fails attachment rather than launching a replacement. Run from the engine’s workspace and omit local scope, model, and apply-grant overrides when attaching automatically.

start_run.sessionId binds the run to an existing session, overriding the connection’s optional --session default. Missing sessions fail attachment; no session or approval is silently recreated. Sessionless launches create an engine session under its current admission grants. Run status, results, and cancellation resolve the same web-owned executions. Disconnecting an attached MCP client detaches its transport while the engine continues running.

start_assessment accepts target, optional sessionId, and a complete plan with goal, depth, runCount, executionMode, timeCapMs, and costCapUsd. The selected engine authorizes the target and executes the structured plan.

Session tools include list_sessions, create_session, attach_session, get_session, get_session_events, send_message, continue_session, cancel_session, resolve_decision, list_saved_sessions, and resume_session. Use an explicit --tools allowlist to expose only the desired operations. Saved-session resume creates a new session under current admission grants. get_capabilities reports supported operations. resume_scan accepts sessionId, scanId, optional nonnegative branchFromEntry, and optional timeCapMs/costCapUsd; it resumes persisted scan work when the engine supports that operation. It does not resume an interrupted workflow graph.

Browser chat offers the same template and run lifecycle operations using its selected runtime. A chat start_run returns a queued requestId; execution waits until that turn ends, the owner configuration remains stable, and the operator approves the launch and target. Read get_run with that request ID to obtain its status and actual runId. A queued request is not an active run; changing the chat’s configuration invalidates the request.

Terminal window
0 mcp-server \
--target https://target.example.com \
--scan-id my-scan-001 \
--scope /absolute/path/to/scope.json \
--tools http_request,crawl,query_findings
OptionDescription
--target <url>Target URL (required whenever live tools are selected)
--scan-id <id>Scan ID for live tool findings and target updates (required whenever live tools are selected)
OptionDefaultDescription
--workflowsfalseExpose workflow, session, and scan resume lifecycle tools instead of the default live tools
--backend <id>—Attach to a trusted registered engine
--backends-config <path>—Trusted backend registry configuration
--engine-url <url>—Attach directly to a running engine
--engine-token-env <name>—Environment variable holding the direct engine credential
--session <id>—Default existing engine session for workflow starts
--workspace <path>—Absolute authorized local root for source workflows
--allow-applyfalsePermit explicit apply requests inside the authorized workflow workspace
--db-path <path>—Path to SQLite database for persistence
--timeout <ms>30000Per-tool timeout in milliseconds (minimum 1000)
--scope <path>—Path to a 0 scope JSON file. Live workflows require active scope enforcement; atomic target tools enforce the file when the scope plugin is enabled
--tools <names>live tools, or workflow tools with --workflowsExact comma-separated tool selection
--rate-limit <spec>5 rpsPer-host request rate limit. An active --engagement-profile caps this
--allow-scannersfalseDisable generic-scanner suppression for scoped engagements
--engagement-profile <name>standardHardening posture: standard (default behaviour) or conservative (1 rps/host ceiling, full jitter, no WAF evasion)
--no-waf-evasionenabledDisable the adaptive WAF-evasion ladder (encoding/casing/whitespace mutation on block)

Use --tools to select from these live-attack tools:

ToolPurpose
http_requestSend an HTTP request to the target
crawlCrawl the target application for endpoints
submit_formSubmit a form on the target
send_promptSend an LLM prompt to the target
save_findingPersist a discovered finding
update_targetUpdate the target definition mid-session
query_findingsQuery persisted findings
update_findingUpdate an existing finding’s status/metadata
doneSignal session completion
payload_lookupLook up a known payload
wp_fingerprintFingerprint WordPress instances
mongo_objectidGenerate/extract MongoDB ObjectIds

For individual live tools, target authentication is provided via the ZERO_MCP_AUTH_JSON environment variable. Set it to a JSON object with one of these shapes:

// Bearer token
{"type":"bearer","token":"eyj..."}
// Cookie
{"type":"cookie","value":"session=abc123"}
// Basic auth
{"type":"basic","username":"admin","password":"pass"}
// Custom header
{"type":"header","name":"X-API-Key","value":"sk-..."}

See Configuration for the full --auth flag details used by 0 scan and 0 review.

Individual live tools support the same engagement hardening as the scan path. When --engagement-profile conservative is active:

  • WAF-evasion ladder is disabled (regardless of --no-waf-evasion)
  • Per-host rate is capped at 1 rps (config override can only lower it further)
  • Full request jitter is applied to all rate-limit buckets

An explicit --rate-limit value is clamped to the posture’s ceiling. The posture clamps, never increases, the configured rate.

When a posture is active, the server attempts to record an engagement_posture_applied event. If the scan is absent from the database, that foreign-key-bound event may not persist; a warning and effective-posture summary go to stderr. --scan-id associates tool state with an ID; it does not create a complete scan pipeline or run an independent verifier.

Individual live tools support attribution headers for authorized engagements:

  • ZERO_MCP_ATTRIBUTION_HEADERS_JSON — JSON array of "Header-Name: value" strings
  • ZERO_MCP_ATTRIBUTION_UA_TOKEN — free-form User-Agent token appended to the default UA string

For a client accepting mcpServers (for example Claude Desktop), add:

{
"mcpServers": {
"0": {
"command": "0",
"args": [
"mcp-server",
"--target", "https://target.example.com",
"--scan-id", "agent-session",
"--scope", "/absolute/path/to/scope.json",
"--tools", "http_request,crawl,query_findings"
]
}
}
}

Use an absolute path for command if a GUI-launched client cannot find 0 on its PATH. For a source workflow client, replace the example args with ["mcp-server", "--workflows", "--workspace", "/absolute/path/to/repo"]. Individual live tools use the MCP client’s reasoning model; assessment workflows require 0’s configured provider. If individual live tools need authentication, provide ZERO_MCP_AUTH_JSON through that client’s secret/environment mechanism. send_prompt sends a prompt to the target under test, not a provider model.

The MCP transport is stdio-only; stdout is reserved for protocol frames and diagnostics go to stderr. The client manages the process lifetime, including cancellation of owned active workflow runs on disconnect. Enable scope in the intended project before relying on atomic tool scope enforcement. Limit the tool list and provide scope explicitly; there is no interactive console approval callback in this server. Enabling a tool is not authorization to test systems you do not own or have permission to assess.

This is the reverse direction: 0 console and the OpenTUI connect external stdio or Streamable HTTP servers from the JSON array in ZERO_MCP. It is not a {"mcpServers": ...} object or a config-file path:

Terminal window
env 'ZERO_MCP=[{"id":"workspace","command":"node","args":["/absolute/path/to/mcp-server.js"],"cwd":"/absolute/path/to/workspace"}]' \
0 console

Replace the command with an installed MCP server you trust; the same environment works with 0 tui. Local entries accept id, command, and optional args, env (string values), and cwd. For a Python stdio server, use command: "python3" and its script path in args; no Python-specific 0 plugin API is required. Provision server dependencies yourself.

Tools become mcp__<server-id>__<tool-name>. Results are untrusted data and tools default to network-capable for authorization purposes. These gates do not sandbox the server process: starting a configured server already executes its code under your account. Give it only the credentials and filesystem access its workflow needs.

Malformed entries and failed connections are skipped rather than preventing console startup. If no tools appear, check the JSON array, executable path, server arguments and stdio handshake; do not assume an empty roster means the server connected successfully. Remote entries accept id, url, and optional headers (string values). Use Streamable HTTP, not a legacy SSE endpoint. HTTPS is required except on loopback; redirects are rejected so authentication headers are never forwarded to a different endpoint. HTTP and stdio entries can share the same array. External MCP tools currently attach to local execution sessions; they are not forwarded into the smolvm workbench.

Connect to Elastic Agent Builder using its Kibana MCP endpoint and an API key with Agent Builder application privileges. Use the encoded API key returned by Elastic. A custom Kibana Space uses /s/<space>/api/agent_builder/mcp instead.

Set KIBANA_URL and ELASTIC_API_KEY through your environment or secret manager, then create the server configuration without putting the key in a command argument:

Terminal window
export ZERO_MCP="$(node --input-type=module -e '
const { KIBANA_URL, ELASTIC_API_KEY } = process.env;
if (!KIBANA_URL || !ELASTIC_API_KEY) throw new Error("Set KIBANA_URL and ELASTIC_API_KEY");
console.log(JSON.stringify([{
id: "elastic",
url: new URL("api/agent_builder/mcp", KIBANA_URL.replace(/\/$/, "") + "/").href,
headers: { Authorization: "ApiKey " + ELASTIC_API_KEY }
}]));
')"
0 console

The tools are discovered from your Elastic deployment; Zero does not hardcode a catalog or install Tracecat. API key privileges determine which data and actions Elastic permits. See Elastic MCP authentication for account setup. You can also connect Elastic from Plugins in the web UI.

Sources: mcp-host.ts, console.ts, tui/run.tsx.

Open Plugins to connect GitHub, Elastic, Semgrep, Snyk, Linear, Jira, Cloudflare, Slack or Microsoft Teams. Each connection is tested before it is saved. Connected plugins have an on/off switch; changes apply to new chats. Manage a connection to update its account or inspect its tools. Leaving a saved secret field blank preserves that secret.

PluginTools
GitHubRepositories, code scanning and Dependabot alerts, issues and pull requests
ElasticTools discovered from the deployment’s Agent Builder MCP endpoint
SemgrepProjects and existing findings in a selected deployment
SnykProjects and existing issues in a selected organization
LinearTeams, issues and creating remediation issues
JiraProjects, JQL search and creating remediation issues
CloudflareZones, DNS records and rulesets
SlackChannels, recent messages and posting summaries
Microsoft TeamsJoined teams, channels and posting channel messages

Setup uses vendor API tokens. Jira Cloud also needs an account email and site URL. Elastic needs its Kibana URL, Semgrep a deployment ID, and Snyk an organization ID. Teams requires a delegated Microsoft Graph token with the permissions for the selected actions; reconnect when it expires. Browser OAuth and automatic token refresh are not implemented. Semgrep and Snyk read their platform findings rather than starting a local scan.

Credentials are operator-global in ~/.0/service-plugins.json (0600, directory 0700), not embedded in portable workflow definitions. The API returns only non-secret settings and tool metadata. Service tools use the mcp__ namespace, the existing MCP permission gates and untrusted-result handling. Connecting a plugin does not grant a token additional vendor permissions.

Local chats connect the enabled accounts directly. SmolVM chats receive only explicitly configured, enabled service credentials through private stdin and connect from inside the guest. The existing workbench network grant is required; Plugins does not enable networking. The current CLI bundle must be rebuilt so the guest receives the updated adapters. Existing chats keep their original tools.

Native sessions can use spawn_agent for one focused task or spawn_agents for a batch of up to eight. Batches default to four concurrent children; env ZERO_SUBAGENT_CONCURRENCY=2 0 tui lowers that concurrency. Each task gets fresh context and its own turn budget, while scope, rate limits and the parent’s shared cost ceiling remain in force. Children do not receive recursive spawn tools. Findings merge back through the parent; a child failure is not silently a successful empty result.

Use the role model picker to assign worker models. A tool request’s role is a routing label, not a permission role. Explicit model choices must be the parent model or an operator-approved role pin. Unmapped roles inherit the parent. Single-model mode overrides child selections with the parent model.

Embedded LlmApiRuntime callers can additionally opt into RuntimeConfig.autoRoute or an agentModels role value of "auto" to widen the model-selection guard. This is not a stock CLI --auto-route flag. Crucially, forked children still inherit the parent’s provider, endpoint and account, with no cross-account fallback chain. Use model IDs that account or gateway actually serves; the presence of another provider’s ambient credentials does not reroute a fork to it. Model selection does not change tool permissions or establish that a model is better at verification. Ordinary worker consensus is not independent reproduction.

Sources: tools.ts, runtime/types.ts, llm-api.ts.

0 h1 provides read-only access to the HackerOne hacker API for program discovery and scope enumeration.

Source: packages/cli/src/commands/h1.ts

SubcommandDescription
0 h1 authVerify H1 credentials against the API
0 h1 programs listPaginate/filter the program list
0 h1 programs show <handle>Program detail + scope summary
0 h1 scope dump <handle>Export structured scopes as scope JSON

Set H1_API_IDENTIFIER and H1_API_TOKEN in the environment, or save the same unquoted KEY=VALUE pairs in ~/.0/h1.env with mode 0600. A complete environment pair takes precedence. The identifier is the name entered at token creation, not your HackerOne handle. The API uses Basic authentication; 0 h1 auth verifies existing credentials and does not perform a login flow.

H1_API_IDENTIFIER=my-security-integration
H1_API_TOKEN=your-api-token

Do not add export prefixes, shell quoting, or multiline values to this file. See h1/credentials.ts.

CodeMeaning
0Success
1User/data error (bad input, parse failure, missing handle)
2Auth failure (missing creds or HTTP 401/403 from H1)
3Rate-limit or network error
Terminal window
# Verify credentials
0 h1 auth
# List programs
0 h1 programs list --limit 20
# Show program detail
0 h1 programs show my-program-handle
# Export scope for use as a 0 scope file
0 h1 scope dump my-program-handle --out my-scope.json

Review the program’s current policy and automation restrictions before using an exported scope. Scope enumeration is not permission to automate testing. This integration does not submit HackerOne reports, rank program fit, or ingest hacktivity; disclosure drafts below are a separate local workflow.

scan, review, and audit accept --format and default to terminal output. Supported formats and aliases vary by command.

Source: packages/cli/src/formatters/

FormatFlagDescription
JSON--format jsonStructured JSON with findings, summary, and metadata
SARIF--format sarifStatic Analysis Results Interchange Format — upload to GitHub Code Scanning or other SARIF consumers
HTML--format htmlSelf-contained HTML report with severity bars, finding cards, collapsed evidence
PDF--format pdfPDF report via pdfkit (US Letter). Tables, severity bars, finding details
Markdown--format markdownMarkdown report
Terminal--format terminalTerminal-formatted output with ANSI colors

The SARIF output is compatible with github/codeql-action/upload-sarif@v4. See GitHub CI for a full workflow example.

Terminal window
0 review . --format sarif > results.sarif
Terminal window
0 scan --target http://127.0.0.1:8080 --scope ./scope.json --format pdf

The PDF formatter lazily loads pdfkit so the bun-compiled binary never bundles it. Output is US Letter format with severity-colored sections.

Terminal window
0 scan --target http://127.0.0.1:8080 --scope ./scope.json --format html

The HTML formatter produces a standalone page with severity bars, finding cards, collapsed request/response evidence, and meta tags.

The Docker publishing workflow builds a Linux amd64 image on GitHub Container Registry. The Dockerfile contains some architecture-aware dependency provisioning, but the current publisher is not multi-architecture:

ghcr.io/0sec-labs/0:latest
ghcr.io/0sec-labs/0:<sha>
ghcr.io/0sec-labs/0:main

Sources: Dockerfile, docker-publish.yml. Use a digest or the published short-SHA tag when repeatability matters; latest follows eligible main builds, not a promise of a stable release.

The runtime image (based on ubuntu:24.04) includes:

CategoryTools
Node.js runtimeNode 24 (copied from builder stage), npm, npx
Static analysisFoxGuard (pre-provisioned, checksum-pinned)
Web pentestingsqlmap, nmap, nikto, gobuster, hydra, ffuf, wfuzz, whatweb, wafw00f, dirb
Active Directoryimpacket (0.13.1), certipy-ad (5.1.0), bloodhound-ce (1.9.1), ldap-utils, krb5-user
Cloud identityAzureHound (v3.0.0, checksum-pinned)
Source analysisripgrep (for fast source-tree searches in audit/scan), jq, git
Container analysisskopeo
Scriptingpython3, python3-requests, python3-bs4
OptionalSecLists wordlists (INSTALL_SECLISTS=1 build arg, ~1GB extra)
Terminal window
docker run --rm \
-e ANTHROPIC_API_KEY=$KEY \
-v "$PWD:/work" -w /work \
ghcr.io/0sec-labs/0:latest review .
# Scan a web target
docker run --rm \
-e OPENAI_API_KEY=$KEY \
-v "$PWD:/work:ro" -w /work \
ghcr.io/0sec-labs/0:latest scan \
--target https://example.com \
--scope /work/scope.json

The container runs as the ubuntu user (uid 1000). Mount your working directory at /work if you need the container to read source code or write reports.

  • The image drops privileges to the ubuntu user before executing commands
  • INSTALL_SECLISTS=1 adds optional wordlists. AzureHound is included by default; changing AZUREHOUND_VERSION also requires matching recorded checksums
  • Ubuntu packages follow the configured apt repositories; the Dockerfile pins the listed AD Python package versions and verifies AzureHound/FoxGuard downloads
  • The AD tools venv is deliberately not on PATH to avoid shadowing system Python packages
Terminal window
docker build -f scripts/docker/Dockerfile -t 0:local .
docker build -f scripts/docker/Dockerfile --build-arg INSTALL_SECLISTS=1 -t 0:full .

0 supports two plugin mechanisms:

  • Model-authored executable plugins — TypeScript code submitted by the model at runtime, executed in isolated Docker containers or smolvm microVMs. This is the primary self-extension path, enabled by default for non-verifier agents (operator can opt out via allowModelSelfExtension: false).
  • Third-party operator plugins: tools installed from Hackstore and enabled for a project. These run as local child processes, not in the self-extension sandbox.

Model-authored executable plugins (self-extension)

Section titled “Model-authored executable plugins (self-extension)”

The model can submit TypeScript source files as an executable plugin during a session. Each plugin declares a manifest with tool names, descriptions, JSON parameter property schemas, and capabilities that gate broker access:

CapabilityDescription
computeGuest-local computation, including scratch files; no host filesystem or provider access
model-callMay call the configured model provider through a controller-owned broker
networkRequests to authorized host network tools, subject to the parent’s scope
filesystem-read / filesystem-writeRequests to authorized host filesystem tools, subject to local scope
process-exec / findings-writeApplicable host execution or finding-publication gates; explicitly denied broker tools remain unavailable

A plugin’s entry source file exports an async run(toolName, args, sdk) function. The sdk object provides three broker methods:

  • sdk.callTool(name, args) — calls another registered executable tool or an available host tool through the parent’s authorization gates. Returns output or throws.
  • sdk.callSkill(name, args) — calls another registered executable skill by name. Throws if not found.
  • sdk.callModel({system?, messages, tools?}) — delegates a model request through the parent’s authorized provider. Requires model-call; messages is required and nonempty. It accepts no model, account, credential, or provider override. Use native worker routing for separately selected models.

Guest code runs in an isolated guest (Docker backend by default) with no network, read-only root, and bounded resources. The guest SDK cannot invoke host execution tools (bash, run_command, python_exec), delegation tools (spawn_agent, spawn_agents), or control tools (self_extend, apply_patch, write_file). Nested invocations share a single broker call budget and are limited to depth 4.

Manifest parameters contains property schemas, such as {"value":{"type":"number"}}; declare required beside it. Node 24 strips erasable TypeScript syntax. Provision dependencies in the toolbox.

  1. Submit — submit({manifest, files, entry, kind?}, context) saves an immutable versioned snapshot, validates the source in a guest container (admission), and activates it.
  2. Execute — execute(toolName, args, context) runs the active version’s entry function with the supplied arguments. Failed executions increment the version’s failureCount and record lastError.
  3. Replace — submitting the same plugin id creates a new active version. Prior versions are retained for rollback. At 32 versions, submission fails rather than silently evicting an old version.
  4. List — list() returns every retained version with its evidenceStatus (structural for direct submits, measured for evolved versions), active flag, failureCount, and lastError.
  5. Rollback — rollback(pluginId, versionId, context) reactivates a prior version. Retains the rolled-back version for further rollback.
  6. Evolve — evolve(pluginId, profile, deps, context) runs the improvement loop over the active version’s snapshot, producing a new measured version on promotion.
  7. Close — releases the manager and aborts pending operations.

For the model-facing lifecycle, use self_extend with action set to submit, list, evolve, or rollback. Point ZERO_PLUGIN_EVOLUTION_CONFIG at an operator-owned source-evolution config to expose the default evaluation profile. It must use the same backend and pinned image as the executable. Creation and replacement work without a profile; measured evolution requires one.

YOLO removes per-action prompts within the configured scope; it does not let generated code replace its evaluator, inherit provider credentials, or expand host authorization. Direct submissions are structurally admitted; measured evolution requires the improvement loop.

To provision the default guest and start a session:

Terminal window
docker build -f scripts/docker/Dockerfile --target toolbox -t 0-toolbox:local .
env ZERO_PLUGIN_BACKEND=docker ZERO_PLUGIN_IMAGE=0-toolbox:local 0 tui

Self-extension is enabled by default for non-verifier sessions; an explicit allowModelSelfExtension: false disables it. Provisioning is still required: enablement does not install Docker or pull the guest image. Ask the agent to submit an executable through self_extend, inspect list for the retained version, and call its declared tool by name. There is no 0 plugin submit command for this path. For measured evolution, start the session with env ZERO_PLUGIN_EVOLUTION_CONFIG=/absolute/path/to/evolution.json 0 tui and use the default profile. Source-access consent and promotion settings in that operator-owned config are separate from self-extension enablement.

Sources: agent/executable-plugins.ts, plugins/executable.ts.

The default store is ~/.0/executable-plugins/, separate from Hackstore’s ~/.0/plugins/. registry.json retains snapshot UUIDs under snapshots/<uuid>, content digests, immutable image identity, manifest digests and evolved-version receipt digests. Registry provenance is checked on read; snapshot contents are verified at refresh/admission/execution boundaries. These are local integrity checks, not registry signatures or an external attestation.

BackendRequirementIsolation
docker (default)Local Docker daemon; configured Node 24 toolbox image--network none, read-only root, cap-drop all, no-new-privs, PIDs limit, bounded memory/CPU
smolvmKVM, smolvm 1.14.6, Node 24 toolbox archiveMicroVM with dedicated kernel; bounded resources and no guest network

Default image for agent-created submissions is 0-toolbox:local, overridable with ZERO_PLUGIN_IMAGE; the smoke script defaults to 0-toolbox:qualification. For smolvm, configure ZERO_SMOLVM_IMAGE_ARCHIVE. The image is resolved to an immutable digest on first use; resumed/promoted versions retain that digest, not a retagged reference.

The backend isolates executable plugins and evolution workers. The controller and authorized host tools execute outside it. Every invocation starts a fresh guest; smolvm incurs VM startup overhead.

Plugin validation imports and invocations share the controller’s worker admission budgets with source evolution. Root calls use a bounded FIFO queue; nested calls reserve additional resources immediately or fail rather than deadlock. Timeouts include queue wait, and uncertain guest cleanup stops new admissions. Listing versions and changing rollback metadata do not start guests.

submit ┌──────────┐ execute ──► success
│ │ Version 1 │ └── failureCount++
├──►active │(structural)│
│ └────┬──────┘
submit v2 │
│ ┌────▼──────┐
├──►active │ Version 2 │ rollback ──► Version 1 active again
│ │(structural)│
│ └────┬──────┘
evolve │
│ ┌────▼──────┐
└──►active │ Version 3 │
│(measured) │
└───────────┘

Source: packages/cli/src/commands/plugin.ts

Hackstore is the default community registry. Override it with ZERO_REGISTRY_URL or --registry on browse, search, and install. An explicit empty setting disables fetching. Entries use the unconfigured signature verifier and are marked unverified.

The author guide covers scaffolding, shared manifest validation, offline installation with 0 plugin install ./extension --local, approval, real tool calls, and 0 hackstore prepare-submission ./extension. Submission preparation produces a reproducible source bundle for a reviewed Hackstore pull request; it does not upload or publish. The installer writes plugin.js and plugin.json only. Check command-specific --help and update 0 if these commands are missing.

SubcommandDescription
0 plugin listList installed code and built-in authorization plugins with project activation state
0 plugin browseList the configured registry
0 plugin search <query>Search the configured registry
0 plugin install <id>Fetch, validate, and write registry code without executing it
0 plugin install <path> --localValidate and install offline source; never execute it or approve a new installation
0 plugin enable <id>Approve installed code or activate built-in scope enforcement for this project
0 plugin disable <id>Revoke project approval or disable built-in scope enforcement
0 plugin info <id>Inspect the manifest/capabilities or built-in authorization state
0 plugin run <id> <tool> [pairs...]Invoke a tool; name it explicitly before key=value arguments. Effectful calls require --yes.
0 hackstore init <name>Scaffold a working example tool and author instructions
0 hackstore validate <path>Validate the shared manifest contract without executing code
0 hackstore prepare-submission <path> --out <directory>Prepare reviewed source under extensions/<id>/; no publication side effects

External CLI-managed plugins have three distinct states:

StateDescription
InstalledFiles on disk. install writes bytes; runs nothing
EnabledPer-project operator decision recorded by the enablement store
LoadedThe enabled plugin starts executing in a child process, before any tool call

Declared capabilities are compute, model-call, network, filesystem-read, filesystem-write, process-exec, and findings-write. They inform host-side approval decisions; they do not enforce operating-system restrictions. A plugin runs under the operator’s account. Review code before enabling it. Omitting --yes for an effectful call prevents the call, not the preceding plugin load.

The first-party scope plugin is a host authorization feature, not external code: it has no installed entry point or child process. It is disabled until 0 plugin enable scope explicitly activates it for the project. Read Scope for the boundaries it controls.

Use 0 plugin enable <id> from the intended project, then launch 0 tui there for agent access. The OpenTUI pins the approved plugin host for each chat; marketplace changes prepare future chats rather than replacing a live chat’s tools. Start a new chat after changing enablement. Disabling a plugin is not a kill switch for already leased hosts: end their sessions to stop that code. Direct plugin run reloads and checks the current approval on each invocation. Do not assume every batch command or the readline console auto-loads Hackstore plugins merely because the core supports a PluginHost.

Source: session-plugin-host.ts.

0 disclose provides structured vulnerability disclosure tooling for findings generated during a scan.

Source: packages/cli/src/commands/disclose.ts

SubcommandDescription
0 disclose [findingId]Assemble advisory drafts for an ID/prefix, or batch persisted findings when omitted
0 disclose evidence-pack <finding.json>Assemble a DRAFT vendor notification markdown (never sends)
0 disclose track <findingId>Drive the disclosure tracking state machine
0 disclose review <finding.json>Render a deterministic reproducibility manifest

Start with 0 disclose <finding-id> --db-path ./scans.db --dry-run to inspect the advisory output plan. Drafting and recording a transition to sent do not send a vendor notification or file a HackerOne report. The separate --reverify mode executes PoC steps against a supplied target; it is not just report formatting and needs its own authorization and scope allowlist.

The evidence-pack subcommand produces a draft vendor notification containing what/where/impact/repro/remediation sections. It emits a mandatory DRAFT — NOT SENT banner.

Terminal window
0 disclose evidence-pack finding.json --target "lodash@4.17.21" --out notification.md

Options:

  • --target <label> — affected target/package label
  • --affected-ref <ref> — git ref or version range
  • --allow-unreproduced — stage a draft even without PoC reproduction
  • --out <file> — write to file instead of stdout

The track subcommand drives a state machine through statuses defined in @0/core:

Terminal window
# Open a fresh draft record
0 disclose track finding-001 --out record.json
# Transition to "sent" with vendor info
0 disclose track finding-001 \
--record record.json \
--to sent \
--disclosed-to "Vendor Security Team" \
--message "Initial notification" \
--out record.json
# Record CVE assignment
0 disclose track finding-001 \
--record record.json \
--to cve_assigned \
--cve-id CVE-2025-12345 \
--out record.json

The review subcommand requires verified findings with sufficient reproducibility evidence; it fails rather than manufacturing missing proof. It renders a redacted manifest and never sends or publishes anything. Supply --timestamp when you need reproducible serialized output across invocations.

Terminal window
0 disclose review finding.json --target "lodash@4.17.21" --out manifest.json

0 orchestrate runs an autonomous work queue over a shared SQLite database.

Source: packages/cli/src/commands/orchestrate.ts

ModeFlagDescription
Worker0 orchestrate --db-path ./scans.dbClaim and execute one batch of runnable work items, then exit
Watcher0 orchestrate --db-path ./scans.db --watchPoll for new work items continuously

--limit defaults to 1 claimed item per pass, and work in a pass executes sequentially. --watch --poll-interval 5000 polls continuously (minimum 1000 ms). Use the database containing the queued cases; this command has no target or queue-creation argument and an empty database produces no work. It is a persisted case worker, not a crash-safe self-improvement campaign controller.

The orchestrator processes these work item kinds in order of priority:

KindPriorityDescription
surface_map0 (highest)Map the target surface
hypothesis1Generate attack hypotheses
poc_build2Build proof-of-concept
blind_verify3Blind verification
consensus4Consensus across findings

A work item is runnable when its status is todo, its dependency is done, and no sibling for the same case is in_progress.

Each pass calls recoverStaleWorkers automatically. Workers whose heartbeat is older than 30 seconds can have in-progress items returned to todo; no manual require('./dist/...') command is needed. Recovery permits another execution, so do not treat it as exactly-once delivery of external effects. Stop an old worker before intentionally replacing it; stable --label values identify superseded workers.

The orchestrator supports these target URL schemes:

FormatTarget typeScan mode
https://example.comURLdeep (default)
web:https://example.comWeb appweb
mcp://host/pathMCP endpointmcp
scan:<value>Strips the scan: prefix and treats the remaining value as a URL targetStored mode, otherwise deep

The scan: parser does not look up a prior scan ID. Execution resumes the persisted scan associated with the queued case; it does not resolve an arbitrary scan:<id> reference to that scan’s target.

0 verify exposes deterministic replay and kernel reproducer workflows. The selected mode controls prerequisites, result shape, and exit-code meanings.

Source: packages/cli/src/commands/verify.ts

Exit codes, results, and runners are mode-specific. Follow Scan Workflows for choosing the mode, Verification Results for deterministic replay statuses, and Kernel VM Verification for QEMU prerequisites.

Local, Docker, and kernel execution have distinct safety boundaries. Use only the runner and fixture options registered by the selected command. An SDK runner type is not automatically a CLI option.

Terminal window
# SARIF for code scanning
0 review . --format sarif > results.sarif
# HTML report
0 scan --target http://127.0.0.1:8080 --scope ./scope.json --format html
# PDF report
0 scan --target http://127.0.0.1:8080 --scope ./scope.json --format pdf

JSON, Markdown, and SARIF are emitted as formatted output. HTML and PDF reports are written to timestamped files under the system temporary directory; the CLI prints the generated path. scan has no --report-path flag. Copy the emitted HTML/PDF file to your desired destination before temporary files are cleaned up. Redirecting stdout does not relocate that report.