Skip to content

CLI (experimental)

@aml-jsx/cli runs an AML workflow source file without a separate application entry point. It loads TypeScript, TSX, or JavaScript through Vite and vite-node, resolves one exported AML value, evaluates it, and prints the result.

The CLI deliberately owns only process-level concerns:

  • loading a trusted workflow module;
  • applying Vite-style environment files before the module is evaluated;
  • selecting the default, main, or requested named export;
  • creating an AmlRuntime, evaluating the exported AML value, and formatting the result;
  • translating process interruption into runtime cancellation so active resources can be released;
  • writing lifecycle and optional trace diagnostics to standard error.

Provider selection and provider-specific options belong in the workflow file. The CLI does not have --agent-provider, --sandbox-provider, model, credential, or Workspace configuration flags.

Install the CLI beside the SDK used by the workflow:

Terminal
npm install @aml-jsx/sdk
npm install --save-dev @aml-jsx/cli

Run it through the project-local executable:

Terminal
npx aml run ./workflow.tsx

From an AML repository checkout, contributors can build and invoke the workspace copy directly:

Terminal window
npm run build --workspace=@aml-jsx/cli
node apps/cli/dist/index.js run ./workflow.tsx

Export an AML renderable directly or export a zero-argument function that returns one. The current CLI creates the AmlRuntime; the module does not export a runtime instance.

workflow.tsx
import { Agent } from "@aml-jsx/sdk"
import { DeterministicAgentProvider } from "@aml-jsx/sdk/testing"
const provider = new DeterministicAgentProvider({
name: "cli-example",
respond: request => ({ text: `Reviewed: ${request.prompt}` }),
})
export default <Agent provider={provider}>README.md</Agent>

This credential-free example prints Reviewed: README.md. Replace the deterministic provider with a supported Agent provider when the workflow is ready to call a live model. Keeping provider construction in the module makes the executable workflow self-contained: another runner can import the same tree, inspect its provider construction, or evaluate it with application-owned infrastructure later.

The command resolves and executes one export in this order:

  1. Use the export selected by --entry, when supplied.
  2. Otherwise use the module’s default export.
  3. Otherwise call an exported main() function.
  4. Await a selected function or promise and validate that it resolves to an AML renderable.

A function can build the tree after environment variables have been loaded:

workflow.tsx
import { Agent, opencodeAgent } from "@aml-jsx/sdk"
export default function ReviewRepository() {
const model = process.env.AML_MODEL
const OpenCode = opencodeAgent(model ? { model } : {})
return <Agent provider={OpenCode}>Review this repository and list the three highest-risk changes.</Agent>
}

The workflow file is the positional argument immediately after run. --entry selects an export inside that file; it does not replace the file argument. Select a different named export when one module contains several entry points:

Terminal
aml run ./workflow.tsx --entry releaseReview

Before importing the workflow, the CLI reads Vite-style environment files from the directory containing the workflow file—not necessarily the process’s current working directory. The mode is NODE_ENV, or development when NODE_ENV is absent.

Project layout
project/
├── .env.ci # explicit override selected from the current directory
└── src/
├── workflow.tsx
├── .env # workflow-local base values
├── .env.local # workflow-local machine values
├── .env.development
└── .env.development.local

Existing process environment values win over values in these files. An explicitly selected runtime environment file is applied last and can override both:

Terminal
aml run ./workflow.tsx --runtime-env-file .env.ci

The option is named --runtime-env-file because modern Node.js interprets --env-file before the AML command receives its arguments. Relative override paths are resolved from the current working directory first, then from the workflow directory.

One module can expose several jobs while keeping provider and environment choices in source. This credential-free example selects one named export and echoes its resolved prompt:

src/automation.tsx
import { Agent } from "@aml-jsx/sdk"
import { DeterministicAgentProvider } from "@aml-jsx/sdk/testing"
const provider = new DeterministicAgentProvider({
name: "ci-example",
respond: request => ({ text: request.prompt }),
})
export const releaseReview = (
<Agent provider={provider}>Review the {process.env.RELEASE_CHANNEL ?? "preview"} release.</Agent>
)
export const dependencyReview = <Agent provider={provider}>Review dependency updates.</Agent>

Put RELEASE_CHANNEL=stable in src/.env, then apply a job-specific override from the process working directory:

.env.ci
RELEASE_CHANNEL=release-candidate
Terminal
npx aml run ./src/automation.tsx \
--entry releaseReview \
--runtime-env-file .env.ci \
--json \
--trace

The JSON result containing Review the release-candidate release. is written to standard output. Lifecycle and metadata-only trace events go to standard error; prompt and result content remain redacted unless --capture-content is supplied explicitly.

The CLI intentionally has one compiler path: Vite and vite-node. It creates a one-shot Vite transform environment, loads the trusted module with source-map support, closes that environment, and then evaluates the selected AML value. There is no --compiler abstraction. A second loader should only be introduced if native platform evidence demonstrates a compatibility gap that Vite cannot address.

Normal output stays easy to pipe: the resolved workflow result is written to standard output, while run lifecycle and trace diagnostics are written to standard error.

Terminal
aml run ./workflow.tsx > result.txt

Use --json for a machine-readable result envelope containing runId, durationMs, success, and result:

Terminal
aml run ./workflow.tsx --json

Use --trace to print metadata-only trace events. Prompt and result content remains redacted unless content capture is requested explicitly:

Terminal
aml run ./workflow.tsx --trace
aml run ./workflow.tsx --trace --capture-content

--capture-content is an AML CLI option, not an ACP option or Agent capability. Treat its output as sensitive. It can include prompts, Agent messages and thoughts exposed through ACP, raw Tool activity, plans, structured results, <Tool /> input and output, commands, errors, and filesystem context. See Observability for the complete event and redaction contract.

aml run translates SIGINT (usually Ctrl+C) and SIGTERM into cancellation of the active runtime evaluation. The signal reaches Agent sessions, ACP requests, MCP relays, and Sandbox operations through the evaluation’s AbortSignal. AML then closes active sessions and releases acquired resource scopes before the CLI exits.

The first signal starts graceful cancellation and allows up to 10 seconds for cleanup. When cleanup settles, the CLI exits with the conventional signal status: 130 for SIGINT or 143 for SIGTERM. A second SIGINT or SIGTERM exits immediately instead of continuing to wait. If cleanup has not settled after 10 seconds, the CLI also forces termination with the first signal’s status.

Cleanup follows provider ownership. AML orchestrates cancellation and invokes the acquired lease’s release boundary; the Sandbox provider decides how to stop its platform-specific resources. Local kills tracked process groups, Docker removes its leased container, and disposable remote providers terminate or delete their remote environment. A provider backed by intentionally persistent infrastructure should terminate evaluation-owned executions and release only the evaluation lease, not destroy the shared infrastructure.

Command or optionBehavior
aml run <file>Load and evaluate one trusted TS, TSX, or JS workflow module.
-e, --entry <name>Select a named export instead of the default export resolution.
--runtime-env-file <file>Apply one explicit environment file after Vite-style environment loading.
--traceWrite metadata-only runtime trace events to standard error.
--capture-contentInclude sensitive trace content and imply --trace.
--jsonEmit a JSON result envelope instead of plain workflow text.
-h, --helpShow CAC-generated command help.
-v, --versionShow the CLI package, platform, architecture, and Node versions.

The experimental CLI is useful for local workflows, repository automation, scheduled jobs with explicit environment injection, and examples that should run without handwritten new AmlRuntime().evaluate(...) glue.

Prefer an application-owned runner when you need to inject runtime defaults, attach custom event sinks, share one runtime configuration across requests, coordinate service shutdown, or expose AML behind an API or queue consumer. Read Deployment for that pattern.