A workspace is a package inside a repository that also contains other packages. The root manifest is private, declares where the members live, and never gets published:
{
"name": "shopmono",
"private": true,
"workspaces": ["packages/*"],
"packageManager": "npm@11.11.0",
"scripts": { "build": "npm run build --workspaces --if-present" }
}One npm 2,036 install at the root resolves every member together, hoists third-party dependencies into the root node_modules, and symlinks the members into it. @shop/cli depends on "@shop/core": "^0.2.0", and because the local copy satisfies that range npm links it instead of downloading:
$ npm ls --workspaces --depth 0 shopmono@ C:\tmp\shopmono +-- @shop/cli@0.1.0 -> .\packages\cli | `-- @shop/core@0.2.0 deduped -> .\packages\core `-- @shop/core@0.2.0 -> .\packages\core
Edit packages/core/src/index.js and the CLI sees the change immediately — no build, no npm link, no ../../core import. Any bin a member declares is linked into the root node_modules/.bin, so npm exec -w @shop/cli shop runs from source.
From the root, -w addresses one member (npm i -w @shop/cli zod, npm run test -w @shop/core, npm publish -w @shop/core) and --workspaces addresses all of them.
pnpm 69,400 lists members in pnpm-workspace.yaml and links local packages only when you write the workspace:* protocol, which makes an accidental registry fetch impossible. packageManager pins the tool the repository expects — Turborepo 226,392 (Task Orchestration) refuses to run without it.