Skip to content

pw add

Terminal window
pw add [registered|discovered|devbox|database|dynamo|firestore|redis-valkey|auth|tailwind|images]
pw add <module-path>

pw init asks which capabilities a project starts with, before the project is understood well enough to answer. pw add installs one afterwards, so a declined answer is not a decision the project is stuck with.

The command runs inside an existing project and asks its questions in a wizard. There is no flag form: unlike pw init, which creates a fresh directory, this edits configuration, migrations, and sources the project already depends on — and the review screen is where that edit is approved.

An argument containing a dot in its first element is read as a module path instead, which installs a component package. That route has no wizard and no review screen, because it copies nothing: it writes the go.mod requirement and one [[packages]] entry, then prints the remaining commands. See The consuming side.

Capability What it installs
registered the handler tree, its mux, and one route registration written in Go
discovered the page tree, its layout, and the generate.pages entry that reads it
devbox devbox.json and devbox.lock, carrying the toolchain this project already uses
database the [middleware.rdb] section, the migration directory, and a typed SQL example
dynamo the [middleware.dynamo] section, a typed record, and the local DynamoDB server
firestore the [middleware.firestore] section, a typed entity, and a .pw.firestore query
redis-valkey the Valkey development server in devbox.json
auth login sessions, the framework tables, and the account resolver
tailwind the pinned Tailwind toolchain, its CSS entry, and the [assets.tailwind] block
images the pinned image encoders and the [assets.images] block that switches conversion on

The argument preselects the first step; omitting it lists only what this project does not already carry. Two capabilities depend on another one: auth needs database, dynamo, or firestore for its login records, and redis-valkey needs devbox, because the Valkey answer writes nothing but a Devbox package. Choosing one in a project that lacks its dependency installs the dependency first and says so on the review screen.

images writes the encoders and the switch in one step on purpose. A project that turned conversion on without them would convert nothing and report that on every build; a project that installed them without the switch would carry two packages it never runs. Without Devbox there is nothing to pin them with, so the capability names the tools in words and leaves the install to you.

A capability is detected from the files that carry it, never from a list in popcornweb.toml — a manifest could disagree with a hand-edited project:

Capability Evidence
devbox devbox.json
database [middleware.rdb] in an environment configuration file
dynamo [middleware.dynamo] in an environment configuration file
firestore [middleware.firestore] in an environment configuration file
redis-valkey the Valkey package in devbox.json
auth the [auth] section, or an init_popcornweb_auth migration at any version
tailwind assets.tailwind.enabled in popcornweb.toml
images assets.images.enabled in popcornweb.toml

Adding a capability the project already has fails and names the file that proves it:

pw: add: this project already has auth, per migrations/00003_init_popcornweb_auth.sql

The review screen lists every change before anything is written:

Review
Capability auth
OIDC provider External provider
create handlers/accounts.go
create migrations/00002_init_popcornweb_session.sql
create migrations/00003_init_popcornweb_auth.sql
append config.dev.toml
edit cmd/lean/main.go
then pw migrate up
enter add · esc back · ctrl+c cancel

Four rules govern that list:

Migrations take the next free version. A project that already applied 00001 through 00007 gets 00008; nothing is renumbered, because a migration the project may have applied can never move.

Configuration is appended, not rewritten. Your comments and tuned values survive. A section of the same name already present stops the command.

pw add auth installs the rdb session backend, the one that fits a project that already has a database. Session storage is opt-in by blank import, so the import line is one of the manual steps — pw init is where the cookie and Redis backends are offered instead.

Application-owned files are never overwritten. A conflict is reported and nothing is written. What the framework will not do for you — the call in main.go, the stylesheet link in the document shell — is printed as a manual step instead.

Nothing is partial. Every file is computed first and written together, so a step that cannot succeed leaves the project as it was.

Situation Exit
capability installed 0
wizard canceled 0, nothing written
no terminal non-zero with usage
already present, or a conflict non-zero with the path and the reason