Environment

Prepare a repository once, then let every session start from the right place.

Ara sessions run in cloud sandboxes. A repository’s Environment is the saved definition of the box its sessions run in. At the start of each session, Ara boots the Image and injects your repo, secrets, tools, and guides on top of it. The Image is built from a Recipe, base, env, and setup steps, just like a Dockerfile.

1Image: # the container each session boots
2 built from a Recipe: # base · env · setup
3
4injected on top, each session:
5 Repo: # your code, cloned in (Clone options)
6 Secrets: # encrypted org / repo secrets
7 MCP servers: # tools + OAuth (Sentry, Linear)
8 Ara skills: # the agent's skill library
9 Session Start Script: # deps + codegen, every session
10 Runbook: # "how this repo runs" guide
11 Knowledge: # reference docs for the prompt

If you know Docker: the Recipe is your Dockerfile and the Image is the built image. base is your FROM, env bakes in variables, setup is your RUN steps. Everything injected on top is per session, so changing it never rebuilds the Image.

A concrete example

acme-ara / acme-monorepo, a Bun app with a little Python tooling:

1Image: # built once from this Recipe, then pinned
2 base: python
3 env: PYTHONUNBUFFERED=1
4 setup: uv pip install ruff mypy # baked in
5
6injected each session:
7 Repo: acme-ara/acme-monorepo → /work
8 Secrets: DATABASE_URL, STRIPE_SECRET_KEY
9 MCP servers: Sentry, Linear # your OAuth
10 Ara skills: built-in skill library
11 Session Start: bun install; bun run prisma generate
12 Runbook: "Run bun test before a PR"
13 Knowledge: test → bun test, lint → bun run lint

Only the Recipe (base, env, setup) becomes an Image and needs a build. Secrets and MCP tools are injected fresh each session, so rotating a key or adding a tool never rebuilds anything.

Use an Environment when a repo needs more than a plain clone. The fastest setup is usually a small Session Start Script. Move only stable, expensive work into the Recipe’s setup steps.

The concepts

NameWhat it is
EnvironmentThe per-repo (or org-wide) definition of everything below. Saved as one YAML spec.
RecipeThe buildable part of the Environment, like a Dockerfile. Made of base, env, and setup steps.
ImageThe built instantiation of the Recipe: a per-repo container image, built once and reused.
Active ImageThe pinned Image your sessions actually boot from.
Session Start Scriptsession_start steps that run after a session claims its sandbox, inside the cloned repo. Not baked into the Image.
Pool PrepareAra’s platform-owned phase when a sandbox starts or enters the warm pool: sync the repo, prepare the workspace, and preboot runtime services.
Ara Base ImagesCurated bases maintained by Ara: Full (default), Slim, Python.
Custom Base ImagesAny public Docker image as your base, Ara adds its runtime layer automatically.

Recipe → Build → Image → Pin

The Recipe is declarative, like a Dockerfile. A Build turns it into an Image, and you pin a successful build to make it the Active Image your sessions boot from.

Recipe ──build──▶ Image ──pin──▶ Active Image
(base + (a built (what cold
env + container starts boot
setup) image) from)

Only changes to base, env, or setup (the initialize key) require a new build. Editing the Session Start Script, Knowledge, or Clone never does. If a pin is missing, stale, or invalid, Ara falls back to the default base image so a bad build never bricks the repo.

Where each part runs

1. Recipe (build)

base, env, and setup steps are baked into the Image at build time. This runs once per build, not per session.

2. Pool Prepare

Ara syncs the repo and prepares a warm sandbox before it can be claimed.

3. Session Start Script

Repo-specific setup runs after a session claims the sandbox, with runtime secrets available.

The Recipe: base, env, and setup

The Recipe is the part of the Environment that becomes an Image. Its setup steps (the initialize key) run at build time, not on every session. Non-secret environment variables go in env, and base selects what everything is built on.

1base: python
2
3env:
4 PYTHONUNBUFFERED: "1"
5
6initialize: # setup steps -> baked into the Image
7 - name: Install Python search dependencies
8 run: uv pip install --system faiss-cpu numpy tiktoken
9
10session_start: # runs every session, not baked
11 - name: Install repo dependencies
12 run: bun install

Use setup steps for stable, expensive tools that do not need the current repo checkout:

  • system packages and language toolchains
  • large Python wheels
  • global CLIs
  • browser or desktop support packages

Do not put repo-lockfile installs in setup; the repo checkout is not part of the Image. Keep bun install, pnpm install, uv sync, and similar commands in the Session Start Script unless they are intentionally global and independent of the repository.

Do not bake credentials into the Image, not in setup steps and not in env. Secret-shaped env names (*_TOKEN, *_SECRET, *_PASSWORD, *_API_KEY, *PRIVATE_KEY) are rejected outright. Steps that need secrets belong in the Session Start Script, where the session’s encrypted secrets are sourced at runtime. env values must be scalars (string, number, or boolean).

Session Start Script

session_start compiles into a shell script that runs in the cloned repository after a session claims the sandbox. It is not baked into the Image, so editing it takes effect on the very next session with no rebuild.

1session_start:
2 - name: Install Bun dependencies
3 run: bun install

The Session Start Script is launched in the background after the repository is cloned and the run’s secrets are available. It does not block the first model token. If the agent reaches a command before setup is done, it receives a note to retry or install what is missing.

Use the Session Start Script for anything that tracks the current repository state:

  • package installs from the lockfile
  • code generation
  • Prisma or ORM generation
  • private registry auth
  • commands that need repo files or run secrets

Base Images

The base key selects what the Recipe is built on.

Ara Base Images

1base: python
2
3session_start:
4 - name: Install project dependencies
5 run: uv sync
BaseNameUse it when
tier0FullYou want the complete default Ara image: Codex, browser/desktop stack, and full-stack toolchain. This is the default.
slimSlimYou want the smallest image with Codex, git, and GitHub CLI essentials, without the browser/desktop stack.
pythonPythonYou want Slim plus Python tooling such as uv, pipx, and build dependencies.

Custom Base Images

Any public Docker image works as a base, write a full image reference instead of a catalog name:

1base: debian:bookworm-slim
2
3initialize:
4 - name: Install my toolchain
5 run: apt-get update && apt-get install -y my-toolchain

Ara automatically appends its runtime layer (the sandbox API, Codex, git, and the GitHub CLI) on top of your base, so any image becomes session-capable without manual setup. A few rules apply:

  • The image must be publicly pullable (private registries are not supported).
  • It must be amd64 and Debian-family (the runtime layer uses apt-get; Alpine/musl bases fail the build).
  • Compressed size is capped at 5 GiB.
  • Before a Custom Base Image can be pinned, Ara boot-tests it: the image must start and pass a runtime check. A failing image is rejected at pin time and your repo keeps its previous Active Image.

A base-only Recipe (no setup steps) still goes through the build-and-pin workflow, so boot behavior is identical whichever parts you use.

A practical Environment

Start with a Session Start Script. Promote only the slow, stable pieces into the Recipe’s setup steps once you see them repeated across sessions.

1base: python
2
3env:
4 PYTHONUNBUFFERED: "1"
5
6initialize:
7 - name: Install global analysis tools
8 run: uv pip install --system ruff mypy
9
10session_start:
11 - name: Install app dependencies
12 run: bun install
13 - name: Generate database client
14 run: bun run prisma generate
15
16knowledge:
17 - name: test
18 contents: Run `bun test` before opening a pull request or merge request.
19 - name: lint
20 contents: Run `bun run lint` for style and type checks.

knowledge is never executed. It remains declarative Environment reference data; it is not copied into the retired Knowledge product or into native Codex memory.

Apply an Environment

You can manage environment setup from the app, or through the API. The API shape below is enough for the common flow; the full request and response schemas live in the API Reference.

1

Save the Environment

$curl https://api.ara.so/v3/organizations/$ORG_ID/environment/recipe \
> -X PUT \
> -H "Authorization: Bearer $ARA_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "repo_name": "acme/web",
> "contents": "session_start:\n - name: Install Bun dependencies\n run: bun install\n"
> }'
2

Preview the Session Start Script

This shows the exact script Ara will run at the start of the next session.

$curl "https://api.ara.so/v3/organizations/$ORG_ID/environment/session-start-script?repo=acme/web" \
> -H "Authorization: Bearer $ARA_API_KEY"
3

Build and pin when the Recipe changes

A pure Session Start Script needs no Image. If you use setup steps (initialize), env, or a non-default base, trigger a build and pin a successful result to make it the Active Image.

$curl https://api.ara.so/v3/organizations/$ORG_ID/environment/builds \
> -X POST \
> -H "Authorization: Bearer $ARA_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{ "repo_name": "acme/web" }'
$curl https://api.ara.so/v3/organizations/$ORG_ID/environment/builds/$BUILD_ID/pin \
> -X POST \
> -H "Authorization: Bearer $ARA_API_KEY"

What goes where

Put it inFor
session_startSession Start Script: repo-dependent work, lockfile installs, generated files, secret-backed setup.
initializeThe Recipe’s setup steps: stable tools and expensive global installs that should be baked into the Image once.
envNon-secret Recipe values baked into the Image.
baseAn Ara base (tier0, slim, python) or any public image as a custom base.
knowledgeHuman-readable Environment reference data. It is not executed and is separate from native Codex memory.
cloneRepo-tier clone overrides such as ref, depth, submodules, tags, and LFS.