Configuring an Nx Cloud pipeline used to mean stringing flags onto a single command. At a small scale that's fine. Here's what it looks like in a more complex monorepo:
# .github/workflows/ci.yml
- run: |
npx nx-cloud start-ci-run \
--distribute-on=".nx/workflows/distribution-config.yaml" \
--stop-agents-after="lint,build,unit-test,integration-test,e2e-test,typecheck,build-storybook" \
--stop-agents-on-failure=false \
--require-explicit-completion \
--with-env-vars="NPM_TOKEN,SENTRY_AUTH_TOKEN,DATADOG_API_KEY,CHROMATIC_TOKEN,GITHUB_RUN_ID,GITHUB_SHA,GITHUB_REF"That's a single command holding seven tasks, seven environment variables, a reference to a distribution configuration file at .nx/workflows/distribution-config.yaml, and two behavioral toggles — all as comma-delimited strings, in a file owned by your CI provider, where nothing validates any of it.
Today we're shipping a new model: a .nx/ci-config.yaml file that lives in your repo, and a new npx nx-cloud start-nx-agents command that takes no configuration flags at all.
Why a centralized config file
The flags themselves were never the issue (albeit the number of options did make them hard to track). The issue was when they were read by Nx Cloud.
The first nx command that contacts Nx Cloud starts your CI Pipeline Execution (CIPE) and locks in its settings. Every command after that inherits those settings.
This made the nx-cloud start-ci-run order-dependent: it had to be the first nx command in your pipeline, or its flags arrived too late to apply. The catch is that a CIPE can span multiple jobs. Being first in your own workflow file wasn't enough — another job sharing the same run could contact Nx Cloud before yours did. In that case, competing configurations could result in runs that had different behaviors applied.
Configuration that doesn't depend on command order
The new model removes the ordering requirement entirely. Every Nx Cloud command reads .nx/ci-config.yaml when it runs, so your configuration applies to the run no matter which command starts it.
start-nx-agents replaces the previous start-ci-run. It provisions the agents your job needs, and that's all it does — it isn't a special command that has to run first to lock in settings:
# .github/workflows/ci.yml
- run: npx nx-cloud start-nx-agentsAnd the configuration it reads — the same pipeline from the top of this post:
# .nx/ci-config.yaml
lifecycle:
stop-after:
- lint
- build
- unit-test
- integration-test
- e2e-test
- typecheck
- build-storybook
fail-after: 0
heartbeat: true
dte:
distribute-on: .nx/workflows/distribution-config.yaml
nx-agents:
with-env-vars:
- NPM_TOKEN
- SENTRY_AUTH_TOKEN
- DATADOG_API_KEY
- CHROMATIC_TOKEN
- GITHUB_RUN_ID
- GITHUB_SHA
- GITHUB_REFThis is the same behavior as the flags, laid out as structured data. stop-after lists the tasks that release your agents, fail-after controls whether a task failure stops the run, heartbeat enables stall detection, distribute-on points at your distribution config, and with-env-vars names the variables forwarded to each agent.
It takes more lines than the flag string, and that's the trade worth making. Each task and variable sits on its own line, so adding one is a one-line diff a reviewer can actually read. The file is versioned alongside the code it configures.
What goes in the file
The file has four top-level sections, all optional, each falling back to its defaults when omitted:
| Section | Purpose |
|---|---|
lifecycle | Stop conditions and stall detection for the run |
dte | Distributed task execution: how tasks are distributed to Nx Agents |
nx-agents | Configuration for the Nx Agents themselves |
overrides | Per-environment overrides keyed by NX_CI_EXECUTION_ENV |
The CI configuration file reference documents every key, its type, and its default.
Seeing the config a run actually used
You don't have to write the file from scratch. Every CIPE has a Configuration section that records the settings the run actually used. Even if you configured it with the legacy start-ci-run, Nx Cloud maps those settings into the shape of the new configuration for you.

The Config YAML page in that section converts your active configuration into a YAML file:

That makes migrating simple: open the Config YAML page for your most recent CIPE, copy the generated YAML into .nx/ci-config.yaml in your repository, and swap start-ci-run for start-nx-agents.
Additional improvements to previously used flags
Moving configuration into a file wasn't purely mechanical. A few options got more capable in the transition.
distribute-on absorbs dynamic agent allocation. Pass a single launch-template string, or a map of changeset sizes when you want small PRs to use fewer agents than large ones:
# .nx/ci-config.yaml
dte:
distribute-on:
small-changeset: 3 linux-medium
medium-changeset: 6 linux-large
large-changeset: 10 linux-largeassignment-rules can be inline. Previously it was a path to a separate file. It still can be, but we recommend you write the rules directly in ci-config.yaml and keep your distribution setup in one place.
overrides has no flag equivalent at all. This is the one that didn't exist before. Varying behavior per environment used to mean maintaining a second full flag string behind an if: condition, with every shared setting copied into both, and the two copies drifting apart over time. Now it's one file and one delta:
# .nx/ci-config.yaml
lifecycle:
fail-after: 1
overrides:
main:
lifecycle:
fail-after: 0Every pipeline stops on the first failure, except when NX_CI_EXECUTION_ENV is main, where the run finishes so you see every failure at once instead of fixing them one round-trip at a time.
One detail worth knowing: overrides apply per key, not as a deep merge. An override replaces the base value for the keys it sets, so an array like assignment-rules is replaced wholesale rather than merged with the base rules. Keys the override doesn't set keep their base values.
Migrating
Every start-ci-run flag has a corresponding key in .nx/ci-config.yaml, and the migration guide walks through the full mapping between the legacy flags and the new configuration schema.
start-ci-run does not read .nx/ci-config.yaml. Once the file exists, start-ci-run exits with an error pointing you at start-nx-agents. Move your flags into the file and change the command in the same commit — there's no gradual rollout where both coexist.
Why this shape
A flag on a shell command is just a string. It gets assembled at runtime, in a file your CI provider owns, and your build tool never sees it until the pipeline is already running. Nothing validates it beforehand.
A structured file with a known schema is different. Nx Cloud can read it, validate it, and tell you it's wrong before you burn a CI run finding out — and it sits in your repo alongside everything else that configures your workspace.
This is the same bet Nx has made everywhere else: the build tool and the CI platform should share information rather than communicating through opaque strings. .nx/ci-config.yaml is that bet applied to pipeline setup.
Get started
If you're setting up a new workspace, Set up CI starts you on the config file directly. If you have an existing start-ci-run setup, the migration guide is a short read: add .nx/ci-config.yaml and change one line in your workflow.







