Four deployment methods: one-shot bootstrap (recommended for new installs), Docker Compose (manual), bare-metal, or K3s.
The install steps depend on your hardware + OS. Find the row that matches your setup, then jump to the linked section.
| Your hardware | OS | Recommended path | Support level (matrix) |
|---|---|---|---|
| NVIDIA RTX 50-series / Blackwell (B100, GB10) | Linux | Method 0: bootstrap or Method 1: Docker | Supported — published CUDA image targets Blackwell |
| NVIDIA RTX 20/30/40, GTX 10xx, datacenter (V100/A100/H100/T4/L4) | Linux | Method 1: Docker + one-time local rebuild | Preview — local rebuild required |
| NVIDIA GPU | Windows (WSL2) | Method 1: Docker — NVIDIA section | Unsupported — untested, no claims made; reports welcome |
| AMD GPU (RX 6000/7000, MI200+) | Linux | Method 1: Docker — AMD ROCm | Community-tested (GH #26) |
| Apple Silicon (M1/M2/M3/M4) | macOS | SETUP_MACOS.md (dedicated guide — hybrid native Metal + Docker) | Supported (maintainer-verified, M2 Pro) |
| Intel Arc / Iris Xe | Linux | Method 1: Docker — Vulkan | Preview — Vulkan is smoke-tested on lavapipe only; no real-GPU validation yet |
| Snapdragon X Elite (laptops) | Linux | Vulkan + arm64 section | Preview (Linux arm64). Windows on ARM is Unsupported |
| Older AMD GPU (Vega, RDNA1, no ROCm 6.x) | Linux | Method 1: Docker — Vulkan | Preview |
| NVIDIA on ARM64 (DGX Spark, Jetson) | Linux | arm64 section (CUDA via sbsa/l4t base swap) | Preview — build recipes provided, no device validated end-to-end yet (#115) |
| Raspberry Pi 5 | Linux | Vulkan + arm64 | Preview — expect CPU-tier perf |
| Intel Mac (pre-2020) | macOS | Method 1: Docker — Vulkan | Unsupported — requires Docker Desktop (untested); Metal is Apple-Silicon-only |
| CPU only, no GPU | any | CPU-only install | Preview — smoke-test only, very slow |
| Kubernetes cluster | Linux | Method 3: K3s | Preview — templates CI-validated; no automated live-cluster test |
| Bare-metal / development | Linux | Method 2: Bare Metal | Preview — manual validation only |
Don't see your setup? File an issue with uname -a output and lspci | grep -i vga (Linux) / system_profiler SPDisplaysDataType (Mac) and we'll add a row.
Single curl command that detects your distro, installs Docker + nvidia-container-toolkit, downloads model weights, and brings the stack up. Idempotent — safe to re-run.
NVIDIA pre-Blackwell GPUs (RTX 20/30/40-series, GTX 10xx, V100/A100/T4/L4/H100): read this first. The published
atlas-llamaCUDA image is compiled for compute capability120;121(Blackwell — RTX 50xx, B100, GB10) only. On older NVIDIA GPUs llama-server will fail at startup withno kernel image is available for execution on the device. Rebuild the inference image once for your GPU's architecture:# find your arch (drop the dot: 8.6 -> 86) nvidia-smi --query-gpu=compute_cap --format=csv,noheader docker compose build --build-arg CUDA_ARCH=86 llama-server # example: RTX 30xx docker compose up -d --no-deps llama-serverFull arch table: CUDA Compute Capability.
curl -fsSL https://raw.githubusercontent.com/inferstep/ATLAS/main/scripts/atlas-bootstrap.sh | bashOr, from a checkout:
./scripts/atlas-bootstrap.shSupported distributions:
| Family | Distros |
|---|---|
| Debian (apt-get) | Ubuntu 20.04+, Debian 11+ |
| RHEL (dnf) | RHEL 9+, Rocky 9+, AlmaLinux 9+, CentOS Stream 9+, Oracle Linux 9+ |
| Fedora (dnf) | Fedora 38+ |
Other distros with ID_LIKE matching one of the above (e.g. Linux Mint, Pop!_OS) are accepted with a warning. Distros not in this list — Arch, openSUSE, Alpine, NixOS — aren't tested and the script will refuse to run on them.
The bootstrap works around EPEL, nouveau driver conflicts, the missing-libnvidia-ml.so.1 case (RHEL minimal installs), and the "user added to docker group but current shell doesn't see it yet" race.
Model selection: .env.example ships with no model selected. When the bootstrap creates .env and ATLAS_MODEL_FILE is empty, it writes the registry's default recommended model into .env (logged as it happens) so the one-shot flow completes without a wizard. Change the selection any time by editing .env or running atlas init. An existing non-empty selection is respected.
CPU-only / no-GPU hosts (Preview — smoke-test only). ATLAS boots without a GPU via the Vulkan image's lavapipe CPU rasterizer, but inference is very slow; use this to verify the stack works, not for real coding sessions.
- The bootstrap refuses no-GPU hosts unless you opt in:
ATLAS_BOOTSTRAP_SKIP_GPU=1 ./scripts/atlas-bootstrap.shIt layersdocker-compose.vulkan.yml(+docker-compose.cpu.ymlwhen/dev/driis absent), writes the model selection andATLAS_BACKEND=vulkan|cpuinto.envitself, and skips the ASA build. - Do not run
atlas initon a GPU-less host — the wizard intentionally refuses (exit 1) rather than write a.envit can't size. The bootstrap handles model selection; change models later viaatlas model install.
Manual equivalent:
cp .env.example .env # set ATLAS_MODEL_FILE / ATLAS_MODEL_NAME
atlas model install Qwen3.5-9B-Q6_K
docker compose -f docker-compose.yml -f docker-compose.vulkan.yml -f docker-compose.cpu.yml up -d
atlas doctor # gpu check WARNS ("CPU-only mode — very slow"); warns exit 0Firewall: the Compose stack publishes every service on 127.0.0.1 only, so local use needs no firewall change and the bootstrap leaves firewalld alone by default. Set ATLAS_BOOTSTRAP_OPEN_FIREWALL=1 to open the service ports (8090, 8099, 8070, 30820) for deployments that rebind services to a routable interface.
Run modes — both work:
# Run as your normal user; sudo elevates as needed (Docker install, etc).
# Install ends up owned by you.
curl -fsSL https://raw.githubusercontent.com/inferstep/ATLAS/main/scripts/atlas-bootstrap.sh | bash
# Run via sudo. SUDO_USER is detected, install still ends up owned by you.
curl -fsSL https://raw.githubusercontent.com/inferstep/ATLAS/main/scripts/atlas-bootstrap.sh | sudo bash
# Real root login (no sudo) — install owned by root. Only do this if there's
# no human user on the box (CI runner, container, etc).Cautious-install variants (same script; for anyone who'd rather not
pipe a moving main script into bash):
# Pinned to a release: fetch the script AT the tag and install that tag.
# The checkout is pinned to the (SSH-signed) tag and ATLAS_IMAGE_TAG is
# pinned to the matching cosign-signed images.
curl -fsSL https://raw.githubusercontent.com/inferstep/ATLAS/v3.1.6/scripts/atlas-bootstrap.sh \
| ATLAS_BOOTSTRAP_REF=v3.1.6 bash
# Review before running: download, read, then execute the same bytes.
curl -fsSL -o atlas-bootstrap.sh https://raw.githubusercontent.com/inferstep/ATLAS/main/scripts/atlas-bootstrap.sh
less atlas-bootstrap.sh
bash atlas-bootstrap.shConfiguration env vars:
| Flag | Effect |
|---|---|
ATLAS_BOOTSTRAP_SKIP_DOCKER=1 |
Don't install Docker (already managed) |
ATLAS_BOOTSTRAP_SKIP_GPU=1 |
Skip the GPU runtime install (NVIDIA toolkit or ROCm setup). |
ATLAS_BOOTSTRAP_SKIP_MODELS=1 |
Don't download model weights |
ATLAS_BOOTSTRAP_SKIP_COMPOSE=1 |
Don't run docker compose up |
ATLAS_BOOTSTRAP_SKIP_ASA=1 |
Skip the ASA steering-vector build (default: built ~5 min after services come up; skipped automatically when no GPU is available) |
ATLAS_BOOTSTRAP_OPEN_FIREWALL=1 |
Open the service ports in firewalld (default: off — services bind loopback) |
ATLAS_BOOTSTRAP_NO_SUDO=1 |
Fail instead of attempting sudo |
ATLAS_BOOTSTRAP_REF=vX.Y.Z |
Pin the install to a git tag/sha instead of tracking main; a vX.Y.Z value also pins ATLAS_IMAGE_TAG to the matching images |
ATLAS_INSTALL_DIR=/path |
Where to clone (default /opt/atlas — see below) |
ATLAS_REPO_URL=https://... |
Alternate repo URL |
ATLAS_GO_VERSION=1.26.2 |
Go toolchain version installed for the TUI build (the TUI needs 1.26.2+; older installed toolchains auto-fetch it) |
Why /opt/atlas? It's the standard FHS prefix for system-wide third-party software, survives $HOME cleanup, and lets multiple users on the same box share one install. If you'd rather it land in your home dir:
curl -fsSL https://raw.githubusercontent.com/inferstep/ATLAS/main/scripts/atlas-bootstrap.sh \
| ATLAS_INSTALL_DIR=$HOME/atlas bashWhen complete, prints a green "ATLAS ready" banner with quick-start commands. Total time on a fresh VM with a fast connection: ~10-30 minutes (model download dominates).
If you'd rather do each step manually, use Method 1 below.
| Requirement | Details |
|---|---|
| GPU | 16 GB+ VRAM. NVIDIA (CUDA, Supported — the published image targets Blackwell; older cards need a one-time local rebuild); AMD (ROCm, Community-tested); Apple Silicon (Metal, macOS hybrid, Supported — see SETUP_MACOS.md); Vulkan (Preview) is the cross-vendor fallback; Intel Arc (SYCL) is Roadmap. See § Supported GPUs. |
| GPU drivers | NVIDIA: proprietary drivers (nvidia-smi should show your GPU). AMD: amdgpu-dkms kernel driver (/dev/kfd must exist; rocm-smi should show your GPU). |
| Python 3.9+ | With pip |
| curl | For downloading model weights |
| Model weights | A registry or BYO GGUF that fits the host. atlas init recommends one and writes the selection to .env. |
NVIDIA:
nvidia-smi
# Should show your GPU with driver version and VRAM
# If this fails, install NVIDIA proprietary drivers firstAMD:
rocm-smi --showproductname --showmeminfo vram
# Should show your GPU model and total VRAM
# If rocm-smi is missing or /dev/kfd doesn't exist, install ROCm:
# RHEL 9: sudo dnf install -y https://repo.radeon.com/amdgpu-install/6.2/rhel/9.4/amdgpu-install-6.2.60200-1.el9.noarch.rpm
# sudo amdgpu-install --usecase=dkms,rocm
# Ubuntu: Follow https://rocm.docs.amd.com/projects/install-on-linux/
# Then REBOOT.Autodetect — let atlas tier autodetect across vendors and tell you what it found:
pip install -e .
atlas tier # prints detected GPU, tier classification, recommended settings
atlas tier --json # machine-readable (used by atlas init wizard)This is the most heavily exercised deployment method: CI validates the compose files and drives the full control plane deterministically (fake inference), and releases are smoke-tested under Compose on real hardware. Real GPU inference behavior is validated on the cards listed in the hardware table below, not in GitHub-hosted CI.
NVIDIA (CUDA):
- Docker with nvidia-container-toolkit, or Podman with the same toolkit
- ~20 GB disk space (model weights + container images)
AMD (ROCm):
- Docker alone — ROCm doesn't need a separate container runtime; passthrough via
--device=/dev/kfd --device=/dev/driis enough - Your user must be in the
videoandrendergroups:sudo usermod -aG video,render $USER(then re-login) - ~22 GB disk space (ROCm image is ~2 GB larger than the CUDA equivalent)
- 30-60 min for the first
up: the ROCm llama-server image is compiled on your machine rather than pulled (see AMD ROCm — what's different)
# 1. Clone
git clone https://github.com/inferstep/ATLAS.git
cd ATLAS
# 2. Install the ATLAS CLI (puts `atlas` in ~/.local/bin)
pip install --user -e .
# Make sure ~/.local/bin is on your PATH so `atlas` resolves:
case ":$PATH:" in *":$HOME/.local/bin:"*) ;; *)
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
;; esac
# 3. Select/install a model and write model-aware runtime sizing
atlas init
# 4. Install Go 1.26.2+ — required for the TUI client (atlas tui) and
# optional for the proxy (proxy builds automatically on first run if Go
# is present; otherwise it runs in Docker with file access limited to
# ATLAS_PROJECT_DIR). Quickest path:
mkdir -p /tmp/go-install && cd /tmp/go-install
curl -LO https://go.dev/dl/go1.26.2.linux-amd64.tar.gz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.26.2.linux-amd64.tar.gz
echo 'export PATH="/usr/local/go/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
cd -
# Then build the TUI:
cd tui && go build -o ~/.local/bin/atlas-tui . && cd ..
# 5. Review the environment generated by `atlas init`
# ATLAS_MODEL_FILE and ATLAS_MODEL_NAME identify this installation's
# selected model; they are intentionally not project-wide defaults.
${EDITOR:-vi} .env
# 6. Start all services (first run builds container images — this takes several minutes)
# NVIDIA hosts (default):
docker compose up -d # or: podman-compose up -d
# AMD ROCm hosts:
docker compose -f docker-compose.yml -f docker-compose.rocm.yml up -d
# `atlas init` writes a marker comment into .env telling you which to use.
# 7. Verify everything is healthy (wait for all services to show "healthy")
docker compose ps
# 8. Start coding (from your project directory)
cd /path/to/your/project
atlasThe ROCm path is identical to NVIDIA except for these four points:
-
Bring up with both compose files (or let
atlas initdo it for you):docker compose -f docker-compose.yml -f docker-compose.rocm.yml up -d
The override switches the llama-server image to the ROCm build, swaps the NVIDIA driver request for
/dev/kfd+/dev/dripassthrough, and forcesATLAS_BACKEND=rocmso the entrypoint takes the HIP-tuning branch. -
The llama-server image is built on your machine, not pulled. GHCR carries prebuilt CUDA and Vulkan llama images; there is no published
atlas-llama-rocm, because CI has no AMD GPU to test one on (ROCm is Community-tested — see SUPPORT_MATRIX.md). The override declarespull_policy: build, sodocker compose pullskips llama-server and theupabove compiles it frominference/Dockerfile.rocm: 30-60 min the first time, seconds afterwards from the layer cache. Every other ATLAS service still pulls its prebuilt image as usual. To build it ahead of time:docker compose -f docker-compose.yml -f docker-compose.rocm.yml build llama-server
-
No
nvidia-container-toolkit— ROCm doesn't need a separate container runtime, just kernel-level device access. Confirm your user is in the right groups:id -nG | tr ' ' '\n' | grep -E '^(render|video)$' # Should print both. If not: sudo usermod -aG video,render $USER # Then log out + back in (or: newgrp render)
-
GPU compute target. The default
Dockerfile.rocmbuild is a "fat" image covering RDNA3 (7000 series), RDNA2 (6000 series), and CDNA2 (MI200) —gfx1100;gfx1101;gfx1102;gfx1030;gfx90a. For a smaller image targeted at your specific GPU, setATLAS_GFX_TARGETbefore building:# Example: only build for RX 7900 XT/XTX ATLAS_GFX_TARGET=gfx1100 docker compose -f docker-compose.yml -f docker-compose.rocm.yml build llama-serverSee LLVM AMDGPU processor table for the gfx target of your card.
For "I have an unsupported GPU but ROCm sort-of works on it" cases (older Vega, RDNA1), see TROUBLESHOOTING.md § AMD GPU not detected for the ATLAS_HSA_OVERRIDE_GFX_VERSION workaround.
When the native vendor backend isn't packaged for your hardware (Intel Arc, Snapdragon Adreno, older AMD without ROCm 6.x), Vulkan is the fallback. One Dockerfile covers AMD (Mesa RADV), Intel (Mesa ANV), NVIDIA (nvidia-container-toolkit), Apple (MoltenVK via macOS Docker), Snapdragon (Adreno), and CPU (Mesa lavapipe).
Tradeoff: typically 20–40% slower than tuned native backends. Use it when CUDA/ROCm isn't an option, or to smoke-test whether ATLAS boots on unusual hardware.
# Option A — let atlas init pick it for you
# (the wizard offers Vulkan when your GPU vendor's native backend isn't packaged,
# or run with --backend vulkan to force it regardless of vendor):
atlas init --backend vulkan
docker compose -f docker-compose.yml -f docker-compose.vulkan.yml up -d
# Option B — already-installed deployment, just switch the override file:
docker compose -f docker-compose.yml -f docker-compose.vulkan.yml up -d
# (the entrypoint dispatches on ATLAS_BACKEND, which the compose overlay
# sets to vulkan; .env's value is ignored when the overlay is in play)What's different from CUDA/ROCm:
- No vendor-specific kernel driver requirement. Vulkan ICDs live inside the image (
mesa-vulkan-driverscovers AMD/Intel/CPU; NVIDIA's ICD comes from the nvidia-container-toolkit mount). /dev/dripassthrough only — no/dev/kfd, no--gpus all(unless you're routing through the NVIDIA toolkit, in which case both still work).- Per-GPU selection via
ATLAS_VK_DEVICE_SELECTinstead ofCUDA_VISIBLE_DEVICES/HIP_VISIBLE_DEVICES. Format is Mesa-standard:"vendorID:deviceID"(hex) or a substring of the device name.GGML_VK_VISIBLE_DEVICES(numeric index) also works. atlas doctorruns a_check_vulkan_via_dockerprobe — but only whenATLAS_BACKEND=vulkanis set (otherwise it skips to keep CUDA/ROCm runs fast).
If you hit vulkaninfo showing only the llvmpipe CPU device when you expected a GPU, the kernel-side device passthrough failed — verify /dev/dri/renderD* exists on the host and your user is in the video + render groups (same as the ROCm requirement above).
ATLAS targets two CPU architectures: x86_64 (default, all backends available) and aarch64 (a subset of backends). Verify with atlas doctor — the arch check surfaces your architecture and which backends are available before the GPU check fires.
Backend availability by architecture:
| Backend | x86_64 | aarch64 | Notes |
|---|---|---|---|
| CUDA | yes (rockylinux9 base) | yes (sbsa or l4t base, build-arg swap) | DGX Spark = sbsa, Jetson = l4t |
| ROCm | yes | no | AMD has no arm64 ROCm release. Use Vulkan instead. |
| Vulkan | yes | yes (Mesa is multi-arch) | Universal fallback for all arm64 GPUs |
| CPU (lavapipe) | yes | yes | Slow but always works |
Targeted arm64 devices:
- NVIDIA DGX Spark (Grace-Blackwell GB10) — CUDA via sbsa base image, compute cap 12.0/12.1
- NVIDIA Jetson Orin / AGX / Nano — CUDA via l4t base image, compute cap 8.7
- Apple Silicon (M1/M2/M3/M4) — Vulkan via MoltenVK in Docker Desktop (slow path); the shipped fast path is the native hybrid Metal install — see SETUP_MACOS.md
- Snapdragon X Elite (Windows on ARM laptops) — Vulkan via the Adreno driver
- Raspberry Pi 5 — Vulkan via Mesa V3D driver, expect CPU-tier performance
- Ampere Altra / AWS Graviton workstations — Vulkan via lavapipe (CPU fallback, since no consumer arm64 dGPU yet)
Building the Vulkan image for arm64:
# Multi-arch build that produces a single image manifest covering both archs:
docker buildx build --platform linux/amd64,linux/arm64 \
-t atlas-llama-server:vulkan \
-f inference/Dockerfile.vulkan inference/Building the CUDA image for arm64 (DGX Spark example):
# Swap to the sbsa-capable ubuntu base, build with --platform linux/arm64:
docker buildx build --platform linux/arm64 \
--build-arg BUILDER_IMAGE=nvidia/cuda:12.9.0-devel-ubuntu22.04 \
--build-arg RUNTIME_IMAGE=nvidia/cuda:12.9.0-runtime-ubuntu22.04 \
-t atlas-llama-server:cuda-arm64 \
-f inference/Dockerfile.v31 inference/For Jetson, swap to nvcr.io/nvidia/l4t-jetpack:r36.3.0 in both build args (l4t ships JetPack + CUDA + cuDNN as one image).
Known gaps (#115 tracks these):
- No prebuilt arm64 images on GHCR yet — arm64 users must build locally with the recipes above. Prebuilt multi-arch images will land once at least one arm64 device has been validated end-to-end.
- Bootstrap installer (
scripts/atlas-bootstrap.sh) hasn't been audited for arm64 paths. - Hardware testing matrix is empty for all five target devices — early adopters with any of these please drop your
atlas doctoroutput andvulkaninfo --summaryon #115.
- Docker pulls 5 prebuilt container images from
ghcr.io/inferstep/atlas-{proxy,v3,lens,llama,sandbox}(~3 min on a fast connection). To build from source instead (the dev path), rundocker compose buildbefore theupstep — see "Image source" below. - llama-server loads the 7GB model into GPU VRAM (~1-2 min)
- All services start health checks
- Once all 5 services (llama-server, geometric-lens, v3-service, sandbox, atlas-proxy) report healthy,
atlasconnects and launches the Bubbletea TUI
Subsequent docker compose up -d starts are fast (seconds) since images are cached.
docker-compose.yml declares both image: (GHCR) and build: (local
Dockerfile) for every service. Compose's default behavior:
| Command | What it does |
|---|---|
docker compose up -d |
Pull image: if not in local cache, else reuse local |
docker compose pull |
Force pull latest tag from GHCR (overwrite local cache) |
docker compose build |
Build from Dockerfile (overrides GHCR image) |
docker compose up -d --build |
Always rebuild from source then start |
Tag pinning. The tag defaults to latest. To pin to a specific
version (recommended for production), set ATLAS_IMAGE_TAG in .env:
ATLAS_IMAGE_TAG=3.1.3 # semver tag from a git release
ATLAS_IMAGE_TAG=sha-abc1234 # exact commit
ATLAS_IMAGE_TAG=dev # bleeding edge from dev branchAvailable tags are listed at https://github.com/inferstep/ATLAS/pkgs/container/atlas-proxy
(swap atlas-proxy for the other service names: atlas-v3,
atlas-lens, atlas-llama, atlas-sandbox).
Edge cases: compose pull fails with unauthorized on a package still
private to GHCR — authenticate with a read:packages token or build from
source instead. compose pull also overwrites a locally-built image sharing
the same tag; while iterating on a service, skip the pull or set
ATLAS_IMAGE_TAG=dev-local so local and registry images live under
different tags. To pull a fork's images, set ATLAS_GHCR_OWNER=<your-username>
in .env.
The fastest way is atlas doctor — checks the host environment (GPU
runtime, model and lens artifacts), the docker stack (containers, health
endpoints, auth, state), and a live model inference, printing each
result as it completes and returning exit 0 (healthy) / 1 (failures).
The exact number of checks varies with backend, stack state, and flags.
This is also what atlas-bootstrap.sh runs at the end of install.
atlas doctor # full check (~5–10s)
atlas doctor --quick # skip the e2e model inference (~2s)
atlas doctor --json # machine output, for scripts/CI (buffered, one JSON document)
atlas doctor -v # verbose: show detail for each checkThe checks:
| Group | Check | What it confirms |
|---|---|---|
| Host | docker | daemon reachable |
| Host | compose | docker compose v2 installed |
| Host | arch | CPU architecture (x86_64 / aarch64) and which backends are available on it (#115) — always runs, before the GPU check |
| Host | gpu | vendor-aware GPU runtime: NVIDIA (nvidia-container-toolkit runs nvidia-smi inside Docker) or AMD (/dev/kfd passthrough); warns when no GPU is detected |
| Host | vulkan | Vulkan ICDs visible inside Docker — only when ATLAS_BACKEND=vulkan |
| Host | metal-native | native llama-server binary present and executable — only when ATLAS_BACKEND=metal (macOS hybrid) |
| Host | model_file | The ATLAS_MODEL_FILE selected in .env exists and is > 100 MB |
| Host | lens_weights | cost_field.pt + G(x) artifacts present |
| Host | asa_steering | ast_edit_steering.gguf present (BiasBusters #4 — warn-not-fail; ATLAS works without it, just unsteered structural_edit-vs-edit_file bias) |
| Host | tier_match | .env model selection matches host hardware (warn on overshoot — OOM risk — pass on match or undershoot) |
| Host | tier_constraints | host CPU/RAM/disk meets the recommended tier minimums (catches "16 GB GPU but 8 GB RAM" mismatches) |
| Stack | container/llama-server, geometric-lens, v3-service, sandbox, atlas-proxy | all 5 running and healthy |
| Stack | health/llama, lens, v3, sandbox, proxy | all 5 /health endpoints return ok |
| Stack | internal_auth | internal service auth: token file present with tight permissions, and live enforcement probed both ways (wrong token → 401, valid token accepted); warns when auth is disabled (no secrets/service-token) |
| Stack | status_dimensions | informational: the seven lens/ASA status dimensions from the proxy /v1/calibration/status (the same source the TUI badge reads); never fails the run |
| Stack | sqlite_state | lens /health reports the SQLite state store available (subsystems.sqlite) |
| Stack | image_skew | all 5 atlas-* images on the same tag |
| End-to-end | e2e_smoke | live /v1/chat/completions round-trip to llama-server (--quick to skip) |
The vulkan and metal-native rows are conditional on the configured backend; the health, internal_auth, status_dimensions, and sqlite_state rows run only when at least one container is up; e2e_smoke is skipped by --quick. The remaining checks always run.
If you'd rather check by hand:
# Hit each health endpoint
curl -s http://localhost:8080/health | python3 -m json.tool # llama-server
curl -s http://localhost:8099/health | python3 -m json.tool # geometric-lens
curl -s http://localhost:8070/health | python3 -m json.tool # v3-service
curl -s http://localhost:30820/health | python3 -m json.tool # sandbox
curl -s http://localhost:8090/health | python3 -m json.tool # atlas-proxy
# Functional test: full install diagnostic (services, artifacts, e2e smoke)
atlas doctorAll health endpoints should return {"status": "ok"} or {"status": "healthy"}.
Note: Plain
atlasin an interactive terminal launches the Bubbletea TUI for the full agent loop (tool calls, V3 pipeline, file read/write). The TUI needs a real terminal — piped stdin/stdout prints a pointer toatlas doctorand exits.
docker compose down # Stop all services (preserves images)
docker compose down --rmi all # Stop and remove images (next start rebuilds)docker compose logs -f llama-server # Follow llama-server logs
docker compose logs -f geometric-lens # Follow Lens logs
docker compose logs -f v3-service # Follow V3 pipeline logs
docker compose logs -f atlas-proxy # Follow proxy logs
docker compose logs -f sandbox # Follow sandbox logs
docker compose logs --tail 50 # Last 50 lines from all servicesgit pull
docker compose down
docker compose pull # grab fresh :latest images from GHCR
docker compose up -d# Stop and remove the containers, network, and named volumes
docker compose down -v
# Remove the published images
docker images "ghcr.io/*/atlas-*" -q | xargs -r docker rmi
# Remove the CLI and TUI binaries
pip uninstall atlas
rm -f ~/.local/bin/atlas-tui
rm -rf ~/.cache/atlas-tui # TUI session history
# The repo checkout, .env, and downloaded models live wherever you put
# them — delete the checkout and its models/ directory to reclaim the
# disk (models are the multi-GB part).K3s installs use scripts/uninstall.sh instead, which tears down the
manifests and (optionally) the K3s node itself.
Run all services as local processes without containers. Useful for development or systems where Docker isn't available.
| Requirement | Details |
|---|---|
| Go 1.26.2+ | For building atlas-proxy and the atlas-tui client (older Go toolchains auto-fetch it) |
| llama.cpp | Built from source with CUDA (see llama.cpp build instructions) |
| Node.js 20+ | Required by sandbox for JavaScript/TypeScript execution |
| Rust | Required by sandbox for Rust execution |
# 1. Clone and install Python CLI
git clone https://github.com/inferstep/ATLAS.git
cd ATLAS
pip install -e .
# 2. Select and install a registry model (or place a BYO GGUF in models/)
atlas model recommend
atlas model install <registry-name>
# 3. Build the proxy
cd proxy
go build -o ~/.local/bin/atlas-proxy-v2 .
cd ..
# 4. Install geometric-lens Python dependencies
pip install -r geometric-lens/requirements.txt
# 5. Install V3 service PyTorch (CPU only)
pip install torch --index-url https://download.pytorch.org/whl/cpu
# 6. Install sandbox dependencies
pip install -r sandbox/requirements-runtime.txt -r sandbox/requirements-verify.txtStart each service in a separate terminal (or use & and redirect to log files):
# Terminal 1: llama-server (GPU)
llama-server \
--model "models/$ATLAS_MODEL_FILE" \
--host 0.0.0.0 --port 8080 \
--ctx-size 32768 --n-gpu-layers 99 --no-mmap \
--embeddings --pooling mean --flash-attn on --fit off
# Terminal 2: Geometric Lens
cd geometric-lens
LLAMA_URL=http://localhost:8080 \
LLAMA_EMBED_URL=http://localhost:8080 \
GEOMETRIC_LENS_ENABLED=true \
# (PROJECT_DATA_DIR is not read by the lens; omitted) \
python -m uvicorn main:app --host 0.0.0.0 --port 8099
# Terminal 3: V3 Pipeline
cd v3-service
ATLAS_INFERENCE_URL=http://localhost:8080 \
ATLAS_LENS_URL=http://localhost:8099 \
ATLAS_SANDBOX_URL=http://localhost:8020 \
python main.py
# Terminal 4: Sandbox
cd sandbox
python executor_server.py
# Terminal 5: atlas-proxy
ATLAS_PROXY_PORT=8090 \
ATLAS_INFERENCE_URL=http://localhost:8080 \
ATLAS_LLAMA_URL=http://localhost:8080 \
ATLAS_LENS_URL=http://localhost:8099 \
ATLAS_SANDBOX_URL=http://localhost:8020 \
ATLAS_V3_URL=http://localhost:8070 \
ATLAS_MODEL_NAME="${ATLAS_MODEL_NAME:-local-model}" \
atlas-proxy-v2Note: The sandbox listens on port 8020 in bare-metal mode (no Docker port remapping). The proxy's
ATLAS_SANDBOX_URLmust use port 8020, not 30820.
The atlas command is the Python package's console entrypoint, installed by pip install -e . in the Build step — no separate launcher script is needed. With the services above running:
cd /path/to/your/project
atlas # Checks atlas-proxy is reachable, then launches the TUIatlas builds the atlas-tui binary from tui/ automatically if it is missing or older than the checkout (requires Go 1.26.2+ on PATH), and verifies the proxy on localhost:8090 before handing over to the TUI.
Kubernetes deployment with GPU scheduling, health probes, and resource limits. Preview — templates are validated and rendered in CI; there is no automated live-cluster test.
| Requirement | Details |
|---|---|
| K3s | Single-node or multi-node cluster |
| NVIDIA GPU Operator or device plugin | GPU must be visible as nvidia.com/gpu resource |
| Helm | For GPU Operator installation |
| Podman or Docker | For building container images |
The install script handles the complete setup — K3s installation, GPU Operator, container builds, and deployment:
# 1. Configure
cp atlas.conf.example atlas.conf
# Edit atlas.conf: model paths, GPU layers, context size, NodePorts
# 2. Run the installer (requires root)
sudo scripts/install.shThe installer will:
- Check prerequisites (NVIDIA drivers, GPU VRAM, system RAM)
- Install K3s if not already running
- Install NVIDIA GPU Operator via Helm (if GPU not visible to cluster)
- Build container images and import to K3s containerd
- Generate manifests from
atlas.confvia envsubst - Deploy to the
atlasnamespace - Wait for all services to be healthy
If K3s is already running with GPU support:
# 1. Configure
cp atlas.conf.example atlas.conf
# Edit atlas.conf
# 2. Build and import images
scripts/build-containers.sh
# 3. Generate manifests from atlas.conf
scripts/generate-manifests.sh
# 4. Deploy
kubectl apply -n atlas -f manifests/
# 5. Verify
scripts/verify-install.shK3s uses atlas.conf (not .env) for configuration. The HTTP contracts and pipeline behavior are identical to Docker Compose; only deployment plumbing differs:
| Setting | Docker Compose | K3s |
|---|---|---|
| Config file | .env |
atlas.conf |
| Service exposure | Host ports (8090, 8080, 8099, 8070, 30820) |
NodePorts (30080, 32735, 31144, 30070, 30820) |
| Project workspace | Bind mount (ATLAS_PROJECT_DIR → /workspace) |
hostPath (ATLAS_PROJECTS_DIR → /workspace on every Pod that needs it) |
| Model files | Bind mount (ATLAS_MODELS_DIR → /models:ro) |
hostPath on the GPU node (ATLAS_MODELS_DIR, Directory, ro) |
| Stateful storage | Named volumes (lens-state, v3-telemetry) |
PVCs (lens-projects sized by ATLAS_PVC_PROJECTS_SIZE) |
| GPU allocation | deploy.resources.reservations.devices (nvidia) |
resources.limits.nvidia.com/gpu: 1 (requires GPU Operator or device plugin) |
| Sandbox toolchain caches | tmpfs mounts per language |
emptyDir with sizeLimit per language (universal pattern, same set) |
Model + runtime parameters (ATLAS_MAIN_MODEL, ATLAS_CONTEXT_LENGTH, ATLAS_PARALLEL_SLOTS, ATLAS_FLASH_ATTENTION, KV cache quantization, --embeddings for the lens scoring path) all read from the same env vars in both modes — see atlas.conf.example and .env.example.
See CONFIGURATION.md for the full atlas.conf reference.
# Check pods
kubectl get pods -n atlas
# Check GPU allocation
kubectl describe nodes | grep nvidia.com/gpu
# Run verification suite
scripts/verify-install.shNote: Docker Compose is the most heavily-exercised deployment method (CI runs against it; every release is smoke-tested under Compose). K3s manifests are generated from
templates/*.yaml.tmplat deploy time viascripts/generate-manifests.sh(orinstall.sh'sprocess_templatesstep). Templates consume the model selected inatlas.conf; benchmark numbers in CHANGELOG record their own frozen model/configuration.
ATLAS classifies GPUs into 5 tiers and recommends a registry model + context
size + parallel-slots configuration per tier. These are current registry
recommendations, not hard-coded runtime requirements. Run atlas tier to see
which tier your hardware lands in and the exact .env values to use.
| Tier | VRAM | Recommended model | Context | Slots | Example GPUs |
|---|---|---|---|---|---|
| cpu | n/a | CPU-only install — Preview, smoke-test only | n/a | n/a | (no GPU) |
| small | 8–12 GB | Qwen3.5 7B Q4_K_M (4.4 GB) | 8K | 1 | RTX 3060/4060 8GB, T4 |
| medium | 12–20 GB | Qwen3.5 9B Q6_K (6.9 GB) | 32K | 1 | RTX 4060/5060 Ti 16GB, 3080 Ti, 4070 Ti Super |
| large | 20–32 GB | Qwen3.5 14B Q5_K_M (10.5 GB) | 32K | 2 | RTX 3090, 4090, 5090 24GB |
| xlarge | 32 GB+ | Qwen3.5 32B Q5_K_M (23 GB) | 64K | 2 | RTX 5090 32GB, A6000, A100, H100 |
atlas tier # classify this host + show recommendations
atlas tier list # show all 5 tier definitions
atlas tier fit # size the runtime for the CONFIGURED model + GPU
atlas tier --json # machine output (for scripts)
atlas tier --raw # just the probe (no classification)The tier table gives per-VRAM-band starting points; atlas tier fit
refines them for the specific model you run — it reads the GGUF's KV
geometry plus your GPU's VRAM and solves for the largest context that
stays fully on-GPU (atlas tier fit --write applies the result to
.env). Run it whenever you change ATLAS_MODEL_FILE or the GPU. See
CLI.md § atlas tier fit, and
TROUBLESHOOTING.md § What fits on my GPU?
for pre-download sizing guidance.
The medium tier is the ATLAS development target — atlas-bootstrap.sh
defaults to its model+context settings. For other tiers, run
atlas init (the first-run wizard) after the bootstrap
completes. It probes hardware via atlas tier, picks the right model
from the registry, downloads it with SHA verification, and rewrites
.env. Re-run with atlas init --reconfigure whenever your hardware
or model registry default changes; after a wizard run, atlas tier fit --write tightens the wizard's tier-level defaults to the chosen model.
| Resource | Minimum | Recommended | Notes |
|---|---|---|---|
| GPU VRAM | 8 GB | 16 GB | See tier table above |
| System RAM | 14 GB | 16 GB+ | PyTorch runtime + container overhead |
| Disk | 15 GB | 25 GB | Model (4.4–23 GB depending on tier) + container images (5–8 GB) + working space |
| CPU | 4 cores | 8+ cores | V3 pipeline is CPU-intensive during repair phases |
Any GPU with 8 GB+ VRAM and a llama.cpp-supported backend:
| Vendor | Backend | Status | Build path | Tested cards |
|---|---|---|---|---|
| NVIDIA (Blackwell — RTX 50xx, B100, GB10) | CUDA | Supported (published image) | inference/Dockerfile.v31 |
RTX 5060 Ti 16GB (primary dev) |
| NVIDIA (pre-Blackwell — RTX 20xx–40xx, GTX 10xx, V100/A100/H100/T4/L4) | CUDA | Preview — one-time local rebuild required | inference/Dockerfile.v31 + --build-arg CUDA_ARCH=<cc> |
— (upstream llama.cpp supports these; no maintainer validation on ATLAS) |
| AMD | ROCm / HIP | Community-tested | inference/Dockerfile.rocm |
RX 7900 XTX (community smoke-test, GH #26) |
| Apple Silicon | Metal | Supported (macOS hybrid: native llama-server + Docker, #32) | scripts/atlas-setup-macos.sh + docker-compose.macos.yml |
M2 Pro 32GB (verified); M3/M4 (target) |
| Any (cross-vendor fallback) | Vulkan | Preview | inference/Dockerfile.vulkan |
lavapipe (CPU ICD) smoke-tested; no real-GPU validation yet |
| Intel Arc | SYCL | Roadmap — Intel Arc uses Vulkan today | TBD | Arc A770 16GB (target) |
atlas tier auto-detects across vendors and picks the largest-VRAM GPU. Override with ATLAS_GPU_VENDOR=amd or ATLAS_GPU_INDEX=1 if you have multiple GPUs and want a specific one.
inference/Dockerfile.v31 compiles llama.cpp for a specific CUDA compute capability. The default — and what the published atlas-llama image on GHCR is built with — is 120;121 (Blackwell: RTX 50xx, B100, GB10) only. The published image contains no kernels for earlier GPUs, and its embedded PTX cannot be JIT-compiled downward, so on RTX 20/30/40-series, GTX 10xx, and pre-Blackwell datacenter cards (V100/A100/H100/T4/L4) llama-server fails at startup with no kernel image is available for execution on the device. You must rebuild the inference image once for your architecture. (A local build with the wrong arch value fails earlier, with nvcc fatal: unsupported gpu architecture.)
Find your GPU's arch, then rebuild with --build-arg CUDA_ARCH=<value>:
# Your GPU's compute capability (drop the dot: 8.9 -> 89)
nvidia-smi --query-gpu=compute_cap --format=csv,noheader
# Compose-native rebuild — only llama-server is rebuilt, the other
# services keep using the GHCR images (~30-75 min, one time):
docker compose build --build-arg CUDA_ARCH=89 llama-server
docker compose up -d --no-deps llama-server
# Or build the image directly:
podman build --build-arg CUDA_ARCH=89 -f inference/Dockerfile.v31 -t llama-server:local inference/
# Multiple archs (semicolon-separated) — build a fat binary for Ampere + Ada + Hopper
docker compose build --build-arg CUDA_ARCH="86;89;90" llama-serverCommon values:
| Arch | Architecture | Cards |
|---|---|---|
60, 61 |
Pascal | GTX 10xx, Tesla P4/P40 |
70 |
Volta | V100 |
75 |
Turing | RTX 20xx, T4 |
80, 86 |
Ampere | A100, RTX 30xx |
89 |
Ada Lovelace | RTX 40xx, L4 |
90 |
Hopper | H100 |
100, 120, 121 |
Blackwell | B100, RTX 50xx |
inference/Dockerfile.rocm compiles llama.cpp's HIP backend for one or more gfx targets. The default is a fat build covering the most common consumer + datacenter AMD GPUs: gfx1100;gfx1101;gfx1102;gfx1030;gfx90a. Each additional target adds ~150 MB to the binary.
Override at build time with --build-arg GFX_TARGET=<value> (or via ATLAS_GFX_TARGET env var, which the compose override forwards):
# Single target — RX 7900 XT/XTX only (smaller image)
ATLAS_GFX_TARGET=gfx1100 docker compose -f docker-compose.yml -f docker-compose.rocm.yml build llama-server
# Two targets for RDNA3 + RDNA2 mixed-fleet
docker build --build-arg GFX_TARGET="gfx1100;gfx1030" -f inference/Dockerfile.rocm -t atlas-llama-rocm:custom inference/Common values:
| Target | Architecture | Cards |
|---|---|---|
gfx1100 |
RDNA3 (Navi 31) | RX 7900 XT, 7900 XTX, 7900 GRE |
gfx1101 |
RDNA3 (Navi 32) | RX 7800 XT, 7700 XT |
gfx1102 |
RDNA3 (Navi 33) | RX 7600, 7600 XT |
gfx1030 |
RDNA2 (Navi 21) | RX 6800, 6800 XT, 6900 XT, 6950 XT |
gfx1031 |
RDNA2 (Navi 22) | RX 6700 XT, 6750 XT |
gfx1032 |
RDNA2 (Navi 23) | RX 6600, 6600 XT, 6650 XT |
gfx90a |
CDNA2 | MI210, MI250, MI250X |
gfx942 |
CDNA3 | MI300X |
gfx900 |
Vega | Vega 56/64 (may need HSA override — see TROUBLESHOOTING.md) |
gfx1200 |
RDNA4 (Navi 44) | RX 9070 |
gfx1201 |
RDNA4 (Navi 48) | RX 9070 XT |
RDNA4 (gfx1200/gfx1201) users: set
ATLAS_ROCM_TAG=7.2.3-complete— the default ROCm 6.2 base image does not include gfx1200/gfx1201 compiler support. ROCm 7.0+ supports these targets natively; do not setATLAS_HSA_OVERRIDE_GFX_VERSION. See TROUBLESHOOTING.md § RDNA4 for details.
Your GPU's gfx target: rocminfo | grep -i gfx | head -1 (or look it up in the LLVM AMDGPU processor table).
ATLAS works without Geometric Lens weights — the service degrades gracefully, returning neutral scores. The V3 pipeline falls back to sandbox-only verification.
To enable C(x)/G(x) scoring, you need trained model weights. Pre-trained weights and training data are available on HuggingFace:
ATLAS Dataset on HuggingFace — includes embeddings, training data, and weight files.
Place weight files in geometric-lens/geometric_lens/models/ (or mount via ATLAS_LENS_MODELS in Docker Compose). The service loads them automatically on startup.
To train on your own benchmark data, the whole loop is CLI-driven:
atlas bench --run-id mymodel_lens --tasks 200 # generate + self-label candidates
atlas lens build --force --from-results benchmark/results/mymodel_lens/v3_lcb/per_taskatlas lens build trains both lens halves, calibrates the thresholds, and writes a provenance.json manifest into the activated bundle. See CLI.md § atlas lens.
If you want to swap in a non-default GGUF, the atlas lens subcommand wraps the probe + train pipeline so you don't have to learn the underlying scripts:
# 1. Drop your GGUF in models/ and update .env to point at it, restart llama-server.
# 2. Probe whether the existing artifacts can score it (cheap, no training):
atlas lens check
# Reports: compat (artifacts work) | needs-build (different dim) | incompatible
# 3. If 'needs-build', train fresh artifacts at the model's native embedding dim:
atlas lens build --samples path/to/labeled.json
# samples format: [{"text": str, "label": 0|1}, ...] where 1 = passing code
# Canonical training set: huggingface.co/datasets/itigges22/ATLAS
# 4. Re-run check — should now report compat:
atlas lens checkFull reference: CLI.md § atlas lens.
May 2026 BiasBusters #4. A residual-stream steering vector that biases
the model toward structural_edit over edit_file for whole-function /
class / element rewrites, applied before the grammar gate has a
chance to reject anything. Strictly optional — ATLAS continues to work
without it, just with an unsteered tool-selection bias.
atlas-bootstrap.sh builds it automatically after the services come
up. The pipeline is:
build_cvector_prompts.pyturns the committedgeometric-lens/asa_calibration/contrast_pairs.jsonl(1000 pairs) into positive / negative prompt files.- The bootstrap stops
llama-serverbriefly, runsllama-cvector-generatoras a one-shot container with--method mean -ngl 99, writesmodels/ast_edit_steering.ggufplus amodels/ast_edit_steering.gguf.modelsidecar marker recording which model the vector was built against, then restartsllama-server. inference/entrypoint-v3.1.shsees the file on the next start, checks that the.modelsidecar marker matches the selected model, and appends--control-vector-scaled /models/ast_edit_steering.gguf:0.5to thellama-servercommand line. A vector whose marker is missing or names a different model stays disabled (the startup banner reports why) — vectors are residual-space artifacts tied to one model.
Total wall time on a 16GB GPU: ~5 minutes. Build runs on the same
hardware the model lives on; the resulting vector is model-specific
(do not move an ast_edit_steering.gguf built against
one model's artifacts to a host running a different base model).
The
ast_edit_steeringfilename is intentional and stable: the registry SHA-pins it and the.modelmarker sits beside it, so it keeps the name even though the tool it steers is now calledstructural_edit.
Override behavior (set in .env if you want to tune):
| Env var | Default | Effect |
|---|---|---|
ATLAS_CONTROL_VECTOR |
/models/ast_edit_steering.gguf |
Override path |
ATLAS_CONTROL_VECTOR_SCALE |
0.5 |
Conservative. Bump to 1.0–1.5 if the bias is too subtle, drop toward 0.2 if non-tool tasks degrade. |
ATLAS_CONTROL_VECTOR_LAYER_RANGE |
(all layers) | Pass two integers, e.g. "24 30", to scope to a layer band. Narrower = safer but weaker. |
ATLAS_CONTROL_VECTOR_ALLOW_UNVERIFIED |
0 |
Set to 1 to apply a vector even when its .model sidecar marker is missing or doesn't match the selected model. Only for vectors you built yourself and know match. |
If the local build fails (e.g. cvector-generator missing in an
older atlas-llama image, GPU OOM, network hiccup pulling the
runtime), the bootstrap falls back to downloading a prebuilt
ast_edit_steering.gguf from the
ATLAS HuggingFace dataset.
If that also fails the install completes with a warning — atlas doctor will flag the gap as warn, not fail.
To skip the build entirely, set ATLAS_BOOTSTRAP_SKIP_ASA=1 before
running the installer.
To rebuild manually (re-curated pairs, different --method, different
base model), see
geometric-lens/asa_calibration/README.md.
- CLI.md — How to use ATLAS once it's running
- CONFIGURATION.md — All environment variables and tuning options
- TROUBLESHOOTING.md — Common issues and solutions
- ARCHITECTURE.md — How the system works internally