Symlink together all packages that are dependencies of each other in Lerna monorepos
npx @tessl/cli install tessl/npm-lerna--link@6.6.0@lerna/link is a Lerna command package that creates symbolic links between packages that depend on each other within a Lerna monorepo. It enables local development workflows where changes in one package are immediately reflected in dependent packages without requiring package republishing or manual linking.
npm install @lerna/link or available via lerna CLI// CommonJS style (Node.js require)
const linkCommand = require("@lerna/link");
const { LinkCommand } = require("@lerna/link");
const command = require("@lerna/link/command");// TypeScript style (using CommonJS imports)
import linkCommand = require("@lerna/link");
import { LinkCommand } = require("@lerna/link");
import command = require("@lerna/link/command");# Link all interdependent packages
lerna link
# Force linking regardless of version ranges
lerna link --force-local
# Use specific subdirectory as symlink source
lerna link --contents dist
# Convert existing links to file: specifiers
lerna link convertconst linkCommand = require("@lerna/link");
// Create command instance
const command = linkCommand(process.argv);
// Initialize and execute
await command.initialize();
await command.execute();@lerna/link is built around several key components:
LinkCommand instances, allowing for dependency injection and testing flexibilityCommand class, integrating with the Lerna command system and lifecycle managementPackageGraph to analyze dependencies between packages and determine which packages need linkingnode_modules directories and .bin directories for executablesfile: specifications in package.json filesThe command operates in two main modes: standard linking (creating symbolic links) and conversion mode (updating package.json files with file: specifications).
Creates a new LinkCommand instance with provided command-line arguments.
function factory(argv: NodeJS.Process["argv"]): LinkCommand;Main command class that handles package linking operations. Extends Lerna's base Command class.
class LinkCommand extends Command<LinkCommandOptions> {
allPackages: Package[];
targetGraph?: PackageGraph;
get requiresGit(): boolean;
initialize(): void;
execute(): Promise<any>;
convertLinksToFileSpecs(): Promise<any>;
}allPackages: Array of all packages in the monorepotargetGraph: Graph of package dependencies for linking operationsrequiresGit: Returns false, indicating git is not required for this commandinitialize(): Sets up the command, validates npm client, and builds package graphexecute(): Performs the linking operation or converts links to file specificationsconvertLinksToFileSpecs(): Converts symbolic links to relative file: specifications in package.json filesYargs command module configuration for CLI integration. Provides the CLI interface and option definitions.
interface CommandModule {
command: string;
describe: string;
builder: (yargs: any) => any;
handler: (argv: any) => any;
}The command module exports:
--force-local, --contents, and the convert subcommandThe builder function also registers the convert subcommand with the description "Replace local sibling version ranges with relative file: specifiers".
Options interface extending Lerna's base CommandConfigOptions.
interface LinkCommandOptions extends CommandConfigOptions {
contents: string;
forceLocal: boolean;
}contents: Subdirectory to use as the source of the symlink (default: current directory)forceLocal: Force local sibling links regardless of version range matchForces creation of symbolic links for local dependencies regardless of whether their version ranges match.
lerna link --force-localSpecifies a subdirectory to use as the source of the symlink, applying to all packages.
lerna link --contents distReplaces local sibling version ranges with relative file: specifiers in package.json files.
lerna link convertinterface LinkCommandOptions extends CommandConfigOptions {
contents: string;
forceLocal: boolean;
}The package relies on several core Lerna types and utilities:
// From @lerna/core
class Command<T extends CommandConfigOptions>;
interface CommandConfigOptions;
class Package;
class PackageGraph;
class PackageGraphNode;
function symlinkDependencies(
packages: Package[],
packageGraph: PackageGraph | undefined,
tracker: any
): Promise<any>;
class ValidationError;The command throws a ValidationError when attempting to use with pnpm workspaces:
class ValidationError extends Error {
constructor(code: string, message: string);
}Specific error thrown:
pnpm install. See the pnpm docs for details: https://pnpm.io/workspaces"This error is thrown during the initialize() method when this.options.npmClient === "pnpm".
The command analyzes all packages in the Lerna monorepo and identifies dependencies between them. It creates symbolic links only for packages that are listed as dependencies of other packages in the same monorepo.
node_modules folders of dependent packages.bin directories for CLI commandspublishConfig.directory in package.json--force-local is usedBy default, symbolic links are only created when the dependency version range matches the local package version. The --force-local flag bypasses this check and creates links regardless of version compatibility.
The convert subcommand transforms the monorepo to use file: dependencies instead of symbolic links, making packages reference each other through relative file paths in their package.json files.
@lerna/link integrates with Lerna's command system and can be invoked through:
require("@lerna/link")lerna linkWorks with packages that use publishConfig.directory to specify build output directories, linking the built artifacts instead of source code.