Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Target configuration

Targets appear in a project’s targets object or workspace targetDefaults. The example uses explicit command execution and output declarations:

{
  "targets": {
    "build": {
      "executor": "nx:run-commands",
      "options": { "command": "pnpm exec tsc --build", "cwd": "{projectRoot}" },
      "configurations": { "release": { "args": "--verbose" } },
      "dependsOn": ["^build"],
      "inputs": ["default", "^default"],
      "outputs": ["{projectRoot}/dist"],
      "cache": true
    }
  }
}

Merging

A target can be defined in several places: target defaults, package.json and project.json (see Configuration precedence). As in Nx 24, each definition merges over the one beneath it field by field: a field it sets replaces the one beneath, except that options merge by option name and configurations by configuration name and then by option name. Arrays and nested option values are replaced.

A definition that runs the target differently replaces the one beneath it whole, every field included: it names another executor, or for nx:run-commands another command, or for nx:run-script another script. A definition without an executor, command or script merges over any.

The spread token "..." merges instead of replacing. In an array, such as inputs, outputs or dependsOn, the item "..." stands for the items beneath it, in its place: "inputs": ["mine", "..."]. In an object, the key "...": true stands for the fields beneath it: a field written after it wins over the one beneath, and one written before it yields to it. It works on the target itself, on options and each option’s value, on configurations, on each configuration and each of its options’ values. Beneath that, a spread is an ordinary value. With nothing beneath it, a spread adds nothing. An object with "..." cannot also have a key that is a whole number, such as "1": Nx cannot tell where it was written.

A target key that is a glob, such as "e2e-ci--*", merges onto every target defined beneath it whose name it matches, and is a target of its own when it matches none. Keys are globs and match as targetDefaults keys do (see Workspace): * does not cross a /.

executor

A string naming nx:run-commands, nx:run-script, or nx:noop. Unsupported names remain inspectable but fail execution preflight. See Executors for their options. A target with neither an executor nor a command runs nx:noop when it has dependsOn, and is left out otherwise, as in Nx.

command

A shorthand command normalized into nx:run-commands options. Prefer an explicit executor with options.commands for multiple commands. A target cannot have both command and executor.

options

An object, empty by default, of executor-specific options. Selected configuration values merge over these by key, followed by task argument overrides. Nested objects, including env, are replaced rather than recursively merged. A configuration with env: {} removes the base option’s overrides; process and dotenv values still apply.

As in Nx, the tokens {projectRoot} and {projectName} are replaced in every string of the options and configurations, nested ones included, as the workspace loads, and qk show project shows the result. {workspaceRoot} may only start a string, and is removed with the slash after it, leaving a path relative to the workspace root: "{workspaceRoot}/dist" becomes "dist". Anywhere else it is an error.

configurations

An object mapping configuration names to option objects, empty by default. Select with -c release or project:target:release. --prod selects production. Requested configuration names propagate through dependencies. A dependency without that configuration uses its own default, while its dependencies still receive the requested name. A configuration’s keys are all options: outputs in a configuration is an option named outputs, not the target’s outputs, as in Nx.

defaultConfiguration

An optional string selecting a configuration when none is requested. Without a requested configuration, each task chooses its own default; a parent’s default does not propagate to its dependencies.

dependsOn

An array of dependency declarations. Without it, a target has no declared task dependencies. Shared dependencies run once.

DeclarationMeaning
"build"Target in the same project
"^build"Target on project dependencies, looking through projects without it
"core:build"Target in an explicit project
"lint-*" or "^build-*"Matching target names
{ "target": "build", "projects": ["tag:library"] }Target on selected projects
{ "target": "build", "dependencies": true }Target on project dependencies

Target names may contain colons. As in Nx, "a:b" names target b of project a when a is a project with that target, and otherwise target a:b of the same project; "^a:b" and { "target": "a:b" } name target a:b.

Object declarations also accept params: "forward" and options: "forward"; any other value, or none, does not forward. params passes the run’s own arguments; options passes the target’s options, its configuration’s included, as the dependency’s options, overriding its own, lists and objects included. With both projects and dependencies: true, projects applies. Other fields are ignored, as in Nx. As in Nx 24, the Nx 15 spellings projects: "self" and projects: "dependencies" fail.

An object declaration naming a continuous target also accepts inputs and waitFor. inputs: false keeps the continuous task’s inputs from counting for the dependent; see Affected selection. waitFor is "started", the default, or "ready", which starts the dependent once the target’s readyWhen check passes. When several declarations name the same task, "ready" wins, and its inputs count unless every declaration sets inputs: false. Both have no effect on a dependency that is not continuous.

Other missing dependency targets are skipped. Unknown explicit projects and task cycles fail unless --nx-ignore-cycles is used. A shared task reached with different forwarded arguments or options keeps those it was first reached with, as in Nx. See Running tasks.

inputs

An array of input declarations. Without it, qk uses default and ^default. Inputs determine both cache keys and task-level affected selection.

outputs

An array of output paths or globs with fixed directory prefixes. On a cache hit these are restored and recorded logs replayed. Explicit outputs also let dependent keys reflect output content instead of the dependency’s entire key. See Inputs and outputs.

cache

A boolean; absent or false means the target does not opt in to result caching. true enables caching when supported by the task’s inputs and outputs. Continuous and readiness tasks run uncached. As in Nx, a target with both cache and continuous set to true is an error. See Local cache.

continuous

A boolean, default false. Dependents may start when this task starts, or, with waitFor: "ready", when its readyWhen check passes. Continuous tasks do not count towards --parallel; they run until exit or cancellation. A continuous task used only as a dependency is stopped successfully once its consumers finish. See Continuous tasks.

readyWhen

How a continuous target tells that it is ready, for tasks depending on it with waitFor: "ready", as in Nx 24. It is an object with exactly one of:

KeyReady when
urlAn HTTP or HTTPS GET gets a status from 200 to 403. Redirects are not followed, and a 404 at the root path is tried again at /index.html.
portA TCP connection succeeds, to 127.0.0.1 or ::1 unless host names the address.
commandThe command, run through the shell at the workspace root with the environment the target’s commands run with, exits with 0. It reads the options they run with, as JSON, from NX_TASK_OPTIONS.
logMatchesEvery one of a string or an array of strings has appeared in the output, terminal control sequences left out.
signaltrue: the task reports that it is ready, as @nx/devkit’s signalTaskReady does, through the socket qk names in NX_READY_SIGNAL_SOCKET.

timeout, 600000 (ten minutes) by default, is how many milliseconds the check may take, and interval, 250 by default, how long a url, port or command check waits between tries. Strings may use {workspaceRoot}, {projectRoot}, {projectName}, {options.name}, {env.NAME} and ?? fallbacks, read from the options, arguments and environment the task runs with. null turns off a check set by a target default. See Continuous tasks.

A signal takes no interval. The address a signalling task reports is passed on in NX_READY_URL to a task that waited for it, when it is the only server that task waited for to report one. A task that sets NX_USE_V8_SERIALIZER=true signals in Node’s own serialization, which qk cannot read.

As in Nx 24.0.1, a task resolves its own readyWhen once the servers it waits for are ready, so {env.NX_READY_URL} and a command check’s environment have the address. Only a signal check reports one: behind a server with another check, {env.NX_READY_URL} has no value. Behind a signalling server, a port read from NX_READY_URL gets the address rather than a ?? fallback, so it is not an integer, and the check is invalid.

This is unrelated to the run-commands readyWhen option, which marks the task itself as ready.

parallelism

A boolean, default true. false runs the task alone, waiting for all other tasks, including continuous ones. No other task starts while it runs. Graphs requiring it to overlap a continuous dependency are rejected.

env

A target-level object of environment variables, for every executor. This is a qk extension; Nx ignores it. Executor options.env and selected configuration env can override it. See Environment precedence.

qk:env

The environment the task inherits: an array of entries, each the name of an environment in nx.json’s qk:environments, whose entries it stands for, or an object with one of these fields:

FieldTypeWhat it does
inheritarray of variable namesPasses the variables through and keys their values
passarray of variable namesPasses the variables through without keying their values, as for credentials and proxies
setobject of string valuesSets the variables, keyed as written
binarray of command names, or of objects with name and keyPuts the commands, as found on the PATH qk inherited, on the task’s PATH, keyed by the files they resolve to, or with "key": "content" by their content
dirsarray of paths, with {projectRoot} and {workspaceRoot}Adds the directories to the task’s PATH, after the commands, keyed as written; relative to the workspace root
fromobject with command and, optionally, inputs, an array of pathsSets the variables the command prints as JSON, as nix print-dev-env --json, direnv export json or mise env --json print them; see Declared environments

A name can contain *, which matches any run of characters, as LC_*. A variable both inherited and passed fails the task, as does a command bin names that is not on PATH. An environment with bin or dirs entries builds PATH, so it cannot also inherit, pass or set it. false inherits every variable, as without the field, which overrides nx.json’s qk:defaultEnv. See Declared environments.

qk:threads

true, or an object containing:

FieldTypeDefault
envobject of string valuesEmpty; {threads} expands to the threads the task is told to start: its share of cores, times scale, rounded up
minpositive integer1
maxpositive integer, at least minRun’s core budget
scalenumber above 0, at most 81; threads the task is told to start per core it holds, rounded up

Opted-in tasks receive QK_THREADS; true sets only that variable. The share is fixed when the task starts. min and max bound the cores a task holds; scale only changes how many threads it is told to start on them. Without this key a task holds one core. The setting and allocated count do not affect cache keys. Continuous tasks do not take a core share; this setting does not allocate threads or set these environment variables for them. false is not a supported value; omit the key to disable it. Other fields are ignored, as Nx ignores keys it does not know, so a configuration can use fields a newer qk added; qk doctor reports them. See Sharing cores for allocation examples.

qk:sandbox

false runs the task unsandboxed under --sandbox, listed with the reason, for a task that applies a sandbox of its own, which cannot run inside qk’s, such as an Xcode build running Swift macros. true, the default, sandboxes it. An object sandboxes it too, and names its scratch directories:

FieldTypeDefault
scratcharray of paths, with {projectRoot} and {workspaceRoot}Empty; directories emptied before each run of the task, with or without --sandbox, which the task may read and write and which nothing keeps

A scratch directory lies in the workspace, outside .git, .qk and node_modules in any case, holds no project and neither qk’s cache nor its state, and neither is nor lies under a symbolic link; a task naming another fails, and so does a run in which two tasks share one or have one inside the other’s. qk doctor reports one, any other value, and fields it does not know. See Scratch directories and ignored reads.

qk:ultracache

An object: the task is keyed by what it read when a run with --record last recorded it, rather than by its declared file inputs, once it has been recorded. See Keying tasks by what they read.

FieldTypeDefault
mode"on", "record" or "off""on"; "record" records the task and reports what its recordings would have done, but keys it by its declared inputs; "off" keys it by its declared inputs, as without the field
ignoreReadsarray of workspace globsEmpty; files left out of recordings, whose changes cannot change the result; the sandbox’s audit leaves them out too, and enforce lets the task read them. A glob starting with ^ is matched from the root of each project the task’s project depends on, directly or not

Nx’s "warn" and "error" modes are not supported yet. Other fields are ignored, as in qk:threads, and qk doctor reports them. The field does not change the task’s key; ignoreReads changes what its recordings key.

qk:warm

An object describing reusable scratch state, or an array of them restored and saved separately. In an array, at most one entry omits group, no group is named twice and no variable is set by two entries. See Several entries. Each object has:

FieldTypeDefault
outputsbooleanfalse; restore previous outputs before execution
pathsarray of workspace paths and globsEmpty; ! excludes; {warm} is not allowed here
envobject of stringsEmpty; {warm}, {workspaceRoot}, {projectRoot} expand to absolute directories
maxSizebytes or size stringNo per-group limit
remotebooleantrue; permit remote exchange when portable is true or "path"
portabletrue, false or "path"false; true permits another worktree’s save and remote exchange; "path" permits remote exchange, restoring a save only when made in a checkout at the same path
mtimes"epoch" or "preserve""epoch"; "preserve" keeps a worktree’s own save’s modification times
keyarray of workspace paths and {"env": name} objectsEmpty; a save is restored only where the key matches
restoreKeyscountNone; how many leading key parts a save must match when none matches whole
groupstringNone; share {warm} and its saves with every target naming the group; an entry with a group cannot set outputs, paths or survive
survivearray of targets, target or project:targetEmpty; keep paths across these dependencies
save"wait" or "background""wait"; "background" saves after the task has reported
restore"whole" or "each-path""whole"; "each-path" restores each missing path from paths and leaves those on disk; see Restoring paths one by one
prefetchbooleanfalse; fetch the remote save as the run starts, while the task’s dependencies run; see Fetching remote state ahead

Other fields are ignored, as in qk:threads, and qk doctor reports them. Put it beside inputs and outputs, rather than in executor options. Environment values retain their other text unchanged; their directory tokens are absolute even when the task runs from a project subdirectory. Warm state is restored on misses and uncached runs, saved after success, and never changes a key or a hit. --skip-cache disables it. See Warm state for tool configurations, portability checks and lifecycle details.