Metadata-Version: 2.5
Name: antioch-sim
Version: 0.4.130
Summary: Antioch simulation SDK: write typed Isaac simulations locally and run them on cloud GPUs.
Project-URL: Homepage, https://antioch.com
Project-URL: Documentation, https://console.preview.antioch.com/docs
Author: Antioch Robotics
License: Proprietary
Keywords: gpu,isaac-sim,rerun,robotics,simulation,telemetry,usd
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Physics
Classifier: Typing :: Typed
Requires-Python: <3.13,>=3.12
Provides-Extra: isaac-lab
Provides-Extra: isaac-sim
Description-Content-Type: text/markdown
Requires-Dist: click<8.5,>=8.1
Requires-Dist: cryptography<50,>=46
Requires-Dist: httpx>=0.28
Requires-Dist: ipykernel<8,>=7.3
Requires-Dist: jupyter-server<3,>=2.17
Requires-Dist: jupyterlab<5,>=4.5
Requires-Dist: nest-asyncio<2,>=1.6
Requires-Dist: pathspec<2,>=0.12
Requires-Dist: protobuf<8,>=6.33.6
Requires-Dist: pydantic<3,>=2.11.10
Requires-Dist: pyjwt<3,>=2.10
Requires-Dist: pyyaml<7,>=6.0.3
Requires-Dist: rerun-sdk==0.36.0
Requires-Dist: rich<15,>=14
Requires-Dist: tomlkit<1,>=0.13
Requires-Dist: tornado<7,>=6.5
Requires-Dist: traitlets<6,>=5.14
Requires-Dist: websocket-client>=1.9

# Antioch simulation SDK

`antioch-sim` is Antioch's typed Python SDK and CLI. Write ordinary Python in
your own project, then run it on managed cloud GPUs. Your computer needs
Python 3.12; it does not need Isaac or a GPU.

## Start a project

These examples use [uv](https://docs.astral.sh/uv/):

```bash
uv init --bare --python ">=3.12,<3.13" my-sim
uv --directory my-sim python pin 3.12
cd my-sim
uv add --compile-bytecode "antioch-sim[isaac-sim]>=0.4.130"
source .venv/bin/activate
antioch auth login
antioch init
antioch services exec python src/main.py
```

The SDK resolves from PyPI. Use `antioch-sim[isaac-lab]>=0.4.130` for Isaac
Lab 3.0. The extra installs editor types and selects the matching starter
project, not a local simulator.

`antioch init` creates the manifest, Dockerfile, source, watch rules, and
example suites. It does not start compute. `antioch services exec` starts or reuses an
interactive session and runs the command. A new session builds the current
project; use `antioch services watch` to apply later local edits.

The generated Dockerfile puts source under `/workspace/project` and pins its
engine image to the installed SDK version. Updating the local SDK does not
rewrite an existing Dockerfile. Update both when moving a project to a new
release.

## Projects, services, sessions, and runs

A **project** is a directory with one `antioch.yaml`. Its **services** are
container workloads. Service names are arbitrary: `sim` is a starter-project
convention, not a required name.

The **simulator** is a role determined by verified image lineage: an Antioch
engine image, or an image built from one. Scenarios, suites, and Jupyter need
that role. If several services use engine images, mark the intended one with
`x-antioch: {runner: true}`. A service-only project is valid too:
`antioch services exec` defaults to the simulator when present,
then to the only active service. Otherwise, select one with `--service`.

A **project revision** saves the source, manifest, and exact service images.
A **session** is temporary compute running one project's services:

- Interactive sessions support scripts, shells, watch, Jupyter, and attached
  scenario or suite runs. Placement prefers nearby available compute.
- Background sessions run detached scenarios and suites without the terminal.

A **scenario** is a typed Python evaluation with parameters, checks, and
results. A **case** names parameter values; a **suite** selects scenarios and
cases. Their saved **run records** survive session retirement. Temporary
service files do not: save results as artifacts or assets.

Mission Control provides a separate temporary development workspace. It is
a client of simulation compute, not a simulation session.

## Define services

Antioch uses a validated Compose-style manifest, not the full Docker Compose
specification. The [manifest guide](https://console.preview.antioch.com/docs/running/understand-antioch-yaml)
lists supported fields.

```yaml
id: warehouse-sim-0123456789abcdef
name: warehouse-sim
scenario_paths: ["src/scenarios.py"]

services:
  physics:
    build:
      context: .
      dockerfile: Dockerfile
    resources:
      gpu: rtx-pro-6000
    watch:
      - action: sync
        path: .
        target: /workspace/project
      - action: rebuild
        path: Dockerfile

  autonomy:
    image: registry.example.com/robot/autonomy:release
    depends_on:
      physics:
        condition: service_started
    restart: on-failure

suites:
  smoke:
    description: Fast simulation checks
    select:
      - tags: ["smoke"]
```

Each service declares exactly one `image` or `build`. A build selects a
context and Dockerfile; source enters the image through `COPY`. Services may
declare dependencies, health checks, resources, restart policies, named ports,
and profiles. Service names are also network names within the session.

An engine Dockerfile uses a versioned base:

```dockerfile
FROM antioch-engine/isaac-sim-6.0.1:0.4.130
```

Public external `FROM` bases may use tags such as `python:3.12-slim`.
Antioch freezes each base to an exact digest before computing the build key,
without changing your Dockerfile. Use `@sha256:` to select a fixed base
yourself. A new preparation can pick up a moved tag; saved revisions keep
their captured source and exact images. The manifest's `image` field may
also use a tag. A watch rebuild freezes new bases for the changed service;
unchanged services keep their previous bindings.

Antioch supplies its pinned Dockerfile frontend. Remove a leading
`# syntax=...` directive: selecting another frontend is not supported and is
refused locally before a build starts.

### Update an interactive session

Watch actions are:

- `sync`: copy matching files to a target under `/workspace`.
- `sync+restart`: copy, then restart the service.
- `sync+exec`: copy, then run a declared command with a timeout of at most
  five minutes.
- `rebuild`: capture the build context and publish a new service image when
  a local trigger path changes. This rule has no container target.

```bash
antioch services watch
antioch services restart
```

Watch respects `.gitignore`, `.dockerignore`, built-in development exclusions,
and each rule's `ignore` and `include` patterns. Watch `ignore` and `include`
patterns do not support `!` negation; use positive patterns.
If no project-root sync is declared, the CLI copies the remaining project files
automatically. That implicit copy leaves authored sync targets alone, including
their ignored files and change triggers. A rule's filters apply to its own
target, not to separate copies made by other authored rules.
After a rule syncs successfully, deleting its local file or directory removes
only the remote paths that this rule previously synced to that session.
Commands remain usable while the path is absent. Recreating it syncs the new
bytes and triggers the rule's action. A path that never existed is still an
error.

Source capture for builds has different rules. It applies the platform floor
(`.venv`, `venv`, `.git`, Python caches, and `node_modules`) plus
`.dockerignore`, not `.gitignore`. The platform floor is never traversed or
included, even for a `Dockerfile` or an explicit `!` pattern. User-ignored
directories are still visited so a later `!` pattern can retain a descendant,
and nested build contexts keep their Docker files. The selected context's
`.dockerignore` is applied again with Docker semantics. Excluded paths do not count toward
source limits. Special files (FIFOs, sockets, and device nodes) are rejected;
exclude them with `.dockerignore` if they are not needed.

## Work in a session

```bash
antioch services exec python src/main.py --seconds 60
antioch services exec --no-stream python -m src.main
antioch services exec --service autonomy -- ros2 topic list
antioch session list
antioch services ps
antioch services logs SERVICE...
antioch shell SERVICE
antioch services cp SERVICE:/workspace/project/output.png ./output.png
antioch session stop
```

Copy preserves symbolic links, including a link named as the source.

Session-scoped commands accept `--session SESSION`. Without it, selection
prefers the live session last used in this worktree, then the project's sole
live interactive session. An explicit ID selects that exact session.
`services exec` may start one when none exists; inspection commands
do not. Use `antioch session start` to start compute explicitly.

`services cp` can download owner-private files inside `/workspace/project`
without changing their modes or owners on the service. Downloads use a private
snapshot capped at 2 GiB of selected file sizes. This can refuse a large source
even when rsync would send only a small delta. Source inspection reads metadata
only. Each agent admits at most two active snapshots. Each snapshot has at most
20,000 filesystem objects and 128 path levels, including generated parent
directories; these limits also apply to metadata inspection. A busy agent
refuses the transfer without queuing it. Paths outside the project are refused.

Commands stream process output and return its exit status.
`services exec` has a 900-second default deadline; set `--timeout` to change
it. A native script starts Isaac itself, usually through
`antioch.start_simulation()`.

Pass Antioch options before the command. Everything from `python`, `bash`, or
another executable onward is literal argv, including repeated flags and `--`.
Use `--service autonomy` for a helper; a helper named `python` never changes
the meaning of `python main.py`. Use repeated `--profile PROFILE` options to
activate authored profiles when a session starts.

Exec forwards stdin until EOF and returns when the remote process exits, even
if local stdin stays open. When stdin and stdout are terminals, exec allocates
a terminal and forwards window-size changes. Use `--tty` or `--no-tty` to
override detection. Terminal output is one channel; non-terminal execution
keeps stdout and stderr separate. `antioch shell` uses the same transport for
an interactive shell. Raw commands do not create scenario or suite history.
PTYs have no write-half-close: with explicit `--tty`, local EOF sends no
synthetic Ctrl-D. Use `--no-tty` for a piped program that must read until EOF.

A session has one Isaac GUI stream. `services exec` requests it by default;
`--no-stream` runs headless and leaves it available to another process.
A second process cannot claim an occupied stream. Mission Control shows the
active stream to one viewer at a time.

Attached scenario and suite runs use authored
`SimulationConfig(stream=..., timeout_s=...)` defaults unless CLI flags
override them. Mixed or partly missing defaults across a selection require
one explicit CLI value. Native scripts honor the `start_simulation()` stream
default, but their outer process deadline remains the CLI deadline.

After `antioch.start_simulation()`, a clean exit returns 0, an uncaught
exception returns 1, and `KeyboardInterrupt` returns 130. Use `sys.exit(n)`
for an explicit status: a bare top-level `raise SystemExit(n)` in a headless
script can return 0 through Isaac's fast shutdown. Replacing
`sys.excepthook` without chaining the prior hook also replaces this error
handling.

## Use Jupyter

Start an interactive session first. Jupyter uses its simulator service and
does not create a session, change profiles, or target background compute.

```bash
antioch session start
antioch jupyter lab
antioch jupyter cell '1 + 1'
antioch jupyter cell --stream 'import antioch; antioch.start_simulation()'
antioch jupyter lab --stop
```

Lab uses the service's reserved `jupyter` route. Cells execute on its live
kernel through Jupyter's REST and WebSocket APIs; a kernel starts if needed.
JupyterLab owns kernel management. `jupyter lab --stop` stops the server and
frees its service command slot. The cell's `--stream` request applies to that
cell only.

`jupyter lab` prints and opens a private `file://` launch URL. With `--no-open`,
open that exact URL in a browser on the same computer, with access to the same
filesystem. The file signs in to the verified loopback Lab server without
printing its token. Keep the command running: its local tunnel and launch file
close when the command ends. A browser on a different computer cannot use this
local file or loopback address directly.

## Evaluate scenarios and suites

Keep Isaac imports inside functions. Scenario discovery runs locally without
a simulator. The [scenario guide](https://console.preview.antioch.com/docs/scenarios/write-scenarios)
and [shipped examples](examples/) cover authoring.

For an authored viewport image, call `antioch.capture_viewport()` between
physics steps, outside physics, render, and Kit-update callbacks. It reuses
the streamed editor viewport and performs at most four render-only updates
to complete that request, returning RGB pixels or `None` if no frame arrives.
It never returns an earlier call's cached image. These updates do not advance
physics, but render completion alone does not establish scene synchronization
or image quality. Callback contexts are unsupported and are not automatically
detected. Automatic streamed recording remains asynchronous and does not pump
renders from its physics callback.

```bash
antioch scenario collect
antioch scenario run --scenario falling_cube --set drop_height=4.5
antioch suite collect
antioch suite run smoke
antioch suite run smoke --detach
antioch scenario show SCENARIO_RUN_ID
antioch scenario download SCENARIO_RUN_ID
antioch scenario rerun SCENARIO_RUN_ID
antioch scenario cancel SCENARIO_RUN_ID
```

Submission uses the selected interactive session and stays attached by
default. `--detach` admits the work to background compute and returns;
`--detach --follow` also watches progress. `--parallel` fans a detached suite
out within the user's capacity. Suites also have `show`, `rerun`, and
`cancel` commands.

Following a scenario or suite shows progress and verdicts, not process output.
Add `--verbose` to include captured output, including Isaac startup logs.
`--no-stream` controls the viewer stream; it does not control terminal logs.
Direct commands (`antioch services exec`) still stream their
process output by default.

If artifact upload or terminal acknowledgement fails, managed scenarios keep
their default recording and runner output in an owner-private directory under
the project and report its path. Recover that directory with `services cp`
before the session stops. The retained files are not durable artifacts.
Explicit recording paths and unmanaged local runs keep their chosen location.

Submission displays its current phase in one transient line. Redirected
output and `TERM=dumb` use plain phase changes instead of animation;
`FORCE_COLOR` never adds terminal controls to a pipe. `NO_COLOR` disables
color without disabling progress. `--json` follows emit only NDJSON frames,
with no human progress mixed in.

Help stacks option descriptions in narrow terminals. Verbose follow separates
CLI messages from an unfinished child line on stderr, without adding bytes to
redirected stdout, native exec output, or JSON frames. After Ctrl-C, human
progress stays quiet while the CLI waits for the saved terminal outcome.

Ctrl-C during an interactive run requests cancellation and waits for the saved
terminal outcome. A second Ctrl-C stops waiting and prints the follow command.
Both presses remain responsive while a follow read is waiting for a response.
Remote cancellation and cleanup are not confirmed until the saved result says
they are complete. The summary reports the session's current state; cancelling
a run does not stop its interactive session. Ctrl-C while following detached
work only stops following it. During submission, an interruption stops the
client; if admission may already have reached Rome, the CLI gives the identity
to inspect. A remote build that has started can continue after the client exits.

A decorated scenario's Python callable omits the injected run argument and
returns `run.results`. In an Antioch-managed session command, calling it
creates a saved run with telemetry and artifacts. Outside a managed command,
it stays local: text is immediate, telemetry is temporary, and artifacts are
unavailable.

A rerun gets a new ID and reuses the original revision, service images,
parameters, and selection. It does not rebuild or resolve moving tags.
Exact inputs do not guarantee the same outcome or timing: scheduling,
simulator behavior, and external asset availability can differ.

## Assets and immutable builds

Assets are named file versions from your organization or Antioch's shared
library. Pin their versions for repeatable evaluations.

```bash
antioch assets list
antioch assets show ASSET
antioch assets pull ASSET --version ASSET_VERSION --output ./asset.usdz
antioch assets push ./asset.usdz --name ASSET --version ASSET_VERSION
antioch assets verify ASSET --version ASSET_VERSION
antioch project build
antioch project revision list
```

Python offers `antioch.fetch_asset`, `antioch.load_asset`, and
`antioch.save_asset`. Project builds need no simulation session. They
finalize immutable revisions and reuse a cached build only when its
content-derived key matches an immutable digest and the expected OCI labels.
Revision tags name existing revisions; moving one does not rebuild anything.

A failed build reports a bounded build-log tail in the terminal error and
the JSON error's `message`. Reading that tail does not retry the build.
If the retained log is unavailable, the build failure still reports its
operation ID and cause. JSON `retryable` carries the build operation's verdict.

## Command help and scripts

Use `antioch --help` or a command's `--help` for the current option list.
Most non-interactive commands support `--json`: data goes to stdout,
diagnostics to stderr. Repeatable mutations return a top-level
`changed` boolean. An already-complete action exits 0 with
`changed: false`, rather than reporting a second mutation.

### Private staging SDK

Staging uses Antioch's Google Artifact Registry Python index. Your account
must belong to the staging SDK reader group. Authenticate with the
[Google Cloud CLI](https://cloud.google.com/sdk/docs/install), then install
the credential helper:

```bash
gcloud auth login
uv tool install keyring --with keyrings.google-artifactregistry-auth
uv tool update-shell
```

Open a new terminal. Verify that the helper can obtain a short-lived
credential without printing it:

```bash
keyring get \
  "https://us-central1-python.pkg.dev/antioch-poc-2607/sdk/simple/" \
  oauth2accesstoken >/dev/null
```

Add this credential-free configuration to the project's `pyproject.toml`:

```toml
[tool.uv]
keyring-provider = "subprocess"

[tool.uv.sources]
antioch-sim = { index = "antioch-staging" }

[[tool.uv.index]]
name = "antioch-staging"
url = "https://oauth2accesstoken@us-central1-python.pkg.dev/antioch-poc-2607/sdk/simple/"
explicit = true
authenticate = "always"
```

Replace `<sdk-version>` below with the exact version approved for the staging
deployment. Use the same command to install, upgrade, or downgrade:

```bash
uv add --compile-bytecode "antioch-sim[isaac-sim]==<sdk-version>"
```

The fixed username `oauth2accesstoken` is not a credential. This configuration
writes neither an access token nor another secret to the project or lockfile.
Commit `pyproject.toml` and `uv.lock`; authorized readers can reproduce the
environment with `uv sync --frozen`.

The index retains candidates and historical wheels, so an unpinned install
is not an approved-release selector. Installing an old wheel does not
guarantee that staging still serves a compatible runtime. Check the selected
SDK with `antioch --version` and keep the project's engine tag in sync.

For `401 Unauthorized`, check that `keyring` is on `PATH` and repeat
`gcloud auth login`. For `403 Forbidden`, check reader-group membership and
the active account. An existing `GOOGLE_APPLICATION_CREDENTIALS` setting or
Application Default Credentials login can select a different identity. See
the [Artifact Registry authentication guide](https://docs.cloud.google.com/artifact-registry/docs/python/authentication)
and [uv's Google integration guide](https://docs.astral.sh/uv/guides/integration/google/).

The full customer guide is in the
[Antioch docs](https://console.preview.antioch.com/docs/quickstart/welcome-to-antioch).
