Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

outrig image

outrig image groups commands for the container images that host an agent’s tools. outrig image add scaffolds a repo-local image-config (a named Dockerfile + MCP-server bundle); outrig image init scaffolds a standalone image project whose build output is a reusable image, outrig image build builds and validates that project, and outrig image inspect reads an image’s declared labels locally by default, or from a registry with --remote. The rest of the group (image ls, image rm) is reserved for later.

outrig image add

outrig image add scaffolds a new image-config. It writes a Dockerfile under .agents/outrig/images/<name>/Dockerfile and appends matching [images.<name>] and [images.<name>.mcp] blocks to your repo’s config.toml.

Run it any time you want to add an image-config – e.g., a planning config alongside the <repo>-standard one outrig init creates by default. init calls image add in a loop for the first (and any further) image-configs you create during initial setup.

Bootstrapping a fresh repo

If you run outrig image add in a directory without an .agents/outrig/config.toml (neither here nor in any parent), outrig prompts before scaffolding:

[outrig] no .agents/outrig/config.toml found in /path/to/repo or any parent.
? Configure outrig in this directory now? [Y/n]:

Answering y walks the same repo-config prompts that outrig init uses (workspace, default agent, preamble), then continues with the image add flow. Answering n exits with the same error a strict find would have produced – run outrig init later when you’re ready.

Synopsis

outrig image add [<name>] [--force]
Argument / flagDefaultDescription
<name>promptedImage-config name (becomes [images.<name>]).
--forceoffOverwrite existing Dockerfile/config entries for this name.

Run it

Every prompt shows the default in [default: ...]; press Enter to accept it. Type ? and Enter at any prompt for an explanation of what’s being asked plus the available options. The default image-config name is <repo-folder>-standard (kebab-cased), so the example below assumes a hello-outrig repo.

$ cd hello-outrig
$ outrig image add
? Image-config name [default: hello-outrig-standard]:
? Base image [default: debian:bookworm-slim]:
? Language toolchains [default: ]: rust, node
? MCP servers [default: fs]:

[outrig] wrote .agents/outrig/images/hello-outrig-standard/Dockerfile
[outrig] added [images.hello-outrig-standard] block to .agents/outrig/config.toml
[outrig] added [images.hello-outrig-standard.mcp] entries: fs

Next: try `outrig build` to verify the image builds, then `outrig run`.

The prompts are intentionally limited – the goal is a known-good starting point you can edit by hand, not an exhaustive Dockerfile generator.

Help at any prompt

? Language toolchains [default: ]: ?

  Pick zero or more language toolchains to install in the image. The Dockerfile
  template adds the corresponding install steps; you can edit the file afterwards.

  rust    rustup + stable toolchain (cargo, rustfmt, clippy).
  node    Node 20 LTS via NodeSource.
  python  CPython 3.12 with pip and venv.
  go      Go 1.22.
  none    Just the base image -- nothing extra installed.

  See: https://tgockel.github.io/outrig/usage/image.html#known-toolchains

? Language toolchains [default: ]:

Known toolchains

The toolchain prompt offers curated options that cover the common cases:

ChoiceWhat gets installed
rustrustup + the stable toolchain, cargo, rustfmt, clippy.
nodeNode 20 LTS via the base image’s package manager (or NodeSource).
pythonCPython 3.12 with pip and venv.
goGo 1.22.
noneJust the base image.

You can pick more than one. The Dockerfile is a starting point – edit it freely afterwards.

Known MCP servers

  • fs – installs @modelcontextprotocol/server-filesystem from npm; default [mcp] entry: { command = ["mcp-server-filesystem", "/workspace"] }.
  • git – installs mcp-server-git from PyPI; default [mcp] entry: { command = ["mcp-server-git", "--repository", "/workspace"] }.

fs is the default. Add git for repo-aware tools, or wire up additional servers by editing the [images.<name>.mcp] block directly – see Concepts -> MCP Servers. A shell MCP server is the usual next tool for coding image-configs; choose a package, install it in the Dockerfile, and declare its command in [images.<name>.mcp].

TODO: Incomplete – the list of “known MCP servers” will grow as the ecosystem does. Anything not listed here you install in the Dockerfile by hand.

When templates do not fit

The prompt flow is intentionally small. If you need an image with a database, internal SDK, unlisted MCP server, or other custom package set, use outrig mcp self. It gives an MCP-capable AI tool the OutRig docs, config schema, suggested tools, and advisory validators so it can propose a Dockerfile and matching [images.<name>] block without being limited to the built-in template menu.

What gets written

.agents/outrig/images/hello-outrig-standard/Dockerfile (excerpt):

FROM docker.io/library/debian:bookworm-slim

RUN apt-get update \
 && apt-get install -y --no-install-recommends \
      ca-certificates curl git build-essential passwd \
 && rm -rf /var/lib/apt/lists/*

# rust toolchain
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
       | sh -s -- -y --default-toolchain stable --profile default
ENV PATH=/root/.cargo/bin:$PATH

# node toolchain
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
 && apt-get install -y --no-install-recommends nodejs \
 && rm -rf /var/lib/apt/lists/*

# MCP servers
RUN npm install -g @modelcontextprotocol/server-filesystem

WORKDIR /workspace
CMD ["sleep", "infinity"]

The Dockerfile is generic – no USER directive, no hard-coded UID. outrig sets up a user matching your host UID/GID at run time (see Concepts -> Workspace). The passwd package keeps useradd/groupadd available for that bootstrap step.

Appended to .agents/outrig/config.toml:

[images.hello-outrig-standard]
dockerfile = ".agents/outrig/images/hello-outrig-standard/Dockerfile"
context    = ".agents/outrig/images/hello-outrig-standard"

  [images.hello-outrig-standard.mcp]
  fs = { command = ["mcp-server-filesystem", "/workspace"] }

Re-running

Without --force, outrig refuses if either the Dockerfile path or the config block already exists for that name:

$ outrig image add hello-outrig-standard
error: .agents/outrig/images/hello-outrig-standard/Dockerfile
       already exists; pass --force to overwrite.

With --force, the Dockerfile is replaced and the [images.<name>] block is rewritten in place (preserving surrounding TOML).

outrig image init

outrig image init scaffolds a standalone image project: a self-contained directory whose build output is a reusable container image. Unlike image add, it writes no repo config – it creates three files and nothing else:

  • Dockerfile – a Debian-slim image with the filesystem MCP server, ending in the standard CMD ["sleep", "infinity"]. It installs the tool binaries; it does not copy OutRig config.
  • image.toml – the standalone image authoring config: [image].ref plus a [mcp] table. outrig image build validates this file and stamps the [mcp] table into the image’s OCI labels, which outrig reads back at session startup and merges with any repo [images.<name>.mcp].
  • README.md – how to build the image and reference it from a repo.

The command is noninteractive – there are no prompts. The project name (used as [image].ref) defaults to the target directory’s name.

Synopsis

outrig image init [<dir>] [--force]
Argument / flagDefaultDescription
<dir>current dirProject directory; its name becomes the image ref.
--forceoffOverwrite the generated files if they already exist.

The directory name must match ^[a-zA-Z][a-zA-Z0-9_-]*$ (e.g. rust-dev). A target that resolves to no usable name is rejected; . and the no-argument form use the current directory’s name.

What gets written

$ outrig image init rust-dev
[outrig] wrote rust-dev/Dockerfile
[outrig] wrote rust-dev/image.toml
[outrig] wrote rust-dev/README.md
[outrig] next: build this image with `outrig image build`

rust-dev/image.toml:

[image]
ref = "rust-dev"

[mcp]
fs = { command = ["mcp-server-filesystem", "/workspace"] }

[build] is omitted, so the build defaults to the sibling Dockerfile with context ..

Consuming the image from a repo

Once built, reference the image from a repo’s config.toml with image-name. Because the MCP server declarations are stamped into image labels, the consuming block needs no [images.<name>.mcp]:

[images.rust-dev]
image-name = "rust-dev"

That authoring split is the key difference from image add: repo-local blocks keep their [images.<name>.mcp] entries in config.toml and stamp them into cache image labels when built; standalone projects carry the declarations in image.toml so the image can be consumed elsewhere without repo-local MCP config. See Concepts -> Containers for the image-name shape.

Re-running

Without --force, init refuses if any of the three files already exists, naming the conflicts:

$ outrig image init rust-dev
error: rust-dev/Dockerfile, rust-dev/image.toml, rust-dev/README.md
       already present; pass --force to overwrite.

--force regenerates the three files and leaves anything else in the directory untouched.

outrig image build

outrig image build builds a standalone image project (the output of outrig image init) and validates that the result is a working OutRig toolset image. It is the standalone-project counterpart to outrig build, which builds repo-local image-configs.

It reads the project’s image.toml, serializes it into OCI labels, builds the declared Dockerfile with buildah, and tags the result with the [image].ref from image.toml – stamping those labels onto the image. Then it always validates the built image, and – unless --no-test – live-tests every MCP server the image declares.

Synopsis

outrig image build [<dir>] [--tag <ref>] [--no-test] [--no-cache]
Argument / flagDefaultDescription
<dir>current dirProject directory holding image.toml.
--tag <ref>[image].refBuild tag override; does not edit image.toml.
--no-testoffSkip the live MCP test; still validates image.toml.
--no-cacheoffForce a clean build; passed through to buildah.

What it does

$ outrig image build rust-dev
[outrig] building image rust-dev
[outrig]   dockerfile: Dockerfile
[outrig]   context:    .
... buildah build output ...
[outrig] image ready
[outrig] image config validated (1 mcp server)
[outrig] mcp fs: initialized (12 tools)
[outrig] image ok

After the build, outrig reads the stamped org.outrig.mcp label back off the built image and validates it (every server name well-formed, every command non-empty). By default it then starts the image, and for each declared MCP server initializes it and calls tools/list, reporting the tool count per server. The image is built locally; nothing is pushed.

Failure modes

The command exits nonzero – printing error: ... – in these cases:

  • image.toml missing, malformed, or missing required fields (no [image].ref, an empty or invalid [mcp] table, a partial [build]): caught before the build runs.
  • The stamped org.outrig.mcp label is missing or malformed: read back off the built image and validated after the build, even with --no-test.
  • A declared MCP server cannot initialize or return tools/list: caught during the live test. --no-test skips this check (the per-server stderr is captured in the error message).

--no-test

--no-test skips only the live MCP server test. The stamped org.outrig.mcp label is still read back from the built image and validated, so a missing or malformed config still fails. Use it to verify a build quickly, or in environments where starting the servers is not wanted.

--tag and --no-cache

--tag <ref> tags the build output as <ref> for that invocation instead of the [image].ref in image.toml; the file is never rewritten. Short refs are passed to buildah verbatim, so both rust-dev and rust-dev:0.1.0 work.

Unlike repo-local outrig build – which tags <image-config-name>:<content-hash> and skips the build on a cache hit – a standalone build tags a stable, caller-named ref with no content hash, so there is no project-level cache to skip: --no-cache only forwards --no-cache to buildah to force a clean build.

outrig image inspect

outrig image inspect prints the OutRig config labels declared by an image. It is read-only: local mode checks the local image store and reads labels with podman image inspect; remote mode uses skopeo inspect against a registry. Neither mode pulls image layers, creates a container, or starts an MCP server. Live initialization and tools/list checks belong to outrig image build.

Synopsis

outrig image inspect [--remote] <ref>
ArgumentDescription
<ref>Image ref to inspect. Never pulled.
--remoteRead registry metadata with skopeo inspect.

Output

The command writes only the inspect result to stdout. Diagnostics and errors go to stderr.

$ outrig image inspect rust-dev
image: rust-dev
description: Rust tooling
version: 0.1.0
tags: ["rust","build"]
mcp:
  fs:
    command: ["mcp-server-filesystem","/workspace"]
  db:
    command: ["db-mcp"]
    env:
      TOKEN: "${DB_TOKEN}"

description, version, and tags appear only when the image carries those labels. If the image has no org.outrig.mcp label, inspect still prints the image ref and any metadata labels it finds, then omits the mcp: section.

Repo-local images built by outrig build, outrig run, or outrig mcp are stamped with an org.outrig.mcp label on cache misses. For those <image-config-name>:<hash> refs, inspect shows the merged MCP declarations from inherited/Dockerfile labels plus [images.<name>.mcp], without starting a container. Standalone images may additionally show description, version, and tags.

Use --remote when the ref is in a registry and you want the labels without pulling it:

outrig image inspect --remote ghcr.io/acme/rust-dev:latest

Remote inspection requires skopeo on PATH. Authentication uses the normal container credentials that skopeo reads, such as credentials created by skopeo login, podman login, buildah login, or docker login.

Failure modes

The command exits nonzero – printing error: ... – in these cases:

  • The image is not present locally: inspect reports a local-only not-found error and does not attempt a pull.
  • --remote is used but skopeo is not installed: inspect reports the missing runtime dependency.
  • The registry request fails: skopeo errors, including missing credentials or denied access, are reported with the command and stderr tail.
  • The remote ref uses an unsupported transport: use a plain registry ref or docker://<ref>.
  • A declared OutRig label is malformed: invalid org.outrig.tags or org.outrig.mcp values fail before anything is started.

See also