Skip to content
Back to Knowledge Base

Fix Nx Commands Failing in Claude Code Sandbox

When running Nx commands inside Claude Code's sandbox mode, you may see errors related to the Nx daemon, plugin isolation, or forked processes failing to communicate. This happens because Claude Code's sandbox (Seatbelt on macOS, bubblewrap on Linux) blocks Unix socket access by default, and Nx relies on Unix sockets for inter-process communication.

Add allowAllUnixSockets: true to your Claude Code sandbox network settings. You can set this at the project level (.claude/settings.local.json) or user level (~/.claude/settings.json):

.claude/settings.local.json
{
"sandbox": {
"network": {
"allowAllUnixSockets": true
}
}
}

This grants Nx the ability to create and connect to Unix sockets, which it needs for daemon communication, plugin isolation, and forked task execution.

Scoped allowlisting with the Nx socket root

Section titled “Scoped allowlisting with the Nx socket root”

The daemon, forked task processes and plugin workers put their sockets beneath one stable root on macOS and Linux: /tmp/.nx, unless overridden via NX_SOCKET_DIR. When that root can't be used they move to ~/.nx, so allowlist both. Neither path varies between machines or users, which makes the rule suitable for team-wide project settings:

.claude/settings.json
{
"sandbox": {
"filesystem": {
"allowRead": ["/tmp/.nx", "~/.nx"],
"allowWrite": ["/tmp/.nx", "~/.nx"]
},
"network": {
"allowUnixSockets": ["/tmp/.nx", "~/.nx"]
}
}
}

~ expands to the home directory of whoever runs Nx, so one committed entry covers every user. Wildcards don't work in these settings, so each entry has to be a literal path.

The write grant covers /tmp/.nx rather than only its sockets descendants because the first Nx run also has to create the root. Nx copies its compiled native binding into a cache under the same root before loading it, which the grant needs to cover too.

Setting $NX_SOCKET_DIR replaces this list rather than joining it: the value is used exactly as given, and a configured directory Nx can't use sends it straight to the workspace with a warning instead of quietly substituting a longer path you never asked for.

Otherwise Nx uses the first of these it can establish. It creates each directory and verifies it afterwards, not before: a check that ran first would leave a window in which someone else could swap the path between the check and the use.

  1. /tmp/.nx/<uid>/sockets needs /tmp/.nx to belong to you or to root, and to be sticky if anyone else can write to it. The two directories beneath it have to be yours and mode 0700.
  2. ~/.nx/sockets needs both directories to be yours and mode 0700. There's no container check here, because nobody else can write to your home directory.
  3. <workspaceRoot>/.nx/workspace-data/d is the last resort. Its length grows with the depth of your checkout, so a deeply nested workspace can push a socket past the 95-character limit Nx enforces. Nx sets that conservative guard to sit under the operating system's own cap on socket paths.

The native binding cache doesn't follow sockets down that list. It lives at /tmp/.nx/<uid>/native-cache/<nxVersion> or nowhere. When that can't be established, Nx skips the cache and loads the binding in place from node_modules. A skipped cache costs one file copy, while a skipped socket costs you the daemon, so only sockets keep looking.

None of this applies on Windows. Named pipes aren't filesystem objects, so sockets stay directly under %TMP%, with no per-user segment and no second location.

Claude Code's allowUnixSockets setting currently only allows connecting to sockets, not creating them. A scoped allowlist works when the daemon is already running (started outside the sandbox, for example from your own terminal), but processes inside the sandbox that need to create sockets, such as a fresh daemon, plugin workers, or forked tasks, still require allowAllUnixSockets: true.

If you prefer not to enable blanket Unix socket access, you can disable the Nx features that require sockets. These workarounds come with tradeoffs:

Terminal window
NX_DAEMON=false nx <command>

The Nx daemon keeps a persistent process running to speed up repeated operations. Disabling it means Nx starts fresh on every invocation, resulting in slower cold starts (especially in large workspaces).

Terminal window
NX_ISOLATE_PLUGINS=false nx <command>

Plugin isolation runs each plugin in a separate forked process to prevent conflicts between multiple TypeScript compilers, module-level caches, and global state. Disabling it runs all plugins in the main process, which can cause issues in workspaces with plugins that have conflicting dependencies.

For advanced use cases, Nx provides environment variables to override where socket files are created:

VariableDescription
NX_SOCKET_DIROverrides the directory for all Nx sockets (daemon, forked process, and plugin). Replaces the default locations listed above rather than joining them. Must name a directory only your user can reach. Nx rejects the system temp directory and its own container/cache roots outright.
NX_DAEMON_SOCKET_DIRLegacy alias of NX_SOCKET_DIR. Used only when NX_SOCKET_DIR is not set. Prefer NX_SOCKET_DIR.
NX_NATIVE_FILE_CACHE_DIRECTORYOverrides the native file cache path

These are primarily useful for environments with restricted temp directory access (e.g., certain Docker or CI setups). For Claude Code's sandbox, allowAllUnixSockets: true is simpler and more reliable.

Last updated: