Download these instructions as Markdown

Container apps

Use this guide to install and register apps inside an existing Outer Shell container, whether you edit its Dockerfile directly or use a coding agent.

Connect to the container

In Outer Shell, choose Add more… → Coding agent under the container and copy the prompt. Outer Loop includes the SSH command and the command to enter that specific container. You can also use the container terminal’s Copy SSH command action. Run that complete command from your computer; a host-only SSH connection does not enter the container.

If your coding agent already runs inside the container, work there directly. Check the environment before installing anything. The instructions below assume an Outer Shell-enabled image with outerctl installed. Host apps use the general integration API instead.

Configure the container

You are configuring an OCI container managed by Outer Shell. You may install software, create services, and otherwise change this container as needed for the user’s request.

Use the publishing reference below for app integration. Your working directory is /work; keep experiments and notebooks here unless the user selects another mounted or persistent directory.

Preserve the result

The reproducible source of truth is the ordinary Docker build context mounted at /var/lib/outershell/project. Its Dockerfile is:

/var/lib/outershell/project/Dockerfile

When a requested change should survive a rebuild or move to another server, edit that Dockerfile and any files beside it. Prefer portable, noninteractive, idempotent Dockerfile instructions. A root process may edit this project directly. Do not create a second recipe or initialization system.

After recording a durable change, prefer to mirror it in the running container so the user can use it immediately. For example, install the same packages, write the same configuration, create the same directories, and start or restart the affected service in the live instance. The Dockerfile remains the source of truth; a live-only change is not complete.

You have two acceptable ways to finish a durable change:

  1. Preferably, update the Dockerfile and mirror the result in the live container. Tell the user that the change is available now and will also be reproduced by future rebuilds.
  2. Ask the user to rebuild the container when mirroring is impossible, unsafe, or significantly more difficult than rebuilding. Explain why the rebuild is needed.

Do not make the user rebuild merely because the Dockerfile changed. Build-only instructions such as COPY, ENV, USER, and VOLUME may require a rebuild, but mirror their intended effect when a safe runtime equivalent exists. Do not run Docker, container, or another host container engine from inside this container.

Folder mounts, persistent volumes, environment variables, and secrets are runtime configuration owned by Outer Shell. Do not add, remove, or change host mounts from inside the container. Treat explicitly mounted user folders as user data and modify their contents only when the request calls for it. Never put credentials or secret values in the Dockerfile or image.

Publish tools in Outer Shell

Outer Shell support is installed in this image. Use build-time outerctl image commands in the Dockerfile so published tools return after every rebuild:

  • outerctl image add-app publishes a browser or Outerframe app backed by a managed service.
  • outerctl image add-command publishes a command-line tool whose launch command can be copied from Outer Shell.

Read the publishing reference below before adding or changing a published tool. Use stable, descriptive IDs. Reference icon files by absolute path with --icon-path; there is no built-in icon-name registry.

After editing the Dockerfile, summarize both the durable change and anything you mirrored into the live container. Ask the user to use Outer Shell’s Rebuild action only when the live result could not reasonably be produced. Do not claim a newly declared app or command is available until it has been published in the running container or by a rebuild.


Publishing container tools with outerctl

outerctl image records portable declarations in an OCI image. These commands are intended for Dockerfile RUN instructions: they do not need a running outershelld, and they do not start software during the image build. When the container starts, Outer Shell’s internal service manager reads the declarations and publishes them to the server-level Outer Shell.

Publish an app

RUN outerctl image add-app \
    --id ID \
    --name "Display Name" \
    [--url /initial/path] \
    [--working-directory /absolute/path] \
    [--icon-path /absolute/path/icon.png] \
    (--socket-argument=OPTION | --tcp-port PORT) \
    -- /absolute/path/to/server [ARGUMENTS...]

Use exactly one transport:

  • --socket-argument=OPTION starts the executable with an additional OPTION=/run/user/0/org.outershell.image.ID argument. Use this when the server can listen directly on a Unix socket.
  • --tcp-port PORT starts the declared server and publishes its loopback TCP port through a Unix socket. The image must provide bash and socat.

The service starts eagerly with the container and is restarted after failure. Its logs are exposed through Outer Shell. --url defaults to /, and --working-directory defaults to /root.

Example:

RUN outerctl image add-app \
    --id jupyter-work \
    --name "JupyterLab: work" \
    --url /lab \
    --working-directory /work \
    --socket-argument=--ServerApp.sock \
    -- /opt/venvs/default/bin/jupyter-lab \
        --allow-root \
        --no-browser \
        --ServerApp.sock_mode=0600 \
        --IdentityProvider.token= \
        --ServerApp.password= \
        --ServerApp.root_dir=/work

Publish a command-line tool

RUN outerctl image add-command \
    --id ID \
    --name "Display Name" \
    [--working-directory /absolute/path] \
    [--user USER] \
    [--icon-path /absolute/path/icon.png] \
    -- /absolute/path/to/executable [ARGUMENTS...]

Outer Shell displays the declaration under COMMAND LINE TOOLS. Selecting it copies a host command that opens the tool interactively inside this container. The working directory defaults to /root, and the user defaults to root.

Example:

COPY codex-cli.png /usr/local/share/outershell/icons/codex-cli.png

RUN outerctl image add-command \
    --id codex \
    --name "Codex CLI" \
    --working-directory /work \
    --user root \
    --icon-path /usr/local/share/outershell/icons/codex-cli.png \
    -- /usr/local/bin/codex --dangerously-bypass-approvals-and-sandbox

Rules and inspection

  • IDs contain 1–48 letters, digits, periods, underscores, or hyphens.
  • Executables, working directories, and icon paths are absolute paths inside the image.
  • Icon files must already exist when outerctl image runs. Common bitmap formats are supported; keep the file at or below 512 KB.
  • Use a different stable ID for each distinct launcher.
  • Add declarations to the Dockerfile. Running them only in a live container is not a reproducible configuration and does not replace an Outer Shell rebuild.
  • outerctl image list-commands prints the command declarations in the current image for machine consumption.

The installed outerctl prints its usage synopsis when an invalid declaration is rejected. Treat that binary as authoritative if it differs from this file.

Local instructions

OpenCode container installations bundle /usr/local/share/outershell/container-agent.md and /usr/local/share/outershell/OUTERCTL.md for automatic context and offline use. This page is generated from the same source files.