Repository navigation
v0.27.0
Added
-
--download[=true|false|ask],--no-download,RUNNER_DOWNLOADand a
top-leveldownloadkey inrunner.tomldecide whether a command that
downloads may run. Every rung of the run cascade and every exec capability
declares whether it can fetch;run <name>throughnpx,bun x,uvx,
deno xormise exec,runner installand a--packagefetch consult
the policy before spawning. Unset, runner asks on an interactive terminal
outside CI and allows elsewhere;askwithout a terminal refuses, and
falserefuses, which makes CI deterministic. Local rungs never ask: the
project's own bin dirs,PATHand a local exec form such asyarn runor
pnpm execcome before any fetching rung. -
[install]takesfrozen,scriptsandtoolsas booleans, the config
forms of--frozen,--scriptsand--toolsand their--no-forms. -
list --only <source>lists one source's tasks, repeatable and
comma-separated, and readsRUNNER_LIST_ONLY. -
npx,pnpx,bunxandyarnpkgare accepted wherever a package manager
is named, asnpm,pnpm,bunandyarn. -
The GitHub Action takes a
version-fileinput: a.tool-versionsfile whose
runnerline (orrunner-run, or a mise backend such as
github:kjanat/runnerornpm:runner-run) sets the version to install.
versionwins when both are set, and a file with no such line fails the
step.versionno longer declareslatestas its default, so an unset
versioncan defer to the file; it still installslatestwhen neither is
set. -
--package <name>selects an npm package, and the task token names one of
the binaries its manifest declares:run --package typescript tsc. An
installed package resolves from its ownpackage.json, or fromyarn bin
under Yarn Plug'n'Play, never from the sharednode_modules/.binlink
another package may have won. One that is not installed goes to the package
manager's package-selecting form (npx --package,bun x --package,pnpm --package= dlx,yarn dlx --package,deno x npm:<name>/<bin>,uvx --from), honouring--runtimeand a non-Node--pmlike the bare-binary
fallback does, and is refused when another installed package already
provides the binary or when the binary is a path such as./tool. A
binary the package does not declare is an error
naming the ones it has, the multi-binary ambiguity message suggests the
--packageform, and a registry specifier such asnpm:typescriptthat no
present tool executes is refused with the equivalent (#126). -
run make,run just,run taskandrun baconinvoke the runner's own
entry point when the project uses it and no task carries that name, so
Make picks its.DEFAULT_GOAL, just its default recipe, and so on.
Arguments are forwarded. A--sourcechoice naming the same runner allows
it; one naming another source refuses. A task named after the
runner wins (#137). -
run testwith notesttask runs the ecosystem's own test runner:
bun test,deno test,cargo test,go test ./...,node --testover
everytest.<ext>and*.test.<ext>file below the current directory, and
for Python whichever of pytest, nose2, ward, Django'smanage.py test,
tox, nox orunittestthe project has. Arguments are forwarded; a Node
file argument skips discovery. -
Mise tasks carry what
mise tasks --jsondeclares beyond name and
description:depends,depends_post,wait_for,dir,env,tools,
usage,file,sources,outputs, andtimeout.runner whyprints
them under the selected task and fills itsdependencies,sources, and
outputsfields,list --jsonaddsdepends,dir, andusage, and
doctor --jsonfillstasks[].dependencies.cwdinwhyanddoctoris
the directory the task runs in when the source declares one. The direct TOML
fallback keepsfileand leaves the rest empty. -
runner installrunsmise installbefore the package managers when the
project has a mise config, so tools the config declares (often the package
managers themselves) exist before they are called.--frozenadds
--lockedwhen the config's lockfile exists. A project with only a mise
config and no manifest installs its toolchain. A missingmisebinary
warns and continues.--no-toolsskips the step;runner doctorlists it
under Decisions. -
Tools mise manages are on the
PATHof every process runner spawns in a
mise project, including the package managermise installhas just put
there. -
runner doctorrelays what mise says about the project: tools the config
declares that are not installed (mise ls --missing), andmise tasks validatefindings such as a missing or circular dependency. They appear
under Decisions and Warnings, and asmisediagnostics in--json. -
[env],[tools.<name>].envand[tasks.<name>].envset variables on the
processes runner spawns, narrowest layer winning. A value set for a task
beats the same name set for the tool running it, which beats the
project-wide one, which beats the inherited environment. Every layer still
contributes the names the narrower ones do not set. -
runner doctor --jsonreportsoverrides.envcarrying the variable
names each layer sets. Values are withheld, since that payload is meant
to be pasted into a bug report. -
Shell completion offers a mise task's own flags and argument choices after
its name, from theusagespec the task declares.run lower:leaf <TAB>
offers--fn;run baseline:explain <TAB>offers that argument's
choices. A flag that takes a value suppresses further flag offers in the
position it consumes. Sources without a spec complete nothing. -
A mise task whose spec marks a flag required fails before dispatch when the
flag is absent, naming the flag and the task's signature. -
runner whyprints a mise task's signature (lower:leaf <--fn <name>> [dir]).
Changed
-
Settings are one model across flags, variables and
runner.toml. A setting
resolves from the first layer that sets it: CLI,RUNNER_*variable,
[tasks.<name>], the rest ofrunner.toml, project evidence, default. An
explicitfalsecounts as a value. Every flag reads a variable derived from
its name,RUNNER_<FLAG>for a global flag andRUNNER_<COMMAND>_<FLAG>
for a command's own; a--no-form or an alias sets the same variable as
its flag, and therunbinary's own flags readRUNNER_RUN_*.runner doctorreports an invalid variable or config value and keeps going; other
commands refuse. Renamed and removed settings:--explainandRUNNER_EXPLAINare--dry-runandRUNNER_DRY_RUN.--runner,RUNNER_RUNNER,[tasks].prefer,[tasks].overridesand
string task entries are--source,RUNNER_SOURCEand
[tasks.<name>].source. A chosen source is a hard selection.[pm].<ecosystem>is[tasks.<name>].pm, or--pmfor the invocation.[runtime].jsis[runtime].javascript, also settable per task.-k,-K,[chain].keep_goingand[chain].kill_on_failare
--on-fail continue|wait|kill,RUNNER_ON_FAILand[chain].on_fail;
-kand-Kstay as aliases, and giving two of them is a usage error.--no-warningsandRUNNER_NO_WARNINGSare--warnings,
--no-warningsandRUNNER_WARNINGS.[runner]is[output], withtask_timingrenamedtimingand
fatal_errorsfolded intoerrors.[host].diagnosticsis
[output.tool].quiet. A task'sverbosity,stdoutandstderrare
[tasks.<name>.output],[tasks.<name>.output.tool].quietand the
[tasks.<name>.output.task]booleansstdoutandstderr.[github].group_output,[github].group_paralleland
[parallel].groupedare[output].groupsand
[output.parallel].buffer.[install].scriptstakestrueorfalse.--fallbackand[resolution].fallbackare removed; a task source with
no package manager takes one fromPATH.--on-mismatchand[resolution].on_mismatchare removed; a manifest
that disagrees with its lockfile wins with a warning.[install].on_collisionandRUNNER_INSTALL_ON_COLLISIONare removed;
one package manager installs each shared directory.--host-streamand[host].streamare removed.
-
--dry-runexplains and stops. Forrun,install,cleanand both
chain modes it prints the plan, the argv, the working directory and the
names of the environment keys, asks for no network consent, and executes
nothing. Builtins reached throughrun(run list,run info) parse
their own flags and run in the current process, and--dry-runnames
that action. -
-qexpands into the individual output settings at its own layer and sets
only what its level names.-qq --warningsshows warnings, and-qleaves
a task's[output.tool].quietalone. GitHub Actions error annotations
follow[output].errors. -
One resolver decides the package manager for every ecosystem. The manager
that dispatchespackage.jsonorpyproject.tomlscripts is chosen from
the evidence in the task's scope: a--pmorRUNNER_PMchoice, then a
[tasks.<name>].pmchoice, then the manifest'spackageManager, then itsdevEngines.packageManager, then
the lockfile, then an executable onPATH. A lockfile the repository
tracks outranks an untracked one beside it.package.json5and
package.yamldeclare a manager the same waypackage.jsondoes.run,
why,doctorandlist --jsonreport the same choice, aspnpm via pnpm-lock.yaml,bun via package.json "devEngines.packageManager" (onFail=warn)ornpm via PATH probe at /usr/bin/npm, andwhyreports
it for the scope of the task it selected.--pm denofills the Node slot,
since deno dispatchespackage.jsonscripts.
--pm cargoon apackage.jsonscript is refused as a missing
capability. -
devEngines.packageManageris checked when a plan is made, so an
install or a package exec through the declared manager sees it too, and
anonFailoferrorrefuses before anything spawns. The check applies
when that field is what selected the manager: apackageManagerfield, a
--pmchoice or arunner.tomlchoice settles the choice without it, and
a manager that cannot take the operation is never asked. The declared
range is checked against<manager> --versionwith npm semver; a
prerelease build clears the range its release clears. A range that cannot
be read proceeds with a cannot-evaluate warning. -
A manifest and a lockfile that name different package managers are
reported as a disagreement, naming both files and both managers; the
manifest still wins. -
run testwith no test script and no test files is an error naming the
directory and the patterns looked for. Discovered TypeScript tests get
--experimental-strip-types. -
A task source that cannot be read at the root or the invocation directory
refusesrunwith the read error;listreports it. Extractors return
the tasks they could read with warnings for the rest, so a broken mise or
turbo member leaves every other task listed. A Yarn manifest or lockfile
that cannot be read stops dispatch. -
Yarn Classic or Berry is decided from
packageManager,devEngines
(>=4and^1.22count),yarn.lock,.yarnrc.yml, and failing all of
those fromyarn --version. A manifest that names another manager says
nothing about Yarn, and.yarnrc.ymlis Yarn config, weaker than any
declaration. One decision drives install,run, exec and--package, in
the member the invocation runs in. Berry's install uses--immutable
under--frozen, and--no-scriptsdenies scripts with
--ignore-scriptson Classic andYARN_ENABLE_SCRIPTS=falseon Berry. -
--runtime bunon a file Bun would run refuses when Bun is absent. A
file in a workspace member runs with the member'snode_modules/.bin
first, whichever runtime takes it, and an explicit
./packages/web/tool.shfrom the root getsweb's bin dirs. -
[tasks.make.env],[tasks.just.env]and the like reachrun makeand
the other default invocations, andrun bacon --ignoredkeeps the--
before the job arguments. -
deno.jsontasks stay listed whenpackage.jsonnames deno as the
package manager,JUSTFILEin any letter case is a justfile, adeno.json
orpyproject.tomlin a parent directory is found from a child
directory, a directory holding onlyhello.goruns it withgo run, and
--pm deno run jsr:@std/http/file-serverreachesdeno x. -
run listand the other builtins take precedence even when two workspace
members define a task of that name. -
.ps1files run through PowerShell on every platform, with-NoProfile -ExecutionPolicy Bypass -File:pwshwhen it is onPATH, else the
powershellevery Windows ships. A runtime that steps in for a file no
project runtime takes observes the host before it plans, so--dry-run
shows which executable won. -
Package managers are probed on
PATHin one declared order (npm, bun,
pnpm, yarn, deno) wherever a task source has no manager of its own.
Project roots and workspaces stop at the VCS root, so an unrelated outer
lockfile is never adopted. Outside a repository they stop below the home
directory or the filesystem root. Inside or outside one, they never climb
into an ancestor directory another user owns or can write to, such as
/tmp, so a.gitor manifest planted there is ignored. -
Node refuses a
.jsxor.tsxfile with the runtime choice that forced
it and the runtimes that can run it (--runtime bun,--runtime deno).
File extensions match case-insensitively. -
RUNNER_INSTALL_PMSis not read:runner installuses every detected
package manager.[task_runner]is an unknown section. -
schemas/doctor.example.jsonis generated from a typed example, and
doctor --jsonnames the lockfile policy (updateorfrozen), the
download policy, the chain failure policy and the output settings under
overrides, with the origin of eachpm,runtimeandsourcechoice. -
runner config initwrites the schema pragma and every default the schema
declares, live, and nothing else. The commented scaffold with its prose is
gone; the schema is the documentation, on hover through the pragma. The
thirteen keys that have an effective default carry it in the published
schema. Unknown-key warnings read the recognised fields from the schema
too, so a struct field cannot fall out of step with the loader. -
The workspace library crates publish to crates.io as
runner-run-core,
runner-run-schemesandrunner-run-providers, internal torunner-run
with no stable API. Their Rust library names stayrunner_core,
runner_schemesandrunner_providers. -
The
schemacargo feature is removed. Every build carries schemars, and
cargo schemaneeds no flag. -
runner why,doctor,listand completion rank same-named tasks with
the keyrunner runselects by: the tier a chosen source, package manager
or runtime puts the source in, then the source's position among the sources that
dispatcher runs, then the source's task priority. The default priority is
turbo,package.json, Makefile, justfile, Taskfile,deno.json, Cargo
aliases, Go, bacon, mise,pyproject.toml.why --jsonreports the key
asmatch.rank, which replacesdepth,display_orderand
source_priority, and eachdoctor --jsonduplicate-name conflict names
the field that decided it. -
Two lockfiles of one ecosystem with equal standing resolve in the
PATH
probe order: npm, bun, pnpm, yarn, deno. -
A task addressed by source or workspace member that does not exist there
is refused with the address, astask "site" not found in package.json of workspace member nope, byrun, both chain modes andwhyalike. -
A
packageManagervalue that names no package manager is reported by the
package.jsonit is in, members included. -
list --json,info --jsonand the humandoctorreport the signals and
the package-manager decision for every task source package managers
dispatch, keyed by the source's label:signals["package.json"],
decisions["pyproject.toml"]. A source appears when a package manager
that dispatches it is detected or the project defines its tasks. Each
decision is{ "pm", "via" }or{ "error" }. PATH-probe hits that are
version-manager shims are listed undershims, each naming its
manager.detected.runtimeslists each runtime the root declares with
its expected version, where it is declared and the installed version,
and replacesnode_versionandcurrent_node.doctor --jsoncarries
the same signals for each ecosystem whose source package managers
dispatch, and a runtime tool for that ecosystem's interpreter. -
A runtime's expected version is read from
.nvmrc,.node-version, the
nodejsline of.tool-versionsandengines.node.infoprints every
runtime the root declares, andrunner installwarns for each whose
installed version falls outside the declared one. An empty.nvmrc
declares nothing. -
Task FQNs use the source's label, so a Cargo alias is
root:cargo#t.
listgroups sources in task-priority order.monorepois true when the
root declares a workspace.doctor --jsondropsoverrides.install_pms
andtasks[].self_executable. -
A task that forwards to another runner's same-named task gets that
runner's refusals, so any script that is a baremake <name>wrapper
forwards only variable assignments. Under--runtime node,node --run
names thepreandpostscripts it skips as anodewarning, and
runner whyreports the runtime's warnings as the runtime note.
Fixed
-
--no-scriptsand--scriptswin over[env],[tools.<name>].envand
[tasks.<name>].env. A repositoryYARN_ENABLE_SCRIPTS = "true"no longer
runs lifecycle scripts underrunner install --no-scriptson Yarn Berry. -
A workspace member symlinked to a directory outside the workspace root is
no member, andcleannever removes a directory that resolves outside the
root. -
run testwith notesttask tries the next present test runner when one
finds no test files. A Go module with apackage.jsonrunsgo test ./...
instead of refusing for want of*.test.jsfiles. -
runner install -qqpasses the package manager its quiet flag, asrun
does:npm --silent install,npm --silent ci,cargo -q fetch,uv --quiet sync, and the same for pnpm, Yarn Classic, Bun, Deno, Poetry and
Pipenv. -
runner install --frozenin a Bundler project setsBUNDLE_FROZEN=true
and refuses withoutGemfile.lock, so Bundler fails instead of rewriting
the lockfile. -
--frozenrefuses before spawning a package manager whose lockfile is
absent, naming the directory and the lockfiles it accepts: npm takes
npm-shrinkwrap.jsonas well, and Deno the file named with"lock"by
the nearest Deno config inside the project tree. A mise config
withoutmise.lockinstalls unlocked, since mise lockfiles are opt-in. A
lifecycle-script policy the manager cannot express is disclosed by
runner installand--dry-run. -
A name reaches an exec primitive only when the primitive takes its shape:
npxrefusesuser/repo#refandgo runrefuses a bare name. -
go runof a directory such as./cmd/toolor.is local and runs
under--no-download; only a module path such asexample.com/tool@v1
counts as a download. -
go runrefuses git and URL specs such asuser/repo#refand
github:owner/repo, so a project with bothgo.modandpackage.json
no longer hands them to Go. -
run .andrun ..with anode_modules/present no longer read
node_modules/./package.jsonor the parent'spackage.jsonas an
installed dependency. A name segment starting with.is never a package. -
run <package>for a Yarn Plug'n'Play dependency runs the binary named
after the package throughyarn exec, sorun @angular/cliruns
yarn exec nginstead ofyarn exec @angular/cli. -
A plan for a file a rung found carries the bin dirs of the workspace
member it sits in, and a member'snode_modules/.binprecedes the
root's. A dependency's binary or a project bin found from a member runs
with that member's bin dirs first even when hoisting installed it at the
root, and so does onerun --packageselects. -
A package manager the
PATHfallback admits gets the same installed
version and variant as one the project names, so apackage.jsonwith
scripts alone runs Yarn 4 as Berry. AdevEnginesrange such as>=1
admits both Yarn lines, so the installed version decides. The version
query runs the Yarn on the hostPATHin the project directory, so
--dirsees the Yarn a directory-aware shim serves there. A
node_modules/.bin/yarnornode_modules/.bin/nodenever runs to report a
version. A Yarn whose line is still unknown runs scripts as
yarn run <task>and gets no--silent. -
Python test detection looks in the invocation directory and then the
provider's scope, soconftest.pybeside the tests andpytest.iniat
the root both select pytest from a subdirectory. -
A
Justfilethat is a symlink is observed and marks the project root, in
any spelling. -
A run reports the package manager of the task it selected, in that task's
workspace member, and warns about that member's manifest disagreeing with
its lockfile. -
--source just run buildfails when the justfile has nobuildrecipe,
naming the source and the task. -
[tasks.<name>].pmnaming a package manager that cannot run the task
fails like--pm, naming therunner.tomlthat chose it, where it used
to fall back to the detected manager. -
Editors complete provider values in
runner.tomlfrom labels alone. File
names and exec binaries such asdeno.jsonandnpxstill validate. -
[tasks.<key>].envmatches the same keys as[tasks.<key>.output]:
build,package.json:build,rfc:buildfor a member task,
andrfc:package.json#build, least specific first. -
A task whose name contains
#, such as the scriptbuild#prod, keeps its
[tasks."build#prod"]settings. Its pm, runtime, source and output
settings used to be dropped once the task was selected. -
A
packageManagervalue that names no known manager, or ends in an@
with no version, voidsdevEngines.packageManagertoo; the lockfile or
PATHdecides. -
On Windows, a file task whose shebang names a POSIX shell (
bash,sh,
zsh, ..., with or without.exe) receives its path in the form that
shell reads: relative to the working directory with forward slashes (a
./prefix kept for a name starting with-), or/c/...for a file
elsewhere. A shell named by a Unix path (#!/bin/sh) is found onPATH
by its name, since\bin\shexists on no Windows drive (#121). -
go runfor a Go task passes-buildvcs=truewhen the project sits in a
checkout Go can read (Git, Mercurial, Subversion, Bazaar, Fossil), that
tool is onPATH, and the toolchain is Go 1.18 or newer, so the binary's
debug.ReadBuildInfocarries the revision instead of(devel). A
GOFLAGSin runner's environment that already decides-buildvcsor
--buildvcsis left alone. A single Go file is never stamped, since Go
stamps nothing intocommand-line-arguments(#130). -
runner installreports which package manager and program it was waiting
on whenwait()fails, and stops and reaps the child first, matching the
parallel install lanes (#135). -
A make target, or a package script that is a bare
make <name>wrapper,
forwards only variable assignments (NAME=value,NAME+=value,NAME:=value
and the other GNU make forms), which the recipe reads as$(NAME). Any other
word is refused before make runs, naming the word and the two ways to pass
it.run --helpsays so (#128). -
runner installin a project with no package manager runs the project's
owninstalltask when one exists, printing the same dispatch line as
run install(#129). -
runner doctorprints signals and a decision only for task sources the
project uses (#122). The PATH probe lists one manager per line, with a
shim's target on a continuation line (#110). -
run <name>with no matching task looks for<name>in the project's
own bin dirs and onPATHbefore any rung that can download, so an
installednpxormakeruns as itself (#136). The fetching rungs come
last:mise exec -- <name>when the project uses mise, then the package
manager's exec primitive. On a terminal, a fetching rung asks[y/N]
first; a pipe proceeds. The resolver'sPATHprobe also searches mise's
tool dirs, so a project whose only package manager is mise-managed and
not yet activated detects it. -
Mise task discovery accepts task references in
runarrays
(run = [{ task = "check" }]) (#138). Referenced tasks render asmise run <task>in the description column; step shapes runner does not model
are skipped. -
Mise task discovery accepts a dependency carrying arguments
(depends = [{ task = "gen", args = ["foo"] }], which mise emits as
["gen", "foo"]) and a structured tool request
(tools = { node = { version = "22" } }). -
A failing
mise tasks --jsonis reported. The TOML fallback serves a
project where mise is not installed. -
--frozenfinds the lockfile for a mise config outside the project root:
.config/mise.toml,mise/config.tomlandmise.local.tomleach pair
with their own lockfile. -
A
--pmorRUNNER_PMchoice without an exec primitive refusesrun <name>once the local rungs miss, naming the chosen manager. A--pm
choice with an exec primitive is the only manager asked. -
Task sources are read concurrently, on as many threads as the host runs
at once, sorun,listand completion wait for the slowest extractor. -
runner cleanfrom a workspace member removes the root's directories as
well as the member's. -
--dry-runreports the quiet support of the package manager variant in
the plan's scope, such as a Yarn Berry member under a Classic root. -
A builtin in a parallel chain (
list,info,completions,clean)
runs once the other items have spawned, and its output goes through the
chain's prefixed lines or its own group. Itscleanprompt reads as
declined, andinstallis refused there. -
run testthrough Node discovers.js,.mjs,.cjs,.ts,.mts
and.ctstest files. A project whose only tests are.jsxor.tsx
gets the no-test-files error. -
runner installwith no package manager signal at the root installs
through the managers observed in the root scope. A manager declared only
in a workspace member stays out of the root install. -
--runtimeon a task in another workspace member looks for the runtime in
that member, so--runtime bunfrom the root runs a member script when
Bun is declared only in the member. -
A
--pmorRUNNER_PMchoice absent from the invocation scope refuses
run <name>once the local rungs miss, withno evidence for package manager <name>. -
run test foo.test.tsthrough Node passes--experimental-strip-types
for a TypeScript file named on the command line. -
run make,run justand the other default entry points refuse under a
--sourcechoice naming another source. -
run --package <name> <bin>under Yarn Plug'n'Play runsyarn binin the
invoking workspace member and accepts a.pnp.cjsthere or at the root. -
runner installin a project with another ecosystem detected also
installs through a package manager thePATHfallback admits for an
observed task source, such as npm for a barepackage.jsonbeside
Cargo.toml.doctorreports the same install set. -
runner installwith two lockfiles that write one install directory,
such asbun.lockbesidepackage-lock.json, runs one installer and
reports the other as shadowed. The install directories come from each package manager's declaration, so uv,
Poetry and Pipenv sharing.venvcollide too. -
A package manager chosen beside a runtime dispatches the task on that
runtime. npm, pnpm and Yarn run on Node, and Bun stands in for Node:
--pm pnpm --runtime bun run buildrunspnpm run buildwith Bun answering
tonodefor its scripts. A runtime that cannot stand in is refused naming
both:runner cannot run the task under package manager pnpm on runtime deno: deno does not stand in for node. The same holds for[tasks.<name>].pm
beside a runtime from any layer. -
A runtime or package manager that only
[tasks.<name>]chooses counts as
present for that task when it is onPATH, so
[tasks.build.runtime] javascript = "bun"runsbuildon Bun without a Bun
lockfile while other tasks, files andinstallkeep their defaults. -
list,doctorandwhyreport the source and runtime a task table
selects, asrunuses them. -
--no-downloador--no-warningsafter a subcommand overrides the
positive flag before it, and the reverse. A short spelling counts by its
position too, alone or in a cluster:install --no-frozen -fand
install --no-frozen -qqfinstall frozen. -
A valid command-line value overrides an invalid
RUNNER_*value for the
same setting:RUNNER_PM=bogus runner --pm npmruns with npm. -
--on-fail continue -kand-K --on-fail killare accepted. Flags that
giveon_faildifferent values are still a usage error. -
The
runner.tomlschema accepts provider aliases (npx,pnpx,bunx,
yarnpkg) wherever it accepts a provider name. -
A mise shim for Volta no longer marks every mise shim as a Volta shim in
doctor,infoand their JSON. -
A command-line choice displaces its opposite from the environment:
RUNNER_RUN_PARALLEL=1 runner run -s a bruns in sequence and
RUNNER_LIST_JSON=1 runner list --rawprints names. Both of a pair set in
the environment is a usage error. -
Under a
--sourcechoice a bare name the source does not supply is refused
instead of running a program fromPATH. File paths, builtins, the
chosen runner's own entry point and the chosen source's own program still
run:runner --source cargo run cargo --versionandrunner --source turbo run turbofind it in the project's bin dirs or onPATH. -
RUNNER_QUIETand-qeach expand at their own layer, so
RUNNER_QUIET=2 runner -qstill hides warnings and quiets the tool. -
runner lspreadsrunner.tomlwith the TOML parser, so hover, completion
and diagnostics work under quoted keys such as
[tasks."package.json:build".runtime]. Config warnings and errors print
such keys quoted. -
A
packageManagernaming Deno dispatchespackage.jsonscripts through
deno taskwhen an npm lockfile or adevEngines.packageManagernaming
npm sits beside it. -
A
Justfilesymlink whose target is missing is absent; the other task
sources are still read. -
A parallel chain item whose output cannot be written, as with stdout on a
full disk, fails with exit 1 in both the prefixed and the grouped mode, and
so does a parallel install lane. -
--pm denoor--runtime denoruns thedeno.jsontask over a
package.jsonscript of the same name, in the order the chosen provider
lists its sources. A--runtimechoice ranks its sources before a--pm
choice does, so--pm bun --runtime deno checkruns the Deno task. -
The dispatch arrow for a file a runtime runs names the runtime's words
and stops at the file, so positional arguments stay[args]. -
--dry-runreports a package manager with one quiet flag as applying the
quiet level, and a-qqqrequest against it records the clamp to quiet. -
The name-conflict footer of
runner listand thedoctorconflicts name
the taskrunner runselects under a--source,--pmor--runtime
choice. -
Inside a workspace member nested in another member, the inner member is
the current one. A bare task name both define runs the inner member's
task, andrunner installandrunner listtreat the inner member's tasks
as local. -
A package manager a task's
pmchooses is admitted fromPATHat the
root when only another workspace member shows it, so a member's
pm = "pnpm"task runs when a sibling holdspnpm-lock.yaml. -
A
--runtimechoice leavesrunner run <name>in a Python, Go or Rust
project to that project's exec primitive, so--runtime bun ruffin a uv
project runsuvx ruffand warns that the runtime was not applied, with or
without--pm uv. -
runner.tomlis read from the project or workspace root, so its settings
apply when runner runs from a subdirectory or a member, andrunner config
reads, writes and prints the root's file. Arunner.tomlor
.runner.toml, in the directory or its.config/, marks the root on its
own.runner config path,showandvalidatename the file that was
loaded, andrunner config initrefuses when any of those files exists and
overwrites that file under--force. -
Bundler's built-in test runner is
bundle exec rake test, sorunner test
runsrakeinside the bundle. -
A
package.jsonorpyproject.tomlthat does not parse declares no
package manager, and the other task sources still list and run. A broken
package.jsonis reported as unreadable. -
Under
--source, a task the chosen source lacks is refused as missing from
that source even when another source, such asturbo.jsonordeno.json,
cannot be read. The chosen source being unreadable still stops the run. -
The directory holding a stand-in link, such as Bun linked as
node, is
named by the user's uid and created with mode 0700. A directory at that path that is a symlink, belongs
to another user, or is writable by group or others is refused instead of
being put on the task'sPATH. -
runner testunder--pm,RUNNER_PMor arunner.tomlpackage manager
reports that manager's refusal instead of running another manager of its
ecosystem, so--pm npm testwith only.tsxtests no longer runsbun test. A chosen manager with no evidence in the project is refused. Other
ecosystems still run their own tests, soRUNNER_PM=npm runner testin a
Cargo project runscargo test. -
A task in a workspace member that calls
runneragain no longer repeats the
workspace's detection and config warnings.
Security
-
[env],[tools.<name>].envand[tasks.<name>].envin a repository
runner.tomlmay not setPATH,BASH_ENV,ENV,LD_PRELOAD,
LD_LIBRARY_PATH,LD_AUDIT,DYLD_*,NODE_OPTIONS,BUN_OPTIONS,
npm_config_node_options,npm_config_script_shell,PYTHONSTARTUP,
PYTHONPATH,PYTHONHOME,PYTHONUSERBASE,RUBYOPT,RUBYLIB,
PERL5OPT,PERL5LIB,PERLLIB,PERL5DB,GOFLAGS,RUSTC,
RUSTC_WRAPPER,RUSTC_WORKSPACE_WRAPPER,CARGO_BUILD_RUSTC,
CARGO_BUILD_RUSTC_WRAPPER,CARGO_BUILD_RUSTC_WORKSPACE_WRAPPER,
CARGO_TARGET_<triple>_RUNNER,CARGO_TARGET_<triple>_LINKER,
GIT_CONFIG*,GIT_SSH,GIT_SSH_COMMAND,GIT_EXEC_PATH,
GIT_ASKPASS,SSH_ASKPASS,GIT_PROXY_COMMAND,GIT_TEMPLATE_DIR,
BASH_FUNC_*,MAKEFILES,npm_config_userconfig,
npm_config_globalconfig,YARN_RC_FILENAME,YARN_YARN_PATH,
GCONV_PATH,JAVA_TOOL_OPTIONS,JDK_JAVA_OPTIONSor_JAVA_OPTIONS.
npm config names match in any case. A layer that does is refused before
anything spawns, naming the variable, so a checkout cannot choose what code
a tool loads. -
The toolchain step resolves
misefrom the hostPATH. It was spawned with
the project's own bin directories front-loaded, so an executable committed
tonode_modules/.bin/miseran in place of the real one, before the package
managers and under the identity runningrunner, and neither--frozennor
--no-scriptsprevented it. Task dispatch is unchanged: a task binary still
resolves fromnode_modules/.binfirst.
What's Changed
- Read mise task references and run
mise installbefore package managers by @kjanat in #139 - Make the schema the config's source of truth by @kjanat in #140
- Split into a Cargo workspace by @kjanat in #141
- doctor: Node signals only where Node exists, one probe per line by @kjanat in #142
- install: run the project's install task when no package manager exists by @kjanat in #143
- run: invoke a task runner's own entry point by its name by @kjanat in #144
- run: forward only NAME=value to a make target by @kjanat in #145
- install: name the package manager when waiting on an install fails by @kjanat in #146
- run: stamp VCS build info when go run spawns inside a checkout by @kjanat in #147
- run: hand a POSIX shell a path it can read on Windows by @kjanat in #148
- Select an npm package's own binary with --package by @kjanat in #149
- action: read the version from .tool-versions with version-file by @kjanat in #152
- Put resolution on the core by @kjanat in #151
- chore(release): 0.27.0 by @kjanat in #153
- Link FreeBSD builds against the FreeBSD 12 libc again by @kjanat in #154
Full Changelog: v0.26.2...v0.27.0