From 3224cbd92b9a695f5b8be5b8caf1e857c1eb6d0e Mon Sep 17 00:00:00 2001 From: thelovekesh Date: Sat, 23 May 2026 00:53:38 +0530 Subject: [PATCH 1/3] Add title and description --- docs/fundamentals/dependencies.md | 7 ++++++- docs/fundamentals/package-types.md | 7 ++++++- docs/fundamentals/registry.md | 7 ++++++- docs/fundamentals/runtime.md | 7 ++++++- docs/fundamentals/wpm-json.md | 11 ++++++++--- docs/fundamentals/wpm-lock.md | 7 ++++++- docs/fundamentals/wpmignore.md | 7 ++++++- docs/getting-started/first-project.md | 7 ++++++- docs/getting-started/installation.md | 7 ++++++- docs/getting-started/overview.md | 9 +++++++-- docs/getting-started/why-wpm.md | 11 ++++++++--- docs/guides/authentication.md | 11 ++++++++--- docs/guides/ci.md | 11 ++++++++--- docs/guides/dependency-management.md | 7 ++++++- docs/guides/publishing.md | 11 ++++++++--- docs/guides/runtime-compatibility.md | 7 ++++++- docs/reference/cli/publish.md | 2 +- docs/reference/glossary.md | 15 ++++++++++----- 18 files changed, 118 insertions(+), 33 deletions(-) diff --git a/docs/fundamentals/dependencies.md b/docs/fundamentals/dependencies.md index f0a1175..7770238 100644 --- a/docs/fundamentals/dependencies.md +++ b/docs/fundamentals/dependencies.md @@ -1,4 +1,9 @@ -# Dependencies +--- +title: Dependencies +description: + How wpm manages dependencies in `wpm.json`, resolves version conflicts, and + creates reproducible installs for WordPress plugins and themes. +--- `dependencies` and `devDependencies` are the two dependency maps in `wpm.json`. They tell wpm which packages to install, at which versions, and in which role diff --git a/docs/fundamentals/package-types.md b/docs/fundamentals/package-types.md index 867821b..e2f53b0 100644 --- a/docs/fundamentals/package-types.md +++ b/docs/fundamentals/package-types.md @@ -1,4 +1,9 @@ -# Package types +--- +title: Package types +description: + The `plugin`, `theme`, and `mu-plugin` package types in wpm, how each maps to + a WordPress directory, and when to use each one. +--- Every wpm package has a `type` field. It tells wpm how to install the package, and it tells WordPress how to load it. Three values are supported: diff --git a/docs/fundamentals/registry.md b/docs/fundamentals/registry.md index f88f411..dffca89 100644 --- a/docs/fundamentals/registry.md +++ b/docs/fundamentals/registry.md @@ -1,4 +1,9 @@ -# Registry concepts +--- +title: wpm registry +description: + How the wpm registry stores package manifests, manages dist tags and + visibility, and distributes WordPress plugins and themes. +--- The wpm registry is the server that hosts published packages and serves them to `wpm install`. By default wpm talks to `registry.wpm.so`. You can point it at a diff --git a/docs/fundamentals/runtime.md b/docs/fundamentals/runtime.md index c27c6a4..91ed7b4 100644 --- a/docs/fundamentals/runtime.md +++ b/docs/fundamentals/runtime.md @@ -1,4 +1,9 @@ -# Runtime compatibility +--- +title: Runtime compatibility +description: + How `requires` and `config.runtime` define WordPress and PHP compatibility, + what your package supports and what you develop against. +--- `wpm.json` has two fields that talk about WordPress and PHP versions: diff --git a/docs/fundamentals/wpm-json.md b/docs/fundamentals/wpm-json.md index bf0fe0c..376bf25 100644 --- a/docs/fundamentals/wpm-json.md +++ b/docs/fundamentals/wpm-json.md @@ -1,4 +1,9 @@ -# wpm.json +--- +title: wpm.json +description: + The full reference for the `wpm.json` manifest, covering required fields, + optional metadata, dependency maps, and runtime configuration. +--- `wpm.json` is the manifest at the root of every wpm package. It declares what the package is, what it depends on, and which versions of WordPress and PHP it @@ -157,5 +162,5 @@ A few things to know: install, and how `config.runtime` participates. - [`wpm.lock`](wpm-lock.md): the resolved snapshot that pairs with `wpm.json`. - [`.wpmignore`](wpmignore.md): controls what `wpm publish` packs. -- [Registry concepts](registry.md): dist tags, visibility, and the difference - between `private: true` and `--access private`. +- [wpm registry](registry.md): dist tags, visibility, and the difference between + `private: true` and `--access private`. diff --git a/docs/fundamentals/wpm-lock.md b/docs/fundamentals/wpm-lock.md index 2468c98..d6f81f8 100644 --- a/docs/fundamentals/wpm-lock.md +++ b/docs/fundamentals/wpm-lock.md @@ -1,4 +1,9 @@ -# wpm.lock +--- +title: wpm.lock +description: + How the `wpm.lock` lockfile captures your resolved dependency tree and keeps + installs reproducible across machines and CI. +--- `wpm.lock` records the exact dependency tree your project resolved to. It keeps installs identical across machines and CI runs. diff --git a/docs/fundamentals/wpmignore.md b/docs/fundamentals/wpmignore.md index 3a37d72..06b937c 100644 --- a/docs/fundamentals/wpmignore.md +++ b/docs/fundamentals/wpmignore.md @@ -1,4 +1,9 @@ -# .wpmignore +--- +title: .wpmignore +description: + How `.wpmignore` controls which files ship with `wpm publish`, using the same + syntax you already know from `.gitignore`. +--- `.wpmignore` is an optional file at the root of your project. It tells `wpm publish` which paths to exclude from the tarball that gets uploaded to the diff --git a/docs/getting-started/first-project.md b/docs/getting-started/first-project.md index 6813899..476dfb6 100644 --- a/docs/getting-started/first-project.md +++ b/docs/getting-started/first-project.md @@ -1,4 +1,9 @@ -# Getting started +--- +title: First project +description: + Build your first wpm plugin or theme project in ten minutes by scaffolding + dependencies, locking versions, and publishing. +--- In about ten minutes, you'll go from a fresh wpm install to a working project with dependencies. You don't need a registry account for the first five steps. diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index 5c69f63..9eb2b64 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -1,4 +1,9 @@ -# Installation +--- +title: Installation +description: + Install wpm on Linux, macOS, Windows, Docker, or from source, including shell + completion setup and where wpm stores its files. +--- wpm ships as a single static binary. There are no runtime dependencies, no PHP requirement on the machine that runs wpm, and no per-project toolchain. Pick the diff --git a/docs/getting-started/overview.md b/docs/getting-started/overview.md index 7ad64a6..517fd07 100644 --- a/docs/getting-started/overview.md +++ b/docs/getting-started/overview.md @@ -1,4 +1,9 @@ -# Welcome to wpm +--- +title: Overview +description: + Get started with wpm for WordPress plugins and themes, including core + commands, project files, and your first install in under a minute. +--- wpm is an open source package manager for WordPress plugins and themes. @@ -99,7 +104,7 @@ Learn how the wpm ecosystem works: Common workflows and real-world usage: - [Authentication](../guides/authentication.md) -- [Publishing packages](../guides/publishing.md) +- [Publishing](../guides/publishing.md) - [CI/CD](../guides/ci.md) ### Reference diff --git a/docs/getting-started/why-wpm.md b/docs/getting-started/why-wpm.md index 89b041e..61479b2 100644 --- a/docs/getting-started/why-wpm.md +++ b/docs/getting-started/why-wpm.md @@ -1,4 +1,9 @@ -# Why wpm +--- +title: Why wpm? +description: + Why wpm exists, how it improves WordPress dependency management, and when to + use it in plugin and theme projects. +--- Managing dependencies in a WordPress project has always been a patchwork. @@ -180,5 +185,5 @@ themes. directory to working project. - **[Dependencies](../fundamentals/dependencies.md)**: the full reasoning behind exact-version pinning. -- **[Registry concepts](../fundamentals/registry.md)**: how the wpm registry - stores manifests and verifies provenance. +- **[wpm registry](../fundamentals/registry.md)**: how it stores manifests and + verifies provenance. diff --git a/docs/guides/authentication.md b/docs/guides/authentication.md index ded2fa5..adc09d2 100644 --- a/docs/guides/authentication.md +++ b/docs/guides/authentication.md @@ -1,4 +1,9 @@ -# Authentication +--- +title: Authentication +description: + How to generate a wpm token, where wpm stores it on disk, and how to manage + multiple registry accounts from a single machine. +--- This page covers everything you need to know about wpm tokens: how to get one, where wpm stores it, and how to manage multiple accounts. @@ -189,6 +194,6 @@ anything, so it's a safe way to confirm that a token works. `logout`. - [`wpm whoami`](../reference/cli/whoami.md): the canonical "am I logged in?" check. -- [Registry concepts](../fundamentals/registry.md): visibility, dist tags, and - what the registry does with your identity. +- [wpm registry](../fundamentals/registry.md): visibility, dist tags, and what + the registry does with your identity. - [CI/CD guide](ci.md): worked examples for running wpm from build pipelines. diff --git a/docs/guides/ci.md b/docs/guides/ci.md index 53cd9e7..f9d4204 100644 --- a/docs/guides/ci.md +++ b/docs/guides/ci.md @@ -1,4 +1,9 @@ -# Running wpm in CI +--- +title: Running wpm in CI +description: + Run wpm in GitHub Actions, GitLab CI, and shell runners with secure token + handling and reproducible installs. +--- This guide covers how to run wpm in continuous integration pipelines: GitHub Actions, GitLab CI, and generic shell-based runners. The patterns apply equally @@ -282,5 +287,5 @@ Before merging your CI configuration, confirm: - [Authentication](authentication.md): the token lifecycle. - [`wpm`](../reference/cli/wpm.md): the full list of global flags and environment variables. -- [Registry concepts](../fundamentals/registry.md): dist tags and visibility - settings used by `wpm publish`. +- [wpm registry](../fundamentals/registry.md): dist tags and visibility settings + used by `wpm publish`. diff --git a/docs/guides/dependency-management.md b/docs/guides/dependency-management.md index 4778160..00473b0 100644 --- a/docs/guides/dependency-management.md +++ b/docs/guides/dependency-management.md @@ -1,4 +1,9 @@ -# Managing dependencies +--- +title: Managing dependencies +description: + Add, remove, update, and inspect dependencies in your wpm project using the + commands you'll use most often. +--- This guide covers the day-to-day work of adding, removing, updating, and inspecting your project's dependencies. diff --git a/docs/guides/publishing.md b/docs/guides/publishing.md index 0faa5ef..e96c1ff 100644 --- a/docs/guides/publishing.md +++ b/docs/guides/publishing.md @@ -1,4 +1,9 @@ -# Publishing packages +--- +title: Publishing +description: + Publish WordPress plugins, themes, and mu-plugins with wpm, including + versioning, dist tags, visibility, and unpublishing. +--- This guide covers everything from your first release to taking one back: version numbers, dist tags, visibility, and the release lifecycle. @@ -142,7 +147,7 @@ publish a new version with the new `--access` value; there is no separate > `--access private` is not the same as `"private": true` in > `wpm.json`. The flag sets the registry's visibility. The manifest flag > prevents publishing entirely. See -> [Registry concepts](../fundamentals/registry.md#private-true-is-not-the-same-as---access-private). +> [wpm registry](../fundamentals/registry.md#private-true-is-not-the-same-as---access-private). ## Republishing the same version @@ -223,7 +228,7 @@ $ wpm publish # Goes to latest - [`wpm publish`](../reference/cli/publish.md): every flag, with troubleshooting. -- [Registry concepts](../fundamentals/registry.md): tags, visibility, and the +- [wpm registry](../fundamentals/registry.md): tags, visibility, and the difference between `private: true` and `--access private`. - [Authentication](authentication.md): tokens and CI patterns. - [`.wpmignore`](../fundamentals/wpmignore.md): syntax for the exclusion file. diff --git a/docs/guides/runtime-compatibility.md b/docs/guides/runtime-compatibility.md index 63fd81f..28afdca 100644 --- a/docs/guides/runtime-compatibility.md +++ b/docs/guides/runtime-compatibility.md @@ -1,4 +1,9 @@ -# Enforcing runtime compatibility +--- +title: Strict runtime mode +description: + Turn on strict runtime mode so wpm verifies that your dependencies work with + the WordPress and PHP versions you target. +--- By default, wpm doesn't check whether your dependencies are compatible with the WordPress and PHP versions you're running. **Strict runtime mode** turns that diff --git a/docs/reference/cli/publish.md b/docs/reference/cli/publish.md index 725ca47..7e917ff 100644 --- a/docs/reference/cli/publish.md +++ b/docs/reference/cli/publish.md @@ -95,7 +95,7 @@ or leave it at `private` for organization-only releases. Any value other than > `--access private` is not the same as `"private": true` in > `wpm.json`. `--access private` publishes the package with private visibility > on the registry. `"private": true` blocks publishing entirely. See -> [Registry concepts](../../fundamentals/registry.md) for the full distinction. +> [wpm registry](../../fundamentals/registry.md) for the full distinction. ### Republishing a version diff --git a/docs/reference/glossary.md b/docs/reference/glossary.md index f7bd342..ff9b678 100644 --- a/docs/reference/glossary.md +++ b/docs/reference/glossary.md @@ -1,4 +1,9 @@ -# Glossary +--- +title: Glossary +description: + Look up the terms that appear across the wpm docs, defined in plain English + and listed alphabetically. +--- Terms that appear across the wpm docs. Listed alphabetically. @@ -8,7 +13,7 @@ The visibility a package has on the registry. Set with `wpm publish --access `. A `public` package is visible to everyone the registry serves; a `private` package is visible only to authorized accounts. Distinct from `"private": true` in `wpm.json`, which prevents -publishing entirely. See [Registry concepts](../fundamentals/registry.md). +publishing entirely. See [wpm registry](../fundamentals/registry.md). ## Auth token @@ -57,7 +62,7 @@ canonical tag is `latest`, which marks the version new consumers should pick up. Maintainers can create others (`beta`, `next`, `lts`) to publish pre-releases without disturbing `latest`. Set with `wpm publish --tag `; selected at install time with `wpm install pkg@`. See -[Registry concepts](../fundamentals/registry.md). +[wpm registry](../fundamentals/registry.md). ## Lockfile @@ -122,13 +127,13 @@ Two distinct meanings, distinguished by context: - `--access private` on `wpm publish` publishes the package with private visibility on the registry. -See [Registry concepts](../fundamentals/registry.md). +See [wpm registry](../fundamentals/registry.md). ## Registry The server wpm talks to. Hosts published packages, dist tags, manifests, and tarballs. Default `registry.wpm.so`. Switch with `--registry `. See -[Registry concepts](../fundamentals/registry.md). +[wpm registry](../fundamentals/registry.md). ## Resolution From a638bf47caced787de353b482c24c85a5f148ef8 Mon Sep 17 00:00:00 2001 From: thelovekesh Date: Sun, 24 May 2026 01:54:52 +0530 Subject: [PATCH 2/3] Fix docs path --- docs/reference/cli/init.md | 2 +- docs/reference/cli/publish.md | 2 +- docs/reference/cli/wpm.md | 24 ++++++++++++------------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/reference/cli/init.md b/docs/reference/cli/init.md index aa97d6d..5be0c2a 100644 --- a/docs/reference/cli/init.md +++ b/docs/reference/cli/init.md @@ -126,7 +126,7 @@ errors. Pass `--version` to recover. Both modes validate `name`, `version`, `type`, and `license` before writing `wpm.json`. The full schema and its rules live in -[`wpm.json` reference](../../fundamentals/wpm-json.md). +[`wpm.json` reference](/fundamentals/wpm-json). ### Troubleshooting diff --git a/docs/reference/cli/publish.md b/docs/reference/cli/publish.md index 7e917ff..7b96574 100644 --- a/docs/reference/cli/publish.md +++ b/docs/reference/cli/publish.md @@ -95,7 +95,7 @@ or leave it at `private` for organization-only releases. Any value other than > `--access private` is not the same as `"private": true` in > `wpm.json`. `--access private` publishes the package with private visibility > on the registry. `"private": true` blocks publishing entirely. See -> [wpm registry](../../fundamentals/registry.md) for the full distinction. +> [wpm registry](/fundamentals/registry) for the full distinction. ### Republishing a version diff --git a/docs/reference/cli/wpm.md b/docs/reference/cli/wpm.md index dd7da37..a08210f 100644 --- a/docs/reference/cli/wpm.md +++ b/docs/reference/cli/wpm.md @@ -137,17 +137,17 @@ when the first signal is caught and graceful shutdown is taking too long. ### Where to go next -- New to wpm? Start with the - [getting started](../../getting-started/first-project.md) walkthrough. -- Releasing a package? See the [publishing guide](../../guides/publishing.md). -- Setting up CI? See the [CI/CD guide](../../guides/ci.md). -- File-format references: [`wpm.json`](../../fundamentals/wpm-json.md), - [`wpm.lock`](../../fundamentals/wpm-lock.md), and - [`.wpmignore`](../../fundamentals/wpmignore.md). -- Concept references: [authentication](../../guides/authentication.md), - [package types](../../fundamentals/package-types.md), and - [registry concepts](../../fundamentals/registry.md). -- Looking up a term? See the [glossary](../glossary.md). +- New to wpm? Start with the [getting started](/getting-started/first-project) + walkthrough. +- Releasing a package? See the [publishing guide](/guides/publishing). +- Setting up CI? See the [CI/CD guide](/guides/ci). +- File-format references: [`wpm.json`](/fundamentals/wpm-json), + [`wpm.lock`](/fundamentals/wpm-lock), and + [`.wpmignore`](/fundamentals/wpmignore). +- Concept references: [authentication](/guides/authentication), + [package types](/fundamentals/package-types), and + [registry concepts](/fundamentals/registry). +- Looking up a term? See the [glossary](/reference/glossary). ## Examples @@ -189,4 +189,4 @@ $ CI=true NO_COLOR=1 wpm install ### First five minutes with wpm For a full walkthrough from scaffold to first publish, see -[Getting started](../../getting-started/first-project.md). +[Getting started](/getting-started/first-project). From c256df9c3e064503aebdb319f48c0ccd51bba0f7 Mon Sep 17 00:00:00 2001 From: thelovekesh Date: Sun, 24 May 2026 02:26:29 +0530 Subject: [PATCH 3/3] Remove docs from this remove and move to trywpm/docs repo --- docs/fundamentals/dependencies.md | 175 ---------------- docs/fundamentals/package-types.md | 131 ------------ docs/fundamentals/registry.md | 154 -------------- docs/fundamentals/runtime.md | 173 --------------- docs/fundamentals/wpm-json.md | 166 --------------- docs/fundamentals/wpm-lock.md | 157 -------------- docs/fundamentals/wpmignore.md | 138 ------------ docs/getting-started/first-project.md | 206 ------------------ docs/getting-started/installation.md | 243 --------------------- docs/getting-started/overview.md | 119 ----------- docs/getting-started/why-wpm.md | 189 ----------------- docs/guides/authentication.md | 199 ------------------ docs/guides/ci.md | 291 -------------------------- docs/guides/dependency-management.md | 150 ------------- docs/guides/publishing.md | 235 --------------------- docs/guides/runtime-compatibility.md | 99 --------- docs/reference/glossary.md | 199 ------------------ 17 files changed, 3024 deletions(-) delete mode 100644 docs/fundamentals/dependencies.md delete mode 100644 docs/fundamentals/package-types.md delete mode 100644 docs/fundamentals/registry.md delete mode 100644 docs/fundamentals/runtime.md delete mode 100644 docs/fundamentals/wpm-json.md delete mode 100644 docs/fundamentals/wpm-lock.md delete mode 100644 docs/fundamentals/wpmignore.md delete mode 100644 docs/getting-started/first-project.md delete mode 100644 docs/getting-started/installation.md delete mode 100644 docs/getting-started/overview.md delete mode 100644 docs/getting-started/why-wpm.md delete mode 100644 docs/guides/authentication.md delete mode 100644 docs/guides/ci.md delete mode 100644 docs/guides/dependency-management.md delete mode 100644 docs/guides/publishing.md delete mode 100644 docs/guides/runtime-compatibility.md delete mode 100644 docs/reference/glossary.md diff --git a/docs/fundamentals/dependencies.md b/docs/fundamentals/dependencies.md deleted file mode 100644 index 7770238..0000000 --- a/docs/fundamentals/dependencies.md +++ /dev/null @@ -1,175 +0,0 @@ ---- -title: Dependencies -description: - How wpm manages dependencies in `wpm.json`, resolves version conflicts, and - creates reproducible installs for WordPress plugins and themes. ---- - -`dependencies` and `devDependencies` are the two dependency maps in `wpm.json`. -They tell wpm which packages to install, at which versions, and in which role -(production or development). - -## Shape - -Both fields are JSON objects whose keys are package names and whose values are -version specifiers. They are completely independent maps, not arrays. - -```json -{ - "dependencies": { - "akismet": "5.3.1", - "hello-dolly": "*" - }, - "devDependencies": { - "query-monitor": "3.20.2" - } -} -``` - -A package lives in one map or the other, never both. When `wpm install` moves a -package, the old entry goes away. - -## Allowed values - -| Form | Meaning | -| :-------- | :--------------------------------------------------------------------------------------- | -| `"X.Y.Z"` | A strict SemVer version. wpm fetches exactly this build. | -| `"*"` | Any version. wpm resolves it to whatever the registry returns for the `latest` dist tag. | - -That's it. The dependency value does not accept SemVer ranges, carets, or -tildes. This is a deliberate design choice, not a limitation we plan to remove. - - -> [!IMPORTANT] -> WordPress plugins and themes are not pure libraries. They can -> change database schema, write options, register cron jobs, and modify content. -> A solver cannot tell whether a "compatible" upgrade is safe for _your_ site, -> because that answer depends on runtime state the solver cannot see. You are -> the only one who can make that call. - -So wpm doesn't let the resolver decide for you. You choose every version -deliberately. Every install reproduces the exact tree you last committed. - -A few consequences: - -- The version saved in `wpm.json` is the version the registry returned, not the - one you typed. Ask for `akismet@latest`, the registry returns `5.3.1`, and - `wpm.json` records `"akismet": "5.3.1"`. -- Ranges are reserved for `requires.wp` and `requires.php` (which describe what - your package needs from WordPress and PHP), not for picking dependencies. See - [Runtime compatibility](runtime.md). -- Before you deploy to a live site, run `wpm ls` to see the exact versions - you're about to ship. No surprises hit production. - -If you want "newest in 1.x" behavior, run `wpm install pkg@latest` whenever you -want to refresh. The trigger is always explicit, and the new version becomes a -clear change in your commit history. - -## Production vs development - -`dependencies` are installed every time. `devDependencies` are installed by -default but skipped (and pruned from disk) when `wpm install --no-dev` is used. -The typical mapping: - -| Map | Examples | -| :---------------- | :--------------------------------------------------------------------------------------- | -| `dependencies` | Packages your code requires at runtime: integrations, sibling plugins you depend on. | -| `devDependencies` | Packages used only during development: debugging tools, code quality tools, sample data. | - -If you move a package from `dependencies` to `devDependencies`, the next -`wpm install --no-dev` will delete it from `wp-content/`. - -## How entries are added - -You rarely edit these maps by hand. `wpm install` writes them for you. The -placement rules: - -| Command | Where the entry lands | -| :------------------------------------- | :------------------------------------------------------------------------------------ | -| `wpm install ` | Stays in `devDependencies` if it was already there; otherwise goes to `dependencies`. | -| `wpm install -P ` (`--save-prod`) | `dependencies`. Removed from `devDependencies` if present. | -| `wpm install -D ` (`--save-dev`) | `devDependencies`. Removed from `dependencies` if present. | - -wpm writes the resolved version, not the one you typed. So -`wpm install akismet@latest` ends up as `"akismet": "5.3.1"` (or whatever the -registry returns). That's what keeps installs identical across machines. - -## How entries are removed - -`wpm uninstall ` deletes the entry from both maps (whichever one has it) -and rewrites `wpm.json`. The same call also reconciles the lockfile and the -filesystem, removing anything no longer reachable from the root. - -If you want to remove a package from `wpm.json` but keep the extracted files on -disk, edit the file directly and skip running install. `wpm install` will -reconcile the disk on its next run, so that state is temporary. - -## Limits when you publish - -The dependency maps have a hard cap of **16 entries each** when wpm validates -your package for publishing. That cap doesn't apply to local WordPress projects. -It only kicks in for packages headed to the registry. - -The reason: a reusable plugin or theme that declares more than 16 direct -dependencies is almost always doing something it shouldn't. The limit is a -guardrail to keep distributable packages small and focused. - -If you hit it while preparing to publish: - -- Look for accidental duplicates or per-environment packages that don't need to - ship. -- Check whether some entries are actually transitive and don't need to be listed - directly. -- If you still need more, your package is probably better split into smaller - pieces with their own manifests. - -Local WordPress projects can declare as many dependencies as they need. -`wpm install` doesn't check the count. - -## Versions, tags, and the resolver - -`wpm install pkg@` parses the part after `@` in this order: - -1. **A valid SemVer** (`X.Y.Z`, no `v` prefix). wpm uses it directly as a - version request. - -2. **A dist tag**. Same character rules as a package name, up to 64 characters. - The registry resolves it to a specific version. - -3. **Anything else** is rejected. - -Either way, `wpm.json` ends up with a concrete version, not the tag. To switch -versions later, run `wpm install pkg@` again. - -When two parts of the dependency tree disagree about a version, `wpm install` -runs conflict resolution. The summary: - -- **Your `dependencies` entry wins** over transitive requests, as long as it - satisfies them. -- **Strictly lower** root pins than a transitive needs produce a "version - downgrade" error. Bump your pin. -- **No root pin** plus disagreeing transitives produces an "unresolvable - conflict" error. Add an explicit entry to `dependencies` to break the tie. - -See the [`wpm install`](../reference/cli/install.md) reference for the full -output format. - -## Sharing across the tree - -wpm keeps one copy of each package per project, shared across everything that -depends on it. Two packages that need the same library end up using the same -copy on disk; there is no per-dependency private copy. - -The shared copy is whichever version the resolver settled on: your root pin if -any, otherwise the version the resolver visited first. This is why the resolver -is strict about conflicts; there is no fallback to a package-specific copy. - -## Related - -- [`wpm install`](../reference/cli/install.md): the command that reads and - writes the maps. -- [`wpm uninstall`](../reference/cli/uninstall.md): removes entries and - reconciles disk. -- [`wpm.lock`](wpm-lock.md): the resolved snapshot. -- [Runtime compatibility](runtime.md): for `requires` constraints, which are - different from dependency specifiers. diff --git a/docs/fundamentals/package-types.md b/docs/fundamentals/package-types.md deleted file mode 100644 index e2f53b0..0000000 --- a/docs/fundamentals/package-types.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: Package types -description: - The `plugin`, `theme`, and `mu-plugin` package types in wpm, how each maps to - a WordPress directory, and when to use each one. ---- - -Every wpm package has a `type` field. It tells wpm how to install the package, -and it tells WordPress how to load it. Three values are supported: - -| Type | WordPress directory | Loaded by WordPress | -| :---------- | :----------------------- | :---------------------------------------------------------------- | -| `plugin` | `wp-content/plugins/` | Only when activated. | -| `theme` | `wp-content/themes/` | Only when set as the active theme (or as a child theme's parent). | -| `mu-plugin` | `wp-content/mu-plugins/` | Always, automatically, on every request. | - -The `type` field is required. There is no automatic fallback if you omit it. - -## `plugin` - -A standard WordPress plugin. Lives in `wp-content/plugins//` and is loaded -by WordPress when an administrator activates it. Plugins are the right choice -for most things you'd publish: an integration with an external service, a -feature you want administrators to opt into, an admin UI addition. - -A `plugin` package usually has a "main plugin file" with standard plugin headers -(`Plugin Name:`, `Version:`, `Description:`, and so on). `wpm init --existing` -looks for this file automatically. - -## `theme` - -A WordPress theme. Lives in `wp-content/themes//` and is loaded only when -an administrator selects it as the active theme. Themes are detected by the -presence of `style.css` at the project root; the headers in that file -(`Theme Name:`, `Version:`, `Author:`, `Theme URI:`, and so on) carry the -theme's metadata. - -Use this type for visual templates, child themes, and block themes. - -## `mu-plugin` - -A "must-use" plugin. Lives in `wp-content/mu-plugins//` and is loaded by -WordPress on every request, before any regular plugin. You cannot deactivate an -mu-plugin from the admin UI; the only way to disable it is to remove its files. - -Use this type sparingly. Common cases: - -- Hosting-side modifications that must always be present. -- Bootstrapping code that other plugins depend on. -- Internal customizations that should never be deactivated. - -If you're not sure whether you need a `plugin` or an `mu-plugin`, start with a -`plugin`. mu-plugins have no off-switch in the admin UI, so removing them later -means deleting the files directly. - -## How wpm chooses where to extract - -When `wpm install` extracts a dependency, it reads the `type` from that -dependency's manifest and picks the matching subdirectory inside your project's -content directory (default `wp-content/`): - -| Dependency `type` | Extracted into | -| :---------------- | :------------------------------ | -| `plugin` | `wp-content/plugins//` | -| `theme` | `wp-content/themes//` | -| `mu-plugin` | `wp-content/mu-plugins//` | - -wpm uses each dependency's _own_ type to pick the path, not your project's type. -A theme can depend on a plugin; that plugin still extracts into -`wp-content/plugins/`. - -You can change the content directory itself with `config.content-dir` in -`wpm.json`. The subdirectory choice (`plugins/`, `themes/`, `mu-plugins/`) is -hard-coded and matches WordPress's expectations. - -## How `wpm init --existing` detects the type - -When you adopt wpm in an existing project, the detection runs on your file tree: - -1. If `style.css` exists at the project root, the type is `theme`. -2. Otherwise the type is `plugin`. - -There is no automatic detection for `mu-plugin`. If you're adopting wpm for an -existing must-use plugin, override the detection explicitly: - -```console -$ wpm init --existing --type mu-plugin -``` - -The override applies to both the type field in `wpm.json` and the header parsing -rules wpm uses. - -## Choosing a type for a new project - -| You're building... | Use | -| :------------------------------------------------ | :----------------------------------------- | -| Most reusable, opt-in functionality | `plugin` | -| A visual template or block theme | `theme` | -| A child theme of an existing theme | `theme` | -| Hosting-baked customizations that must always run | `mu-plugin` | -| Code that bootstraps other plugins | `mu-plugin` | -| A library that has no WordPress entry points | (Not a fit; wpm is for WordPress packages) | - -When in doubt, start with `plugin`. You can publish a new version with a -different `type` later, but anyone who installed the old type keeps it until -they re-install. - -## Naming conventions - -Package names follow the same rules regardless of type: 3 to 164 lowercase -characters, hyphens allowed, no underscores or uppercase letters (see the -[`wpm.json` reference](wpm-json.md) for the full regex). A few practical -conventions: - -- Plugins are usually named after what they do (`woocommerce-stripe-gateway`, - `query-monitor`, `redirection`). -- Themes are usually named with the theme's display name in hyphen-case - (`twenty-twenty-four`, `astra`, `divi`). -- Must-use plugins often carry a host or org prefix to make their ownership - obvious (`acme-hosting-cache`, `acme-saml-auth`). - -The registry doesn't enforce these patterns, but consistent naming makes search -and discovery work better. - -## Related - -- [`wpm.json` reference](wpm-json.md): the schema where `type` is declared. -- [`wpm init`](../reference/cli/init.md): the detection logic for existing - projects. -- [`wpm install`](../reference/cli/install.md): how the extracted path is - computed at install time. diff --git a/docs/fundamentals/registry.md b/docs/fundamentals/registry.md deleted file mode 100644 index dffca89..0000000 --- a/docs/fundamentals/registry.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -title: wpm registry -description: - How the wpm registry stores package manifests, manages dist tags and - visibility, and distributes WordPress plugins and themes. ---- - -The wpm registry is the server that hosts published packages and serves them to -`wpm install`. By default wpm talks to `registry.wpm.so`. You can point it at a -different deployment with the global `--registry` flag. - -This page covers the registry concepts you'll run into: dist tags, package -visibility, and the tricky difference between "don't publish this" and "publish -this privately." - -## The default registry - -Out of the box, every wpm command uses `registry.wpm.so`. Override it on a -per-invocation basis with `--registry`: - -```console -$ wpm --registry registry.staging.wpm.so install -``` - -`--registry` is a global flag, so it must appear before the subcommand name. -There's no environment variable for it today. To set a different default across -all invocations, use a shell alias. - -## Dist tags - -A **dist tag** is a friendly label that points at a specific version. The -default tag is `latest`, which marks the version that new consumers should pick -up. Maintainers can create extra tags like `next`, `beta`, or `lts` to ship -pre-releases or parallel release lines without moving `latest`. - -You set the tag with `--tag` at publish time: - -```console -$ wpm publish --tag beta -``` - -Consumers select a tag by appending `@` to a package specifier just like a -version: - -```console -$ wpm install akismet@latest -$ wpm install akismet@beta -``` - -A few important details: - -- `--tag` defaults to `latest`. Publishing with no `--tag` updates `latest` to - point at your new release. -- Once `wpm install` resolves a tag, the resulting `wpm.json` and `wpm.lock` - record the concrete version, not the tag. The next install will use the - version, not chase the tag. To follow a tag, re-run install with the `@` - specifier. -- `wpm outdated` always checks against `latest`. Pre-release tags (`beta`, `rc`, - and so on) won't surface as updates. -- Tag names follow the package name rules (lowercase, hyphens, no whitespace), - with an upper bound of 64 characters. - -## Package visibility - -Every published package has a **visibility** setting on the registry. It is set -at publish time: - -```console -$ wpm publish --access public -$ wpm publish --access private -``` - -The two valid values are `public` and `private`. The default is `private`. Any -other value is rejected. - -- **`public`** packages are visible to everyone the registry serves. -- **`private`** packages are only visible to authorized accounts (typically - members of the publishing organization). - -Visibility is metadata on the published manifest. Changing it requires -publishing a new version with the desired `--access` value. - -### `private: true` is not the same as `--access private` - - -> [!IMPORTANT] -> These two settings share a word but produce opposite outcomes. -> The table below makes the distinction explicit. - -| Setting | Lives in | Effect | -| :----------------- | :----------------- | :------------------------------------------------------------------------------------------------------ | -| `"private": true` | `wpm.json` | `wpm publish` refuses to upload the package at all. A tripwire on internal-only projects. | -| `--access private` | `wpm publish` flag | Publish proceeds, and the registry stores the release with private visibility (the default if not set). | - -If your project should never reach a registry, set `"private": true` in -`wpm.json`. If your project should be on the registry but only visible to your -organization, leave that out and publish with `--access private`. Trying to -publish a `"private": true` package fails with: - -``` -package marked as private cannot be published -``` - -There is no way to unset `private` from the command line: edit `wpm.json` to -remove the flag. - -## Manifests on the registry - -When you publish, wpm uploads two things together: - -- A JSON **manifest** describing the release: name, version, type, `requires`, - `dependencies`, `devDependencies`, tag, visibility, the SHA-256 digest of the - tarball, and a few size counters. -- The **tarball** itself, a Zstandard-compressed tar archive built from your - working directory (minus what `.wpmignore` excludes). - -`wpm install` reads the manifest during resolution and uses it to fill out each -entry in `wpm.lock`. wpm fetches the tarball separately, only when it needs to -extract the package. - -The 128 MiB cap on the packed tarball and the 50 KiB cap on the attached -`readme.md` are enforced client-side, before anything is uploaded. - -## Self-hosted and staging registries - -The wpm client treats the registry as a plain HTTP endpoint, so any deployment -that speaks the same API works. Common use cases: - -- A staging deployment for testing changes against real packages without - affecting the production registry. -- An internal mirror for organizations that prefer to host their own packages. - -Switch by passing `--registry `. Your token is tied to whichever registry -was active when you logged in. Logging in against a different registry -overwrites the existing token, unless you use a separate config directory: - -```console -$ wpm --config ~/.wpm-staging --registry registry.staging.wpm.so auth login -$ wpm --config ~/.wpm-prod --registry registry.wpm.so auth login -``` - -After that, any command run with `--config ~/.wpm-staging` targets the staging -registry, and any command with `--config ~/.wpm-prod` targets production. - -## Related - -- [`wpm auth`](../reference/cli/auth.md): how credentials are obtained and - stored. -- [`wpm publish`](../reference/cli/publish.md): the command that uploads new - versions and sets the dist tag and visibility. -- [`wpm install`](../reference/cli/install.md): the command that reads manifests - and downloads tarballs. -- [`wpm.json`](wpm-json.md): the `private` flag, distinct from registry - visibility. diff --git a/docs/fundamentals/runtime.md b/docs/fundamentals/runtime.md deleted file mode 100644 index 91ed7b4..0000000 --- a/docs/fundamentals/runtime.md +++ /dev/null @@ -1,173 +0,0 @@ ---- -title: Runtime compatibility -description: - How `requires` and `config.runtime` define WordPress and PHP compatibility, - what your package supports and what you develop against. ---- - -`wpm.json` has two fields that talk about WordPress and PHP versions: - -- **`requires`**: what your package needs from WordPress and PHP. "I need at - least WordPress 6.0." -- **`config.runtime`**: what you're testing your package against. "I'm - developing this on WordPress 6.9 and PHP 8.2." - -They look similar but answer different questions. Here's the distinction at a -glance: - -| Field | Lives in | Answers... | Format | -| :--------------- | :--------- | :------------------------------------------ | :----------------------- | -| `requires` | `wpm.json` | "What does my package need from the host?" | SemVer constraint string | -| `config.runtime` | `wpm.json` | "What am I developing and testing against?" | Concrete SemVer version | - -The rest of this page covers each field in detail and how they cooperate during -`wpm install`. - -## `requires`: what your package needs - -`requires.wp` and `requires.php` are SemVer constraint strings. Every package on -the registry has them, so consumers can see what hosts you support. - -```json -{ - "requires": { - "wp": ">=6.0", - "php": ">=7.4 <8.4" - } -} -``` - -Examples of valid constraint strings: - -| Constraint | Matches | -| :----------- | :---------------------------------------------- | -| `>=6.0` | WordPress 6.0 and anything newer. | -| `>=6.0 <7.0` | WordPress 6.0 through 6.x. | -| `^6.4` | WordPress 6.4 through 6.x (caret = same major). | -| `~6.4` | WordPress 6.4.x only (tilde = same minor). | -| `*` | Any version. Same as omitting the field. | - -Leave a constraint empty to mean "no opinion." That's the default when -`wpm init --existing` can't read it from your plugin or theme headers. - -The `requires` block is informational by default. wpm doesn't check it against -your project unless you opt in (see below). - -## `config.runtime`: what you target - -`config.runtime` is your project's declared host environment: - -```json -{ - "config": { - "runtime": { - "wp": "6.9", - "php": "8.2" - } - } -} -``` - -The values are concrete version strings, not constraints. They are specific -versions you've tested with. - -As soon as you set `runtime.wp` or `runtime.php`, wpm starts checking each -dependency's compatibility during install. This is **strict runtime mode**. -Here's how it works: - -- If `requires.wp` is set on a dependency and your `runtime.wp` does not satisfy - it, install fails with a message like: - - ``` - package akismet@5.3.1 incompatible: - requires WordPress >=6.5, but runtime WordPress version is 6.4 - ``` - -- If `requires.php` is set and your `runtime.php` does not satisfy it, install - fails with the same shape of error. - -- If a dependency has no `requires` field, or that field is empty, the check - passes silently. - -Without `config.runtime`, wpm skips the check entirely. Installs go through -without testing compatibility. - -## How they interact - -A worked example. You're building `my-plugin`. You target WordPress 6.9 and PHP -8.2: - -```json -{ - "name": "my-plugin", - "version": "1.0.0", - "type": "plugin", - "requires": { - "wp": ">=6.0", - "php": ">=7.4" - }, - "dependencies": { - "akismet": "5.3.1" - }, - "config": { - "runtime": { - "wp": "6.9", - "php": "8.2" - } - } -} -``` - -Two things are happening here: - -- **For consumers**: anyone who installs `my-plugin` as a dependency sees your - `requires`. If they have strict mode on, their install fails when their host - doesn't meet it. - -- **For you**: every dependency's `requires` is checked against your - `config.runtime` (6.9 / 8.2) during install. For `akismet@5.3.1`: - - If it declares `requires.wp: ">=6.5"`, the check passes. Your 6.9 satisfies - it. - - If it declares `requires.php: ">=8.3"`, install fails. Your 8.2 doesn't - satisfy it. - -## When to opt in to strict mode - -Set `config.runtime` when: - -- You want CI to catch dependencies that quietly bumped their minimum WordPress - or PHP version. -- You're testing your plugin against a specific WordPress and PHP matrix and - want installs to fail fast on incompatible dependencies. -- You're locking down a long-term-support branch and want to be sure nothing in - the tree drifts past your supported versions. - -Leave it unset when: - -- You're experimenting and want installs to succeed even if some dependencies - declare conservative `requires`. -- Your project is a library that targets a broad range and you rely on the - registry to surface compatibility issues separately. - -You can toggle strict mode by adding or removing the runtime block; no other -configuration changes are needed. - -## Troubleshooting - -- `package @ incompatible: requires , but runtime version is `: - a dependency in your tree declares a runtime requirement your `config.runtime` - does not meet. Either bump your runtime, swap the dependency for a version - that supports your target, or remove the runtime block to opt out of the - check. -- `invalid requirement in package `: the package's `requires.` - is not a valid SemVer constraint. This is a bug in the dependency's manifest; - report it to the maintainer. -- `invalid runtime version provided`: `config.runtime.` is not a - SemVer version. Fix the value in your `wpm.json`. - -## Related - -- [`wpm.json` reference](wpm-json.md): the full schema and all field rules. -- [`wpm install`](../reference/cli/install.md): where the strict check runs. -- [Dependencies](dependencies.md): the difference between dependency specifiers - (no ranges) and `requires` constraints (ranges allowed). diff --git a/docs/fundamentals/wpm-json.md b/docs/fundamentals/wpm-json.md deleted file mode 100644 index 376bf25..0000000 --- a/docs/fundamentals/wpm-json.md +++ /dev/null @@ -1,166 +0,0 @@ ---- -title: wpm.json -description: - The full reference for the `wpm.json` manifest, covering required fields, - optional metadata, dependency maps, and runtime configuration. ---- - -`wpm.json` is the manifest at the root of every wpm package. It declares what -the package is, what it depends on, and which versions of WordPress and PHP it -targets. Every wpm command that touches the current project reads this file. - -## A minimal manifest - -The three required fields are `name`, `version`, and `type`. Everything else is -optional. - -```json -{ - "name": "my-awesome-plugin", - "version": "1.0.0", - "type": "plugin" -} -``` - -## A complete example - -The following manifest exercises every field. Use it as a reference when you're -not sure what a section looks like. - -```json -{ - "name": "my-awesome-plugin", - "description": "Doing awesome things since 1066.", - "type": "plugin", - "version": "1.0.0", - "private": false, - "license": "GPL-2.0-or-later", - "homepage": "https://example.com/my-awesome-plugin", - "tags": ["seo", "performance"], - "team": ["alice", "bob"], - "requires": { - "wp": ">=6.0", - "php": ">=7.4" - }, - "dependencies": { - "akismet": "5.3.1", - "hello-dolly": "*" - }, - "devDependencies": { - "query-monitor": "3.20.2" - }, - "config": { - "bin-dir": "wp-bin", - "content-dir": "wp-content", - "runtime": { - "wp": "6.9", - "php": "8.2" - } - } -} -``` - -## Field reference - -### Required fields - -| Field | Type | Rules | -| :-------- | :----- | :------------------------------------------------------------------------------------ | -| `name` | string | 3 to 164 characters; lowercase alphanumeric and hyphens (`^[a-z0-9]+(-[a-z0-9]+)*$`). | -| `version` | string | Strict SemVer `X.Y.Z`; 5 to 64 characters; no `v` prefix. | -| `type` | string | One of `plugin`, `theme`, or `mu-plugin`. | - -wpm rejects the entire manifest if any required field is missing or invalid. -`wpm publish` always validates first. Commands that change the file -(`wpm install`, `wpm uninstall`) validate the new version before saving it. - -### Optional metadata - -| Field | Type | Rules | -| :------------ | :------- | :----------------------------------------------------------------------------------------------------- | -| `description` | string | 3 to 512 characters. | -| `private` | boolean | When `true`, `wpm publish` refuses to upload. Use it as a tripwire on internal-only packages. | -| `license` | string | 3 to 100 characters. SPDX-style identifiers like `GPL-2.0-or-later` are conventional but not enforced. | -| `homepage` | string | A `http` or `https` URL, 10 to 200 characters. | -| `tags` | string[] | Up to 5 entries; each 2 to 64 characters; duplicates rejected. | -| `team` | string[] | Up to 100 entries; each 2 to 100 characters; duplicates rejected. | - -`tags` are short keywords the registry uses for search and discovery. Pick words -a consumer would type when looking for your package, like `seo`, `caching`, or -`payments`. Tags are not categories; they're free-form. - -`team` lists the people or organizations responsible for the package, typically -by username or display name. wpm populates this automatically from plugin and -theme headers (`Author`, `Contributors`) when you run `wpm init --existing`. - -wpm rejects ASCII control characters and a few look-alike Unicode code points -(zero-width separators and similar) in `tags`, `team`, `description`, and -`license`. - -### Dependencies - -| Field | Type | Notes | -| :---------------- | :--------------------- | :--------------------------------------------------------------------- | -| `dependencies` | object | Production dependencies. Installed by default. | -| `devDependencies` | object | Development dependencies. Skipped when `wpm install --no-dev` is used. | - -Each key must satisfy the package name rules. Each value must be strict SemVer -or `*`. When you publish a package, wpm caps each map at 16 entries as a -guardrail; local projects have no such cap. See [Dependencies](dependencies.md) -for the full behavior, including the publish-time limit and how `wpm install`, -`wpm uninstall`, and the conflict resolver interact with these maps. - -### Compatibility - -| Field | Type | Notes | -| :--------- | :----- | :--------------------------------------------------------------------------------------- | -| `requires` | object | What your package needs from WordPress and PHP. See [Runtime compatibility](runtime.md). | - -`requires.wp` and `requires.php` are SemVer constraint strings, for example -`>=6.0` or `>=7.4 <8.2`. Leave a field empty to mean "no opinion." - -### Build and runtime configuration - -| Field | Type | Notes | -| :-------- | :--------------------- | :------------------------------------------------------------------------------------------------- | -| `config` | object | Project-relative paths and the runtime you're developing against. | -| `bin` | object | Reserved. Binary linking is declared by some packages but not yet wired into install. | -| `scripts` | object | Reserved. Lifecycle scripts are not yet wired up; `wpm install --ignore-scripts` is a no-op today. | - -The `config` object accepts: - -- `bin-dir` (string, default `wp-bin`): where wpm would place executable links. - Currently informational; binary linking is not yet wired up. Must be a - relative, in-tree path. -- `content-dir` (string, default `wp-content`): where `wpm install` extracts - packages. Must be a relative, in-tree path. -- `runtime` (object): the WordPress and PHP versions your project runs against. - Setting either `runtime.wp` or `runtime.php` turns on a strict compatibility - check during `wpm install`. See [Runtime compatibility](runtime.md). - -## Editing the file by hand - -You can edit `wpm.json` directly. wpm keeps your indentation style (two spaces -by default). Commands that change the file (`wpm install`, `wpm uninstall`) -rewrite it the same way. - -A few things to know: - -- After editing dependency entries by hand, run `wpm install` to bring - `wpm.lock` and `wp-content/` back in sync. -- Validation errors tell you which field broke, by path (for example, `tags[2]` - or `config.content-dir`). -- If another tool writes an invalid manifest, the next wpm command that - validates (like `wpm publish`) will fail with a clear message pointing at the - bad field. - -## Related - -- [Dependencies](dependencies.md): how `dependencies` and `devDependencies` - interact with `wpm install`. -- [Runtime compatibility](runtime.md): when wpm enforces `requires` during - install, and how `config.runtime` participates. -- [`wpm.lock`](wpm-lock.md): the resolved snapshot that pairs with `wpm.json`. -- [`.wpmignore`](wpmignore.md): controls what `wpm publish` packs. -- [wpm registry](registry.md): dist tags, visibility, and the difference between - `private: true` and `--access private`. diff --git a/docs/fundamentals/wpm-lock.md b/docs/fundamentals/wpm-lock.md deleted file mode 100644 index d6f81f8..0000000 --- a/docs/fundamentals/wpm-lock.md +++ /dev/null @@ -1,157 +0,0 @@ ---- -title: wpm.lock -description: - How the `wpm.lock` lockfile captures your resolved dependency tree and keeps - installs reproducible across machines and CI. ---- - -`wpm.lock` records the exact dependency tree your project resolved to. It keeps -installs identical across machines and CI runs. - -The next install reads `wpm.lock` first. If the versions you've asked for still -match what's in the file, wpm skips the registry entirely and uses the lockfile -directly. - - -> [!IMPORTANT] -> Commit `wpm.lock` to version control. Without it, installs are -> not reproducible across machines or CI runs. - -## Lifecycle - -- `wpm install` creates the lockfile on the first run and rewrites it after - every subsequent install. The packages in the file are always sorted - alphabetically. -- `wpm uninstall` rewrites the lockfile to remove anything no longer reachable - from `wpm.json`. -- `wpm ls`, `wpm outdated`, and `wpm why` read the lockfile but do not modify - it. They refuse to run if it is missing. -- `wpm publish` does not read the lockfile. The published tarball is built from - your source tree, not from resolved dependencies. - -The lockfile is the source of truth for what's installed. Every install -reconciles `wp-content/` against it: - -- Delete an extracted plugin or theme by hand, and the next install puts it - back. -- Delete an entry from the lockfile, and the next install treats the package as - new and downloads it again. - -## File format - -`wpm.lock` is a JSON file with two top-level fields: - -```json -{ - "lockfileVersion": 1, - "packages": { - "akismet": { - "version": "5.3.1", - "resolved": "/akismet/5.3.1.tar.zst", - "digest": "sha256:9j6Q7l8s...", - "type": "plugin", - "dependencies": { - "jetpack": "13.0.0" - } - }, - "jetpack": { - "version": "13.0.0", - "resolved": "/jetpack/13.0.0.tar.zst", - "digest": "sha256:1pP4mY7Z...", - "type": "plugin" - } - } -} -``` - -### Top-level fields - -| Field | Type | Notes | -| :---------------- | :-------------------------- | :--------------------------------------------------------- | -| `lockfileVersion` | integer | Current format version. Today this is `1`. | -| `packages` | object | Every package in the resolved tree, keyed by package name. | - -The `packages` map is flat. wpm does not nest dependencies under their parents; -both direct and transitive packages live at the same level. This matches how wpm -extracts them under `wp-content/`. - -### `LockPackage` entries - -Each entry in `packages` has the following shape: - -| Field | Type | Notes | -| :------------- | :--------------------- | :--------------------------------------------------------------------------------- | -| `version` | string | The resolved SemVer (`X.Y.Z`). | -| `resolved` | string | The registry-relative path to the tarball (for example, `/akismet/5.3.1.tar.zst`). | -| `digest` | string | The `sha256:` digest of the tarball, used for integrity verification. | -| `type` | string | One of `plugin`, `theme`, `mu-plugin`. Determines the extraction directory. | -| `bin` | object | Optional. Binary mappings declared by the package. Currently informational. | -| `dependencies` | object | Optional. The package's own direct dependencies, copied from its manifest. | - -Because each entry stores its own dependency list, wpm can rebuild the full -install tree without calling the registry. When `wpm install` finds a matching -version in the lockfile, it reads the dependencies straight from the entry -instead of fetching a fresh manifest. - -## Reproducibility - -Two `wpm install` runs against the same `wpm.json` and `wpm.lock`, on the same -registry, produce the same on-disk state. Concretely: - -- The package versions on disk match the `version` field of every lockfile - entry. -- The tarballs on disk hash to the `digest` field. Mismatches cause the affected - package to be re-extracted. -- Adding or removing entries from `wpm.json` is the only way to change the - resolved tree. The lockfile passively records what happened; it does not - impose its own preferences. - -This is why CI builds should always run `wpm install` against a committed -`wpm.lock`: it lets the install step skip resolution entirely when nothing has -changed. - -## Forward-compatibility - -wpm refuses to load a lockfile whose `lockfileVersion` is newer than the version -it understands. The error reads: - -``` -wpm upgrade required: lockfile version is newer than this version of wpm -``` - -When you see this, upgrade wpm. A teammate's newer wpm wrote the lockfile. If -you run with the older version, you'll lose fields the older format doesn't -understand. - -## Hand-editing - - -> [!CAUTION] -> Never edit `wpm.lock` by hand in normal use. Use `wpm install` to -> regenerate it from `wpm.json`. Direct edits can desync the lockfile from -> what's actually on disk and produce hard-to-diagnose install failures. - -If you've gotten into a state where you think you need to: - -- To reset the lockfile, delete it and run `wpm install`. wpm will rebuild it - from scratch using `wpm.json` and the registry. -- To force a re-extraction of a package, delete its directory under - `wp-content/`. The next `wpm install` will reinstall it because the lockfile - entry no longer matches what's on disk. -- To change a resolved version, edit `wpm.json` (not the lockfile) and re-run - `wpm install`. The resolver picks up the new request and rewrites the lockfile - accordingly. - -If you do edit the file directly, take care to keep `lockfileVersion` at the -supported value and to preserve the required fields on every entry. Invalid -package names in the `packages` map are rejected on load. - -## Related - -- [`wpm.json`](wpm-json.md): the request that the lockfile records the answer - to. -- [Dependencies](dependencies.md): how the request is expressed. -- [`wpm install`](../reference/cli/install.md): the command that writes the - lockfile. -- [`wpm ls`](../reference/cli/ls.md) and [`wpm why`](../reference/cli/why.md): - the two read-only commands that work from the lockfile. diff --git a/docs/fundamentals/wpmignore.md b/docs/fundamentals/wpmignore.md deleted file mode 100644 index 06b937c..0000000 --- a/docs/fundamentals/wpmignore.md +++ /dev/null @@ -1,138 +0,0 @@ ---- -title: .wpmignore -description: - How `.wpmignore` controls which files ship with `wpm publish`, using the same - syntax you already know from `.gitignore`. ---- - -`.wpmignore` is an optional file at the root of your project. It tells -`wpm publish` which paths to exclude from the tarball that gets uploaded to the -registry. Without it, every file in the project directory is packed. - -The syntax is the same as `.gitignore`. If you've used `.gitignore`, you already -know how to write a `.wpmignore`. - -## A small example - -```gitignore -# Build artifacts -dist/ -node_modules/ - -# Anything that came out of your editor -.idea/ -.vscode/ -*.swp - -# Files for local development only -.env -.env.local -docker-compose.override.yml - -# wpm's own bookkeeping -wpm.lock - -# Tests don't belong in a published package -tests/ -phpunit.xml -*.test.php -``` - -The intent is to ship only the runtime code, assets, and the readme. Everything -else stays out. - -## Pattern syntax - -The patterns follow gitignore semantics. The most useful subset: - -| Pattern | Matches | -| :--------------- | :-------------------------------------------------------------------------------------- | -| `name` | A file or directory called `name` anywhere in the tree. | -| `name/` | A directory called `name` (and everything under it). | -| `/name` | A file or directory called `name` only at the project root. | -| `*.log` | Any file with the `.log` extension at any depth. | -| `build/*.zip` | `.zip` files directly inside `build/` (one level only). | -| `**/cache` | A `cache` entry at any depth (the `**` matches any number of intermediate directories). | -| `!important.log` | Re-include a file that an earlier rule excluded. | -| `# comment` | A comment. The whole line is ignored. | - -A few practical reminders: - -- Patterns are applied to paths relative to the project root. -- The order of rules matters: a later `!pattern` line can re-include something - an earlier line excluded. -- Whitespace at the end of a line is significant; trim accidental trailing - spaces. -- Empty lines are skipped. - -## What gets packed - -`wpm publish` walks your project directory and checks each file against the -patterns. Anything that matches a pattern gets dropped from the tarball. - -A few wpm-specific notes about what to include and exclude: - -- **`wpm.json`** must be present in the tarball. Don't exclude it. -- **`readme.md`** at the project root is read and attached to the published - manifest as the package's readme. Capped at 50 KiB; if you exclude it, the - registry won't render a readme. -- **`wpm.lock`** is usually safe to exclude from published packages. Consumers - run their own resolver. -- **`.wpmignore` itself** is excluded automatically by the underlying archive - code; you don't need to list it. -- Source control directories (`.git`, `.hg`, `.svn`) are not excluded - automatically. Add them to `.wpmignore` if you don't want to ship a copy of - your VCS metadata. - -## Scope - -`.wpmignore` only affects `wpm publish`. It doesn't change what `wpm install`, -`wpm ls`, or any other command do. Installed dependencies under `wp-content/` -are untouched by your project's `.wpmignore`. - -A dependency might have its own `.wpmignore` in its source, but that only shaped -the tarball when the maintainer published it. By the time wpm extracts the -package on your machine, the file isn't there. - -## Sizing constraints - -`wpm publish` caps the packed tarball at 128 MiB. If you see this error: - -``` -tarball size exceeds 134217728 bytes, refusing to continue -``` - -your project is too big even after `.wpmignore` is applied. Common culprits: - -- A `node_modules/` or `vendor/` directory that wasn't excluded. -- Pre-built binaries or large images committed to the source tree. -- Test fixtures that were never meant to ship. - -Add the offending paths to `.wpmignore` and try again. - -If `.wpmignore` excludes too much and the tarball is empty, `wpm publish` errors -with: - -``` -tarball size is zero, cannot publish empty package -``` - -Loosen the patterns until at least one file is included. - -## Preview what will be packed - -The fastest way to check `.wpmignore` is a verbose dry run: - -```console -$ wpm publish --verbose --dry-run -``` - -Each included file is printed with its packed size before the summary block. Use -this to confirm that the right files are in and the right files are out. - -## Related - -- [`wpm publish`](../reference/cli/publish.md): the only command that reads - `.wpmignore`. -- [`wpm.json`](wpm-json.md): the manifest whose required fields must remain in - the tarball. diff --git a/docs/getting-started/first-project.md b/docs/getting-started/first-project.md deleted file mode 100644 index 476dfb6..0000000 --- a/docs/getting-started/first-project.md +++ /dev/null @@ -1,206 +0,0 @@ ---- -title: First project -description: - Build your first wpm plugin or theme project in ten minutes by scaffolding - dependencies, locking versions, and publishing. ---- - -In about ten minutes, you'll go from a fresh wpm install to a working project -with dependencies. You don't need a registry account for the first five steps. - -If you don't have wpm yet, follow the [installation guide](installation.md) -first. - -## Before you start - -You'll need: - -- wpm installed and on your `PATH`. Run `wpm --version` to check. -- A shell. The examples use bash, but zsh, fish, and PowerShell all work. -- An empty directory for your project. - -You don't need a running WordPress site. wpm manages plugin and theme files -directly in your project directory. You'll only need a real WordPress install -when you want to use the plugins you've downloaded. - -## What you'll build - -A small WordPress plugin called `my-first-plugin`. It will end up with three -packages installed: two production dependencies and one dev dependency, all -locked to specific versions. You'll also learn how to inspect dependencies, -update packages, and publish your project. - -## Step 1: Scaffold a project - -Make an empty directory and run `wpm init -y --type plugin`: - -```console -$ mkdir my-first-plugin -$ cd my-first-plugin -$ wpm init -y --type plugin -config created at /work/my-first-plugin/wpm.json -``` - -The `-y` flag tells wpm to skip the prompts and use defaults. `--type plugin` -tells wpm to create a WordPress plugin package. - -Open `wpm.json` in your editor. It should look like this: - -```json -{ - "name": "my-first-plugin", - "version": "1.0.0", - "type": "plugin", - "license": "GPL-2.0-or-later" -} -``` - -wpm created the required fields for you (`name`, `version`, and `type`) and -added a default license. You can add everything else later as your project -grows. See the [`wpm.json` reference](../fundamentals/wpm-json.md) for the full -list of fields. - -## Step 2: Install production dependencies - -`wpm install` adds packages to your `wpm.json` and downloads them into -`wp-content/plugins/`. You can install several at once: - -```console -$ wpm install akismet hello-dolly@1.7.2 -wpm install v0.1.0 - -+ akismet 5.3.1 -+ hello-dolly 1.7.2 - -2 packages installed -``` - -wpm wrote two things just now: a `dependencies` block in `wpm.json`, and a new -`wpm.lock` next to it. The lockfile records the exact versions wpm installed. - -Commit `wpm.lock` to version control alongside `wpm.json`. This keeps installs -consistent across machines and CI. - -## Step 3: Install development dependencies - -For tools you only need during development, use `-D`: - -```console -$ wpm install -D query-monitor -wpm install v0.1.0 - -+ query-monitor 3.20.2 - -1 package installed -``` - -wpm adds these packages to `devDependencies`. - -Later, you can skip them in production with `wpm install --no-dev`. - -## Step 4: Inspect the tree - -`wpm ls` shows what's installed: - -```console -$ wpm ls -my-first-plugin -├── akismet@5.3.1 -├── hello-dolly@1.7.2 -└── query-monitor@3.20.2 -``` - -`wpm why` shows why a package is installed: - -```console -$ wpm why akismet -my-first-plugin (dependencies) -└─ akismet@5.3.1 -``` - -## Step 5: Check for updates - -`wpm outdated` shows outdated packages. It labels each update as major, minor, -or patch: - -```console -$ wpm outdated -wpm outdated v0.1.0 - -akismet [plugin] -├── current: 5.3.1 -└── latest: 5.4.0 (minor update) -``` - -To upgrade, install the package again at the new version: - -```console -$ wpm install akismet@5.4.0 -``` - -wpm updates both `wpm.json` and `wpm.lock` for you. - -## Step 6: Publish (optional) - -If you have a registry account, you can publish your project. Skip this step if -you don't have an account yet. - -First, log in. You only need to do this once per machine: - -```console -$ wpm auth login -Token: -welcome ! -``` - -It's a good idea to preview the package before publishing. `--dry-run` packs the -tarball, prints the summary, and stops there. Nothing is uploaded: - -```console -$ wpm publish --dry-run -📦 my-first-plugin@1.0.0 - -├─ Tag: latest -├─ Access: private -├─ Files: 3 -├─ Size: 1.2 KB (2.1 KB unpacked) -└─ Digest: 9j6Q7l8s...= - -dry run complete, my-first-plugin@1.0.0 is ready to be published -``` - -When the summary looks right, drop `--dry-run` to publish for real: - -```console -$ wpm publish -📦 my-first-plugin@1.0.0 -... - -✔ published my-first-plugin@1.0.0 -``` - -Before you publish, check that `.wpmignore` excludes everything you don't want -to ship: build artifacts, secrets, test fixtures. See -[`.wpmignore`](../fundamentals/wpmignore.md) for the syntax. - -## What you have now - -- A `wpm.json` with the three required fields, plus `dependencies` and - `devDependencies`. -- A `wpm.lock` that pins the exact versions wpm installed. -- An optional `.wpmignore` if you got to step 6. -- The packages themselves under `wp-content/plugins/`. - -Commit everything except `wp-content/` to version control. Those files can -always be reinstalled from `wpm.lock`. - -## Where to go next - -| If you want to... | Read | -| :------------------------------------------- | :----------------------------------------------------------------- | -| Understand `wpm.json` in detail | [`wpm.json` reference](../fundamentals/wpm-json.md) | -| Run wpm in CI | [CI/CD guide](../guides/ci.md) | -| Manage tokens and multiple accounts | [Authentication](../guides/authentication.md) | -| Learn the plugin/theme/mu-plugin differences | [Package types](../fundamentals/package-types.md) | -| Browse all CLI commands | [`wpm`](../reference/cli/wpm.md) | -| Adopt wpm in an existing plugin or theme | [`wpm init`](../reference/cli/init.md) (see the `--existing` mode) | diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md deleted file mode 100644 index 9eb2b64..0000000 --- a/docs/getting-started/installation.md +++ /dev/null @@ -1,243 +0,0 @@ ---- -title: Installation -description: - Install wpm on Linux, macOS, Windows, Docker, or from source, including shell - completion setup and where wpm stores its files. ---- - -wpm ships as a single static binary. There are no runtime dependencies, no PHP -requirement on the machine that runs wpm, and no per-project toolchain. Pick the -install method that fits your environment. - -## Linux and macOS - -The recommended method is the install script. It detects your platform, -downloads the matching release binary from GitHub, and drops it on your `PATH`. - -```sh -curl -fsSL https://wpm.so/install | bash -``` - -The script removes any previous binary at `/usr/local/bin/wpm` (using `sudo`) -before installing the new one. You can also pin a specific release: - -```sh -curl -fsSL https://wpm.so/install | bash -s -- 0.1.0 -``` - -Supported platforms: - -| OS | Architectures | -| :---- | :--------------------------------------- | -| Linux | `amd64`, `arm64` | -| macOS | `amd64` (Intel), `arm64` (Apple Silicon) | - -If your platform isn't on the list, build from source (see below). - -## Windows - -Run from PowerShell: - -```powershell -powershell -c "irm wpm.so/install.ps1|iex" -``` - -This pulls the Windows release binary and installs it on your `PATH`. - -## Docker - -A pre-built image is available on Docker Hub: - -```sh -docker pull trywpm/cli -``` - -Run wpm against your project by mounting it as a volume: - -```sh -docker run --rm -v "$PWD":/work -w /work trywpm/cli wpm install -``` - -The image is useful for CI pipelines that don't want to manage binaries -themselves, and for ephemeral environments where you don't want wpm on the host. - -## Go toolchain - -If you have Go installed, you can install wpm directly from source: - -```sh -go install go.wpm.so/cli/cmd/wpm@latest -``` - -The binary lands in `$GOPATH/bin` (typically `~/go/bin`). Make sure that -directory is on your `PATH`. To pin a release: - -```sh -go install go.wpm.so/cli/cmd/wpm@v0.1.0 -``` - -## Build from source - -For development, a fork, or an unsupported platform: - -```sh -git clone https://github.com/trywpm/cli wpm -cd wpm -go build -o wpm ./cmd/wpm -``` - -The resulting `wpm` binary in the current directory is fully functional. Move it -onto your `PATH` to use it from anywhere: - -```sh -sudo mv wpm /usr/local/bin/wpm -``` - -## Shell completion - -The install script for Linux and macOS, and the PowerShell installer for -Windows, set up shell completion for you. There's nothing extra to do if you -used one of them. - -What the installers do: - -- **Linux and macOS (`install.sh`)**: generates completion scripts under - `~/.wpm/completions/` for `bash`, `zsh`, and `fish`, then adds a one-line - `source` to your shell's startup file (`.bashrc`, `.zshrc`, or - `~/.config/fish/config.fish`). Open a new shell or `source` the file once to - pick the changes up. -- **Windows (`install.ps1`)**: generates a `wpm.ps1` completion script under the - install directory and adds a load line to your PowerShell profile - (`$PROFILE`). Either run `. $PROFILE` once or open a new PowerShell window. - -### Windows: enable script execution - - -> [!IMPORTANT] -> PowerShell blocks profile scripts by default on Windows. If -> completion doesn't work after installing, your execution policy is the most -> likely reason. - -Set the policy once per user with: - -```powershell -Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned -``` - -Then reopen PowerShell. `RemoteSigned` allows local scripts (including your -profile) to run while still requiring signatures on scripts downloaded from the -internet. Microsoft has the full reference at -. - -### Manual setup - -If you installed wpm a different way (`go install`, source build, Docker without -the installers), wire completion up yourself. wpm can emit the right script for -any supported shell: - -```sh -wpm completion -``` - -One-time setup per shell: - -```sh -# bash -wpm completion bash | sudo tee /etc/bash_completion.d/wpm > /dev/null - -# zsh (with compinit enabled) -wpm completion zsh > "${fpath[1]}/_wpm" - -# fish -wpm completion fish > ~/.config/fish/completions/wpm.fish -``` - -```powershell -# powershell -wpm completion powershell | Out-File -Encoding utf8 "$PROFILE.d\wpm.ps1" -``` - -For a one-off in the current session, source the output instead: - -```sh -source <(wpm completion bash) -``` - -The same works for `zsh` and `fish` with the appropriate shell-source syntax. - -## Verify the install - -After installing, confirm wpm is on your `PATH` and check its version: - -```console -$ wpm --version -wpm version v0.1.0 (abc1234) -``` - -The output shows the release version and the short git commit it was built from. - -If you see `command not found`, the install directory is not on your `PATH` yet. -Open a new terminal session (so the shell's startup file is re-sourced), or run -`hash -r` in your current one to refresh the shell's command cache. If the -problem persists, confirm that the install path is in `PATH`: - -- Linux/macOS script: `/usr/local/bin` should be in `PATH`. -- Windows PowerShell: `%USERPROFILE%\.wpm\bin` should be in `PATH`. -- `go install`: `$(go env GOPATH)/bin` should be in `PATH`. - -## Where wpm keeps its files - -| Path | Purpose | -| :------------------------ | :----------------------------------------------- | -| `~/.wpm/config.json` | Client config: auth token, default user. | -| `~/.wpm/cache/` | Registry response cache and download cache. | -| `~/.wpm/cache/install/` | HTTP cache for install-time GET requests. | -| Per project `wpm.json` | Package manifest. | -| Per project `wpm.lock` | Resolved dependency snapshot. | -| Per project `wp-content/` | Where dependencies are extracted (configurable). | - -The config directory can be moved with the global `--config` flag or the -`WPM_CONFIG` environment variable. To clear the registry response cache, delete -`~/.wpm/cache`; the lockfile and `wp-content/` are untouched. - -## Upgrade - -Re-run whichever install method you used the first time. The install script and -the PowerShell installer both replace the existing binary in place. For -`go install`, run it again with `@latest`. For source builds, `git pull` and -rebuild. - -To upgrade to a specific version, use the version-pinned form of your install -method (shown in each section above). - -## Uninstall - -The binary is the entire install. Delete it: - -| Install method | Path to remove | -| :----------------- | :------------------------------- | -| Linux/macOS script | `/usr/local/bin/wpm` | -| Windows PowerShell | `%USERPROFILE%\.wpm\bin\wpm.exe` | -| Docker | `docker rmi trywpm/cli` | -| `go install` | `$(go env GOPATH)/bin/wpm` | -| Source build | wherever you placed the binary | - -Your project's `wpm.json`, `wpm.lock`, and `.wpmignore` are not touched by -uninstalling wpm. - -If you want a clean slate, also remove the config directory: - -```sh -rm -rf ~/.wpm -``` - -That clears your saved auth token, your `defaultUser` cache, and the install -cache under `~/.wpm/cache/install`. - -## Next steps - -- New to wpm? See [Getting started](first-project.md) for a 10-minute end-to-end - walkthrough. -- Setting up a build pipeline? See the [CI/CD guide](../guides/ci.md). -- Looking for the `wpm.json` reference? See - [`wpm.json`](../fundamentals/wpm-json.md). diff --git a/docs/getting-started/overview.md b/docs/getting-started/overview.md deleted file mode 100644 index 517fd07..0000000 --- a/docs/getting-started/overview.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: Overview -description: - Get started with wpm for WordPress plugins and themes, including core - commands, project files, and your first install in under a minute. ---- - -wpm is an open source package manager for WordPress plugins and themes. - -It's built in Go for performance and reliability, with a globally distributed -registry powered by Cloudflare Workers for fast installs around the world. - -wpm makes WordPress dependencies reproducible, shareable, and easy to manage. - - -> [!IMPORTANT] -> wpm is in active, early development. Expect breaking changes to CLI -> flags and to the `wpm.lock` format before we reach a stable 1.0 -> release. Significant changes are called out in release notes. - -## Why wpm? - -- Built for WordPress out of the box. No extra configuration required. -- Plugins, themes, and mu-plugins are first-class package types. -- Dependency resolution works automatically. -- Reproducible installs with `wpm.lock`. -- Built-in package integrity and supply chain security checks. -- Fast installs and reliable caching. -- Fully open source. - -For the longer rationale, a concrete comparison with Composer, and the design -choices behind wpm, see [Why wpm](why-wpm.md). - -## Quick install - -### Linux and macOS - -```bash -curl -fsSL https://wpm.so/install | bash -``` - -### Windows (PowerShell) - -```powershell -irm https://wpm.so/install.ps1 | iex -``` - -For Docker, `go install`, source builds, and shell completions, see the -[installation guide](installation.md). - -After installation, verify that wpm is available on your system path: - -```bash -wpm --version -``` - -## First steps - -Create a new project: - -```bash -mkdir my-wp-project -cd my-wp-project - -wpm init -y -``` - -Install dependencies: - -```bash -wpm install akismet hello-dolly -``` - -wpm downloads the packages into `wp-content/plugins/` and records the exact -versions in `wpm.lock`. - -Inspect the dependency tree: - -```bash -wpm ls -``` - -Continue with: - -- [Why wpm](why-wpm.md) -- [Installation](installation.md) -- [First project](first-project.md) - -## Learn wpm - -### Fundamentals - -Learn how the wpm ecosystem works: - -- [Dependencies](../fundamentals/dependencies.md) -- [`wpm.json`](../fundamentals/wpm-json.md) -- [`wpm.lock`](../fundamentals/wpm-lock.md) -- [Runtime compatibility](../fundamentals/runtime.md) -- [Package types](../fundamentals/package-types.md) -- [Registry](../fundamentals/registry.md) - -### Guides - -Common workflows and real-world usage: - -- [Authentication](../guides/authentication.md) -- [Publishing](../guides/publishing.md) -- [CI/CD](../guides/ci.md) - -### Reference - -- [CLI reference](../reference/cli/wpm.md) -- [Glossary](../reference/glossary.md) - -## Community - -- GitHub: https://github.com/trywpm/cli -- Issues: https://github.com/trywpm/cli/issues -- Discussions: https://github.com/trywpm/cli/discussions diff --git a/docs/getting-started/why-wpm.md b/docs/getting-started/why-wpm.md deleted file mode 100644 index 61479b2..0000000 --- a/docs/getting-started/why-wpm.md +++ /dev/null @@ -1,189 +0,0 @@ ---- -title: Why wpm? -description: - Why wpm exists, how it improves WordPress dependency management, and when to - use it in plugin and theme projects. ---- - -Managing dependencies in a WordPress project has always been a patchwork. - -A mature site pulls from many places: free plugins, commercial plugins, themes -from independent vendors, and code your team writes itself. None of this follows -a shared standard for installing, updating, or auditing. - -So teams improvise. Some extend Composer with mixed repositories. Some maintain -shell scripts that download ZIPs during CI. Some commit vendor plugins straight -into the repo as Git submodules. These patterns work fine for small sites, but -production WordPress at scale exposes the gaps. - -wpm is the native answer. It treats WordPress plugins and themes as first-class -packages and gives them the tooling that Node, Rust, and Go developers take for -granted. - -## Where current workflows break down - -If you've shipped serious WordPress, you've felt some version of these problems. - -### Vendor distribution is fragmented - -WordPress doesn't define a standard for how commercial plugin and theme vendors -distribute their software. So every vendor invents their own: - -- Some publish a ZIP behind an account-gated download URL. -- Some expose a native API you can hit from automation. -- Some support Composer through a custom repository. -- Some only offer a download link on their dashboard. - -A serious project ends up writing per-vendor integration for each pattern. -There's no single workflow that handles them all. - -### ZIPs are operationally heavy - -Every vendor update means a new ZIP. Teams stage it somewhere their CI can reach -(S3, a private CDN, Git LFS), update the reference in each project, and verify -each install. Multiply by the number of vendor plugins a serious site uses, and -the operational tax adds up fast. - -### Updates don't integrate with your toolchain - -Dependabot, Renovate, and the rest of the modern dependency tooling work by -reading declared dependency metadata. ZIP-based distribution sidesteps that -entirely. There's no machine-readable place to watch for new versions, so -monitoring becomes a manual workflow: check the vendor portal, hope you don't -miss a critical release, repeat. - -### There's no WordPress-specific advisory database - -npm has the [GitHub Advisory Database](https://github.com/advisories). PyPI has -its own. RubyGems has `bundler-audit`. WordPress has Patchstack and WPScan, both -excellent, but neither is wired into a native package manager. Auditing -installed plugins for known vulnerabilities is a manual, separate workflow. - - -> [!NOTE] -> A WordPress-specific advisory database integrated into wpm is on the -> roadmap. Once it lands, `wpm audit` will surface known -> vulnerabilities in your installed packages without leaving the CLI. - -### No standardized dependency metadata - -WordPress plugins don't declare what they depend on. The -`dinopack-for-elementor` plugin needs `elementor` to function, but nothing in -the WordPress.org listing tells your tooling that. With Composer plus -wpackagist: - -```console -$ composer require wpackagist-plugin/dinopack-for-elementor -# Installs dinopack-for-elementor. -# Does not install elementor. -# You have a broken site. -``` - -You have to figure out the right Elementor version yourself, then install it in -a second command. - -With wpm, the dependency is part of the package's manifest in the registry: - -```console -$ wpm install dinopack-for-elementor -wpm install v0.1.7 - -+ dinopack-for-elementor 1.0.5 -+ elementor 3.34.1 - -2 packages installed -``` - -`wpm why` gives you full visibility into why each package is present: - -```console -$ wpm why elementor -my-cool-project (dependencies) -└─ dinopack-for-elementor@1.0.5 - └─ elementor@3.34.1 -``` - -## How wpm closes the gap - -Four design choices get wpm there. - -### A registry that speaks WordPress - -The wpm registry enforces a strict metadata schema (`wpm.json`) for every -package. Dependencies are declared, not inferred. Public plugins, commercial -plugins, and packages you publish yourself all live in the same registry with -the same publishing model. Your CI pulls them through one tool. - -### An installer, not a solver - -wpm doesn't compute the "best intersection of versions" the way most package -managers do. It installs the exact versions you commit. - -WordPress plugins can change database schema, write options, register cron jobs, -and modify content. A solver-based upgrade can trigger a database migration you -weren't ready for. wpm refuses to make that choice automatically. Every upgrade -is an explicit decision you make. - -This is why wpm rejects SemVer ranges in `dependencies` and only accepts exact -versions or `*`. See [Dependencies](../fundamentals/dependencies.md) for the -full reasoning. - -### A single static binary - -wpm ships as a Go binary with no runtime dependencies. It brings its own -networking stack and its own Zstandard decompressor. It runs on the OS, not the -PHP runtime, so it works on the restrictive hosting environments where PHP-based -tools can't. - -### Supply-chain security as a first-class concern - -Every package wpm installs is cryptographically verifiable. You can trust that -what you install is what the author published. - -The registry signs each manifest at publish time. Every install verifies the -SHA-256 digest against what the registry recorded. If the bytes don't match -(corrupted download, man-in-the-middle, compromised mirror), the install fails -before anything lands on disk. - -This is the foundation for the upcoming advisory database. Verified provenance -comes first; auditing for known vulnerabilities builds on top of it. - -## Beyond the CLI - -wpm is one piece of a broader effort. Sister projects: - -- **[wp-to-wpm](https://github.com/trywpm/wp-to-wpm)**: migrates plugins and - themes from WordPress.org SVN to the wpm registry, designed to run as a GitHub - Action. -- **[setup-wpm](https://github.com/trywpm/setup-wpm)**: a GitHub Action that - installs and configures the wpm CLI for your CI/CD pipelines. - -All of it is open source. Contributions, design discussions, and ecosystem -feedback are welcome. - -## When wpm is the right call - -Reach for wpm when: - -- You're running WordPress in production and want reproducible installs across - environments. -- You manage a mix of public and commercial plugins. -- You want cryptographic supply-chain guarantees, not just downloaded ZIPs. -- Your hosting environment is locked down and you can't rely on PHP CLI being - available. -- You want your WordPress dependency workflow to integrate with the modern - dependency-management toolchain (CI, security scanners, audit logs). - -Composer remains a great tool for general PHP libraries. The two can coexist in -a single project: Composer for PHP packages, wpm for WordPress plugins and -themes. - -## Where to go next - -- **[Install wpm](installation.md)** in a single command. -- **[First project](first-project.md)**: a ten-minute walkthrough from empty - directory to working project. -- **[Dependencies](../fundamentals/dependencies.md)**: the full reasoning behind - exact-version pinning. -- **[wpm registry](../fundamentals/registry.md)**: how it stores manifests and - verifies provenance. diff --git a/docs/guides/authentication.md b/docs/guides/authentication.md deleted file mode 100644 index adc09d2..0000000 --- a/docs/guides/authentication.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Authentication -description: - How to generate a wpm token, where wpm stores it on disk, and how to manage - multiple registry accounts from a single machine. ---- - -This page covers everything you need to know about wpm tokens: how to get one, -where wpm stores it, and how to manage multiple accounts. - -For the per-command reference, see [`wpm auth`](../reference/cli/auth.md), -[`wpm auth login`](../reference/cli/auth_login.md), and -[`wpm whoami`](../reference/cli/whoami.md). - -## Why wpm needs a token - -Most wpm commands talk to the registry. The registry needs to know who you are -before it shows you private packages or lets you publish under a name. It -identifies you by the **token** that wpm sends with each request. - -A token is a long string of letters and numbers that proves who you are. Treat -it like a password: anyone who has it can act as you. - -## Getting a token - -Create a personal access token from your account settings on the registry's web -interface, typically at `https://wpm.so/dashboard/tokens`. - -A token can usually be scoped (read-only, publish-only) and given an expiration. -The exact options depend on the registry; consult the registry's documentation -for what's available. - -Once issued, the token is shown to you once. Copy it somewhere safe. You cannot -recover it later from the registry; if it leaks, revoke it and issue a new one. - -## Logging in - -`wpm auth login` checks your token with the registry, then saves it locally. - -On your own machine, use the interactive prompt. wpm hides the token as you -type, so it doesn't end up in your shell history: - -```console -$ wpm auth login -Token: -welcome ! -``` - -In CI runners and image builds, pass the token with `--token`. wpm prints a -warning because the flag value can show up in process lists and build logs: - -```console -$ wpm auth login --token "$WPM_TOKEN" -WARNING! Using --token via the CLI is insecure. -welcome ci-bot! -``` - -In CI, you usually don't need to log in at all. Set `WPM_TOKEN` in the -environment and other wpm commands will use it automatically. See "How tokens -are resolved" below. - -## Where the token is stored - -After login, wpm writes two fields into your client config file: - -| Field | What it holds | -| :------------ | :----------------------------------------------- | -| `authToken` | The token itself, base64-encoded. | -| `defaultUser` | The username the registry resolved the token to. | - -The file lives at `~/.wpm/config.json` by default. You can move it with the -`--config` flag or the `WPM_CONFIG` environment variable. - - -> [!CAUTION] -> The base64 encoding of `authToken` is obfuscation, not encryption. -> Anyone with read access to `config.json` can recover your token. Treat the -> file like an SSH private key. - -A few additional security notes: - -- The directory itself is created with mode `0700`, so only your user account - can list its contents. -- The token is sent over HTTPS to the registry. - -## How tokens are resolved - -wpm finds your token in this order: - -1. The `authToken` field in your client config file. -2. The `WPM_TOKEN` environment variable, used only when (1) is empty. - -If neither is set, the registry rejects the request with an authentication -error. - -One catch: `wpm auth login` itself does **not** read `WPM_TOKEN`. It only -accepts a token from `--token` or the interactive prompt. The environment -fallback applies to every other command (install, publish, whoami, and so on). - -## Logging out - -`wpm auth logout` removes the `authToken` and `defaultUser` fields from your -config file. This is a local change. The token itself stays valid on the -registry until you revoke it from your dashboard. - -If a token leaks, you have to revoke it from the registry. `wpm auth logout` -only protects the machine where you ran it. - -## Multiple identities - -You can keep multiple wpm identities side by side. Point each one at its own -config directory. This is useful when you have personal and work accounts, or -when you switch between production and staging registries. - -```console -$ wpm --config ~/.wpm-personal auth login -Token: -welcome alice! - -$ wpm --config ~/.wpm-work --registry registry.org.example auth login -Token: -welcome alice-at-org! -``` - -Subsequent commands need the same `--config` value to find the right token: - -```console -$ wpm --config ~/.wpm-personal whoami -alice - -$ wpm --config ~/.wpm-work whoami -alice-at-org -``` - -A few practical patterns: - -- Use shell aliases (`alias wpm-work='wpm --config ~/.wpm-work'`) to keep - invocations short. -- Set `WPM_CONFIG` in a directory-scoped tool like [direnv](https://direnv.net) - so the right identity is picked up automatically when you `cd` into a project. - -## CI patterns - -For one-off jobs, skip `wpm auth login` and use the environment: - -```sh -export WPM_TOKEN="" -wpm install -``` - -For longer-lived runners that should publish under a specific identity: - -```sh -wpm auth login --token "$WPM_TOKEN" -wpm publish --access public -``` - -For multi-tenant CI (publishing under more than one account from the same -runner), use a separate `--config` directory per identity. See the -[CI/CD guide](ci.md) for full recipes. - -## Rotating tokens - -The recommended rotation process: - -1. Issue a new token from the registry's web interface. -2. On every machine and CI runner that uses the old token, run `wpm auth login` - (or update the `WPM_TOKEN` secret) with the new value. -3. Verify each one with `wpm whoami`. -4. Revoke the old token from the registry. - -`wpm whoami` is handy during rotation. It hits the registry without changing -anything, so it's a safe way to confirm that a token works. - -## Troubleshooting - -- **`token cannot be empty`**: you pressed Enter at the interactive prompt - without typing anything. Re-run `wpm auth login`. -- **`failed to retrieve username`**: the registry accepted the request but - returned an empty username. This usually means the registry is misconfigured. - Report it to the registry's operator. -- **Authentication errors from the registry**: the token is unrecognized. It may - have been revoked, may have expired, or may be for a different registry. Run - `wpm whoami` against the registry you intend to use, and confirm the token is - current. -- **`user must be logged in to perform this action`** (during `wpm publish`): no - token is stored locally. Run `wpm auth login` or set `WPM_TOKEN`. Note that - `publish` does not read `WPM_TOKEN` as a fallback in the same way other - commands do; you need to be logged in. - -## Related - -- [`wpm auth`](../reference/cli/auth.md): the parent command for `login` and - `logout`. -- [`wpm whoami`](../reference/cli/whoami.md): the canonical "am I logged in?" - check. -- [wpm registry](../fundamentals/registry.md): visibility, dist tags, and what - the registry does with your identity. -- [CI/CD guide](ci.md): worked examples for running wpm from build pipelines. diff --git a/docs/guides/ci.md b/docs/guides/ci.md deleted file mode 100644 index f9d4204..0000000 --- a/docs/guides/ci.md +++ /dev/null @@ -1,291 +0,0 @@ ---- -title: Running wpm in CI -description: - Run wpm in GitHub Actions, GitLab CI, and shell runners with secure token - handling and reproducible installs. ---- - -This guide covers how to run wpm in continuous integration pipelines: GitHub -Actions, GitLab CI, and generic shell-based runners. The patterns apply equally -to other systems. - -## The shape of a wpm CI step - -Every wpm CI step boils down to the same four lines: - -1. Install wpm (or use a container that ships it). -2. Make a token available as `WPM_TOKEN`. -3. Run `wpm install` (or the command you actually want). -4. Make sure logs stay clean by setting `CI=true` and `NO_COLOR=1`. - -The key insight: you usually don't need `wpm auth login` in CI. Just set -`WPM_TOKEN` and wpm picks it up. CI runners start fresh each time with no token -on disk, so the environment variable always wins. - -## Token storage - - -> [!WARNING] -> Never commit `WPM_TOKEN` to version control, paste it into chat or -> issue trackers, or echo it in build logs. CI secrets managers exist for -> exactly this; use them. - -Treat your wpm token like a deployment key. Store it in your CI system's secret -manager (GitHub Actions secrets, GitLab CI variables, HashiCorp Vault, your CI's -equivalent), inject it into the job's environment as `WPM_TOKEN`, and never echo -it to the log. - -`wpm auth login` won't read your input in a non-interactive session unless you -pass `--token`. The cleaner approach in CI: skip `auth login` entirely and let -`WPM_TOKEN` do the work. - -If you do need `auth login` (say, to populate `defaultUser`), use -`--token "$WPM_TOKEN"`. wpm will print a security warning, but CI runners are -ephemeral, so shell-history leakage isn't a real concern. - -## Output and logging - -By default wpm prints a spinner and ANSI color codes. Both are noisy in CI logs. -Two environment variables clean things up: - -- `CI=true` turns off the spinner. wpm checks for `CI` directly and skips the - progress indicator when it sees it. -- `NO_COLOR=1` strips ANSI color escapes from all output. Useful when your log - viewer doesn't render them. - -With both set, the output is plain text that grep, awk, and log search tools can -handle. - -## Reproducible installs - -Three rules for reproducible installs in CI: - -- Commit `wpm.lock` to version control. -- Pin the wpm version your CI uses, either by installing a tagged release or by - using a versioned Docker image. -- Don't run commands that modify `wpm.json` (`wpm install `, - `wpm uninstall`) in the same job that performs the build. If you do, the - lockfile and the manifest will diverge and the next developer to run - `wpm install` locally will see noisy changes. - -For a deploy-time install, `wpm install --no-dev` is the right choice. It skips -dev-only packages and removes them from disk if they're there. - -## GitHub Actions - -A typical workflow for a wpm-backed project: - -```yaml -name: build - -on: - push: - branches: [main] - pull_request: - -jobs: - install: - runs-on: ubuntu-latest - env: - CI: "true" - NO_COLOR: "1" - WPM_TOKEN: ${{ secrets.WPM_TOKEN }} - steps: - - uses: actions/checkout@v4 - - - name: Install wpm - run: | - curl -fsSL https://wpm.so/install | bash - wpm --version - - - name: Install dependencies - run: wpm install --no-dev -``` - -A few notes: - -- `secrets.WPM_TOKEN` is set in the repository's secret manager (Settings → - Secrets and variables → Actions). It's exposed only to the workflow that - references it. -- Pin the wpm version by passing it to the install script if you want hermetic - builds: - ```sh - curl -fsSL https://wpm.so/install | bash -s -- 0.1.0 - ``` -- For matrix builds, the `env` block applies to every matrix combination. - -To publish a release on a tag push: - -```yaml -publish: - runs-on: ubuntu-latest - if: startsWith(github.ref, 'refs/tags/v') - env: - CI: "true" - NO_COLOR: "1" - WPM_TOKEN: ${{ secrets.WPM_TOKEN }} - steps: - - uses: actions/checkout@v4 - - run: curl -fsSL https://wpm.so/install | bash - - run: wpm publish --access public -``` - -## GitLab CI - -```yaml -variables: - CI: "true" - NO_COLOR: "1" - -install: - stage: build - image: ubuntu:24.04 - before_script: - - apt-get update && apt-get install -y curl ca-certificates - - curl -fsSL https://wpm.so/install | bash - script: - - wpm install --no-dev - rules: - - if: $CI_COMMIT_BRANCH - -publish: - stage: deploy - image: ubuntu:24.04 - before_script: - - apt-get update && apt-get install -y curl ca-certificates - - curl -fsSL https://wpm.so/install | bash - script: - - wpm publish --access public - rules: - - if: $CI_COMMIT_TAG -``` - -Define `WPM_TOKEN` as a masked, protected variable in _Settings → CI/CD → -Variables_. Mark it masked so it never appears in logs. - -If you prefer the official Docker image to a fresh install, swap the `image:` -and drop `before_script`: - -```yaml -install: - image: trywpm/cli:latest - variables: - CI: "true" - NO_COLOR: "1" - script: - - wpm install --no-dev -``` - -## Generic shell runners - -For anything that runs a shell (Jenkins, CircleCI, self-hosted agents), the bare -pattern is the same: - -```sh -#!/usr/bin/env bash -set -euo pipefail - -export CI=true -export NO_COLOR=1 -export WPM_TOKEN="${WPM_TOKEN:?WPM_TOKEN must be set}" - -curl -fsSL https://wpm.so/install | bash -wpm install --no-dev -``` - -The `${WPM_TOKEN:?...}` syntax aborts immediately if the variable is missing, -with a clear error in the log. - -## Docker-based pipelines - -If your build container is `trywpm/cli`, wpm is already inside. Just run it: - -```dockerfile -FROM trywpm/cli AS deps -WORKDIR /work -COPY wpm.json wpm.lock ./ -RUN --mount=type=secret,id=wpm_token \ - WPM_TOKEN=$(cat /run/secrets/wpm_token) \ - CI=true \ - NO_COLOR=1 \ - wpm install --no-dev -``` - -The `--mount=type=secret` form keeps `WPM_TOKEN` out of the image's layer -history. Build with: - -```sh -docker build --secret id=wpm_token,env=WPM_TOKEN . -``` - -## Caching strategies - -wpm maintains an HTTP cache under `~/.wpm/cache/install` for registry GET -requests. Caching this directory between CI runs can speed up manifest -resolution. - -GitHub Actions example: - -```yaml -- uses: actions/cache@v4 - with: - path: ~/.wpm/cache - key: wpm-${{ runner.os }}-${{ hashFiles('wpm.lock') }} - restore-keys: | - wpm-${{ runner.os }}- -``` - -GitLab CI example: - -```yaml -cache: - key: - files: - - wpm.lock - paths: - - .wpm-cache/ - -before_script: - - export WPM_CONFIG="$CI_PROJECT_DIR/.wpm-cache" -``` - -In the GitLab example we set `WPM_CONFIG` so wpm uses a project-relative -directory that GitLab knows how to cache. - -The cache is purely an optimization. Builds remain correct without it; they just -spend more time talking to the registry. - -## Identity for multi-tenant setups - -If your CI has to publish under more than one identity (different organizations, -different registries), use `--config` to keep their config directories separate: - -```sh -wpm --config "$RUNNER_TEMP/.wpm-org-a" --registry registry.org-a.example install -wpm --config "$RUNNER_TEMP/.wpm-org-b" --registry registry.org-b.example install -``` - -Set `WPM_TOKEN` from a different secret for each block. Because `WPM_TOKEN` is -only read when the local config lacks a token, the isolation is automatic. - -## Checklist - -Before merging your CI configuration, confirm: - -- [ ] `WPM_TOKEN` is stored as a secret, not in plain text. -- [ ] `CI=true` and `NO_COLOR=1` are set on the job. -- [ ] `wpm.lock` is committed and not produced inside the job. -- [ ] The wpm version is pinned, either by version string or by a tagged Docker - image. -- [ ] `wpm install` uses `--no-dev` in deploy steps, but not in verification - steps that need dev tools. - -## Related - -- [Installation](../getting-started/installation.md): how the install script - works. -- [Authentication](authentication.md): the token lifecycle. -- [`wpm`](../reference/cli/wpm.md): the full list of global flags and - environment variables. -- [wpm registry](../fundamentals/registry.md): dist tags and visibility settings - used by `wpm publish`. diff --git a/docs/guides/dependency-management.md b/docs/guides/dependency-management.md deleted file mode 100644 index 00473b0..0000000 --- a/docs/guides/dependency-management.md +++ /dev/null @@ -1,150 +0,0 @@ ---- -title: Managing dependencies -description: - Add, remove, update, and inspect dependencies in your wpm project using the - commands you'll use most often. ---- - -This guide covers the day-to-day work of adding, removing, updating, and -inspecting your project's dependencies. - -For the schema rules and the reasoning behind exact-version pinning, see -[Dependencies](../fundamentals/dependencies.md). - -## Adding a production dependency - -```console -$ wpm install akismet -``` - -wpm fetches the latest version from the registry, downloads it into -`wp-content/plugins/`, and records the resolved version in both `wpm.json` and -`wpm.lock`. - -To pin a specific version, use `name@version`: - -```console -$ wpm install akismet@5.3.1 -``` - -## Adding a dev dependency - -For tools you only need during development (debuggers, code quality checks, -sample data), use `-D`: - -```console -$ wpm install -D query-monitor -``` - -wpm adds the package to `devDependencies` instead of `dependencies`. A -production install with `wpm install --no-dev` will skip them. - -## Adding several at once - -You can mix production and dev in a single call. Specifiers can be plain names -or `name@version`: - -```console -$ wpm install akismet hello-dolly@1.7.2 -$ wpm install -D query-monitor -``` - -## Moving between production and dev - -Use `-P` to move a dev dependency into `dependencies`: - -```console -$ wpm install -P query-monitor -``` - -And `-D` to move a production dependency into `devDependencies`: - -```console -$ wpm install -D akismet -``` - -In both cases, wpm removes the old entry and writes the new one in the same -step. - -## Removing a dependency - -```console -$ wpm uninstall hello-dolly -``` - -wpm deletes the entry from `wpm.json` (whichever map it was in), updates -`wpm.lock`, and removes the package's files from `wp-content/`. - -`wpm rm` and `wpm remove` are aliases for `wpm uninstall`. - -## Checking for updates - -```console -$ wpm outdated -``` - -`wpm outdated` asks the registry for the latest version of each installed -package and flags anything that's behind. Each update is labeled as major, -minor, or patch. - -This command only reads. It never changes your project for you. - -## Updating to a new version - -To upgrade, install the package again at the new version: - -```console -$ wpm install akismet@5.4.0 -``` - -wpm updates both `wpm.json` and `wpm.lock`. To follow the registry's `latest` -dist tag, use `@latest`: - -```console -$ wpm install akismet@latest -``` - - -> [!NOTE] -> wpm uses exact versions, not ranges. Every upgrade is an explicit choice -> you make. See [Dependencies](../fundamentals/dependencies.md) for the -> reasoning. - -## Inspecting the tree - -`wpm ls` shows the full dependency tree from `wpm.lock`: - -```console -$ wpm ls -my-plugin -├── akismet@5.3.1 -├── hello-dolly@1.7.2 -└── query-monitor@3.20.2 -``` - -`wpm why` shows why a package is installed. Useful when you see a package you -don't recognize: - -```console -$ wpm why akismet -my-plugin (dependencies) -└─ akismet@5.3.1 -``` - -## Verify before you deploy - - -> [!TIP] -> Run `wpm ls` before deploying to a live WordPress site. It shows the -> exact plugin and theme versions you're about to ship, so nothing -> surprises you in production. - -## Related - -- [Dependencies](../fundamentals/dependencies.md): the schema, the rules, and - why wpm rejects version ranges. -- [`wpm install`](../reference/cli/install.md): every flag and example. -- [`wpm uninstall`](../reference/cli/uninstall.md): every flag. -- [`wpm ls`](../reference/cli/ls.md), [`wpm why`](../reference/cli/why.md), - [`wpm outdated`](../reference/cli/outdated.md): the read-only inspection - commands. diff --git a/docs/guides/publishing.md b/docs/guides/publishing.md deleted file mode 100644 index e96c1ff..0000000 --- a/docs/guides/publishing.md +++ /dev/null @@ -1,235 +0,0 @@ ---- -title: Publishing -description: - Publish WordPress plugins, themes, and mu-plugins with wpm, including - versioning, dist tags, visibility, and unpublishing. ---- - -This guide covers everything from your first release to taking one back: version -numbers, dist tags, visibility, and the release lifecycle. - -If you only want the command reference, see -[`wpm publish`](../reference/cli/publish.md). If you haven't built a package -yet, start with [Getting started](../getting-started/first-project.md) and come -back when you have a `wpm.json` you'd like to share. - -## Before you start - -A few preconditions: - -- You have a registry account and a personal access token. Create one from - [your dashboard](https://wpm.so/dashboard/tokens). -- You're logged in. `wpm whoami` should print your username. -- Your `wpm.json` has the three required fields (`name`, `version`, `type`) and - `"private": true` is **not** set. -- A `readme.md` exists at the project root if you want the registry to render - documentation alongside the listing. -- A `.wpmignore` excludes anything you don't want in the published tarball: - build artifacts, secrets, test fixtures, IDE files. - -## Your first publish - -Preview the publish before you upload. `--dry-run` packs the tarball locally and -prints the summary block, but skips the upload: - -```console -$ wpm publish --dry-run -📦 my-plugin@0.1.0 - -├─ Tag: latest -├─ Access: private -├─ Files: 42 -├─ Size: 1.5 MB (3.4 MB unpacked) -└─ Digest: 9j6Q7l8s...= - -dry run complete, my-plugin@0.1.0 is ready to be published -``` - -If the summary block looks right, drop `--dry-run`: - -```console -$ wpm publish -📦 my-plugin@0.1.0 - -├─ Tag: latest -├─ Access: private -├─ Files: 42 -├─ Size: 1.5 MB (3.4 MB unpacked) -└─ Digest: 9j6Q7l8s...= - -✔ published my-plugin@0.1.0 -``` - -The package is now on the registry. Anyone with read access can install it with -`wpm install my-plugin`. - - -> [!TIP] -> Run `wpm publish --verbose --dry-run` before every real publish. It -> prints every file that will be included, with sizes, so you can catch a stray -> `node_modules/` directory or a forgotten secrets file. - -## Versioning your releases - -Every published version must be strict SemVer (`X.Y.Z`, no `v` prefix). The -standard convention applies: - -| Bump | When | Example | -| :---- | :---------------------------------------------------- | :-------------- | -| MAJOR | A change consumers' code or configuration depends on. | `1.0.0 → 2.0.0` | -| MINOR | A new feature, backward-compatible. | `1.0.0 → 1.1.0` | -| PATCH | A bug fix, no new behavior. | `1.0.0 → 1.0.1` | - -For pre-1.0 packages, treat `0.X.Y → 0.(X+1).0` as a minor and -`0.X.Y → 0.X.(Y+1)` as a patch. Breaking changes are still possible across minor -bumps below 1.0, but be courteous to your users and call them out in release -notes. - -### Pre-releases - -Use a SemVer pre-release suffix to publish a build that consumers must opt into -explicitly: - -| Version | What it signals | -| :------------- | :------------------------------------------------ | -| `1.2.0-beta.1` | A pre-release of 1.2.0; not picked up by default. | -| `1.2.0-rc.1` | A release candidate of 1.2.0. | -| `1.2.0` | The actual 1.2.0 release. | - -Pre-releases sort below their release counterparts in SemVer. `wpm outdated` -will not surface `1.2.0-beta.1` as an update over `1.1.5`. Consumers have to -install the pre-release explicitly: - -```console -$ wpm install my-plugin@1.2.0-beta.1 -``` - -## Choosing a dist tag - -`wpm publish` writes to the `latest` tag by default. That's what new consumers -pick up when they run `wpm install my-plugin`. - -For pre-releases, publish under a separate tag so `latest` doesn't move: - -```console -$ wpm publish --tag beta -``` - -Consumers then opt in with `wpm install my-plugin@beta`. Common conventions: - -| Tag | Use case | -| :------- | :------------------------------------------------------------------ | -| `latest` | The current stable release. Default for `wpm install`. | -| `beta` | Pre-releases for early testers. | -| `next` | Releases of the upcoming major while the current major still ships. | -| `lts` | Long-term-support releases on an older major branch. | - -A dist tag always points at exactly one version. Publishing again with the same -`--tag` moves the tag to your new release. `latest` always points at whatever -you most recently published with the default `--tag`, unless you explicitly -chose a different tag. - -## Visibility (public vs. private) - -`--access public` makes the release discoverable by everyone the registry -serves. `--access private` keeps it limited to authorized accounts. - -```console -$ wpm publish --access public -``` - -The default is `private`. To change visibility on an already-published version, -publish a new version with the new `--access` value; there is no separate -"change visibility" command. - - -> [!IMPORTANT] -> `--access private` is not the same as `"private": true` in -> `wpm.json`. The flag sets the registry's visibility. The manifest flag -> prevents publishing entirely. See -> [wpm registry](../fundamentals/registry.md#private-true-is-not-the-same-as---access-private). - -## Republishing the same version - - -> [!CAUTION] -> A published version cannot be replaced. The registry rejects any -> publish for a version it already holds, and yanked versions stay reserved (you -> cannot reuse the number for a new build). - -wpm needs unique versions to keep installs reproducible. `wpm.lock` pins each -package's tarball by SHA-256 hash, so a given version is always the same bytes -for everyone. - -To release again, bump the `version` field in `wpm.json` to the next SemVer -value and run `wpm publish` again. - -## Taking a release back - -You can't undo a publish from the CLI. If you need to take a release back -(broken build, accidental secret leak, contractual issue), use the registry's -web interface to **yank** the release. - -Yanking has a soft effect: the version stays in the registry's history. Anyone -who already has it in their `wpm.lock` keeps working. New installs can't pick it -up. - -Either way, the version number stays reserved. Your next publish has to use a -new number. - -## A typical release cycle - -A simple flow for a stable package: - -```sh -# 1. Make changes, run tests -$ vim src/main.php -$ ./vendor/bin/phpunit - -# 2. Bump the version -$ vim wpm.json # 1.0.0 → 1.0.1 for a bugfix - -# 3. Preview -$ wpm publish --verbose --dry-run - -# 4. Publish for real -$ wpm publish -``` - -A flow for shipping a pre-release of an upcoming major: - -```sh -$ vim wpm.json # 1.0.0 → 2.0.0-beta.1 -$ wpm publish --tag beta -``` - -When the pre-release graduates: - -```sh -$ vim wpm.json # 2.0.0-beta.1 → 2.0.0 -$ wpm publish # Goes to latest -``` - -## Common mistakes - -- **Publishing without bumping the version.** You'll get the "version already - exists" error. Bump the `version` field in `wpm.json`. -- **Forgetting `.wpmignore`.** A 200 MB `node_modules` directory in the tarball, - or worse, a `.env` with secrets. Preview every publish with - `wpm publish --verbose --dry-run`. -- **Mixing tags.** If you publish a beta with `--tag latest` by accident, every - consumer's next install picks up the beta. Check the summary block before you - confirm. -- **Leaving `"private": true` set.** The publish fails with - `package marked as private cannot be published`. Edit `wpm.json` to remove the - flag. - -## Related - -- [`wpm publish`](../reference/cli/publish.md): every flag, with - troubleshooting. -- [wpm registry](../fundamentals/registry.md): tags, visibility, and the - difference between `private: true` and `--access private`. -- [Authentication](authentication.md): tokens and CI patterns. -- [`.wpmignore`](../fundamentals/wpmignore.md): syntax for the exclusion file. -- [`wpm.json`](../fundamentals/wpm-json.md): the manifest schema. diff --git a/docs/guides/runtime-compatibility.md b/docs/guides/runtime-compatibility.md deleted file mode 100644 index 28afdca..0000000 --- a/docs/guides/runtime-compatibility.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Strict runtime mode -description: - Turn on strict runtime mode so wpm verifies that your dependencies work with - the WordPress and PHP versions you target. ---- - -By default, wpm doesn't check whether your dependencies are compatible with the -WordPress and PHP versions you're running. **Strict runtime mode** turns that -check on. This guide walks through enabling it, reading the errors, and deciding -when to use it. - -For the field-level reference (what `requires` and `config.runtime` each mean), -see [Runtime compatibility](../fundamentals/runtime.md). - -## When to enable strict mode - -Turn it on when: - -- You want CI to catch dependencies that quietly bumped their minimum WordPress - or PHP version. -- You're testing your plugin against a specific WordPress and PHP matrix and - want installs to fail fast on incompatible dependencies. -- You're maintaining a long-term-support branch and want to be sure nothing in - the tree drifts past your supported versions. - -Leave it off when: - -- You're experimenting and want installs to succeed even when some dependencies - declare conservative `requires`. -- Your project is a library that targets a broad range and you rely on the - registry to surface compatibility issues separately. - -## Setting it up - -Add a `config.runtime` block to your `wpm.json`: - -```json -{ - "name": "my-plugin", - "version": "1.0.0", - "type": "plugin", - "config": { - "runtime": { - "wp": "6.9", - "php": "8.2" - } - } -} -``` - -The values are concrete versions, not constraints. They are the specific -versions you're testing against. - -Setting either `runtime.wp` or `runtime.php` is enough to turn strict mode on -for the whole project. - -## What wpm checks - -During every `wpm install`, wpm reads each dependency's `requires` field and -compares it against your `config.runtime`. If any dependency declares a -constraint your runtime can't satisfy, the install fails before anything is -downloaded. - -## Reading the error - -A typical strict-mode failure looks like this: - -``` -package akismet@5.3.1 incompatible: - requires WordPress >=6.5, but runtime WordPress version is 6.4 -``` - -This tells you: - -- **Which package** failed (`akismet@5.3.1`). -- **What it needs** (`WordPress >=6.5`). -- **What you have** (`runtime WordPress version is 6.4`). - -You have three options: - -- **Bump your runtime**: edit `config.runtime.wp` in `wpm.json` to a version - that satisfies the requirement. -- **Pick a different version** of the dependency that supports your current - runtime. -- **Opt out**: remove `config.runtime` from `wpm.json` to skip the check - entirely. - -## Turning it off - -Delete `config.runtime` from `wpm.json`, or just remove `runtime.wp` and -`runtime.php`. No other configuration change is needed. - -## Related - -- [Runtime compatibility](../fundamentals/runtime.md): the field reference and a - worked example. -- [`wpm install`](../reference/cli/install.md): where the check runs. -- [`wpm.json`](../fundamentals/wpm-json.md): the manifest schema. diff --git a/docs/reference/glossary.md b/docs/reference/glossary.md deleted file mode 100644 index ff9b678..0000000 --- a/docs/reference/glossary.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Glossary -description: - Look up the terms that appear across the wpm docs, defined in plain English - and listed alphabetically. ---- - -Terms that appear across the wpm docs. Listed alphabetically. - -## Access level - -The visibility a package has on the registry. Set with -`wpm publish --access `. A `public` package is visible to -everyone the registry serves; a `private` package is visible only to authorized -accounts. Distinct from `"private": true` in `wpm.json`, which prevents -publishing entirely. See [wpm registry](../fundamentals/registry.md). - -## Auth token - -A long string of letters and numbers the registry issues to identify you. wpm -sends it on every authenticated request. Stored in `~/.wpm/config.json` after -`wpm auth login`. Treat it like a password. See -[Authentication](../guides/authentication.md). - -## Conflict resolution - -The resolver's process for deciding which version to pick when two parts of the -dependency tree disagree. Root pins in `wpm.json` win over transitive requests, -as long as they satisfy the requests. Unresolvable conflicts produce an error -pointing at the responsible packages. See [`wpm install`](cli/install.md). - -## Content directory - -The directory wpm extracts dependencies into. Default `wp-content/`. -Configurable via `config.content-dir` in `wpm.json`. Inside it, packages are -organized into `plugins/`, `themes/`, and `mu-plugins/` subdirectories based on -each package's `type`. - -## Dev dependency - -A package declared in the `devDependencies` map of `wpm.json`. Installed by -default but pruned with `wpm install --no-dev`. Use for development-only tools -(debuggers, code quality checks, sample data). See -[Dependencies](../fundamentals/dependencies.md). - -## Digest - -The SHA-256 hash of a published tarball. Recorded in `wpm.lock` and on every -entry in the registry's manifest. wpm uses the digest to verify integrity after -downloading. - -## Direct dependency - -A package listed in `dependencies` or `devDependencies` in your `wpm.json`. The -opposite of _transitive dependency_, which is a dependency of another package in -your tree. - -## Dist tag - -A label that points at a specific version of a package on the registry. The -canonical tag is `latest`, which marks the version new consumers should pick up. -Maintainers can create others (`beta`, `next`, `lts`) to publish pre-releases -without disturbing `latest`. Set with `wpm publish --tag `; selected at -install time with `wpm install pkg@`. See -[wpm registry](../fundamentals/registry.md). - -## Lockfile - -`wpm.lock`. The frozen snapshot of the resolved dependency tree, including exact -versions, tarball URLs, and SHA-256 digests. Commit to version control. See -[`wpm.lock`](../fundamentals/wpm-lock.md). - -## Lockfile version - -The integer field at the top of `wpm.lock` that identifies the file format's -revision. Currently `1`. wpm refuses to load a lockfile with a newer version -than it understands. - -## Manifest - -Two related things in wpm, distinguished by context: - -- **Project manifest**: your `wpm.json`. Describes the local package and its - dependencies. -- **Registry manifest**: the JSON document the registry serves for a published - version. Includes everything in the project manifest plus distribution - metadata (tag, digest, sizes, visibility). - -## Mu-plugin - -A "must-use" plugin. Installed under `wp-content/mu-plugins/` and loaded -automatically by WordPress on every request. Cannot be deactivated from the -admin UI. See [Package types](../fundamentals/package-types.md). - -## Package name - -The unique identifier for a package on the registry. 3 to 164 characters, -lowercase alphanumeric and hyphens. Matched by the regex -`^[a-z0-9]+(-[a-z0-9]+)*$`. See -[`wpm.json` reference](../fundamentals/wpm-json.md). - -## Package type - -One of `plugin`, `theme`, or `mu-plugin`. Declared in `wpm.json`, required for -every package. Determines where wpm extracts the package and how WordPress loads -it. See [Package types](../fundamentals/package-types.md). - -## Plan - -The list of `Install`, `Update`, and `Remove` actions that `wpm install` -calculates by comparing the resolved tree against `wpm.lock` and the filesystem. -Printed line by line during the install. Use `--dry-run` to see the plan without -applying it. - -## Pre-release - -A SemVer version with a pre-release suffix, like `1.0.0-beta.1`. Sorts below the -corresponding release in SemVer ordering, so `wpm outdated` will not flag a -pre-release as an update over the release. - -## Private - -Two distinct meanings, distinguished by context: - -- `"private": true` in `wpm.json` prevents publishing entirely. A tripwire on - internal-only projects. -- `--access private` on `wpm publish` publishes the package with private - visibility on the registry. - -See [wpm registry](../fundamentals/registry.md). - -## Registry - -The server wpm talks to. Hosts published packages, dist tags, manifests, and -tarballs. Default `registry.wpm.so`. Switch with `--registry `. See -[wpm registry](../fundamentals/registry.md). - -## Resolution - -The process of expanding a `wpm.json` into a flat set of resolved packages, by -recursively fetching each dependency's manifest from the registry. Performed by -`wpm install`. The output is cached in `wpm.lock`. - -## Resolved version - -The concrete version that the resolver picked for a package, after applying -conflict resolution. Recorded in `wpm.lock` as the `version` field, and copied -into `wpm.json` whenever the package is added via the CLI. - -## Runtime (strict mode) - -The opt-in compatibility check `wpm install` performs when `config.runtime.wp` -or `config.runtime.php` is set in `wpm.json`. Every dependency's `requires` is -checked against your declared runtime; mismatches fail the install. See -[Runtime compatibility](../fundamentals/runtime.md). - -## SemVer - -[Semantic Versioning](https://semver.org/) (`X.Y.Z`). wpm requires strict SemVer -for `version` and for entries in `dependencies` (or `*`). Range syntax (`^1.0`, -`~1.2`, `>=6.0 <7.0`) is only allowed in `requires.wp` and `requires.php`. - -## Tarball - -The compressed archive that the registry stores for each published version. -Format is Zstandard-compressed tar (`.tar.zst`). Capped at 128 MiB at publish -time. - -## Transitive dependency - -A dependency of one of your direct dependencies. Reachable through the -dependency graph but not declared directly in your `wpm.json`. Trace one to its -root with `wpm why `. - -## Visibility - -See _Access level_. - -## Workspace lock - -A file-based lock wpm holds inside your project's content directory while it -runs install or uninstall. Prevents two wpm processes from corrupting each other -in the same project. Distinct from `wpm.lock` (the lockfile). Released when the -holding process exits. - -## wpm.json - -The project manifest. Lives at the root of every wpm package. Required fields -are `name`, `version`, `type`. See -[`wpm.json` reference](../fundamentals/wpm-json.md). - -## wpm.lock - -The lockfile. See _Lockfile_ and [`wpm.lock`](../fundamentals/wpm-lock.md). - -## .wpmignore - -A gitignore-style file controlling which paths `wpm publish` includes in the -published tarball. Optional. See [`.wpmignore`](../fundamentals/wpmignore.md).