For the complete documentation index, see llms.txt. This page is also available as Markdown.

Claude Code

Claude Code is an agentic coding assistant that can read, edit, test, and debug code from a terminal. On ExCL systems, run Claude Code inside an isolated environment rather than directly from your normal home directory.

The ExCL Claude Code sandbox is available at:

Repository: https://code.ornl.gov/7ry/claude-hpc

Quickstart

Clone the repository and run Claude Code in three steps:

git clone git@code.ornl.gov:7ry/claude-hpc.git
cd claude-hpc
make install

Then launch Claude Code from any repository:

cd /path/to/repository
claude-hpc .

To use an Ubuntu 24.04 base image, Slurm commands (squeue, sbatch, etc.), and/or Lmod modules inside Claude, switch to the slurm branch before building:

git checkout slurm

Run Claude Code inside an Apptainer container with:

  • A throwaway home directory

  • Only the current repository bind-mounted

  • No access to your real ~/.ssh, ~/.aws, ~/.kube, ~/.docker, or ~/.gnupg

  • Claude Code permissions (or Auto mode) as a second safety layer

While Claude Code includes its own permission system and command sandboxing, Anthropic notes that the built-in sandbox does not isolate every tool, MCP server, or hook. Running the entire Claude Code process inside an Apptainer container provides an additional security boundary while preserving a normal development workflow.

Installation

Clone the repository:

Build the container

The container definition is provided in claude-code.def.

Build the Claude Code image:

The first build automatically creates the base image if it does not already exist.

To rebuild only the base image (system packages, LaTeX, ripgrep, etc.):

Install Claude Code

Install Claude Code into the persistent container home so it can update itself independently of the container image:

This sets the npm prefix to ~/.local inside the persistent home and installs @anthropic-ai/claude-code there. Because the persistent home is writable, Claude Code can download and apply updates on its own without rebuilding the container.

To update Claude Code later, run make install-claude again, or let Claude Code update itself automatically.

Install the launcher

Install the launcher script, copy the image, and install Claude Code into the persistent home:

This installs:

  • claude-hpc into ~/bin

  • the Apptainer image into ~/.containers/images (copied with rsync -ah --progress)

  • Claude Code into the persistent home via make install-claude (skipped if already installed)

Running Claude Code

From the repository you want Claude to work on:

The launcher automatically:

  • mounts the repository as /work

  • uses a persistent isolated home located at

  • starts Claude Code inside the Apptainer sandbox

Available Make Targets

The repository provides several convenience targets:

Target
Description

make build

Build the Claude Code image (builds the base image if necessary)

make build-base

Build the base image containing system tools

make run

Run Claude Code

make remote

Run Claude Code with --remote-control

make danger

Run Claude Code with --dangerously-skip-permissions

make shell

Open a Bash shell inside the container

make install

Install the launcher and image

make install-claude

Install Claude Code into the persistent home (user-updatable)

make install-uv

Install uv into the persistent Claude home

make show-home

Print the path to the persistent Claude home

make clean-home

Delete the persistent Claude home (reset authentication and settings)

Override the working directory when using the make targets:

First-time Login

The first time Claude Code starts, authenticate normally.

Authentication is stored inside the persistent container home rather than your real home directory.

For normal development:

or

Claude can then inspect code, implement features, fix bugs, write documentation, generate tests, and perform code reviews.

Remote Control Mode

To allow IDE integrations or other remote clients to control Claude Code, start it with:

or

Because the container home persists between runs, remote clients can reconnect without re-authenticating.

Dangerous Mode

Normally Claude Code asks for confirmation before performing potentially destructive actions.

To disable those prompts:

or

Only use this mode:

  • inside the Apptainer sandbox

  • on disposable branches or worktrees

  • in repositories that do not contain sensitive credentials

Do not run:

directly on the host.

Working in a Temporary Worktree

For experimental changes:

Review changes before merging:

Read-only Data Mounts

Reference datasets can be mounted read-only. When mounting from ExCL Shared project storage, always bind the specific subdirectory the agent needs rather than the entire project tree.

claude-hpc forwards extra arguments to Claude Code, not to apptainer, so additional bind mounts must be specified via the APPTAINER_BINDPATH environment variable, which apptainer merges with its own --bind flags automatically.

Inline — set the variable for a single run:

Multiple paths are comma-separated:

direnv — automatically set the bind path whenever you enter the repository:

For multiple directories, separate paths with a comma:

Then allow it once:

After that, claude-hpc . picks up the bind mount automatically in any shell that enters the directory.

Mount the narrowest subdirectory that satisfies the task. Do not bind /auto/projects/<project> or any other large shared tree when only a subdirectory is needed.

What Not to Mount

Do not expose your real home directory or credential stores to the container.

Avoid mounting:

ExCL Shared Project Storage

Do not mount the ExCL Shared project storage unless Claude actually needs to read files from it. Even then:

  • Mount read-only (:ro) — never give the agent write access to shared storage.

  • Mount only the specific subdirectory required, not the project root or any parent directory.

  • Prefer copying or symlinking the specific files into your work directory when only a few files are needed.

Scenario
Mount

Claude needs to inspect one dataset

--bind "/auto/projects/<project>/datasets/foo:/data:ro"

Claude needs to read a config file

copy the file into your repo; no bind needed

Claude is writing or building code

no shared-storage mount needed

Mounting more than necessary increases blast radius if the agent misbehaves and increases the risk of accidental reads of unrelated project data.

Normal development:

or

Remote control:

Dangerous mode (sandbox only):

Temporary worktree:

Sub-Agents

Claude Code can spawn background sub-agents to handle tasks in parallel (for example, during multi-agent code review or long-running searches). Before exiting, stop any active agents through the Claude Code interface.

Pressing Ctrl+C will interrupt Claude and reveal whether any background agents are still running, but it does not stop them. You must explicitly stop each active agent before exiting to avoid leaving orphaned agent processes behind. Press Ctrl+C a second time to exit Claude Code.

Best Practices

Isolating uv virtual environments

If you use uv and work on the same repository both on the host and inside the container, UV_PROJECT_ENVIRONMENT needs to be set inside the container's persistent home so Claude creates its own .venv instead of reusing (or clobbering) the one from your host checkout. make install-uv sets this automatically by appending to ~/.containers/homes/claude-hpc/home/.profile:

This matters because the container cannot see the uv-managed files stored under your real home directory (e.g. ~/.cache/uv, ~/.local/share/uv), so a virtual environment created on the host will not resolve correctly from inside the container, and vice versa. Giving Claude a distinct environment directory avoids that mismatch and keeps the two environments from interfering with each other.

Notes

Claude Code's permission system and the Apptainer sandbox serve different purposes:

  • Permissions determine whether Claude is allowed to perform an action.

  • Sandboxing limits what Claude can access after the action is performed.

Neither replaces the other. Running Claude Code inside an Apptainer container while leaving Claude's permission system enabled provides a secure default for ExCL development while minimizing changes to existing workflows.

Last updated

Was this helpful?