LPM CLI

lpm.config.json

Define source-package prompts, file selection, dependencies, and import rewriting for lpm add.

Package authors put lpm.config.json at the tarball root to configure lpm add. It defines consumer choices, source files, import rewriting, and optional dependency installation. It works with packages from npm, private registries, and LPM.dev Registry.

For a complete package example and publication recipes, see Source packages.

lpm.config.json
{
  "$schema": "https://cli.lpm.dev/schemas/lpm.config.json",
  "configSchema": {
    "theme": {
      "type": "select",
      "options": ["light", "dark"],
      "default": "light",
      "required": true
    }
  },
  "files": [
    { "src": "src/component.ts", "dest": "component.ts" },
    { "src": "src/dark.css", "include": "when", "condition": { "theme": "dark" } }
  ]
}

Preview a consumer installation without prompts:

lpm add '@acme/components?theme=dark' --path src/ui --yes --dry-run --json

Replace the example package with your published package. Quote package names that contain query parameters. Remove --dry-run to copy the selected files.

This file configures source delivery. Use lpm.json for project tasks, runtimes, and development services. Use lpm install to install dependencies into node_modules.

Editor autocomplete

The schema URL is https://cli.lpm.dev/schemas/lpm.config.json. The older https://lpm.dev/schemas/lpm.config.json URL remains a compatibility alias.

To export the schema from your installed CLI:

lpm schema lpm.config.json -o lpm-config.schema.json

lpm schema emits configuration schemas. It does not check a package or run its installation. Commands also check selected values, dependency specifications, and file paths.

Top-level shape

All fields are optional. The smallest valid file is {}. Unknown fields and unsupported field types are rejected.

FieldPurposeDefault
$schemaEditor schema URL.Unset.
typeLPM.dev Registry package classification.Inferred from published contents.
ecosystemSource ecosystem: js or swift.js.
importAliasAuthor import prefix to rewrite.Unset.
configSchemaConsumer prompt definitions.No prompts.
defaultConfigDefaults that override field defaults.{}.
filesOrdered file selection and destination rules.Source-selection fallback.
dependenciesDependency lists by selected configuration value.Package manifest dependencies and peers.

If the file is absent, lpm add uses plain source delivery without automatic dependency installation. Plain delivery still applies source-selection fallback. A valid configuration file activates configured delivery even with type: "package".

type

ValueLPM.dev Registry classification
packageDependency package.
sourceSource package.

The field affects classification, not source-copy behavior. Other values are rejected. The Registry infers classification when the field is absent.

ecosystem

{ "ecosystem": "js" }
ValueBehavior
jsJavaScript or TypeScript source. Framework detection chooses the default destination.
swiftSwift source. Swift package targets use Sources/<target>/; Xcode projects can use Packages/LPMComponents/Sources/<target>/.

For example, Next.js uses components/, and Vite uses src/components/. Consumers can choose a destination with --path <DIR>. See lpm add for Swift target selection.

importAlias

{ "importAlias": "@/components" }

This string identifies the author import prefix. LPM CLI rewrites matching internal imports to the consumer alias or relative destination path. The consumer can supply --alias or use detected TypeScript path configuration.

Relative internal imports do not require this field. They follow the source-to-destination map when files move. Bare package imports remain unchanged. Mapped .js, .mjs, .cjs, and .json imports keep runtime extensions, including explicit index paths. TypeScript imports retain extension-free behavior.

configSchema

{
  "configSchema": {
    "component": {
      "type": "select",
      "label": "Component",
      "options": ["dialog", { "value": "menu", "label": "Menu component" }],
      "required": true
    },
    "withTests": { "type": "boolean", "default": false }
  }
}

Each field defines a prompt and a value for file conditions or dependency selection.

Field propertyTypeDefaultPurpose
typestring, boolean, or selectstringText input, confirmation, or selection prompt.
labelstringField namePrompt label.
defaultstring, boolean, or numberUnsetInitial value.
requiredbooleanfalseRequire a nonempty resolved value.
multiSelectbooleanfalseAllow several selections for a select field.
optionsarrayRequired for selectOne or more strings or { "value": "...", "label": "..." } objects.

Option objects require value. An absent label uses that value. Resolved booleans and numbers become strings for condition matching. Multiple selections become a comma-separated value.

Defaults and non-interactive use

Explicit query values override defaultConfig, which overrides each field's default. Interactive prompts use the resolved default. An optional single-select field without a default starts at Leave unset. A multi-select field without a default starts empty.

With --yes or non-interactive input, LPM CLI applies defaults without prompts. A required boolean without a default resolves to false. A required select with one option can use that option. Other unresolved required fields fail before source files are copied.

lpm add '@acme/components?component=dialog&withTests=false' --path src/ui --yes

An omitted optional value keeps conditional files whose condition key remains unset, but selects no matching dependencies. An explicit empty optional multi-select, such as ?features=, excludes its conditional files and selects no dependencies. Empty values for other optional field types become unset. See Pre-answer prompts for encoding and multiple selections.

defaultConfig

{ "defaultConfig": { "withTests": false, "component": "dialog" } }

Values can be strings, booleans, or numbers. They override defaults in the matching configSchema entry. Explicit consumer query values take precedence over both sources.

files

{
  "files": [
    { "src": "src/index.ts", "dest": "index.ts" },
    { "src": "src/styles/**", "dest": "styles" },
    { "src": "src/test.ts", "include": "when", "condition": { "withTests": true } }
  ]
}

Rules run in their declared order. The selected file list must be nonempty, and destinations must be unique.

Rule fieldTypeDefaultPurpose
srcstringRequiredSource path or supported glob relative to the tarball root.
deststringSource-relative pathDestination relative to the consumer install directory.
includealways, when, or neveralwaysCopy unconditionally, evaluate conditions, or skip this rule.
conditionobjectRequired for whenExpected configuration values as strings, booleans, or numbers.

Source selectors support trailing /* and /**. For a glob, dest is a directory even if one file matches. Paths after the fixed glob prefix remain relative to that destination. For a single file, a trailing destination slash preserves its filename. Otherwise, dest renames the file. Unsafe source or destination paths fail before copying.

A when rule requires a condition object. Every supplied condition key must match. A multi-select matches if any selected value equals the expected value. An omitted consumer key does not exclude the file. An explicitly empty multi-select does. A never rule skips that rule. It does not subtract files selected by another rule.

If files is absent, LPM CLI first checks package.json > lpm > source. Without that legacy selector, fallback copying excludes package.json, lpm.config.json, and the directories node_modules, .git, __tests__, test, and tests. A declared empty files array does not enable fallback. See lpm add for the complete copy workflow.

dependencies

{
  "dependencies": {
    "icons": {
      "lucide": ["lucide-react"],
      "heroicons": ["@heroicons/react@^2"]
    },
    "withMotion": { "true": ["framer-motion@latest"] }
  }
}

The outer key is a configuration field. The next key is a selected value. Its array lists dependencies to add to the consumer manifest. Multiple selections combine matching lists. Duplicate package names keep the first entry.

Dependency entrySaved version
Bare name, such as reactResolve through the registry, then apply consumer save policy.
Exact version, such as react@19.1.0Preserve the exact version.
Range, such as react@^19Preserve the range.
Tag, such as react@latestResolve the tag. Stable versions use save policy; prereleases save exact versions.
Wildcard, such as react@*Preserve *.

Package-authored dependency entries must refer to registry packages. Local workspace, file, Git, and URL specifications are rejected. Consumers can still use workspace specifications directly with lpm install. See Save policy for consumer defaults.

Registry agnostic

Dependency names follow the consumer registry configuration. Public npm packages, private packages from .npmrc, and @lpm.dev/* packages are supported. Only @lpm.dev/* packages always route through LPM.dev Registry.

--pm selects lpm, npm, pnpm, yarn, bun, or auto. The default is lpm. The auto value detects the project package manager. Use --no-install-deps to skip dependency installation for one source-copy operation.

Resolve-then-write, with rollback

Bare names and tags resolve before manifest changes. Explicit ranges, versions, and wildcards can fail later during dependency installation. A normal command failure restores tracked source changes, manifests, and selected package-manager lockfiles. Source tracking in the committed lpm-sources.json and overwrite backups in .lpm/added-source-backups/ recover with the copied files. See Files LPM CLI creates.

PathRecovery
package.jsonRestore the previous bytes.
lpm.lock, lpm.lockbRestore previous bytes or remove newly created files.
Selected package-manager lockfilesRestore previous bytes or remove newly created files.
Copied source filesRestore previous files and remove newly created files.
.lpm/install-hashInvalidate it so the next install checks project state.

New directories are removed only if empty. After an interruption, later user edits prevent automatic restoration of the affected path. A hard stop has narrower recovery than a normal command failure. The next add or remove recovers source files, tracking, backups, and staged manifests. Dependency lockfiles and node_modules can require lpm install.

Recursive Swift copies share source and manifest recovery with the root operation. Earlier completed package-manager lockfiles are outside that durable recovery. Package skills use separate reconciliation. A skills failure produces a warning after source delivery. See Interruption recovery.

Author opt-out of legacy fallback

A declared dependencies field disables the manifest fallback, even if no branch matches. Use { "dependencies": {} } to declare no automatically installed dependencies.

Legacy fallback

If dependencies is absent, configured delivery reads dependencies and peerDependencies from the package manifest. The declared version specifications follow the same source-package dependency rules. A package without lpm.config.json does not use this automatic dependency fallback.

LPM.dev Registry publication limits

LPM CLI accepts configuration files up to 16 MiB. LPM.dev Registry applies additional publication limits:

ItemLimit
Root configuration file and canonical JSON128 KiB each.
Labels, option values, option labels, import alias200 characters each.
Options in one field64.
Source path1–512 characters.
Destination path512 characters.
File rules1,000.
Dependency entry200 characters.
Entries in one dependency array200.

The Registry reads the physical configuration file from the uploaded tarball. Invalid JSON, invalid configuration, and non-regular configuration files fail publication. Separate metadata cannot replace or create that file. Other registries can apply different limits.

Generate a config with an agent

Install the lpm-guide skill:

lpm skills add lpm-dev/lpm-guide

Ask the agent to inspect the actual package:

Use the lpm-guide Source Config workflow to create lpm.config.json.
Read the source files, package metadata, and internal imports.
Define only the consumer choices that this package needs.
Add deterministic non-interactive examples and check the file against the published schema.

See also