Publishing your first package
From lpm init to lpm publish, with quality checks and provenance.
This guide walks through publishing a package from scratch. By the end you'll have a package on lpm.dev that anyone you grant access to can lpm install. We'll cover quality gates, secret scanning, and provenance — the things you can't see from the command name alone.
1. Authenticate
lpm loginOpens your browser, you authenticate against lpm.dev, the CLI captures the redirect token and stores it in your OS keychain. You only do this once per machine.
lpm whoamiConfirms the identity, plan tier, and any orgs you belong to.
2. Create the package
mkdir my-pkg && cd my-pkg
lpm initlpm init walks you through owner / name / version / description. The published name will be @lpm.dev/<owner>.<name> — pick an owner you've claimed on lpm.dev (or one your org owns).
For a non-interactive bootstrap (CI scripts):
lpm init -y3. Write your code
Build out the package — src/ (or wherever), dist/ (your build output), README, license. The defaults lpm init writes to package.json (substituting the owner/name you supplied):
{
"name": "@lpm.dev/<owner>.<name>",
"version": "1.0.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"type": "module",
"license": "MIT",
"files": ["dist"]
}Tighten files to whatever you actually want shipped. Anything not listed (README, LICENSE, package.json) is included by default per npm convention.
4. Preview the publish
lpm publish --dry-runRuns every step except the upload: packs the tarball, scans for hardcoded secrets, computes the quality score. If anything's wrong, this is where you find out.
lpm publish --checkEven shorter — only runs the quality report. Useful as a pre-commit hook.
5. Set a quality floor (optional)
lpm publish --min-score 80Aborts the publish if the quality score is below 80. Pairs well with CI gates — your team can't ship a package missing a README, types, or a license without explicit override.
The score is computed from readme presence/length, license declaration, types coverage, test signals, and maintenance heuristics. See lpm quality to view the report for an already-published lpm.dev package.
6. Publish
lpm publishPack → secret scan → quality report → confirmation prompt → upload. Skip the prompt with -y (good in CI).
The package starts in private distribution mode — only you (and anyone you grant access to) can install it. To make it discoverable or paid, flip the distribution mode in the lpm.dev dashboard:
| Mode | What it means |
|---|---|
| Private (default) | Only the publisher and granted users can install. Metadata is not public. |
| Pool | Metadata is public. Installs gated to pool subscribers. Publisher earns a share of pool revenue. |
| Marketplace | Installs require a license purchase. |
Mode changes are irreversible — going public is a one-way door. See Distribution mode.
7. (Optional) Provenance
In CI with an audience-sigstore OIDC token — GitHub Actions or GitLab CI:
lpm publish --provenanceGenerates a Sigstore-signed attestation that proves which workflow built the tarball and which commit it came from. Consumers can verify it via the audit pipeline or the registry UI.
--provenance fails loud (non-zero exit) if no usable Sigstore-audience token is found or if Sigstore signing fails — it never silently publishes without provenance. Useful as a hard gate in security-critical packages.
On GitHub Actions, enable permissions: id-token: write on the job. On GitLab CI, mint SIGSTORE_ID_TOKEN via the id_tokens block with aud: sigstore. Other platforms aren't supported.
8. Publishing elsewhere
lpm publish defaults to lpm.dev. To target other registries:
lpm publish --npm # registry.npmjs.org
lpm publish --github # GitHub Packages
lpm publish --gitlab # GitLab Packages
lpm publish --publish-registry https://r.example.com # custom npm-compatibleYou must have auth for the selected target first: lpm login --npm opens npm's browser login, while lpm login --github / --gitlab can use existing gh / glab auth without storing a copied token. Custom registries still use lpm login --login-registry <URL> --token <T>. For multiple targets in one go, set lpm.json > publish.registries — see lpm.json.
Common pitfalls
init -ydefaults aren't directory-derived. Under-y, owner is yourlpm whoamiprofile username (or the literal"username"if offline / not logged in) and name is literally"package"(not your directory's name). The published shape becomes@lpm.dev/<your-username>.package— update both before publishing.- Quality score below 80 by default = no readme, no license, no types. Easy fix; usually a 5-minute task.
- Distribution mode is irreversible. Pool / marketplace are one-way doors. Stay private until you're sure.
- Provenance only works in OIDC-capable CI. Don't pass
--provenancefrom a developer laptop.
See also
lpm publish— full flag referencelpm quality— what the score coverslpm init— manifest scaffolding- Authentication — token management