# Run Atlas Headless in CI in a JavaScript Project (2026)

> `atlas run` is non-interactive by default: it sends one prompt, streams events to stdout, and exits when the session goes idle, which is what a JavaScript CI job needs.

Atlas runs headless in CI through `atlas run`, which is built for exactly that. Its default mode is non-interactive: it sends a single prompt, streams events to stdout, and exits when the session goes idle, so a JavaScript pipeline step behaves like any other command. `atlas run` supports --format json for raw event streaming, --command for slash-command execution, and --continue or --session for resumption, so a step can be replayed or resumed. In a JavaScript repo that means Atlas can run after `pnpm install`, before or after `pnpm vitest run`, with its output parsed by a later step and prettier applied to whatever it wrote.

## Key takeaways

- `atlas run` is non-interactive by default: one prompt, events streamed to stdout, exit when the session goes idle.
- --format json turns the run into machine-readable output a Node script can parse in the next JavaScript pipeline step.
- The GitHub path requires provider/model form for the model and rejects anything else, so pin it in the workflow file.
- Pre-approve permissions before the job runs, because with no human present an ask prompt is functionally a deadlock.
- --continue, --session, and --fork let a later step hand `pnpm vitest run` failures back into the same Atlas session.

## How do you run Atlas non-interactively in a CI pipeline?

`atlas run` is the non-interactive entrypoint: invoke it with the prompt as an argument and it sends exactly 1 prompt, streams events to stdout, and exits when the session goes idle. That is the contract a CI step needs, with no TTY, no keypress, and no job hanging on a permission prompt nobody will answer.

In a JavaScript pipeline, put `atlas run` in the same job that already runs `pnpm install` and `pnpm vitest run`, so the working tree Atlas sees is the one the tests see. Because the session exits when it goes idle, the step's exit is a real signal rather than a timeout. Keep the prompt narrow and mechanical: "update the failing snapshot in src/components and explain what changed" is a CI-shaped task, while "improve the codebase" is not. Atlas is a terminal-native TUI in interactive use, but `atlas run` is the headless path, and it is the one that belongs in a pipeline definition next to your pnpm commands.

## How do you parse Atlas's output in a JavaScript CI step?

Atlas streams machine-readable events when you pass --format json to `atlas run`, so a later pipeline step can parse the event stream rather than read prose. In a 2026 JavaScript repo the natural consumer is a small Node script that reads stdout, filters the events it cares about, and turns them into a check annotation or a comment.

Prose output is for humans; --format json is for the next step. Pipe the raw event stream to a file, then let a JavaScript step read it with `node scripts/parse-atlas.mjs` and decide what to do: fail the job, post a summary, or write a report artifact. Keep the parser in the repo alongside your other tooling so `prettier` formats it and `vitest` can test it, because a parser that silently returns an empty array on a schema change is worse than no parser. `atlas run` streams events to stdout, so the parser can also consume the stream live rather than after the fact when a long job needs progress reporting.

## How do you configure permissions for a headless Atlas run?

Atlas requires the tools a headless job needs to be pre-approved in the permission config, because a headless run has nobody to answer an ask prompt. Every Atlas tool call is gated against 3 rule types, allow, ask, and deny, before it runs, so an unconfigured CI job stalls on the first edit rather than proceeding unsafely.

Permissions are the difference between a CI job that works and one that hangs. Decide up front what the job may do: allow bash for `pnpm vitest run` and `pnpm prettier --write`, allow read and grep, and decide deliberately whether edit is allowed or denied. A job that only reviews the diff should deny edit outright, which makes it structurally incapable of writing to your JavaScript source. A job that fixes lint errors needs edit allowed for src/**, and nothing else. The permission model is the security boundary for the entire headless run, and it is not optional: with no human present, ask is functionally a deadlock, so every tool the prompt might reach for must be resolved to allow or deny before the job starts.

## How do you set the model for an Atlas run in GitHub CI?

Atlas's GitHub path requires the model in provider/model form and rejects anything else, so in 2026 a bare model name still will not start the job. Passing the fully qualified provider/model string is a one line change in the workflow YAML, and it is the difference between a green run and an immediate rejection.

Explicit model selection also makes a JavaScript pipeline reproducible. A job pinned to a specific provider/model behaves the same on rerun, which matters when the step's output is being parsed with --format json by a downstream script and consumed by a check. In interactive use Atlas lets you switch the active model and provider on the fly with favorites and recents, but a CI job should never be implicit about which model ran, because the reason a step's behavior changed between Tuesday and Thursday should never be a silent model default. Put the provider/model string in the workflow next to the `pnpm` version pin and treat both as part of the pipeline's contract.

## How do you resume or replay an Atlas CI run?

Atlas resumes or forks a prior session with 3 flags, --continue, --session, and --fork, when a JavaScript job needs to build on an earlier run. A pipeline that ran `atlas run` in one step and `pnpm vitest run` in the next can hand the test failures back into the same session rather than starting cold.

Session continuity is what turns a single-shot command into a pipeline. Use --continue to pick up the previous session, --session to target a specific one by id, and --fork to branch from a session without disturbing it, which is useful when you want two candidate fixes explored from the same starting state. In practice a JavaScript job might run `atlas run` to make a change, run `pnpm vitest run` to test it, and then resume with the failing output to iterate. Atlas snapshots file changes as git patches, so edits made by a headless run can be diffed and rolled back, and Atlas reads git branches, status, and diffs, so the job can inspect exactly what it wrote before opening a pull request.

## Steps

1. Add a CI step in the same job that runs `pnpm install`, so the working tree Atlas sees is the tree your JavaScript tests see.
2. Invoke `atlas run` with the prompt as an argument; the default mode is non-interactive, sends one prompt, and exits when the session goes idle.
3. Pass --format json when a later pipeline step needs to parse the event stream rather than read prose, and pipe the stream to a file the next step reads.
4. Set the model explicitly: the GitHub path requires provider/model form and rejects anything else, so a bare model name fails the job immediately.
5. Pre-approve the tools the job needs through the permission config, because a headless run has nobody to answer an ask prompt; allow bash for `pnpm vitest run` and decide deliberately whether edit is allowed.
6. Use --command when the job should execute a slash command rather than a free-form prompt.
7. Parse the JSON event stream with a small Node script such as `node scripts/parse-atlas.mjs`, kept in the repo so `prettier` formats it and `vitest` tests it.
8. Resume or fork a prior session with --continue, --session, or --fork when a later step needs to hand `pnpm vitest run` failures back into the same Atlas session.

## FAQ

### how to run an AI coding agent headless in CI

Use `atlas run`. Its default mode is non-interactive: it sends a single prompt, streams events to stdout, and exits when the session goes idle. Pass --format json when a later step needs to parse the events, and pre-approve permissions before the job starts.

### how do I get machine-readable output from atlas run

Pass --format json. `atlas run` then emits the raw event stream to stdout, which a JavaScript step can consume with a Node script rather than parsing prose. Keep the parser in the repo so prettier formats it and vitest tests it.

### why does my headless Atlas run hang in CI

A headless run has nobody to answer an ask prompt. Every Atlas tool call is permission-gated against allow, ask, and deny rules before it runs, so every tool the prompt might reach for must be pre-approved to allow or deny in the permission config before the job starts.

### does atlas run need a model flag in GitHub Actions

Yes. Set the model explicitly, because the GitHub path requires provider/model form and rejects anything else. Pinning the provider/model string alongside your pnpm version pin also keeps the pipeline reproducible across reruns.

### can I resume an Atlas CI session from a later pipeline step

Yes. Use --continue to pick up the previous session, --session to target one by id, and --fork to branch from a session without disturbing it. That lets a `pnpm vitest run` failure be handed back into the same Atlas session rather than starting cold.

### can atlas run execute a slash command in CI

Yes. `atlas run` supports --command for slash-command execution, so a pipeline step can invoke a defined command rather than a free-form prompt, which makes the step's behavior easier to keep stable across runs.

### how do I review what Atlas changed during a CI run

Atlas snapshots file changes as git patches so edits can be diffed and rolled back, and Atlas reads git branches, status, and diffs. A headless job can therefore inspect exactly what it wrote before opening a pull request.

### how do I start Atlas in a JavaScript project

Run atlas where your package.json lives. Atlas maps your modules, npm scripts, and bundler config, and you can have it modernize callbacks to async/await or add tests, reviewing each diff before it is written.

---

Canonical HTML: https://runatlas.sh/resources/stacks/run-atlas-headless-in-ci-in-javascript
Source of truth: aeo_pages row `/resources/stacks/run-atlas-headless-in-ci-in-javascript` (segment: Stacks) (this file is generated from it, never hand-edited).
Licence: Atlas is proprietary with a free core. It is not open source and there is no public source repository.
