$ ps-lando

Selecting modules

Use --exclude / --only globs (or pslando.config.json) to filter which modules get installed.

Since 1.0.0 (1.0.0), ps-lando picks modules in two layers:

  1. Interactive multiselect prompt during create — every module zip detected in the cwd is pre-checked. Untick what you don't want, hit enter, those zips never enter the install graph.
  2. Glob filters--exclude=<glob> and --only=<glob> (repeatable, picomatch-backed, case-insensitive) for CI / scripts / configs. Both also live in pslando.config.json.

The pre-1.0 group flags (--skip-easybuilder, --skip-blog, --skip-social, --skip-marketing) were removed — running them now exits 64 with a one-line migration hint to stderr.

Breaking change in 1.0.0. All four --skip-* group flags are gone. See the Migrating from 0.x guide for a step-by-step replacement table.

The interactive multiselect

Run ps-lando create (without -y) in a folder with one or more module zips:

?  Pick modules to install · multiple selection
●  steasybuilder
●  steasy_trans_panda
●  stmegamenu
●  stbanner
○  stblog        ← unticked manually
●  stsocial
  • Defaults to all detected modules pre-checked (back-compat with v0.6 "install everything").
  • Selection writes through to excludePatterns in .ps-lando.json so db reset reapplies the same set.
  • With -y: the prompt is skipped and every detected module is installed (same as a fully-checked multiselect).
  • The CLI only considers zips dropped in the cwd (or --zips=<dir>). PS-bundled modules sitting inside the PS download are never re-installed by pslando create — that fixed the 1.0.0-rc.1 bug where stock modules sneaked into the count.

Why generic --exclude

ps-lando ships sensible zero-config defaults — install every theme module bundled in your theme zip plus any st* / module-* zips alongside it. That's right for the first sandbox. But:

  • Not every shop has a blog → --exclude=stblog* drops the blog modules in one expression.
  • No Easy Builder → omit the zips, or --exclude=steasybuilder* if they're around.
  • Reproducing a single-module bug → --only=stbanner installs only that one module.
  • Stripped-down minimal core → combine multiple --exclude patterns or define them in config.

Globs are picomatch-style (*, **, ?, [abc], !negation). Repeatable. Composes with --only. Case-insensitive.

The --exclude flag

# Skip the blog modules
ps-lando create -y --exclude=stblog*

# Skip Easy Builder + bridge
ps-lando create -y --exclude=steasybuilder*

# Skip blog AND social modules in one go
ps-lando create -y --exclude=stblog* --exclude=stsocial* --exclude=stinstagram*

# Combine with --only (intersection)
ps-lando install-modules --only=stbanner --exclude=stbanner-old

--exclude= (empty) exits 64 (UsageError) with a hint pointing at the spec — empty patterns are always rejected so a misconfigured CI doesn't silently pass nothing.

The panda preset's group filters

The bundled panda preset ships with the same four conceptual groups the 0.x flags used to expose, but they're exposed as exclude-glob shortcuts in pslando.config.json, not as flags. Once the preset is loaded (auto when a panda*.zip is detected, or explicit via --preset=panda), these are the documented globs:

GroupGlob equivalentModules
blogstblog*stblog, stblogarchives, stblogblockcategory, stblogcomments, stblogeditor, stblogfeaturedarticles, stbloglinknav, stblogrecentarticles, stblogrelatedarticles, stblogsearch, stblogtags
easybuildersteasybuilder*steasybuilder, steasy_trans_panda
socialstcontact* stnewsletter* stsocial* stinstagram* (subset)stsocial, stfblikebox, stinstagram, sttwitterembeddedtimelines
marketingstcountdown* stnewsletter* stnotification* ststickers* (subset)stcountdown, stnewsletter, stnotification, ststickers

Compose them in config:

{
  "modules": {
    "exclude": ["stblog*", "steasybuilder*"]
  }
}

…or top-level for shorthand:

{
  "exclude": ["stblog*", "steasybuilder*"]
}

The shorthand merges into modules.exclude BEFORE CLI flags apply. CLI --exclude always wins.

--only — install just a subset

# Install ONLY two specific modules on an existing sandbox
ps-lando install-modules --only=stmegamenu --only=stbanner

# Or via config
{ "modules": { "only": ["stmegamenu", "stbanner"] } }

When both --exclude and --only are set, the resolver computes included = (only filter) − (exclude filter). Empty result short-circuits with a clear message.

Filtering install vs filtering copy

By default, --exclude / --only only filter what gets installed — every module in the cwd is still copied into modules/, so re-running ps-lando install-modules later (without flags) picks up modules you originally excluded.

Pass --no-copy-skipped to also skip the copy step — modules/ ends up clean. The deployModules log reflects the filtered count, e.g. "Copying 43 of 54 modules — 11 excluded via --no-copy-skipped".

--no-copy-skipped is a no-op when used without --exclude / --only.

Common combos

# Shop without blog (auto-loads panda preset because panda*.zip is present)
ps-lando create -y --exclude=stblog*

# Minimal core: no blog, no Easy Builder, no social, no marketing
ps-lando create -y \
  --exclude=stblog* \
  --exclude=steasybuilder* \
  --exclude=stsocial* --exclude=stfblikebox* --exclude=stinstagram* --exclude=sttwitterembeddedtimelines* \
  --exclude=stcountdown* --exclude=stnewsletter* --exclude=stnotification* --exclude=ststickers*

# Same thing, but persisted in config
{
  "schema": 1,
  "presets": ["panda"],
  "exclude": [
    "stblog*",
    "steasybuilder*",
    "stsocial*", "stfblikebox*", "stinstagram*", "sttwitterembeddedtimelines*",
    "stcountdown*", "stnewsletter*", "stnotification*", "ststickers*"
  ]
}
# Debugging just 2 modules on an existing sandbox
ps-lando install-modules --only=stmegamenu --only=stbanner

# Skip blog AND don't even copy the blog modules into modules/
ps-lando create -y --exclude=stblog* --no-copy-skipped

Modules from a non-Panda theme

The same flow works for any theme — Panda, Falcon, Leo Classic, your own. Drop the theme zip plus its module zips alongside it:

my-shop/
├── leo_classic.zip          ← theme, classified by config/theme.yml
├── stmegamenu.zip           ← module, classified by stmegamenu/stmegamenu.php
├── stbanner.zip
└── stsocial.zip

Run ps-lando create. The theme select prompt lists leo_classic (and None); the module multiselect lists stmegamenu, stbanner, stsocial all pre-checked. No preset binding fires (the panda preset only matches the literal name panda), so you get a generic deploy: theme extracted to themes/leo_classic/, modules installed in dependency order, no Easy Builder bridge.

Want the same selection persisted for db reset? Run ps-lando init afterwards and accept the auto-detected values — it writes the config + zip set to pslando.config.json.

How -y interacts with --exclude / --only

  • ps-lando create -y (no flags) → all detected modules selected, --exclude / --only empty, install everything.
  • ps-lando create -y --exclude=stblog* → all detected modules selected by the implicit multiselect, then stblog* is filtered before install.
  • ps-lando create -y --only=stbanner → only stbanner installed, even if other module zips are present.

CLI flags always win — they apply on top of whichever set the multiselect (or its -y shortcut) produced.

Persistence in .ps-lando.json

The resolved selection is persisted to .ps-lando.json so ps-lando db reset re-applies the same filtering when it reinstalls modules:

{
  "schema": 1,
  "theme": "panda",
  "presets": ["panda"],
  "excludePatterns": ["stblog*", "steasybuilder*"]
}

Sandboxes created on 0.6.x are auto-lifted on first write — see the migration guide for the legacy → v1 schema mapping.

Next steps

On this page