@manypkg/get-packages
Async and sync APIs that discover every package in a Yarn, npm, pnpm, Bun, Lerna, or Rush monorepo.
Repository Health
Technical Analysis
@manypkg/get-packages is the package-discovery core of Thinkmill’s manypkg toolkit. Given any directory inside a repository, it walks upward to find the monorepo root, detects which workspace tool manages it (Yarn, npm, pnpm, Bun, Lerna, Rush, or a plain single-package repo), and returns every package’s parsed package.json alongside its absolute and relative directory paths.
It underpins @manypkg/cli’s linting and fixing of package.json inconsistencies across workspaces, and is built for reuse by other monorepo tooling that needs to enumerate packages without re-implementing tool-specific glob and lockfile parsing for every package manager.
What You Get
- Automatic tool detection - Walks up from any starting directory to find and identify whether the repo uses Yarn, npm, pnpm, Bun, Lerna, Rush, or a single root package.
- Unified package list - Returns a consistent Packages object with parsed packageJson, absolute dir, and relativeDir for every workspace member regardless of which tool manages it.
- Sync and async entry points - getPackages and getPackagesSync cover both promise-based and blocking call sites.
- Name-field validation - Throws a PackageJsonMissingNameError listing every package.json missing a required name field instead of failing on the first one found.
- Pluggable tool list - Accepts a custom tools array to restrict or extend which monorepo implementations are checked.
Common Use Cases
- Building custom monorepo scripts that need to iterate over every internal package, such as running a command per package.
- Writing linting or codemod tools that check package.json consistency across a workspace, as @manypkg/cli itself does.
- Implementing release tooling that needs to know a monorepo’s package graph without shelling out to the package manager.
- Building editor, IDE, or dashboard tooling that needs a live, tool-agnostic list of packages in a repository.
Under The Hood
Architecture getPackages(dir) calls findRoot from @manypkg/find-root, which walks up directories testing each registered Tool’s isMonorepoRoot until a match is found, then getPackages delegates to tool.getPackages(rootDir) from @manypkg/tools and finally runs validatePackages, which checks every discovered package.json for a name field and throws a single PackageJsonMissingNameError listing all offenders if any are missing. The architecture is intentionally thin: get-packages is a small orchestration layer with no tool-specific logic of its own — all package-manager detection (Yarn’s workspaces field, pnpm-workspace.yaml, npm workspaces, Bun’s workspaces, Lerna’s lerna.json, Rush’s rush.json) lives in the sibling @manypkg/tools package behind a common Tool interface, and the upward directory-walking algorithm lives in @manypkg/find-root. This separation means adding support for a new package manager only requires a new Tool implementation registered in DEFAULT_TOOLS, with no change to get-packages itself.
Tech Stack A TypeScript ESM package (type: module) built via @preconstruct/cli alongside its sibling packages in the manypkg Yarn workspace, tested with Vitest and the fixturez fixture-copying library for repo-based integration tests. Its only dependencies are two sibling workspace packages, @manypkg/find-root and @manypkg/tools, with zero third-party runtime dependencies. It targets Node >=20. The wider monorepo uses Changesets for versioning and publishing, TypeScript in strict mode, and Knip for unused-code detection, with GitHub Actions running CI.
Code Quality index.test.ts exercises both getPackages and getPackagesSync against real fixture repositories for every supported tool — yarn, npm, pnpm (including exclude rules), bun (including JSON-lock and object-form workspaces), lerna (with and without explicit package globs), a single root-only package, a missing-name-field case, and a cyclic local-dependency case — copied fresh per test via fixturez rather than mocked. Errors are explicit, typed classes (PackageJsonMissingNameError, and NoPkgJsonFound/NoMatchingMonorepoFound in the sibling find-root package) carrying descriptive, actionable messages rather than generic throws. Naming and types are consistent throughout, with shared types (Packages, Package, MonorepoRoot) re-exported directly from @manypkg/tools instead of being redefined.
API Design The public surface is deliberately narrow: two functions (getPackages, getPackagesSync), one options type, and one error class, with zero configuration required for the common case and a single escape hatch (the tools option) for advanced callers who want to restrict or extend detection. JSDoc comments annotate every exported symbol, and the returned Packages shape is symmetric across every supported tool so calling code never needs per-tool branching. The tradeoff is that understanding the full detection behavior requires reading the sibling @manypkg/tools package, since none of the tool-specific logic is visible from get-packages alone.
Used by 3 apps in this directory
Grafana
Monitoring · Analytics
The open-source observability platform that unifies metrics, logs, and traces from any data source into dynamic, queryable dashboards.
GraphQL Hive
Developer Tools · Devops · Monitoring
Open-source GraphQL schema registry and observability platform with breaking change detection, federation support, and CI/CD integration for teams of any size.
Mastra Code
AI Code Assistants
"A coding agent that never compacts" — a terminal-based AI coding agent built on the Mastra framework, with Observational Memory instead of context compaction, multi-model support, and OAuth login for Claude Max or ChatGPT Plus.