Get Started
Internals

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

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 & monorepo discovery#

Validates that a given path exists and identifies the git root (by walking upward looking for .git). Also detects monorepo structures (pnpm-workspace.yaml, turbo.json, nx.json, lerna.json, or root package.json workspaces), resolves package subdirectories via --dir or --workspace, and allows sub-packages to inherit root lockfiles (pnpm-lock.yaml, bun.lockb, yarn.lock, package-lock.json). 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 → AnalyzeProject
  • build.json → RunBuildCommand
  • test.json → RunTests
  • planner.json → orchestrator (planner, not a tool)
  • deployment.json → orchestrator (deployment record, tracking LastHealthyDeployment)

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 detection (supports Next.js, React, Express, Go, Django, FastAPI, Flask, Astro, Svelte, SvelteKit, Vue, Nuxt, Vite; package managers npm, pnpm, yarn, bun, uv, poetry)
  • GitValidate — checks for clean working tree, extracts commit SHA for rollback
  • RunBuildCommand — executes the framework-specific build command, captures logs
  • FixCode — calls the LLM (GoAI GenerateObject) with the build log and skill prompt, writes the patched file
  • WriteFile — atomic file write with workspace-root sandboxing
  • RunCommand — generic shell command execution

internal/doctor — Environment & security diagnostics#

Runs diagnostic checks across developer tools (Git, Node, npm, pnpm, yarn, bun, Go, Python, Docker), OS keychain readiness (go-keyring vs 0600 filesystem fallback), authenticated provider credentials, live LLM completion ping latency, and Atlas version status. Emits structured report types (DiagnosticReport) consumable by both interactive CLI rendering and automated JSON tooling (--json).

internal/audit — Pre-flight secret & environment variable auditing#

Scans templates (.env.example, .env.sample, .env.template, .env.local.example) and source files (JS/TS, Python, Go, Ruby, PHP) for referenced environment variables. Checks their configuration state against local OS environment and target deployment providers, while strictly guaranteeing zero secret leakage (values are never captured, printed, or saved). Operates standalone (atlas audit) or as a pre-flight deployment gate with --strict-env.

internal/llm — LLM provider resolution#

Wraps GoAI v0.8.6 to provide:

  • ResolveModel(cfg) — maps config.LLMProvider to a provider.LanguageModel
  • GenerateStructured[T](ctx, model, system, user) — typed structured generation (used by FixCode)
  • NewClient(cfg) → Client.Complete(ctx, system, user) — plain text generation (used by testllm)

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:

  1. Load config
  2. Resolve workspace
  3. Resolve LLM model + open credential store
  4. Pre-flight auth check (EnsureVercelAuth for Vercel)
  5. Create session
  6. Analyze project
  7. Validate git state
  8. Build → on failure: fix (LLM) → rebuild (loop, max 4 retries)
  9. Approval gate (manual or auto)
  10. Deploy
  11. Record deployment URL
  12. Post-deploy HealthCheck: Verify application health (HTTP 200)
  13. Rollback: If the health check fails, prompt to rollback to the LastHealthyDeployment (or automatically rollback if --auto-rollback-on-unhealthy is passed).

When invoked with --json, the orchestrator suppresses interactive terminal banners, spinners, and ANSI formatting, emitting a structured PipelineSummary JSON document on stdout with execution metadata (session_id, action, provider, framework, package_manager, commit_sha, deployment_url, duration_sec, error).

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:

  1. The build log tail (last 40 lines) is sent to the LLM with the embedded fix_build.md system prompt (or project-level override at .atlas/skills/fix_build.md if present).
  2. The LLM returns a FixResponse struct (file path + new content + reasoning).
  3. The exact-match patch is applied and the build is re-run.

Stuck Loop Prevention: Atlas tracks normalized SHA-256 signatures of build error logs. If an applied patch produces the exact same compiler error signature on rebuild, Atlas detects a stuck loop, restores workspace file snapshots from the session backup directory, and escalates immediately to prevent wasting LLM budget.

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 restores files from session snapshots 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.