# lpm add (/docs/packages/add)



```bash
lpm add <package>
```

`lpm add` extracts a package's source files into your project rather than installing it as a runtime dependency. Think `shadcn-ui` style: the code lands in your repo, you own it, you edit it.

`lpm install` is the runtime-dependency command. `lpm add` is the source-delivery command. The two are not aliases.

Works with **any registry** the resolver can reach — LPM.dev Registry, npmjs.org, or a `.npmrc`-declared private registry. Anything that ships a tarball is fair game.

Try the public npm example package:

```bash
lpm add lpm-source-package
```

[`lpm-source-package`](https://www.npmjs.com/package/lpm-source-package) is a minimal configurable source package published to npm, so it exercises the same registry-agnostic `lpm add` path without requiring an LPM.dev Registry package.

Like [`lpm install`](/docs/packages/install#typosquat-guard), `lpm add` rejects a likely typosquatted package name before any registry fetch. Intentional names use the committed [`policy.typosquat.allow`](/docs/reference/lpm-toml#typosquat-policy) list in `lpm.toml`.

When npm firewall mode is `monitor` or `enforce`, LPM CLI checks the selected source package with LPM Firewall at `firewall.lpm.dev` when it is a routed public npm package. LPM Firewall is an LPM.dev Registry Pro/Org feature, so active modes send LPM.dev Registry auth; run `lpm login` locally, or use `LPM_TOKEN` / registry-audience OIDC in CI. `monitor` warns and continues when entitlement is denied, while `enforce` blocks packages whose effective firewall action is `block` or denied by entitlement before the source tarball is downloaded or copied. In human output, the source-package download line shows `🔥 LPM Firewall active` when that check is active. LPM.dev Registry packages and other `.npmrc`-declared private/custom registry packages are not sent to the npm firewall verdict API. Dependencies installed after a config-aware source copy use the normal install pipeline and its firewall checks. The legacy string `report` is still accepted as a `monitor` alias.

## Examples [#examples]

```bash
lpm add @lpm.dev/owner.ui-kit                      # add an LPM.dev Registry package
lpm add @lpm.dev/owner.ui-kit@1.2.0                # add a specific version
lpm add @lpm.dev/owner.ui-kit?component=dialog     # add only one component
lpm add lodash.merge                               # add an npm package's source
lpm add @my-co/internal --path ./src/vendor        # custom destination
lpm add my-pkg --dry-run                           # preview without writing
lpm add @lpm.dev/owner.ui-kit --no-skills          # skip package skills once
```

## How it works [#how-it-works]

1. Resolves the spec against the appropriate registry.
2. Downloads the tarball into a temporary file and extracts it to a tempdir. Unlike `lpm install`, the tarball is **not** persisted to `~/.lpm/store/` — `lpm add` is a copy-and-discard flow. Re-running `lpm add` re-downloads.
3. Picks where to put the files. With `--path`, honors it. Without `--path` in a TTY (and not `--yes` / `--json`), prompts for an install directory. Non-interactive (`--yes`, `--json`, or non-TTY) requires `--path` for simple-path packages (no `lpm.config.json`); config-aware packages auto-detect from their declared ecosystem.
4. Copies the source into the destination, prompting on conflicts.
5. If the package declares an `lpm.config.json`, runs the package's configured install steps (component selection, alias rewrites, dep installation). If not, it's a plain source copy and you handle dependencies yourself.

`lpm add` does **not** auto-install bare imports it discovers in the copied source. It will surface them at the end of the run so you can add them yourself.

With the default `--pm lpm`, declared dependencies honor the same [minimum release age](/docs/packages/install#recently-published-packages) policy as [`lpm install`](/docs/packages/install). A bare dependency or `name@latest` selects the newest version old enough to install, then saves the project range from that selected version. An author-written range such as `name@^1.11.5` remains unchanged: fallback can only select older versions that still satisfy that range. If no mature version satisfies it, `lpm add` fails and restores the copied files, `package.json`, and lockfiles to their pre-add state.

Human output is structured around the source-copy flow:

```text
› Downloading source package source-pkg@1.0.0
› Detecting project structure
    Framework:    Vite
    Install path: src/components
    Import alias: @/src/components/
✓ Files copied
+ Foo.tsx
› Installing declared dependencies
+ lucide-react@^0.400.0
✓ Done · added 1 file and 1 dependency in 486ms
```

File conflicts use a slim warning line (`! File exists: ...`) before the interactive choice.

## Config-aware vs simple copy [#config-aware-vs-simple-copy]

A package becomes "config-aware" by shipping an `lpm.config.json` at the tarball root. That file declares components, dependencies to auto-install, import aliases, and editor integration hints. Without it, `lpm add` is a plain source copy — useful for any tarball, not just LPM.dev Registry packages.

For `@lpm.dev/*` source packages, `lpm add` also reconciles package-published agent guidance into `.lpm/skills/<package>/` by default. Use `--no-skills` to skip that step once, or `lpm config lpm-skills --set false` to persist the preference. `--skills` overrides the persistent opt-out for one run. The setting does not delete existing package skills or affect explicit `lpm skills add` commands; see [AI agent skills](/docs/reference/ai-agent-skills).

## Swift packages [#swift-packages]

For Swift packages, prefer &#x2A;*[`lpm install`](/docs/packages/install)** — it's the right command for SPM dependencies (resolves through the [SE-0292 registry](/docs/packages/swift-package-registry) and edits `Package.swift`). `lpm add` still works for Swift sources today and respects `--target` for Xcode-target wiring, but consider it the legacy path for that ecosystem.

## Authoring config-aware packages: `lpm.config.json` [#authoring-config-aware-packages-lpmconfigjson]

Ship `lpm.config.json` at the root of your tarball to control how `lpm add` extracts your package. With the file present, `lpm add` becomes a configurable installer — interactive prompts, conditional file copying, conditional dependency injection, import-path rewriting.

Install the [`lpm-guide`](https://github.com/lpm-dev/lpm-guide) skill if you want an agent to draft the config from your source tree:

```bash
npx skills add lpm-dev/lpm-guide
```

Then paste a prompt like this into your agent:

```text
Use the lpm-guide skill's Source Config workflow. Inspect this package's source tree and generate an lpm.config.json for a configurable source package.

Identify the options consumers should choose, such as components, styling framework, variants, or optional examples. Use required fields when choices would conflict, add defaultConfig so lpm add --yes works, map files[] from the package root to the consumer install path, declare conditional dependencies, and include example lpm add commands with query params.
```

```json title="lpm.config.json (sketch)"
{
  "$schema": "https://cli.lpm.dev/schemas/lpm.config.json",
  "ecosystem": "js",
  "importAlias": "@/",
  "configSchema": {
    "component": {
      "type": "select",
      "label": "Which component?",
      "options": ["dialog", "popover"],
      "default": "dialog",
      "required": true
    },
    "withTests": { "type": "boolean", "label": "Include tests?", "default": false }
  },
  "files": [
    { "src": "src/dialog/**", "dest": "dialog", "include": "when",
      "condition": { "component": "dialog" } },
    { "src": "tests/**", "dest": "__tests__", "include": "when",
      "condition": { "withTests": true } }
  ],
  "dependencies": {
    "withTests": { "true": ["vitest"] }
  }
}
```

The full schema reference — every field, every value type, every default — lives at [`lpm.config.json`](/docs/reference/lpm-config-json). The published JSON Schema at [`https://cli.lpm.dev/schemas/lpm.config.json`](https://cli.lpm.dev/schemas/lpm.config.json) drives editor autocomplete (add `$schema` as shown above).

### Pre-answering prompts [#pre-answering-prompts]

Prompts can be pre-answered from the CLI by appending `?key=value&key=value` to the package spec:

```bash
lpm add @lpm.dev/owner.ui-kit?component=dialog&styling=panda
```

Inline values bypass the prompt entirely. With `--yes`, prompts are skipped and `defaultConfig` / `configSchema.<field>.default` fill in any `required` fields the user didn't supply.

### Behavior matrix [#behavior-matrix]

| State                                                   | What `lpm add` does                                                                                                                       |
| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| No `lpm.config.json`                                    | Plain copy of the package's source. No prompts. No auto-install. Surfaces bare imports for you to install yourself.                       |
| `lpm.config.json` present, TTY                          | Prompts for every `configSchema` key not already inlined; copies per `files[]` rules; installs `dependencies` matching the chosen values. |
| `lpm.config.json` present, `--yes` / `--json` / non-TTY | Skips prompts; uses defaults for `required` fields; copies per matching rules; installs deps.                                             |

### Prerequisites [#prerequisites]

If the source package declares dependencies (config-driven or via its own `package.json`), your project must already have a `package.json`. `lpm add` runs a preflight check before copying any files and exits early with a remediation hint if the manifest is missing — there's nowhere for the dep entries to land otherwise, and we'd rather fail loudly than copy source files you can't `import` from.

```
$ lpm add @author/ui-kit
error: this source package declares dependencies, but the project has no
       `package.json` to record them in.
       Run `lpm init` (or `npm init -y`) first to create a manifest, then
       re-run `lpm add`.
       To copy the source files without installing the declared dependencies,
       pass `--no-install-deps` and resolve the imports yourself.
```

If you only want the source files (and you'll handle the imports yourself), pass `--no-install-deps` to skip the preflight and let the copy proceed without touching `package.json`.

## Flags [#flags]

| Flag                 | Effect                                                                                                                                                                                                                                                                    |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--path <DIR>`       | Target directory (overrides interactive prompt and auto-detection)                                                                                                                                                                                                        |
| `-y`, `--yes`        | Skip interactive prompts, use defaults                                                                                                                                                                                                                                    |
| `--force`            | Overwrite existing files without prompting                                                                                                                                                                                                                                |
| `--dry-run`          | Show what would be done without writing anything                                                                                                                                                                                                                          |
| `--no-install-deps`  | Skip dependency installation after copy (for config-aware packages)                                                                                                                                                                                                       |
| `--skills`           | Install package-published LPM.dev skills for this invocation, overriding user config                                                                                                                                                                                      |
| `--no-skills`        | Skip package-published LPM.dev skill auto-install for this invocation                                                                                                                                                                                                     |
| `--no-editor-setup`  | Compatibility flag. Package skills do not create editor integrations.                                                                                                                                                                                                     |
| `--pm <NAME>`        | Package manager for dep installation (`lpm`, `npm`, `pnpm`, `yarn`, `bun`, `auto`; default `lpm`)                                                                                                                                                                         |
| `--alias <ALIAS>`    | Import alias prefix (e.g., `@/components`) — overrides auto-detection                                                                                                                                                                                                     |
| `--target <NAME>`    | Swift SPM target name (Swift packages only)                                                                                                                                                                                                                               |
| `--no-engine-strict` | Use warning-only root checks and, when LPM installs dependencies, dependency checks (see [`lpm install`](/docs/packages/install#engines-enforcement)). Root preflight runs before any manifest mutation, so a constraint violation can't leave the project half-modified. |

Plus the [global flags](/docs/commands#global-flags).

## See also [#see-also]

* [`lpm remove`](/docs/packages/remove) — undo an `lpm add`
* [`lpm install`](/docs/packages/install) — install runtime dependencies
* [Registries](/docs/registries) — how packages route
* [Swift Package Registry](/docs/packages/swift-package-registry) — SE-0292 design and the `lpm install`-preferred path for Swift
