English | 日本語
ato is a meta-CLI that interprets capsule.toml to execute, distribute, and install capsules.
It is designed around a Zero-Trust / fail-closed model: normal runs stay quiet, while consent prompts and policy violations are surfaced explicitly.
ato run [path|publisher/slug] [--registry <url>]
ato open [path] [--watch] # compatibility command (deprecated; prefer run)
ato ps
ato close --id <capsule-id> | --name <name> [--all] [--force]
ato logs --id <capsule-id> [--follow]
ato install <publisher/slug> [--registry <url>]
ato install --from-gh-repo <owner/repo>
ato build [dir] [--strict-v3] [--force-large-payload]
ato publish [--registry <url>] [--artifact <file.capsule>] [--scoped-id <publisher/slug>] [--allow-existing] [--prepare] [--build] [--deploy] [--legacy-full-publish] [--fix] [--no-tui] [--force-large-payload]
ato publish --dry-run
ato publish --ci
ato gen-ci
ato inspect requirements <path|publisher/slug> --json [--registry <url>]
ato search [query]
ato source sync-status --source-id <id> --sync-run-id <id> [--registry <url>]
ato source rebuild --source-id <id> [--ref <branch|tag|sha>] [--wait] [--registry <url>]
ato config engine install --engine nacelle [--version <ver>]
ato setup --engine nacelle [--version <ver>] # compatibility command (deprecated)
ato registry serve --host 127.0.0.1 --port 18787 [--auth-token <token>]- Primary product surface stays
ato build,ato publish, andato install. - For the current Tauri darwin/arm64 PoC,
capsule.tomlis the canonical project manifest. A default target withdriver = "native"and a.appentrypointis enough for native build detection. ato.delivery.tomlis still accepted as a compatibility sidecar. When present, it must match thecapsule.tomlnative target contract; the build rewrites/stages compatibility metadata into the artifact.- Native install JSON exposes
local_derivationandprojectionenvelopes. For this contract generation,schema_version = "0.1"is the stable machine-readable version for fetch/finalize/project/unproject/install metadata. fetch,finalize,project, andunprojectremain advanced/debug surfaces. Most users should stay on the integratedbuild/publish/installflow.- Local finalize is currently fail-closed and limited to macOS darwin/arm64 with
codesign. - Projection currently creates a macOS
~/Applicationssymlink on macOS hosts, and a Linux.desktoplauncher plus~/.local/binsymlink on Linux hosts.
capsule.toml is the source of truth for project input. The current canonical contract is:
schema_version = "0.2"
name = "my-app"
version = "0.1.0"
type = "app"
default_target = "desktop"
[targets.desktop]
runtime = "source"
driver = "native"
entrypoint = "MyApp.app"For this .app-entrypoint form, ato derives the current PoC defaults internally:
artifact.framework = "tauri"artifact.stage = "unsigned"artifact.target = "darwin/arm64"artifact.input = <targets.<default>.entrypoint>finalize.tool = "codesign"finalize.args = ["--deep", "--force", "--sign", "-", <artifact.input>]
If the native target is command-driven (entrypoint = "sh" plus cmd = [...]), then the build still needs explicit delivery metadata today. That metadata may live inline in capsule.toml as [artifact] + [finalize], or in ato.delivery.toml as a compatibility sidecar. Partial inline metadata is rejected fail-closed.
ato.delivery.tomlis not the canonical project manifest anymore. It is an accepted compatibility input for command-mode native builds and a compatibility mirror for.app-entrypoint projects.- Build always stages
ato.delivery.tomlinto the artifact payload, even when the source project used only canonicalcapsule.toml. This keeps the artifact self-describing for local finalize/install without requiring the original source tree. ato install,ato finalize, andato projectread the staged artifact metadata pluslocal-derivation.json; they do not require the source checkout's sidecar to be present later.- Near-term policy: keep accepting
ato.delivery.tomlas backward-compatible input, but treat it as optional compatibility metadata rather than product-surface source of truth.
For the current schema_version = "0.1" generation, the repo documents and test-guards the presence of these machine-readable fields:
fetch.json:schema_version,scoped_id,version,registry,parent_digest- build JSON:
build_strategy = "native-delivery",schema_version,target,derived_from - finalize JSON:
schema_version,derived_app_path,provenance_path,parent_digest,derived_digest local-derivation.json:schema_version,parent_digest,derived_digest,framework,target,finalize_tool,finalized_at- project JSON:
schema_version,projection_id,metadata_path,projected_path,derived_app_path,parent_digest,derived_digest,state - unproject JSON:
schema_version,projection_id,metadata_path,projected_path,removed_projected_path,removed_metadata,state_before - install JSON:
install_kind,launchable,local_derivation,projectioninstall_kind = "NativeRequiresLocalDerivation"means install succeeded, but the launchable path is the locally derived app bundle, not the stored.capsulelaunchable.pathis the path a caller should use to open/runlocal_derivation.provenance_path,parent_digest, andderived_digestare the stable linkage between fetch/finalize/project/installprojection.metadata_pathis the stable recovery handle forato unprojectand for launcher state inspection
These guarantees are intentionally narrow: additive fields may still appear, but removing or renaming the documented fields should be treated as a schema-version change.
Still experimental:
- exact on-disk directory layout under
~/.ato/fetches,~/.ato/apps, and~/.ato/native-delivery/projections - any future additional keys beyond the stable fields above
- advanced/debug command UX (
fetch,finalize,project,unproject) beyond their currentschema_version = "0.1"JSON envelopes - host/tool support beyond the current macOS darwin/arm64 +
codesignPoC
- Current:
capsule.tomlis canonical;ato.delivery.tomlremains accepted as compatibility input/output metadata. - Next: command-mode native builds keep working, but product docs and tooling point users at canonical
capsule.tomlfirst; sidecar use becomes optional wherever canonical manifest data is sufficient. - Later: internal artifact metadata can be abstracted away from the user-facing sidecar name, while preserving the
schema_version = "0.1"JSON/provenance contract for automation.
# build
cargo build -p ato-cli
# install nacelle engine if not installed (recommended)
./target/debug/ato config engine install --engine nacelle
# compatibility: setup subcommand
./target/debug/ato setup --engine nacelle
# run
./target/debug/ato run .
# hot reload during development
./target/debug/ato open . --watch
# background process management
./target/debug/ato run . --background
./target/debug/ato ps
./target/debug/ato logs --id <capsule-id> --follow
./target/debug/ato close --id <capsule-id>- Official registries (
https://api.ato.run,https://staging.api.ato.run):ato publishis CI-first (OIDC). Direct local uploads are not allowed. Default phase selection isdeployonly (handoff/diagnostics). If you need local build checks, explicitly add--build(or--prepare --build) before--deploy. - Personal Dock (default when logged in and no registry is specified):
ato publishresolves the target fromato loginand uploads directly tohttps://store.ato.run/d/<handle>.--artifactis recommended to avoid re-packing, and--scoped-idis auto-filled as<handle>/<slug>. - Custom/private registries (any other
--registry):ato publish --registry ...performs direct uploads.--artifactis recommended to avoid re-packing.--artifactsupports standalone artifact flow (no localcapsule.tomlrequired).--allow-existingis available only on deploy phase (--deploy) for private/local registries.
ato publish runs 3 internal phases in fixed order: prepare -> build -> deploy.
- Default (official registries): run
deployonly. - Default (private/local registries): run all phases.
- If any of
--prepare/--build/--deployis specified: run only selected phases. --artifactalways skips build phase.official + deployreturns handoff only (no local upload).--legacy-full-publish(official only) temporarily restores legacy default (prepare -> build -> deploy), is deprecated, and is scheduled for removal in the next major release.--ci/--dry-runcannot be combined with phase flags.
Official registry helpers:
ato gen-cigenerates the fixed GitHub Actions workflow for OIDC publish.ato publish --fixapplies the official workflow fix once, then reruns diagnostics.ato publish --no-tuidisables the interactive handoff UI and prints CI guidance directly.
The Dock-first path uses existing commands (no new subcommands):
- Run
ato loginonce and create/connect your Dock from Store Web/publish. - Build artifact locally:
ato build . - Publish to your Dock:
ato publish --artifact ./<name>.capsule - Share your public Dock page:
/d/<handle> - When ready for the official Store, use
ato publish --registry https://api.ato.runorato publish --ci. - Final review/submission continues from Dock Control Tower (
Submit to Official Marketplace).
# login once, then publish to your Personal Dock (recommended default)
ato login
ato build .
ato publish --artifact ./<name>.capsule
# pre-build + direct publish to a custom/private registry
ato build .
ATO_TOKEN=pwd ato publish --registry http://127.0.0.1:18787 --artifact ./<name>.capsule
# phase-filtered execution examples
ato publish --prepare
ato publish --build
ato publish --artifact ./<name>.capsule # default target: My Dock
ATO_TOKEN=pwd ato publish --deploy --artifact ./<name>.capsule --registry http://127.0.0.1:18787
ato publish --registry https://api.ato.run # default: deploy only
ato publish --registry https://api.ato.run --build # explicit local build + official handoff
ato publish --deploy --registry https://api.ato.run
# temporary compatibility flag (official only; deprecated and will be removed in next major)
ato publish --registry https://api.ato.run --legacy-full-publish
# idempotent retry for the same version/content (CI retry best practice)
ATO_TOKEN=pwd ato publish --registry http://127.0.0.1:18787 --artifact ./<name>.capsule --allow-existingprotoc is not required for normal builds.
Run this only when core/proto/tsnet/v1/tsnet.proto changes.
./core/scripts/gen_tsnet_proto.shUse these commands for source-backed registry workflows:
# inspect a sync run
ato source sync-status --source-id <source-id> --sync-run-id <sync-run-id> --registry <url>
# trigger rebuild / re-sign and optionally wait for status
ato source rebuild --source-id <source-id> --ref <branch|tag|sha> --wait --registry <url>Notes:
sync-statusis read-only and can emit JSON with--json.rebuildcan be used without--ref; the registry default ref is used.rebuild --waittriggers then polls the resulting sync run status.
# Terminal 1: start local HTTP registry
ato registry serve --host 127.0.0.1 --port 18787
# Terminal 2: build -> publish(artifact) -> install -> run
ato build .
ATO_TOKEN=pwd ato publish --artifact ./<name>.capsule --registry http://127.0.0.1:18787
ato install <publisher>/<slug> --registry http://127.0.0.1:18787
ato run <publisher>/<slug> --registry http://127.0.0.1:18787 --yesNotes:
- Write operations (
publish) requireATO_TOKENwhenregistry serve --auth-tokenis enabled. - Read operations (search/install/download) can remain unauthenticated.
- Use
18787in local verification to avoid collision with app services that also use8787(for example, worker HTTP ports). publish --artifactis the recommended path for local/private workflows.--scoped-idcan override publisher/slug for artifact upload.--allow-existingis not a blind conflict ignore; it is an idempotent operation gated by artifact hash/manifest consistency checks.- In enterprise CI, attach
--allow-existingto retry paths to make reruns deterministic and safe. - Version conflict is reported as
E202with next actions (bump version,--allow-existing, or reset local registry).
Local registry Web UI:
- The detail page stores per-target runtime config under
/v1/local/.../runtime-config. - You can save target-specific
envandportoverrides from the UI. - Tier2 targets can also persist execution permission mode (
sandboxordangerous) and reuse it on later runs.
# Server side: non-loopback exposure requires --auth-token
ato registry serve --host 0.0.0.0 --port 18787 --auth-token pwd
# Client side: install/run do not require token (read APIs)
ato install <publisher>/<slug> --registry http://100.x.y.z:18787
ato run <publisher>/<slug> --registry http://100.x.y.z:18787
# Token required only for publish
ATO_TOKEN=pwd ato publish --registry http://100.x.y.z:18787 --artifact ./<name>.capsuleato run validates required environment variables before startup.
If missing or empty, execution stops fail-closed.
targets.<label>.required_env = ["KEY1", "KEY2"](recommended)- Backward compatibility:
targets.<label>.env.ATO_ORCH_REQUIRED_ENVS = "KEY1,KEY2"
ato inspect requirements <path|publisher/slug> --json returns a stable machine-readable
requirements contract derived from capsule.toml.
capsule.tomlis the only source of truth for requirement discovery- local paths and remote
publisher/slugrefs return the same top-level JSON shape - state-related requirements are exposed under
requirements.state(state-first), notstorage - success prints JSON only to
stdout --jsonfailures print structured JSON tostderrand exit non-zero
Success shape:
{
"schemaVersion": "1",
"target": {
"input": "./examples/foo",
"kind": "local",
"resolved": {
"path": "/abs/path/to/examples/foo"
}
},
"requirements": {
"secrets": [],
"state": [],
"env": [],
"network": [],
"services": [],
"consent": []
}
}Failure shape:
{
"error": {
"code": "CAPSULE_TOML_NOT_FOUND",
"message": "capsule.toml was not found",
"details": {
"input": "./examples/foo"
}
}
}ato build --strict-v3 disables fallback when source_digest / CAS(v3 path) is unavailable.
Use it when you want build diagnostics to fail immediately instead of falling back to a looser manifest path.
For multi-service apps (for example: dashboard + API + worker), use a single web/deno target with top-level [services]. ato run starts services in DAG order, waits on readiness probes, prefixes logs, and fail-fast stops all services when one exits.
- Pre-bundle artifacts before packing (for example:
next build, worker build, lockfiles). - Include only runtime artifacts via
[pack].include(do not package rawnode_modules,.venv, caches). - Build once, then publish with
--artifactto avoid re-packing.
Minimal capsule.toml pattern:
schema_version = "0.2"
name = "my-dynamic-app"
version = "0.1.0"
default_target = "default"
[pack]
include = [
"capsule.toml",
"capsule.lock",
"apps/dashboard/.next/standalone/**",
"apps/dashboard/.next/static/**",
"apps/control-plane/src/**",
"apps/control-plane/pyproject.toml",
"apps/control-plane/uv.lock",
"apps/worker/src/**",
"apps/worker/wrangler.dev.jsonc"
]
exclude = [
".deno/**",
"node_modules/**",
"**/__pycache__/**",
"apps/dashboard/.next/cache/**"
]
[targets.default]
runtime = "web"
driver = "deno"
runtime_version = "1.46.3"
runtime_tools = { node = "20.11.0", python = "3.11.10", uv = "0.4.30" }
port = 4173
required_env = ["CLOUDFLARE_API_TOKEN", "CLOUDFLARE_ACCOUNT_ID"]
[services.main]
entrypoint = "node apps/dashboard/.next/standalone/server.js"
depends_on = ["api"]
readiness_probe = { http_get = "/health", port = "PORT" }
[services.api]
entrypoint = "python apps/control-plane/src/main.py"
env = { API_PORT = "8000" }
readiness_probe = { http_get = "/health", port = "API_PORT" }Recommended flow:
# 1) pre-bundle app artifacts
npm run capsule:prepare
# 2) package once
ato build .
# 3) publish artifact (private/local registry)
ATO_TOKEN=pwd ato publish --registry http://127.0.0.1:18787 --artifact ./my-dynamic-app.capsule
# 4) install + run
ato install <publisher>/<slug> --registry http://127.0.0.1:18787
ato run <publisher>/<slug> --registry http://127.0.0.1:18787Notes:
- For Next.js standalone, copy
.next/static(andpublicif used) into standalone output beforeato build. ato runstops before startup ifrequired_envkeys are missing.services.mainis required in services mode and receivesPORT=<targets.<label>.port.targets.<label>.entrypoint = "ato-entry.ts"is deprecated and rejected.- If a service command starts with
node,python, oruv, pin the matching version inruntime_tools.
web/static: Tier1 (driver = "static"+targets.<label>.portrequired; nocapsule.lockneeded)web/deno: Tier1 (capsule.lock+deno.lockorpackage-lock.json)web/node: Tier1 (Deno compat execution; requirescapsule.lock+package-lock.json)web/python: Tier2 (requiresuv.lock;--sandboxrecommended)source/deno: Tier1 (capsule.lock+deno.lockorpackage-lock.json)source/node: Tier1 (Deno compat execution; requirescapsule.lock+package-lock.json)source/python: Tier2 (requiresuv.lock;--sandboxrecommended)source/native: Tier2 (--sandboxrecommended)
Notes:
- Node is Tier1 and does not require
--unsafe. - Tier2 (
source/native|python,web/python) requires thenacelleengine. If not configured, execution stops fail-closed. Configure viaato engine register,--nacelle, orNACELLE_PATH. - Legacy compatibility flags (
--unsafe,--unsafe-bypass-sandbox) remain but are discouraged. - Unsupported or out-of-policy Node/Python behavior does not auto-fallback; it stops fail-closed.
runtime=webrequiresdriver(static|node|deno|python).publicis deprecated forruntime=web.- For
runtime=web, CLI prints the URL and does not auto-open a browser.
# Resolve by skill name (default search paths)
ato run --skill <skill-name>
# Point to a specific SKILL.md
ato run --from-skill /path/to/SKILL.md--skill and --from-skill are mutually exclusive.
- Minimal output on success (tool stdout-first)
- Prompt only when explicit consent is required
- In non-interactive environments,
-y/--yesauto-approves consent - Policy violations and unmet requirements are emitted as
ATO_ERR_*JSONL tostderr
- Required env validation: startup fails if
targets.<label>.required_env(orATO_ORCH_REQUIRED_ENVS) is missing/empty - Dangerous flag guard:
--dangerously-skip-permissionsis rejected unlessCAPSULE_ALLOW_UNSAFE=1 - Local registry write auth: when
registry serve --auth-tokenis enabled,publishrequiresATO_TOKEN - Engine auto-install: checksum retrieval/verification failures stop execution fail-closed
CAPSULE_WATCH_DEBOUNCE_MS: debounce interval foropen --watch(ms, default:300)CAPSULE_ALLOW_UNSAFE: explicit allow for--dangerously-skip-permissions(only1is valid)ATO_TOKEN: auth token for local/private registry publishATO_STORE_API_URL: API base URL forato search/ install flows (default:https://api.ato.run)ATO_STORE_SITE_URL: store web base URL (default:https://store.ato.run)ATO_TOKEN: session token for headless/CI environments
ato search ai
ato login
ato whoamiDefault endpoints:
ATO_STORE_API_URL(default:https://api.ato.run)ATO_STORE_SITE_URL(default:https://store.ato.run)ATO_TOKEN
cargo test -p capsule-core execution_plan:: --lib
cargo test -p ato-cli --test local_registry_e2e -- --nocaptureApache License 2.0 (SPDX: Apache-2.0). See LICENSE.