CLI reference
| Command | Result |
|---|---|
qk inputs analyze <task> [--report <path>] [--previous <path>] [--suggestions <path>] | Execute tasks without caching, record file accesses and review input coverage; macOS, or Linux with eBPF or strace. See Recording task inputs |
qk show projects [--json] | Project names in Nx graph order, one per line or as a compact JSON array |
qk show projects -p 'web,tag:library' --exclude 'experimental-*' | Matching names, globs, tags and roots, minus exclusions |
qk show projects --with-target e2e --type app [--sep ,] | Projects with one of the targets, of a type (app, lib or e2e, as Nx types them), joined by a separator |
qk show projects --affected -t build,export | Projects owning an affected task of one of the targets, or under project selection the affected projects with one of them, as qk affected selects them |
qk show projects --affected --affected-targets build,export | Affected projects where a task of one of the targets is affected, as task selection decides it |
qk show project [name] [--json] | A project’s graph node, as Nx’s summary or one line of JSON; the current directory’s project by default, and a name that is no project matches as a pattern, as in Nx |
qk graph --file <path>.json | Workspace project graph in a { "graph": { "nodes": ..., "dependencies": ... } } envelope |
qk graph, qk graph --file stdout or --file - | The same graph on stdout |
qk graph --external | The graph with the packages the pnpm lockfile installs as externalNodes |
qk graph --focus web --exclude 'tag:e2e' | Only web, what it depends on and what depends on it, minus exclusions |
qk run <project>:<target>[:<configuration>], qk run -p <project> -t <target> | Execute a task and its dependencies |
qk <target> [project], qk <project>:<target>, qk <project> | Nx-style shorthand for qk run |
qk run-many -t build,test -p 'web,core' --parallel 4 | Execute matching targets with bounded task concurrency |
qk exec -p web -- <command> | Run a command in projects, or as a package script’s target, as nx exec does |
qk run web:build --dry-run | Prepare every planned task without running it, and print the task graph as JSON |
qk show projects --affected [--base <rev>] [--head <rev>] | Projects affected by the changes, in graph order |
qk affected -t build,test [--base <rev>] [--head <rev>] | Execute the affected tasks of the targets, and the tasks they depend on |
qk show affected [project] [--json] | Why projects are affected, or why one project is, and the granularity qk affected selects by |
qk affected -t build --granularity project | Execute the targets of the affected projects, as affected.legacy does |
qk show tasks -t build,test --affected [--json] | The affected tasks and why |
qk show runs, qk show run [id] | Recent runs; one run’s tasks, cache results and critical path |
qk show flaky [task] | Mixed successful/failed executions for identical declared inputs |
qk show log <run> <task> | Replay retained stdout/stderr from an actual cacheable execution |
qk show task <project:target> | A task’s recent runs and why its cache key changed |
qk show hash <project:target> [--against <task|run>] | A task’s cache key and what it covers, or where it differs from another key, without running the task |
qk cache path | Print the local cache directory without creating it |
qk cache prune [--max-size 1GB] | Evict entries unused for a week, then least recently used entries until the cache fits |
qk warm suggest <project:target> | Run a task in the sandbox and list directories it wrote outside its outputs, as candidate warm paths (macOS) |
qk reset [--only-cache | --only-workspace-data] | Remove the cache and this worktree’s state, as nx reset does |
As in Nx, qk build web and qk web:build mean qk run web:build, and take the
same options. qk run reads its task as Nx’s run does: a
project:target[:configuration], else -t/--target (for a target whose name
has a colon) with -p/--project or the positional naming the project, else
a project with a run target, which qk tool and qk run tool run, else a
target. The project may be a name or a pattern matching exactly one project;
a pattern matching several fails with Nx’s “Multiple projects matched”. As
in Nx, b, e, l, s and t name the build, e2e, lint, serve
and test targets. Without a project, qk build and qk run build use the project
whose root most specifically contains the current directory, as Nx does:
in the root project, NX_DEFAULT_PROJECT picks another, and where no
project contains the directory, NX_DEFAULT_PROJECT, then nx.json
cli.defaultProjectName, then defaultProject. As in Nx, --base, --head,
--files, --uncommitted and --untracked imply --affected for
show projects. qk’s own
subcommands, and Nx commands qk does not implement such as format and
release, are never read as targets; use qk run for a target
with one of those names.
As in nx graph, --focus keeps the project and every project connected to
it through dependencies in either direction, and --exclude takes
project selectors. The kept projects’ edges are unchanged, so they can name projects
left out. --print and --file stdout write to stdout. qk has no browser
view, so nx graph’s --affected, --view and server options do not apply;
for a task graph, use qk run-many -t <targets> --graph.
Options are read as Nx’s yargs configuration reads them. They may be
spelled in camelCase as well as kebab-case, so Nx’s --outputStyle works as
--output-style. A boolean option takes a value or a negation:
--nx-bail=false, --skip-nx-cache true and --no-nx-bail all work, and
any value other than true means false. An explicit --nx-bail=false or
--verbose=false overrides NX_BAIL and NX_VERBOSE_LOGGING.
On the commands that run tasks, run and its shorthand, run-many and
affected, an option qk does not know, and a positional beyond the
command’s own, is forwarded to the requested tasks, as Nx’s
unknown-options-as-args forwards it: qk test web --coverage runs
web:test with --coverage. They are forwarded in order and as spelled,
followed by any arguments after --, which are forwarded unchanged. Nx
drops the unknown options when a -- is also given; qk keeps them. The
other commands reject unknown options.
As in Nx, the hidden affected:build, affected:test, affected:lint and
affected:e2e run affected for that target, and affected:graph and
print-affected, which Nx removed, fail with Nx’s message.
--workspace <path> works before or after the subcommand. As in Nx, a
graph --file path is relative to the workspace root, its directories are
created, and it must end in .json; qk has no HTML graph, so a .html file
fails. JSON output has no progress messages mixed into stdout. Errors go to
stderr and return a nonzero exit code. Unknown commands fail explicitly.
exec
qk exec -- <command> runs a command as nx exec does. Each argument is
wrapped in double quotes and the result runs in the shell tasks use, so
$NAME expands; NX_PROJECT_NAME and NX_PROJECT_ROOT_PATH name the project.
- Inside a task, where
NX_TASK_TARGET_PROJECTis set, the command runs in the current directory for that project. - From a package script, where the package manager sets
npm_lifecycle_event, the current directory’s project runs the script’s target instead, with the run options and any arguments beyond the script’s own. That task runs the script again, which then takes the first case, so a script such as"build": "qk exec -- tsc"is cached. Nx runsnx runfor it without the run options, and reads the extra arguments as its own options; qk passes the options to the run and the arguments to the task. - Otherwise it runs in each project
-pand--excludeselect, all by default, and in every project they depend on, dependencies first. The first failure stops it.--exclude-task-dependenciesruns only the selected projects.
The command is what follows --; as in Nx, other options exec does not
know are ignored. A failing command exits with 1, as in Nx. Only the package-script case
runs a task, so the others refuse --sandbox, --dry-run and --graph
rather than run the command without them.
Shared run options
These options apply to run, run-many and affected:
| Option | Behavior / default |
|---|---|
-c, --configuration <name> | Select named options; otherwise defaultConfiguration |
--prod | Select production |
--parallel [value] | Number, percentage, or false; NX_PARALLEL, then workspace parallel, then 3 |
--cores <count> | Positive core budget; QK_CORES, then qk:cores, then available cores |
--skip-cache | Bypass all result caching and warm state |
--cold | Run each task from scratch: restore no result and empty its warm paths rather than restore them, then save both as usual; QK_COLD=true too. See Replacing a bad save |
--skip-remote-cache | Keep local caching only |
--nx-bail | Stop starting tasks after the first failure; NX_BAIL=true too |
--nx-ignore-cycles | Drop cycle-closing dependency edges with a warning |
--exclude-task-dependencies | Run only requested tasks |
--graph[=<file>] | Write Nx-shaped project/task graph without execution; default stdout |
--dry-run | Print qk’s task graph; no dotenv, runtime inputs or executor preflight |
--output-style <style> | Select output behavior; see Running tasks |
--verbose | Set NX_VERBOSE_LOGGING=true for tasks, which otherwise see false unless it is set to true; print every task in full under static-failures-only |
--sandbox[=audit|enforce] | Report (audit) or refuse (enforce) what tasks read and write in the workspace beyond their declarations. A task restored from the cache is not checked; add --skip-cache to check every one. See Checking inputs in a sandbox |
--sandbox-report <path> | Write every sandbox finding as JSON |
--record | Record what each task with qk:ultracache reads when it executes, and key its result by that; Linux only. With --sandbox, audit what it records. See Keying tasks by what they read and Auditing recorded runs |
--report <path> | Save JSON run report; defaults to NX_RUN_REPORT when set |
--profile | Print cache input and restore phase timings to stderr; see Profiling cache operations |
-- <args> | Forward arguments to requested tasks, after any unknown options |
--parallel alone uses NX_PARALLEL, otherwise 3. Percentages are
rounded down with a minimum of one task. --skip-nx-cache and
--disable-nx-cache alias --skip-cache, as NX_SKIP_NX_CACHE=true and
NX_DISABLE_NX_CACHE=true do; --disable-remote-cache aliases
--skip-remote-cache. The corresponding environment flags are documented in
Environment variables.
Profiling cache operations
Run qk run web:build --profile (or set QK_PROFILE_CACHE=1) to print lines
such as qk profile: task=web:build stage=local_restore ms=3.197.
Profiling is disabled by default and reads no clocks while disabled.
Timings cover dependency inputs, declared inputs, runtime commands, remote
fetches, local restore phases, restoring and saving
warm state, the command itself (execute), the
input recheck after it (inputs_recheck) and storing its result
(publish). Input resolution also times listing the workspace’s files
(inventory_list), waiting for another task’s listing (inventory_wait) and
parsing pnpm-lock.yaml (lockfile_parse); each is charged to the task that
needed it. A remote fetch also times waiting for the store’s index
(remote_index_wait), waiting for the store to respond (remote_response) and
receiving the entry (remote_body). From a store server that sends a
Server-Timing header, as qk’s does, remote_response adds it as server:
the part of the wait the server spent, the rest being the network. The last adds bytes, what was received,
held_bytes, how much of the files it carried the local cache held already,
apart_bytes, what was received for outputs stored apart, and
skipped_bytes, the outputs stored apart that were not fetched because the
local cache held them. Fetching outputs stored apart is remote_blobs, with
their count, and waiting for another fetch of the same entry is
remote_flight_wait. Fetches made ahead of the tasks that need them are
timed under the task prefetch, and a run that prefetched ends with
task=run stage=remote_prefetch, counting the entries fetched ahead, those
claimed by a task, and the bytes received. Runtime lines identify the command; other lines identify the task.
Spans can overlap: runtime evaluation and the inventory are part of input
resolution, restore phases are part of local restoration, and storing new warm
files is part of saving warm state. Do not sum them as exclusive costs. Shared runtime commands are timed only when
evaluated, so a task reusing a result has no separate runtime line.
The flag leaves task stdout and cache results unchanged. Timings are diagnostic stderr output, available with every output style, and are not task warnings. Compare repeated runs with the same cache state; a remote fetch, a local restore into missing outputs and a hit with outputs already present do different work.
Change selection
affected, show affected, show tasks, and show projects accept:
| Option | Behavior |
|---|---|
--base <revision> | Base: NX_BASE, then defaultBase, then main |
--head <revision> | Head: NX_HEAD, otherwise working tree |
--affected-profile <name> | Opt-in refinement of selection from qk:affectedProfiles: change projections, which apply to project selection and require a committed comparison, and import reachability, which applies to project and task selection and requires the head to be the checkout |
--fail-on-projection-fallback[=all|adapter] | Fail on every fallback (bare flag or all), or adapter failures (adapter) with notices for conservative comparisons; requires --affected-profile and a committed head, rejects explicit/working-tree file selection |
--files <paths> | Replace Git comparison with named workspace-relative paths |
--stdin | Read changed workspace-relative paths from stdin, one per line; an empty list means no changes |
--uncommitted | Only uncommitted changes |
--untracked | Only untracked files |
show projects change options imply --affected. As in Nx, --head needs
--base; --files, --stdin, --uncommitted and --untracked exclude
--base, --head and each other, except that the paths --stdin reads are
added to --files. --stdin preserves spaces in paths. For show tasks, use
--affected to filter the planned tasks. affected --granularity task
selects tasks by their inputs and --granularity project the targets of
affected projects; without it, NX_LEGACY_AFFECTED, then nx.json
affected.legacy, decide, and tasks are the default, as in Nx 24. See
Tasks or projects.
See Affected selection for merge-base behavior.
Selection and inspection
run-many, affected and show tasks accept -t/--targets
(--target too), -p/--projects and --exclude; lists accept commas,
spaces or repeated flags. run-many accepts Nx’s deprecated --all, the
default; --all=false without --projects selects nothing, as in Nx.
show projects accepts -p/--projects, --exclude, -t/--with-target,
--type app|lib|e2e, and --sep. --sep conflicts with --json. With
--affected and -t, it lists the projects owning an affected task of the
targets under task selection, which --granularity decides as for
affected, except that, as in Nx, -p selects projects unless given
--granularity task. --affected-targets lists the projects where a task
of one of the targets is affected by its inputs, narrowed by
--affected-profile, whatever the granularity; it has no Nx equivalent.
Quote name/tag globs so the shell does not expand them.
show runs --limit defaults to 20, and show task <id> --limit to 10.
show run without an ID uses the most recent run. All support --json.
show flaky [task] --limit defaults to 20 task/key groups and supports --json.
show log <run> <task> replays output to its original stdout/stderr streams.
See Run history for retention limits and interpretation.
Cache administration
cache path prints the location without creating it. cache prune uses
--max-size, else NX_MAX_CACHE_SIZE, else maxCacheSize, else the default
disk fraction. See Storage limits.
reset, or its alias clear-cache, removes the local cache and this
worktree’s state: file digests, output records and warm directories. The
cache is shared by the repository’s worktrees, so resetting clears it for
all of them. Run history and the remote cache are kept. --only-cache and
--only-workspace-data (or --onlyCache and --onlyWorkspaceData) limit it
to one of the two; --only-daemon and --only-cloud are accepted without
effect.
Accepted Nx options
--runner, --batch, --skip-sync, --cloud, --no-cloud, --dte,
--no-dte, --agents, --tui, --no-tui, and --tui-auto-exit, and
--verbose on show projects, are accepted without
effect. They do not enable Nx plugins, distributed execution or Nx Cloud.
As in Nx, --runner must name default or a runner in nx.json
tasksRunnerOptions.
Target inspection
qk show target <project:target[:configuration]> --json shows the resolved
executor, options, caching and concurrency settings, task dependencies,
readyWhen with the timeout its check gets, or null where it turns one off,
and qk’s own fields, such as qk:warm and qk:threads, as configured.
-c <configuration> selects a configuration. A target name without a project
uses the current project, as run does.
qk show target inputs <target> --json lists files and declared environment,
runtime and dependency-output inputs. qk show target outputs <target> --json
lists resolved output patterns, existing output paths and unresolved templates.
Without --json, inputs and outputs print one entry per line. Inspection does
not load dotenv files, execute runtime inputs or require a supported executor.
The listed inputs include qk’s mandatory workspace and package configuration
files; these can differ from Nx’s hash plan.
Both input and output commands accept --check <values...>. File and directory
queries use workspace-relative paths. Inputs also accept declared environment
variable names and runtime commands. The command exits with 1 if any query does
not match. --json returns each query and its membership result.
Key inspection
qk show hash <project:target[:configuration]> prints the key qk run would
cache the task under now, without running the task, and a summary of what the
key covers: the declared inputs, file count, env and runtime values,
dependencies and tooling. --json prints the key and everything it is computed
from, with set env values shown as "<redacted>" and unset ones as null. Arguments after -- are
forwarded as qk run forwards them, to both tasks with --against <task>. A target name without a project uses the
current project.
Computing a key executes the task’s runtime inputs. Dependencies are not run: each counts as having succeeded, with its outputs as they are on disk, so a dependency that has not run yet, or whose outputs are stale, keys differently here than after it runs.
--against <task> keys another task the same way, a target name alone
naming one of the current project’s targets, and lists where the two keys
differ: the definition fields with both values, the files added, removed or
changed, and the values and dependencies that differ. --against <run-id>
compares with this task’s key in a recorded run, as qk show runs lists them,
while that run’s inputs are kept. Differences read from the --against key to
this one. Two different tasks always differ in id. With --json, the report
holds both keys and their inputs, same, and differences in the shape
qk show task reports causes.
$ qk show hash web:build --against web:check
web:build 55a02f0c…
web:check 963b6121…
keys differ in: definition, files
field id: "web:check" -> "web:build"
field definition.inputs[0]: "{projectRoot}/src/**/*" -> "{projectRoot}/**/*"
field definition.inputs[1]: {"runtime":"node -v"} -> {"env":"MODE"}
field definition.inputs[2]: {"env":"MODE"} -> {"runtime":"node -v"}
added apps/web/README.md
The target definition is part of the key as written, so reordering inputs
changes the key even when the files and values it selects do not; such a
change shows as definition.inputs reordered.
Project watch
qk watch -p web --includeDependencies -- <shell command> watches the selected
projects and, optionally, their project dependencies. --all watches all projects,
including projects created after watch starts. --initialRun runs once before
waiting for edits. -g/--includeGlobalWorkspaceFiles also reacts to files
that belong to no project, such as root configuration; as in Nx, a command
naming NX_PROJECT_NAME is refused with it. The kebab-case aliases also work.
Callbacks run from the invocation directory with NX_PROJECT_NAME and
NX_FILE_CHANGES (workspace-relative paths joined with spaces). If the command
mentions NX_PROJECT_NAME, a batch runs concurrently once per changed project;
otherwise it runs once for the batch with an empty project name. Initial --all
also runs once with an empty project name, matching Nx. Quote the shell command
so variables expand in the callback rather than in the invoking shell.
Native file events are debounced and changes arriving during a callback are
queued for the next batch. A directory event or backend rescan can include other
eligible source files in the reported batch. Callback failures are reported;
watch continues.
Edits to sources known to be regular files reuse the current project view. Configuration
and ignore-policy changes, file creation/deletion, directories, symlinks and
backend rescans reload discovery and selection before the next callback.
Workspaces using package presets or presets outside the workspace retain a reload
on every source batch, because preset resolution has inputs outside the source set.
Ctrl+C cancels callbacks and their process groups and exits with 130. Ignored
source files, node_modules, Git/qk state, configured caches, explicit target
outputs and warm paths do not trigger callbacks. Files outside any selected
project do not trigger callbacks, unless -g is given and they belong to no
project at all. Watch uses no daemon or Nx plugins.
Compatibility diagnostics
qk doctor reports unsupported executors, configured Nx plugins, sync
generators and fields in qk:warm or qk:threads that this qk does not know,
without executing commands, loading dotenv files or running plugins.
It also reports dependentTasksOutputFiles globs that select nothing for any
task of a target, which therefore key nothing: none of those tasks depends on
a task declaring outputs, or the outputs on disk hold no file the glob
matches. Outputs not built yet are taken to match. Targets sharing a set of
such globs, as through a named input, are one finding.
It also lists Nx CLI options accepted without effect. --json returns a
versioned report with stable finding codes, locations and error/warning counts.
Unsupported executors cause exit code 1; --strict also fails on warnings.
This checks normalized explicit target definitions. A clean report does not establish that commands can execute or that plugin-inferred targets exist.