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.
{
"$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 --jsonReplace 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.jsonlpm 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.
| Field | Purpose | Default |
|---|---|---|
$schema | Editor schema URL. | Unset. |
type | LPM.dev Registry package classification. | Inferred from published contents. |
ecosystem | Source ecosystem: js or swift. | js. |
importAlias | Author import prefix to rewrite. | Unset. |
configSchema | Consumer prompt definitions. | No prompts. |
defaultConfig | Defaults that override field defaults. | {}. |
files | Ordered file selection and destination rules. | Source-selection fallback. |
dependencies | Dependency 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
| Value | LPM.dev Registry classification |
|---|---|
package | Dependency package. |
source | Source 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" }| Value | Behavior |
|---|---|
js | JavaScript or TypeScript source. Framework detection chooses the default destination. |
swift | Swift 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 property | Type | Default | Purpose |
|---|---|---|---|
type | string, boolean, or select | string | Text input, confirmation, or selection prompt. |
label | string | Field name | Prompt label. |
default | string, boolean, or number | Unset | Initial value. |
required | boolean | false | Require a nonempty resolved value. |
multiSelect | boolean | false | Allow several selections for a select field. |
options | array | Required for select | One 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 --yesAn 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 field | Type | Default | Purpose |
|---|---|---|---|
src | string | Required | Source path or supported glob relative to the tarball root. |
dest | string | Source-relative path | Destination relative to the consumer install directory. |
include | always, when, or never | always | Copy unconditionally, evaluate conditions, or skip this rule. |
condition | object | Required for when | Expected 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 entry | Saved version |
|---|---|
Bare name, such as react | Resolve through the registry, then apply consumer save policy. |
Exact version, such as react@19.1.0 | Preserve the exact version. |
Range, such as react@^19 | Preserve the range. |
Tag, such as react@latest | Resolve 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.
| Path | Recovery |
|---|---|
package.json | Restore the previous bytes. |
lpm.lock, lpm.lockb | Restore previous bytes or remove newly created files. |
| Selected package-manager lockfiles | Restore previous bytes or remove newly created files. |
| Copied source files | Restore previous files and remove newly created files. |
.lpm/install-hash | Invalidate 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:
| Item | Limit |
|---|---|
| Root configuration file and canonical JSON | 128 KiB each. |
| Labels, option values, option labels, import alias | 200 characters each. |
| Options in one field | 64. |
| Source path | 1–512 characters. |
| Destination path | 512 characters. |
| File rules | 1,000. |
| Dependency entry | 200 characters. |
| Entries in one dependency array | 200. |
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-guideAsk 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.