Verified against aomi-sdk@08b21f9 on 2026-06-29.
cli feature builds aomi-build; the dev-runtime feature builds aomi-run. Install with --features cli alone and you get only aomi-build, not aomi-run. These binaries have no --version flag; run aomi-build --help (or --help on either of them) to confirm the install.
These are not standalone crates or npm packages, so there is no
aomi-run to find on crates.io or npm. They are binaries built from the aomi-sdk crate, which is why the install command points at that crate and uses feature flags to choose which binaries you get.aomi-build is the single CLI: it scaffolds, compiles, deploys, and activates. aomi-run exercises a built plugin locally.
aomi-build
Scaffold from an OpenAPI spec, compile the plugin, deploy your source through the backend, and activate the release. This is where an App is born and how it ships.
aomi-run
Chat with your compiled plugin against a real LLM, locally, with no backend. This is how you sanity check tool behavior.
You can run either of these without installing. Prefix with
cargo run -p aomi-sdk --features cli --bin aomi-build --, or --features dev-runtime --bin aomi-run --. The install is just a convenience.Which tool, when
1
Build
Use aomi-build to turn an OpenAPI spec into a compiled plugin (a
cdylib). It scaffolds the app crate, generates a typed client, stubs one tool per endpoint, and compiles. You then curate the tools by hand. End with a passing test.json.2
Run
Use aomi-run to chat with that compiled plugin locally. It loads the
.dylib, reads its manifest, and opens a REPL wired to Anthropic, OpenAI, or OpenRouter. No backend, no deploy. You watch which tools the model picks and how they respond.3
Ship
Use aomi-build to publish. First
connect installs the Aomi GitHub App on your source repo and saves your activation token. Then deploy sends a deploy request to the backend, which reads your source through that install, opens a pull request, and CI builds and cuts a release. activate then tells a backend to load that release. You run activate yourself, using your activation token.aomi-build
aomi-build scaffolds, compiles, and end to end tests an App. The full path from “external API docs” to “tested plugin” is a six stage pipeline. Every stage runs on its own, and new-app is the one shot orchestrator for the first stages plus the compile.
test.json authoring in stage 6 are done with the authoring skills, not the binary.
Subcommands
aomi-build is the single CLI for the whole life of an App. Running it with no subcommand launches an interactive wizard that walks connect then deploy then activate.
Build and scaffold:
Deploy and activate:
Here
<p> is the platform slug, for example petstore or khalani.
Flags
Spec generation stages default to app local: every artifact lives under
apps/<p>/. Pass --shared only when several Apps wrap the same upstream (say, multiple Apps over one exchange) and should reuse one client under ext/.Scaffold and compile a new App
- From an OpenAPI spec
- Bare skeleton
- Compile existing apps
new-app finishes, the App compiles but its tools are mechanical, one per endpoint, with machine names. You make it useful by curating the tool layer (stage 4) with the authoring skills, then rebuilding.
aomi-build compile builds the apps inside an aomi-sdk style workspace and writes them into plugins/. If you are building a single standalone App crate, the kind you publish to community-apps, you do not need aomi-build. Build it with cargo build --release and find the plugin in target/release/.Sharpen and validate the spec
The end to end test
Each App carries one canonical e2e spec atapps/<platform>/test.json. It describes a real LLM run: an optional wallet seed, a list of user prompts, the tools expected per turn, optional wallet callbacks, and a final state assertion. The runner lives in the backend repo, not here. You point it at your compiled plugin with an env var:
test.json shape (abridged)
test.json shape (abridged)
The spec runs turn by turn. Two limits worth knowing. Host tools (
expected_tools checks must_call (all listed) or any_of (at least one). final_assertion checks the user state, tool responses, and turn cap.stage_tx, simulate_batch, commit_txs) carry a model set topic arg, so listing them in must_call will not match; the runtime fires them internally during routed enforcement. And a terminal wallet:tx_complete callback consumes pending_txs, so assert max_count: 0 after a callback rather than min_count: 1.aomi-run
aomi-run loads a compiled plugin and opens an interactive REPL against a real LLM, locally, with no backend required. It is how you feel out whether the model reaches for the right tools before you ever ship.
There are no subcommands. You pass the plugin path as the one positional argument, then a handful of flags.
aomi-run prints a summary of what it loaded, stubs any host namespaces the plugin asked for, and opens the REPL. The block below is illustrative, not literal output, and the version reflects the current SDK line (3.0.x):
tools line lists your App’s own tools. The namespaces line and the ⚙ stubbed line show the host capabilities the dev runtime stands in for, since the real backend is not present. Inside the REPL, /help lists commands and /quit exits.
aomi-run calls a real LLM, so it needs a provider key in your environment. With the default Anthropic provider, set ANTHROPIC_API_KEY before you run. aomi-run checks for the key before it even loads the plugin. Pass --env-file to load it from a dotenv file.Flags
claude-sonnet-4-6 for Anthropic, gpt-5 for OpenAI, and anthropic/claude-sonnet-4 for OpenRouter. The provider’s API key must be present in the environment (or in --env-file); aomi-run checks for it before it even loads the plugin.
Deploy and activate with aomi-build
The deploy half ofaomi-build publishes your App source through the backend, then activates the resulting release. The CLI never clones a platform repo or pushes branches. It is a thin relay: deploy POSTs to the backend, and the backend reads your source through the connected Aomi GitHub App, opens a pull request, and lets CI build the cdylib and cut the release.
Run these from your source repo, the crate that holds aomi.toml and src/lib.rs.
The backend identifies your source through the GitHub App install, recorded as
app_source_id. The deployed App lands at apps/<installation-id>/<repo-key>/<app>/ on the community-apps publish branch, and CI publishes a release tagged apps-<installation-id>-<repo-key>-<app>-<short-commit>.connect
The first step for a new contributor.connect installs the Aomi GitHub App on your source repo and saves the activation token you use to activate releases. Run it once, before your first deploy.
installation_id GitHub shows you. After that, every deploy reads your source through this install.
deploy
deploy sends POST /api/platforms/:platform/deploy carrying your app_source_id. The backend reads your source through the GitHub App, opens a pull request, and CI builds and publishes the release. A successful deploy writes .aomi/deployment.json with the backend’s deployment record, including the release tags activate reads later.
--dry-run is an alias of --preflight. Both preview the plan and run the checks without deploying.status
status reads .aomi/deployment.json and, when a backend URL is configured, reports the backend load state for each release tag.
activate
Run by the app author with the activation token saved duringconnect. It tells the backend to fetch a release by tag, validate it, and load it. Run it from your source repo and it reads the release tags from .aomi/deployment.json, so usually you set only AOMI_APP_ACTIVATION_TOKEN and AOMI_BACKEND_URL and run aomi-build activate.
activate sends POST /api/platforms/:platform/apps/activate. By default it uses the release tags recorded in .aomi/deployment.json.
When you pass app names with
--release-tag, their count must match the tag count, and the backend verifies each app name matches its release tag.The validation pipeline
Everydeploy, including --dry-run, runs a validation pipeline and records the result in .aomi/deployment.json. It runs in four ordered stages. Each stage is a precondition for the next, so a failing gate short circuits the rest and downstream stages are recorded as skipped.
Stages 1 and 2 are offline, computed from local git and aomi.toml. Stages 3 and 4 are online: they only run when a backend URL is available, and otherwise stay skipped.
Each check is
error (a gate that fails the stage and should block the deploy) or warn (advisory; downgrades the stage to warning but does not block). The two warn checks are git_declared and git_url_matches_platform, since a backend lookup can supply the repo and forks are tolerated. The big one to watch is branch_matches_contract: if your target branch is not the platform’s contractual deployment_branch, the push will not auto deploy.
What a passing preflight looks like
What a passing preflight looks like
The human summary prints one line per stage:A stage rolls up to
passed (all checks passed), failed (an error check failed, blocked here), warning (only warn checks failed), or skipped (an upstream gate failed or inputs were absent, such as no backend URL).The deployment.json artifact
.aomi/deployment.json is the deployment record the backend writes back next to your aomi.toml after a successful deploy. It carries the resolved plan and the release tags, and three independent state flags:
deployed: the backend accepted the deploy and opened the pull request that CI builds.activated: the backend wrote the app row withis_active = true.
--dry-run deploy previews the plan and runs the checks but does not record a deploy. activate reads this file for its defaults, including the release tags, so running it from the same directory as a prior deploy lets you drop most flags.
Related
Building an App
The full authoring walkthrough, from spec to curated tools to test.
SDK reference
The Rust plugin SDK that your App compiles against.
Client CLI
The npm
aomi command for chatting with and driving a deployed App from your terminal.