You clone a repo, run the install command, and six minutes later find out you needed pnpm rather than npm. Or that the .nvmrc says one thing and CI pins another. The mismatch was sitting in the files the whole time — nothing bothered to read them.
House reads what a project already declares, works out what it takes to build, and checks your machine against it. One command, no config file, and no adoption needed from you or the maintainer.
Why
Every ecosystem already has somewhere to write down its requirements: engines, .nvmrc, go.mod, rust-toolchain, .tool-versions, requires-python. Projects use them inconsistently and often disagree with themselves. Nothing reads all of them at once and tells you, plainly, whether this machine can build this checkout.
House is purely diagnostic. It never installs or manages a runtime, so it sits alongside whatever version manager you already use rather than competing with it. Every finding carries the file it came from, because an unexplained demand from a diagnostic tool is worse than no demand at all.
Install
Usage
$ house
🩺 Diagnosing environment...
[x] Node.js Found v22.12.0 (Required: >=22.18.0 via package.json engines.node)
[x] pnpm Found v10.6.2 (Required: 11.18.0 via package.json packageManager)
[x] Go Found v1.23.5 (Required: 1.26.5 via go.mod toolchain)
[✓] Python Found v3.13.3 (Required: >=3.10 via pyproject.toml project.requires-python)
[✓] uv Found v0.11.31 (Required: present via uv.lock)
Status: 3 blocking. Not cleared to build.
Exit codes: 0 clear, 1 worth a look, 2 blocking.
What it reads
Every source is a peer. None of them has to be there, and house never asks a project to add one.
| Source | What it gives |
|---|---|
package.json |
engines, devEngines, packageManager, volta |
.nvmrc, .node-version |
Node |
pnpm-lock.yaml, package-lock.json, yarn.lock, bun.lock |
the package manager the project is really built with |
Cargo.toml rust-version, rust-toolchain.toml |
Rust |
go.mod |
the go floor and the toolchain pin |
pyproject.toml, setup.py, setup.cfg, requirements.txt |
Python, and pip |
uv.lock, poetry.lock, Pipfile |
uv, poetry, pipenv |
.python-version, .go-version, rust-toolchain |
Python, Go, Rust |
.tool-versions, mise.toml |
every tool listed in them |
A yarn.lock says more than "yarn": a berry lockfile rules out yarn 1, and yarn 1's rules out berry.
Versions are compared at the precision they were written at, so 1.23 and 1.23.0 are the same release rather than a conflict. A value house cannot parse — an alias like lts/*, a PEP 440 operator, or prose someone left in a version field — is no signal, never an error. One broken manifest never fails a scan.
How it works
Detect find the directories that can be built on their own
Extract read requirements from every source that has an opinion
Resolve fold duplicates together, record where sources disagree
Probe inspect the host, in parallel
Report rank findings, worst first
A monorepo is split into units. Repo roots and workspace roots become units; workspace members fold into their root rather than each producing a near-identical finding. Any directory bringing in a toolchain no other unit covers becomes a unit of its own, so a Go service with a React dashboard is two units and not one — and a repo with no root manifest at all is still visible.
When several sources have an opinion about the same tool, the narrowest one is what house checks. The others are not discarded: if two of them name different releases, that disagreement is reported as a finding in its own right. Nothing else in this space does that.
Requirements carry a confidence level. Declared means the project said so outright and can block; anything less is phrased as a suggestion.
Versions read off your PATH are cached against each binary's path and modification time, so a repeat scan does not spawn a process per tool. Reinstall a tool and the entry stops matching by itself.
Related
House deliberately does not do what these do — it reads the same files and tells you what is missing.
- mise — polyglot version manager, reads
mise.tomland.tool-versions - asdf — the
.tool-versionsformat - proto — pluggable toolchain manager
- nvm / Volta — Node version managers