Ok, so this one is gonna be a bigger release post as I decided to catch you up on everything that landed across all the releases starting from 22.3 in December until now.
The biggest things to call out: task sandboxing (catch hidden cache dependencies via real I/O tracing), a 7x reduction in daemon memory, and worktree-aware caching.
Nx Caching got an upgrade
Caching got meaningful upgrades across 22.6 and 22.7.
Cache is now worktree-aware
Nx now uses the same cache across git worktrees. Building in one worktree and switching to another gives you a cache hit instead of a rebuild. It also saves disk space, since artifacts live in one place instead of being duplicated per worktree.
This matters a lot for parallel agentic development, where it's common to spin up several worktrees and run a different agent in each.
Finer-grained control over hashing
Two additions give you more precise control over what actually invalidates a task's cache.
Dependency filesets with ^{projectRoot} (22.6). You could already reference files in your own project with {projectRoot}, but walking into the source of a dependency required workarounds. 22.6 adds native support for ^{projectRoot} in input patterns, so a target can declare inputs that reach into dependency source directly. Hashing is more precise and dependency config changes no longer over-invalidate their consumers.
{
"targetDefaults": {
"build": {
"inputs": [
"default",
"^{projectRoot}/src/**/*.ts"
]
}
}
}json input type (22.7). A new input type lets you hash only specific fields of a JSON file instead of the whole thing. Useful when whole-file hashing is too coarse: you can say "only invalidate the build cache when dependencies, devDependencies, or peerDependencies change in package.json", ignoring edits to scripts or author.
{
"targetDefaults": {
"build": {
"inputs": [
"default",
{ "json": "{projectRoot}/package.json", "fields": ["dependencies", "devDependencies", "peerDependencies"] }
]
}
}
}Inspect target inputs and outputs
We've added a new nx show target command that prints the resolved configuration for a target. Useful when a project's behavior surprises you and you want to see what Nx actually computed.
nx show target my-app:buildIt comes with four flags for inspecting and testing cache inputs and outputs:
nx show target my-app:build inputs
nx show target my-app:build inputs --check src/app.ts
nx show target my-app:build outputs
nx show target my-app:build outputs --check dist/my-app/main.jsinputs and outputs print the resolved patterns for a target. Passing --check <file> tells you whether that specific file matches: useful when you suspect a file is (or isn't) contributing to a task's hash and want an answer instead of guesswork.
We also added source map annotations, so you can see exactly which plugin, preset, or config file produced each piece of the resolved configuration. Run it with --verbose to get the source location for each input, output, and option:
nx show target my-app:build --verboseTask sandboxing
Caching is hugely effective at speeding up tasks, but it's based on trust: you trust the caching mechanism to be correct. A cache miss when there shouldn't be one is harmless. A false cache restore that deploys an old or wrong version to production isn't, and we've seen workspaces disable caching on main because of exactly that.
The correctness of any caching mechanism doesn't only depend on its implementation, but also largely on the user configuration. The cache inputs are part of the cache key that determines whether a task gets restored from cache. Miss a crucial input and the cache may return a false positive.
Most of these mistakes go undiscovered. That's why we introduced task sandboxing in Nx 22.6. Nx traces the real file I/O each task performs and compares it against what you declared. Any read outside inputs or write outside outputs gets flagged as a violation, so you catch hidden dependencies the moment they appear instead of weeks later on CI.

Tasks still run successfully when violations exist, the cache entry just isn't trustworthy. Below, astro-docs:validate-links reads index.html files that aren't declared inputs. The task passes, but the next cache hit would replay against stale files. This was a real bug on the Nx repo, found and fixed via sandboxing.

No other monorepo tool gives you this. Turborepo, Gradle, Lerna, and Rush trust your inputs config blindly. Bazel enforces hermeticity, but only if you adopt its sandbox model end-to-end, which means rewriting builds in BUILD files, declaring every dependency upfront, and giving up the toolchain you already have. Nx gets you the same correctness guarantee on top of your existing setup.
When you do hit a violation that's expected (a timestamp file, a local cache dir), you whitelist it in .nx/workflows/sandboxing-config.yaml with exclude-reads and exclude-writes:
# applies to every task in the workspace
exclude-reads:
- '**/vite.config.*.timestamp-*'
exclude-writes:
- '**/*.log'
# applies only to matching tasks
task-exclusions:
- target: lint
exclude-reads:
- .eslintcache/**
- project: myapp
target: build
exclude-writes:
- logs/**See the sandboxing docs for how to turn it on.
Nx is 7x more memory efficient
Back in 22.3 we shipped a resource usage dashboard on Nx Cloud that surfaces memory consumption per process during a CI run. Using it, we noticed that processes owned by Nx (the daemon and CLI) were chewing through a lot of memory, even inside agents. So we spent 22.6 and 22.7 cutting that footprint down. On Nx's own repo:
- Before: the Nx daemon would typically use 1.5 to 1.6 GB
- After: it now settles around 200 MB
That's roughly a 7x reduction. It's impactful both locally and on CI, but especially on CI, where less memory per run means more parallelism per machine.
If you're on Nx Cloud, you should see this directly in your agent resource usage stats. Here's the same effect on our own Nx Cloud dashboard, with Nx CLI and subprocess memory settling well below the old baseline across a CI run:

Faster restore from cache
We've put significant work into speeding up cache replay in 22.7. Restoring 1110 cached tasks with topological dependencies now takes 1.16s, down from ~17s, roughly 90% faster.
To track this kind of work going forward, we've set up a suite of synthetic benchmarks that now run on every PR against a 1110-project workspace. Here's where the rest of them stand today:
| Benchmark | Before | After |
|---|---|---|
nx show projects | 710ms | 434ms |
| 1110 flat lint-like tasks (cached terminal output, no file outputs) | 2.44s | 1.04s |
| 1110 flat test-like tasks (cached terminal output and file outputs) | 6.85s | 1.31s |
| 1110 topological build-like tasks (10 → 100 → 1000, cached terminal output and file outputs) | 17.75s | 1.16s |
We're not done yet. We have some stricter goals we're currently working towards.
More agentic improvements: setup, configuration, and nx import
AI is a fundamental part of the software development lifecycle, and we're continuing to push Nx forward on that front. A few things that landed across the recent releases:
nx initandcreate-nx-workspacenow detect when they're running inside an AI agent and wire up agent rules automaticallynx configure-ai-agentswires up your agent to use Nx: installs the Nx plugin, teaches the agent how to use Nx, and drops in Nx skills/subagents. It supports Claude, Codex, Cursor, Gemini, and OpenCode.nx listgained a--jsonflag so agents can consume the plugin list as structured data
If you run Nx from inside Claude, Codex, Cursor, or a similar agent, these changes should make setup noticeably smoother.
nx import with an agent
One of the trickiest parts of adopting a monorepo is getting your existing projects into it without losing their git history. nx import has been our answer to that for a while: a deterministic command that clones a repo, filters and rewrites its history, merges it into your workspace, and detects which Nx plugins to wire up.
The catch with any deterministic command is that it can only anticipate so many situations. Real-world repos have odd layouts, custom configs, and edge cases the command doesn't know about. Pairing it with an AI agent closes that gap: the agent runs the deterministic pieces, then adapts around the cases the command wasn't built for.
We're working on a similar agent mode for nx migrate which should be available in one of the upcoming releases.
Framework and language support
Vite 8 and ESLint v10. If you use @nx/vite or @nx/eslint, both major-version bumps are supported.
Yarn Berry catalogs. 22.6 understands Yarn Berry catalog syntax in the project graph and during nx release publishing.
Angular. 21.1 and 21.2 support landed, along with ngrx v21 and zoneless Cypress component testing. Angular Rspack got fixes in 22.7: Windows i18n, fileReplacements wired into resolve.alias, and HMR.
Maven and Gradle. Maven now has a batch executor, enabled by default, which runs multiple Maven tasks in a single JVM for a significant performance boost. Maven 4 and Spring Boot 4.0 are supported, and external Maven dependencies now show up in the project graph. On the Gradle side, the batch executor is now enabled by default too, bringing the same in-JVM speedup to Gradle tasks.
Quality of life improvements
A few DX improvements worth calling out.
nx release improvements. A top-level --otp flag with automatic EOTP detection makes 2FA publishing a single-command flow, publish errors now surface when stdout isn't valid JSON, and changelog handling got cleaner around dependent projects and deduplication.
--stdin for nx affected. Since 22.6, you can pipe a list of files into nx affected (e.g. git diff --name-only main | nx affected --stdin -t test), which helps custom CI pipelines and git hooks that compute their own change set.
A huge thanks to the ~55 outside contributors who shipped fixes and features across 22.4 through 22.7. A few highlights:
Decoupling formatting from generators. @baer added NX_SKIP_FORMAT=true to opt out of the Prettier pass generators run after they write files. Formatting has historically been tightly coupled into Nx's generator pipeline: fine if you use Prettier, a bit awkward if you want a different formatter. This is the first step toward pulling that coupling apart, which opens the door to integrating formatters like Oxfmt more natively into the toolchain. More on that soon.
Bail on the first failure. @jase88 added NX_BAIL=true to stop a run as soon as a single task fails, instead of continuing through the rest of the graph.
TUI polish. @yharaskrik added page up/down shortcuts. We also improved scrollbar positioning and shipped miscellaneous perf fixes.
We've also been labeling good-first-time GitHub issues with the community label. If you want to chip in, that's the best place to start. These folks already did. You can be next.
How to update Nx
As always, updating to the latest version of Nx is straightforward:
npx nx migrate latestThis analyzes your workspace and creates a migration file with all necessary updates. Review the changes, then apply them:
npx nx migrate --run-migrationsFor a more visual migration experience, use the Migrate UI in Nx Console, which lets you review and approve each migration individually.
New to Nx? Create a fresh workspace with npx create-nx-workspace@latest, or run nx init inside an existing npm/pnpm workspace to start using Nx with it. Head over to the Getting Started guide for a walkthrough.







