1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# Node — and the package manager question, which is a property of the project
# rather than of the developer.
#
# One marker covers projects using npm, pnpm, yarn and bun, and they are
# mutually exclusive: a repo using npm must not get pnpm installed on the
# strength of being a node project. So each manager is its own provide with its
# own `when`, and the repo's own committed files decide.
#
# `when` is a shell predicate — exit 0 applies, 1 does not, anything higher
# means it could not answer and is reported rather than guessed at. It runs
# **in the sandbox** with the repo mounted read-only, never on the host: a
# stack definition executing shell on somebody's laptop is the one thing omh
# exists to avoid.
= "node"
= "package.json"
# Nothing to install — stated anyway. The base image is node:22-bookworm-slim,
# and writing that down turns an unwritten assumption into one the sandbox probe
# checks — so a change to the base image is caught at `omh init` rather than at
# somebody's turn one.
[[]]
= "runtime"
= ["node", "npm"]
= "the base image already ships these; declaring them is how a change to it gets noticed"
# The lockfile first and `packageManager` second, in that order deliberately:
# the lockfile records what was actually used, the field records what was
# declared, and where they disagree the lockfile is the better witness.
[[]]
= "pnpm"
= ["pnpm"]
= "test -f pnpm-lock.yaml || jq -e '(.packageManager // \"\") | startswith(\"pnpm\")' package.json >/dev/null"
= "corepack enable pnpm"
= "a repo whose lockfile is pnpm's cannot be installed or tested with anything else"
[[]]
= "yarn"
= ["yarn"]
= "test -f yarn.lock || jq -e '(.packageManager // \"\") | startswith(\"yarn\")' package.json >/dev/null"
= "corepack enable yarn"
= "a repo whose lockfile is yarn's cannot be installed or tested with anything else"
[[]]
= "bun"
= ["bun"]
= "test -f bun.lock || test -f bun.lockb || jq -e '(.packageManager // \"\") | startswith(\"bun\")' package.json >/dev/null"
= "npm install -g bun"
= "a repo whose lockfile is bun's cannot be installed or tested with anything else"