Atlas Architecture
Deep dive into the internal design and deployment pipeline of Atlas.
Atlas Architecture#
Atlas is an autonomous deployment pipeline — a Go CLI that takes a project directory, runs the analysis → build → fix → deploy pipeline, and manages credentials and LLM calls along the way.
Package Layout#
- main.go
- root.go
- deploy.go
- debug.go
- testllm.go
- providers.go
- models.go
- fix_build.md
- ARCHITECTURE.md
- COMMANDS.md
Internal Subsystems#
internal/config — Project-local configuration#
Owns .atlas/config.json per project. Defines LLM provider, model, local LLM base URL, and approval mode. If the file doesn't exist, sane defaults are returned. Config is intentionally project-local, not global, because different projects may use different LLM providers or models.
internal/credentials — Global per-user credential store#
Deliberately global (one store per OS user, at %AppData%\atlas on Windows), because deploy credentials (Vercel tokens, API keys) are per-user, not per-project. Storing them per-project would mean re-authenticating for every new repo.
The metadata file (credentials.json) tracks which method is being used and when it was verified — but never stores a raw secret. Secrets live exclusively in the OS keychain via go-keyring, with an automatic fallback to a 0600 file when no keychain backend is available (e.g., headless Linux servers).
This is the only Atlas subsystem that is global rather than project-local.
internal/workspace — Workspace resolution#
Validates that a given path exists and identifies the git root (by walking upward looking for .git). The resolved Workspace struct is the input boundary for the orchestrator — nothing downstream deals with raw paths.
internal/session — Session lifecycle#
Creates a timestamped session directory under .atlas/sessions/<id>/ for each atlas deploy run. Each session gets its own log directory, context JSON files, and planner state. Sessions are project-local — they're scoped to the workspace they were started against.
internal/state — JSON persistence#
Thin helpers (LoadJSON, SaveJSON) for reading and writing session context files (project.json, build.json, planner.json, deployment.json). These files are the pipeline's "shared memory" — each tool reads inputs written by previous steps.
Context file ownership rule: each context file is owned by exactly one tool:
project.json→AnalyzeProjectbuild.json→RunBuildCommandtest.json→RunTestsplanner.json→orchestrator(planner, not a tool)deployment.json→orchestrator(deployment record, trackingLastHealthyDeployment)
No tool writes to a context file it doesn't own.
internal/tools — Pipeline tools#
Each tool implements the Tool interface (Name() string, Execute(ctx, sess) (ToolResult, error)). Tools are pure functions — they read inputs from session context files and write outputs back. They don't call each other directly.
Currently implemented tools:
AnalyzeProject— framework/package manager detectionGitValidate— checks for clean working tree, extracts commit SHA for rollbackRunBuildCommand— executes the framework-specific build command, captures logsFixCode— calls the LLM (GoAIGenerateObject) with the build log and skill prompt, writes the patched fileWriteFile— atomic file write with workspace-root sandboxingRunCommand— generic shell command execution
internal/llm — LLM provider resolution#
Wraps GoAI v0.8.6 to provide:
ResolveModel(cfg)— mapsconfig.LLMProviderto aprovider.LanguageModelGenerateStructured[T](ctx, model, system, user)— typed structured generation (used byFixCode)NewClient(cfg)→Client.Complete(ctx, system, user)— plain text generation (used bytestllm)
Supported providers: anthropic, openai, gemini, mistral, groq, grok, local (OpenAI-compatible).
internal/deploy — Deployment providers#
Implements Provider interface (Name(), Deploy(...), HealthCheck(...), Rollback(...)). Supports providers like Vercel, Netlify, and Render.
Also houses EnsureVercelAuth, EnsureRenderAuth, and EnsureNetlifyAuth, the pre-flight auth checks wired into the orchestrator. It checks credentials in priority order (env var → stored token → CLI delegation) before any build work starts, so a misconfigured credential fails fast rather than after a multi-minute build.
internal/orchestrator — Pipeline orchestration#
The central loop. Stages:
- Load config
- Resolve workspace
- Resolve LLM model + open credential store
- Pre-flight auth check (
EnsureVercelAuthfor Vercel) - Create session
- Analyze project
- Validate git state
- Build → on failure: fix (LLM) → rebuild (loop, max 4 retries)
- Approval gate (manual or auto)
- Deploy
- Record deployment URL
- Post-deploy HealthCheck: Verify application health (
HTTP 200) - Rollback: If the health check fails, prompt to rollback to the
LastHealthyDeployment(or automatically rollback if--auto-rollback-on-unhealthyis passed).
On build exhaustion, the orchestrator reverts to the original git commit SHA captured in step 7.
Retry and Escalation Model#
The build→fix loop has a configurable maximum retry count (default: 4). On each failure:
- The build log tail (last 40 lines) is sent to the LLM with the
skills/fix_build.mdsystem prompt. - The LLM returns a
FixResponsestruct (file path + new content + reasoning). - The file is written and the build is re-run.
If the LLM call itself fails (e.g., no API key), FixCode returns a ToolResult with Success: false and a descriptive Error string — never a silent blank error.
If all retries are exhausted, the orchestrator reverts the workspace to the pre-deploy commit SHA via git checkout <sha> -- . and returns a non-zero exit code.
Why credentials are global but session state is project-local#
Session state tracks what happened in this deploy run for this project: build logs, git SHA, detected framework, deployment URL. This is inherently project-specific — the build log for Project A is useless for Project B.
Credentials track who the user is with which provider. A Vercel account is tied to the developer, not to any one project. Storing it per-project would mean running vercel login once per repo, which is the exact friction we're eliminating.
The credential store sits at the OS user config level (%AppData%\atlas, ~/.config/atlas) for the same reason that your SSH keys sit in ~/.ssh, not in each repo's .git.