Inheritance and overrides
Two mechanisms share one rule: a name means one command across the repository, and inheriting can only add to it.
extends
An extends script resolves another script's command and appends its own arguments.
test:ci resolves to:
Chains resolve transitively, in declaration order from the base outward. A cycle is rejected with the names that form it.
appendArgs entries are quoted per element for the shell that will run the command, the same way
arguments after -- are. An entry containing a space arrives as one argument.
appendArgs without extends is a type error, and Rune rejects it as an unknown field.
Package overrides
A package may hold its own rune.config.ts. Rune uses the nearest one it finds, so a script name
defined in both resolves to the package's version.
Inside packages/legacy, rune run test runs the root command plus --maxWorkers=1. Everywhere
else it runs the root command. Neither package.json changed.
Extend, never replace
A package config that gives a colliding name its own command is a validation error:
The reason is what the tool is for. A test that means one command in nine packages and something
unrelated in the tenth reproduces the situation Rune removes, and it does it invisibly.
A name that does not exist at the root is not an override. It is a new script, scoped to that package.
Ignoring the override
--root resolves against the root config only.
Seeing the chain
rune inspect prints the resolution, and it never spawns anything.
rune list annotates the same information more briefly: (defined here) for a script this package
owns, (overridden here) for one it sharpens.
The cache and two configs
The resolved config is cached by content. When a package override is in play, both configs and everything they import enter the cache key, so editing either one invalidates the entry. See Config evaluation.