Skip to main content
Version: 1.0

Naming a place in your monorepo

Three flags on the two shell helpers ask the same question: where in the monorepo do you mean? They all take the same answers, so once you know one you know all three.

$ dispat exec build --for pkg:core # whose script, and whose environment
$ dispat exec build --script-from space:libs # whose script text, only
$ dispat exec build --in pkg:core # which folder to run in

The five answers

You writeYou mean
pkg:corethe package called core
space:libsthe space called libs
rootthe top level, meaning your repository root
cwdwherever you are standing right now
packages/corethat folder, and only --in accepts this

Names are exact. There are no globs here, because each of these flags wants one answer and a pattern matching two packages has no answer to give.

cwd, and what "standing" means

cwd is the folder you ran the command from. It is the same thing dispat run uses when you type no --package and it works out which package you are in:

$ cd packages/core
$ dispat exec build --for cwd
core-build

dispat looks for the deepest thing containing your folder. A package wins over the space that holds it, and a folder inside neither one means the top level:

Standing incwd means
packages/corethe package core
packages/core/srcstill core, since you are inside it
packagesthe space libs, if that is its folder
docsthe top level

That last row is worth knowing. Standing somewhere that is no package and no space is not an error, it just widens to the top level, and dispat says so in the log so you are never left wondering why a different script ran.

One subtlety: cwd follows --root when you pass it. --root is how you tell dispat where you are standing, so dispat exec build --for cwd --root apps/web means the same as running the command from apps/web.

Which folder does my script run in

By default, the one you are standing in. --in moves it:

$ cd packages/core
$ dispat exec build # runs here, in packages/core
$ dispat exec build --in root # runs at the repository root instead

--in takes a folder path as well as the four words above. A relative path is relative to where you are standing, so --in ../api does what it looks like.

If you have a folder genuinely called root or cwd, write ./root and ./cwd. The bare words are taken as the reserved ones, the same way a shell would.

A folder that is not there stops the command with a message naming it, rather than letting your shell complain about a directory it could not enter.

The subject and the folder are separate questions

This trips people up once, and then never again. --for says whose script and whose environment. --in says where it runs. Neither implies the other:

$ dispat exec release --for pkg:core --in root

That runs core's release script, with core's environment and core's DISPAT_* variables, from the repository root. If you want both to be core, say so twice, or stand in core's folder and use --for cwd.

dispat compares folders as they are written, without following symlinks. If you reach your packages through a symlinked path, cwd may not recognise where you are. dispat run behaves the same way, so the two stay consistent, but it is worth knowing if your checkout is unusual.

What about dispat if

dispat if takes --in too, with the same values:

$ dispat if CI --then 'make ci' --in pkg:core

dispat if normally reads no config file at all, which is what makes it cheap enough to call in a loop. A path or cwd keeps it that way, since your command line already said everything needed. Naming pkg:, space: or root does make it read your config, because there is no other way to find out where a package lives. So does the --changed condition, which asks about the repository itself. You pay for that only when you ask for it.

See also