Source code delivery

Source packages deliver editable files into a consumer's project. LPM CLI uses lpm add for this workflow instead of installing the package as a resolver-managed dependency.

lpm add @lpm.dev/acme.login-form

The copied files become part of the project. The consumer owns them, can modify them, and chooses when to bring in a newer package version.

Source delivery or dependency installation

lpm addlpm install
PurposeDeliver project-owned sourceManage a versioned dependency
UpdatesRe-run deliberately and review conflictsResolver-managed
CustomizationEdit the delivered files directlyWrap, configure, or fork the dependency
Typical useComponents, templates, starters, examplesLibraries, tools, and Swift packages

LPM.dev Registry package pages show lpm add when a version contains a valid lpm.config.json or a valid package.json > lpm.source path. Other versions show lpm install.

LPM CLI itself is registry-agnostic: lpm add can copy a tarball from LPM.dev Registry, npm, or a .npmrc-configured private registry. See the complete LPM CLI add reference for routing and every command flag.

Configurable or simple delivery

Source packages have two delivery paths:

Package contentsLPM CLI behavior
Root lpm.config.jsonPrompts for options, selects files, rewrites imports, and installs declared dependencies
package.json > lpm.source without configCopies the declared source path without interactive package options or automatic dependency installation

LPM CLI can also source-copy an ordinary package explicitly. Without lpm.config.json, it treats the package as a simple copy and reports external JavaScript or TypeScript imports that the consumer may need to install.

Choose package options

Authors define configurable fields in lpm.config.json. An interactive run asks for every field that was not supplied in the package spec:

lpm add @lpm.dev/acme.ui-kit

Consumers can pre-answer fields with query values:

lpm add "@lpm.dev/acme.ui-kit?component=dialog,button&styling=panda"

Inline values skip their corresponding prompts. Multiple selections use comma-separated values.

--yes skips prompts, but it does not apply every optional default. It fills missing fields marked required from defaultConfig or the field's default; optional fields remain absent. An absent condition key uses the source-delivery include-all behavior.

lpm add @lpm.dev/acme.ui-kit --yes

See Source Configuration for the authoring contract.

Choose a destination

--path sets the destination explicitly:

lpm add @lpm.dev/acme.ui-kit --path src/components/ui

In an interactive JavaScript or TypeScript project, LPM CLI proposes a destination based on the project structure and lets the user change it. A non-interactive simple copy without lpm.config.json requires --path; config-aware packages can use their ecosystem's default.

Preview the selection and file actions without modifying the project:

lpm add @lpm.dev/acme.ui-kit --dry-run

Import rewriting

For JavaScript and TypeScript source, LPM CLI can rewrite internal imports to match the consumer's destination and import alias.

It obtains the consumer alias from:

  1. An explicit --alias.
  2. tsconfig.json or jsconfig.json path mappings.
  3. The interactive alias prompt.

If the author declares importAlias in lpm.config.json, author-alias imports can be translated. Relative imports between delivered files can still be rewritten when the consumer supplies an alias, even if the author did not declare one.

// Package source
import { cn } from "../../lib/utils"

// Delivered source
import { cn } from "@/components/design-system/lib/utils"

Bare imports such as react, next/link, and @radix-ui/dialog are external and remain unchanged.

Existing files

When a destination file already exists:

  • An interactive run can keep the file, overwrite it, or show a diff first.
  • --yes, JSON output, and non-interactive runs keep the existing file.
  • --force overwrites conflicts.
  • Identical files are skipped.

This makes re-running lpm add deliberate: the Registry package does not silently replace local customization.

Declared dependencies

A config-aware source package can declare dependencies for each consumer choice. LPM CLI adds matching dependencies to the consumer's package.json and runs the selected package manager.

Dependencies can come from npm, LPM.dev Registry, or a .npmrc-configured private registry. The default package manager is LPM CLI; consumers can choose npm, pnpm, yarn, bun, or automatic project detection with --pm.

lpm add @lpm.dev/acme.ui-kit --pm lpm
lpm add @lpm.dev/acme.ui-kit --no-install-deps

If the config omits its dependencies field, LPM CLI uses the source package's dependencies and peerDependencies as a legacy fallback. Declaring dependencies, even when the selected options match no entries, disables that fallback.

When dependencies must be installed, the consumer project needs a package.json. LPM CLI checks this before copying files. --no-install-deps opts out when the consumer wants to manage imports manually.

Failure and removal

If file delivery, manifest mutation, or dependency installation fails, LPM CLI restores copied files, package.json, and affected lockfiles to their pre-add state. Newly created empty destination directories can remain.

Successful source deliveries are tracked so the related LPM CLI removal workflow can identify the files written by the package. See the lpm remove reference for removal behavior.

Swift packages

Use lpm install for Swift libraries. It integrates with SPM, edits Package.swift or the Xcode dependency host, resolves transitive dependencies, and verifies Registry signatures.

lpm add remains a legacy Swift source-copy path. It does not create a Swift manifest or link a local package into .xcodeproj, so those behaviors are not part of the supported source-delivery workflow.

See Swift Package Registry for the current Swift installation model.

See also