nrwl/nx
github.com/nrwl/nx ↗ · 3998 files · 22.1 MB · scan capped
Smart Monorepos · Fast Builds Docs • Changelog • Blog • Courses • YouTube Nx is a monorepo solution for TypeScript and polyglot codebases.
Overview
Nx is a monorepo toolchain for teams coordinating TypeScript and polyglot projects: it discovers projects, builds dependency graphs, selects affected work, runs tasks, caches artifacts, and generates code through plugins. Its TypeScript CLI coordinates Rust native services, an optional workspace daemon, executor processes, and remote cache providers. This checkout also contains the browser graph application, Astro documentation, framework integrations, and release automation. The brief describes source inspected at commit bedd602304d762fd160b5f2a6a81990aa1903ccb; the investigation is bounded and no repository code was executed.
System map
The principal product boundary is the installed Nx CLI, with TypeScript orchestration and Rust native services. Project discovery and hashing can run through a daemon or inside the invoking process. Artifact storage, database state, executor processes, and browser visualization have distinct ownership boundaries. Distribution includes npm packages and platform binaries, while documentation is a separate Astro application.
- The published nx package exposes nx and nx-cloud binaries under dist/bin and distributes command implementations, schemas, executor registries, and generator registries.
- bin/nx.ts owns platform checks, workspace discovery, environment initialization, local installation resolution, and delegation; initLocal routes arguments into the shared Yargs commandsObject.
- The Cargo workspace contains packages/nx; its npm manifest declares N-API binaries for Linux, macOS, Windows, and FreeBSD, and native/index.js intercepts loading of Nx native modules.
- createProjectGraphAsync chooses cached graph reuse or createProjectGraphAndSourceMapsAsync; the latter requests daemon state when enabled and otherwise coordinates construction with a file lock.
- runCommand wraps execution with plugin hooks; defaultTasksRunner creates TaskOrchestrator, which owns scheduling, cache access, executor process runners, and continuous-task state.
- Native NxCache indexes artifacts through a database connection; getDbConnection uses shared workspace data, while getLocalDbConnection explicitly scopes running-task state to a worktree.
- The browser graph has React Router project, task, and project-details surfaces; Astro documentation uses Starlight, Markdoc, React, and Netlify, with plugin references generated from package metadata.
- Root scripts define pnpm-driven build, test, e2e, and local-registry workflows; native builds use @monodon/rust:napi, and release publication runs in the npm-registry GitHub environment after native build jobs.
Feature catalog
Nx exposes its primary capabilities through a centrally registered CLI command surface. Task execution supports individual projects, multiple projects, affected selection, custom commands, caching, and several output modes. Workspace maintenance, generation, cloud operations, and agent integration are additional command families. The graph browser and documentation provide separate interactive and reference surfaces; this catalog groups the inspected features without asserting exhaustive coverage of every plugin.
- Users can run project:target:configuration or infix target/project syntax; both handlers call runOne, and --skip-nx-cache is documented on the run command.
- Affected execution can select tasks through computeAffectedTasks when enabled and targets are supplied, or select affected projects through filterAffected; graph requests retain a separate visualization branch.
- Generation resolves plugin schemas and implementations, combines options with workspace defaults, supports help and dry-run, and delegates non-Nx generators through the Angular compatibility adapter.
- The command table registers workspace setup and maintenance families including add, init, import, list, migrate, release, repair, report, reset, format, show, sync, watch, and run-many.
- Cloud and agent command families include login/logout, record, start-ci-run, start-nx-agents, start-agent, stop-all-agents, fix-ci, apply-locally, download-cloud-client, configure-ai-agents, MCP, and shell completion.
- Caching supports local artifacts, Nx Cloud, optional S3/shared-filesystem/GCS/Azure packages, and a self-hosted HTTP provider; HTTP remote caching is explicitly unavailable under WASM.
- The graph browser exposes projects, tasks, tasks/all, and project-details routes; task loading accepts target/project selections, returns an empty graph for insufficient selection, and caches combinations by workspace.
- Core executors provide noop, run-commands, and run-script; run-commands supports parallel execution and readiness markers, while task output can use summary, dynamic/static renderers, or the native TUI.
Data flow
CLI arguments and workspace configuration are transformed into project graphs, task selections, execution options, and hashes. The daemon boundary carries graph and hashing requests, while executor boundaries carry task options and environments. Completed work becomes terminal output, copied artifacts, database records, and optional remote cache uploads. Generator changes follow a separate staged-file path, and documentation loaders transform package schemas into rendered collection entries.
- runOne reads nx.json and the project graph, parses project/target/configuration, splits Nx arguments from executor overrides, resolves matching projects, then chooses graph generation or task execution.
- Graph construction combines specified/default plugins, retrieves project configurations and source maps, retrieves workspace files and Rust references, then builds dependencies using the file map and prior cache when enabled.
- Daemon graph requests use REQUEST_PROJECT_GRAPH; the server parses messages, checks workspace identity for recognized daemon messages, applies supplied client environment, and returns serialized graph/source-map results.
- Upfront hashing excludes custom hashers and tasks reading dependency outputs, supplies a separate environment per task, and records returned hash values/details; the coordinator later hashes eligible tasks after dependencies complete.
- runExecutorInternal resolves an executor and schema, combines overrides with target configuration, invokes the implementation with graph/workspace context, and accepts a Promise or AsyncIterator result.
- postRunSteps separates terminal-output persistence from cache writes; DbCache.put calls native put, reports expanded output files, and optionally uploads them, while native put copies normalized workspace outputs and records cache_outputs metadata.
- Remote HTTP retrieval downloads a gzipped archive, extracts artifacts under cache_directory/hash, reads terminalOutput and a four-byte exit code, and returns CachedResult; successful remote outputs can be restored when native apply_remote_cache_results records the entry.
- Generators stage FileChange records in FsTree before flushChanges writes them; documentation separately parses generator/executor schemas, renders Markdown, and stores collection entries with technology slugs and package metadata.
Behavior traces
The inspected paths cover startup, task execution, cache persistence/replay, and code generation in execution order. Branches matter: completion bypasses ordinary initialization, graph requests bypass task execution, and sync checks vary with CI and terminal availability. Cache hits restore or retain outputs before reporting task results. These are source-derived traces, not observed runtime sessions.
- Startup fast paths: main checks NX_COMPLETE and attempts value then command-surface completion; ordinary startup checks supported platforms and discovers the workspace, while --version skips root environment loading.
- Local startup: main resolves the local installation, initializes analytics, and calls initLocal; initLocal marks NX_CLI_SET, optionally queries the daemon for editor-extension status, then parses or rewrites arguments through commandsObject.
- Primary action: yargsRunCommand.handler calls runOne; runOne reads configuration and graph, parses options, selects tasks through selectTasksForProjects/createTaskGraph, calls runCommand, drains output, and exits with its status.
- Pre-execution: runTasksForCommand calls ensureWorkspaceIsInSyncAndGetGraphs, which validates targets/cycles, skips sync in CI or with skipSync, and otherwise obtains sync-generator changes; non-TTY out-of-sync execution exits before interactive application.
- Execution dispatch: invokeTasksRunner resolves the runner, loads Ultracache configuration before creating the hasher, performs upfront hashing, and calls tasksRunner; defaultTasksRunner constructs TaskOrchestrator, whose coordinator resolves cache hits, handles batches, then dispatches discrete workers.
- Persistence: postRunSteps records output hashes, persists terminal output, and calls cache.put; native put recreates the hash directory, writes terminal output, expands/copies declared artifacts, and upserts cache_outputs before completion releases further work.
- Replay: fetchCacheHits calls getBatch and checks whether each stored exit code is replayable; finalizeCacheHits checks output hashes, copies artifacts when necessary, derives local/remote/failure status, and prints stored output. runCommand returns failure for failed or skipped results and interruption status for incomplete runs.
- Generation: generate retrieves configurations, converts arguments, resolves generator information, and combines schema options; an Nx implementation receives FsTree, then the tree locks, changes print, and non-dry-run execution flushes changes before invoking the returned callback.
Testing signals
Tests and CI were inspected, not executed; test existence does not establish a passing result. Core Nx TypeScript tests use Vitest, alongside Jest configurations elsewhere and Rust tests in native source. Inspected tests cover argument parsing, staged file changes, cache failure policy, and hostile archive extraction. Mocking and disabled CI matrix entries impose specific limits, and this bounded inspection does not measure whole-repository coverage.
- Core Nx Vitest selects **/*.spec.ts in a Node environment, uses forked workers, excludes native TUI tests, and configures source export conditions plus external native bindings to avoid duplicate native heaps.
- The shared Jest preset transforms TypeScript through SWC, runs one worker in Node, and installs mock mappings; e2e/nx instead uses ts-jest with global setup/teardown. Both Jest and Vitest target defaults allow no-test runs.
- run-one.spec.ts constructs a synthetic project graph and directly verifies parsing of project:target:configuration and project:target; these inspected assertions do not launch an executor.
- tree.spec.ts creates temporary filesystem fixtures, checks staged read/write changes, flushes them, and verifies actual file contents; it exercises the Tree boundary rather than a full plugin-generation command.
- Orchestrator tests verify default rejection of cached failures, NX_CACHE_FAILURES opt-in, and failure status/output on replay; their cache and output-hash checks are mocked, so they do not establish remote-provider integration.
- Rust HTTP-cache tests construct hostile archives for parent traversal, absolute paths, and Unix symlink escape, plus a legitimate artifact; these exercise extract_tarball directly rather than the HTTP transport.
- framing-reconnect.spec.ts runs a synthetic socket peer that always sends an unframed response and expects exactly three connections followed by watcher closure, covering a concrete reconnect-loop limit.
- CI declares affected lint/test/build/e2e/native checks and fix-ci on failure; scheduled e2e configuration comments out Windows, while CodeQL comments out Java/Kotlin. These workflow definitions were inspected, with no CI results retrieved or executions performed.
Risk map
The security-sensitive boundaries are workspace-supplied executable code, shell commands, daemon messages, native module loading, and replayed cache artifacts. Several inspected paths contain explicit containment and ownership safeguards. The observations below distinguish implemented behavior from hypotheses; they are not confirmed vulnerabilities. One inspected test contains an ineffective assertion, and native/testing module boundaries require particular care.
- run-commands launches command strings with shell:true and inherited stdin; calculateCwd accepts absolute paths, and processEnv combines process/local environments with executor overrides. Workspace task configuration therefore controls execution beyond the repository directory.
- Generator dry-run still invokes the plugin implementation before skipping flushChanges and the returned callback; FsTree normalization and flushChanges use joined paths. Dry-run is a host-write preview, not an execution sandbox for arbitrary generator code.
- The self-hosted HTTP cache reads a bearer token and server URL from environment variables and explicitly accepts invalid certificates when NODE_TLS_REJECT_UNAUTHORIZED=0; the TypeScript factory emits an insecure-TLS warning for that setting.
- Hypothesis: large remote artifacts could create memory or disk pressure because retrieval buffers the full response and extraction accumulates metadata content before returning. The inspected path enforces archive containment, but resource-exhaustion behavior was not measured. (inferred)
- Shared artifact/database paths are a replay trust boundary: establishUserRoot checks private owned directories and probes both leaves with exclusive random files; native cache output normalization rejects declared paths outside the workspace.
- Daemon input parsing checks workspace identity for recognized messages and closes malformed streams; plugin worker startup refusals can instead move plugins into the main process, with an explicit warning that isolation-dependent plugins may misbehave.
- Native loading hooks Module._load and caches binaries outside their installed location; Vitest configuration explicitly warns that native bindings are unsafe across worker threads and duplicate binding heaps can kill a worker. Preserve loader identity and process-pool assumptions together.
- The cache-size test for multiple decimal points references .toThrow without calling it, so that assertion does not verify rejection; the neighboring invalid-number test correctly calls .toThrow(). This is a source-observed test defect, not an observed runtime failure.
Extension points
Nx separates command registration, graph inference, executor resolution, generation, and remote-cache integration. Plugin contracts carry workspace configuration and graph context rather than requiring edits to the CLI entrypoint. Package registries pair implementations with schemas, and reference documentation consumes those registries. Browser navigation has its own route table and loaders.
- New CLI commands plug into commandsObject through imported Yargs command modules; the object is deliberately exported separately from argv evaluation so documentation generation can inspect it.
- Project inference plugins implement CreateNodes as a file-pattern/function pair returning project-root and external-node maps, with workspaceRoot and nxJsonConfiguration supplied through context.
- Dependency and metadata extensions use createDependencies and createMetadata; dependency context includes projects, external nodes, full file maps, changed files, and workspace configuration.
- Execution hooks use preTasksExecution and postTasksExecution, with run ID, argv, workspace configuration, and post-run results/timestamps; runCommand calls them around task execution.
- Executor registry entries pair implementation and schema paths; runExecutorInternal resolves the factory and supplies target, project, workspace, and graph context, normalizing Promise and AsyncIterator results.
- Generator registry entries pair factory and schema paths; generate resolves implementationFactory and passes a Tree plus combined options, with an optional callback executed after filesystem flush.
- RemoteCacheV2 defines retrieve/store contracts and adapts legacy RemoteCache implementations; DbCache selects Nx Cloud or optional cache packages before its HTTP fallback.
- Graph navigation extends childRoutes and environment-specific route trees; documentation extends package-schema parsing/rendering and technology slug mapping, with core packages deliberately handled by a separate reference loader.
Contributor handoff
Begin with the owning package and follow the smallest concrete command or API path before changing shared orchestration. Tests and CI were inspected, not executed, and this inventory is bounded rather than exhaustive. Native builds, inferred targets, export conditions, and cache relocation make seemingly local changes cross several boundaries. Validation commands below are future workflow guidance; none were run during this read-only investigation.
- Read AGENTS.md and owning package configuration first; use the root pnpm 12.4.2 pin and workspace package membership, including native packages and separate example workspaces.
- Treat explicit project targets as partial configuration: workspace targetDefaults add dependency/cache behavior, and plugins infer TypeScript, Jest, Playwright, Next, Gradle, and .NET targets with include/exclude rules.
- For CLI changes, read bin/nx.ts, init-local.ts, nx-commands.ts, and the command handler together; preserve completion/version initialization shortcuts and global-to-local delegation.
- For cache changes, read cache-directory.ts and db-connection.ts together: relocation is memoized, environment/configured paths disable sharing, and artifact/database scope must stay aligned while running-task state remains local.
- Keep source implementations separate from generated distributions; package exports select TypeScript under @nx/nx-source and dist otherwise, while native build outputs include bindings and generated declarations.
- Core test edits must respect Vitest's fork pool and source conditions; its setup notes that lazy require-loaded modules are separate from Vite imports and do not see vi.mock, and its preload guard blocks writes to the real root nx.json/package.json.
- For a separately authorized change, the documented sequence is project test/build/lint, affected build/test/lint, affected e2e-local, and nx prepush before committing, with package-manager-prefixed Nx commands. Tests and CI here were inspected, not executed; no passing status is established.
- Documentation work starts with astro-docs/README.md and edits .mdoc/.mdx content; plugin/CLI references derive from implementation schemas and require rebuild/restart. CONTRIBUTING.md still describes the older docs layout, so use the current documentation-specific guidance.
Languages
| Language | Files | Share of source |
|---|---|---|
| TypeScript | 5223 | 90% |
| JSON | 2341 | docs/config |
| Markdown | 491 | docs/config |
| JavaScript | 232 | 4% |
| Rust | 184 | 3% |
| Kotlin | 97 | 2% |
| YAML | 71 | docs/config |
| C# | 39 | 1% |
Start reading here
Probable source entrypoint: Cargo.toml — inferred from the directory tree and manifest, not the upstream docs.
Source roots
packages/ (630 files)
Repository structure
| Top-level path | Files |
|---|---|
packages/ | 630 |
benchmarks/ | 630 |
astro-docs/ | 628 |
nx-dev/ | 581 |
e2e/ | 469 |
examples/ | 375 |
graph/ | 306 |
tools/ | 92 |
Docs found: AGENTS.mdCLAUDE.mdCONTRIBUTING.mdREADME.md
Package
Cargo.toml — , 0 declared dependencies.
CI & config entrypoints
README.md— Repository readmeAGENTS.md— Agent instructionsCLAUDE.md— Claude instructions.github/workflows/banner-monitor.yml— GitHub Actions workflow.github/workflows/ci.yml— GitHub Actions workflow.github/workflows/codeql-master.yml— GitHub Actions workflow.github/workflows/codeql-pr.yml— GitHub Actions workflow.github/workflows/do-not-merge.yml— GitHub Actions workflow.github/workflows/e2e-matrix.yml— GitHub Actions workflow.github/workflows/generate-embeddings.yml— GitHub Actions workflow
Structural health signals
Average score 6.6/10 across 96 analyzed source files; 45 hotspots surfaced.
graph/client/src/assets/release-static/environment.js— 1459 lines, score 5 (Large file, Deep nesting)examples/angular-rspack/appshell-css/src/app/nx-welcome.component.ts— 951 lines, score 5 (Large file, Deep nesting)examples/angular-rspack/csr-css-assets/src/app/nx-welcome.component.ts— 951 lines, score 5 (Large file, Deep nesting)
These are deterministic review leads — size, churn, and structural signals — not proof of a bug in this project.
Recent history
bedd602304d72026-10-02 — fix(angular-rspack): update piscina to address critical vulnerability (#37252)fccd1125783f2026-10-02 — fix(core): close the task DB before nx reset deletes workspace-data (#37250)032dcd81c21e2026-10-02 — cleanup(core): rename io snapshots to ultracache configurations (#37245)f2e72857f1e62026-10-02 — fix(core): treat a cache record whose artifacts are missing as a miss (#37111)6db155fdc60a2026-10-01 — fix(core): cache only declared outputs under ultracache (#37243)