sympress / cli
Standalone Symfony Console CLI for creating configured SymPress projects from starter templates.
Requires
- php: ^8.5
- ext-json: *
- symfony/console: ^8.0
- symfony/filesystem: ^8.0
- symfony/process: ^8.0
Requires (Dev)
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^11.5
- squizlabs/php_codesniffer: ^3.13
- symfony/dotenv: ^8.1
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-06 18:19:30 UTC
README
Standalone Symfony Console CLI for creating configured SymPress projects from
Composer starter templates such as sympress/starter.
This package is intentionally independent from a website installation. It does not boot WordPress, does not require the SymPress kernel and does not need a starter project around it. The only runtime dependencies are PHP, Composer and Symfony components declared in this package.
The goal is similar to Symfony Maker's guided flow, but for a complete project: choose a starter, choose the project type, fill the important first-run values, review package suggestions, then let the wizard create and configure the project.
Install
composer global require sympress/cli
After a global Composer install, make sure Composer's global vendor/bin
directory is in your shell PATH, then run:
sympress --help
Install directly from GitHub before a Packagist release:
composer global config repositories.sympress-cli vcs https://github.com/SymPress/cli composer global require sympress/cli:dev-main sympress --help
Clone and run locally:
git clone https://github.com/SymPress/cli.git
cd cli
composer install
bin/sympress --help
From the local SymPress workspace:
cd cli
composer install
bin/sympress --help
Create A Project
Interactive:
sympress new
With a target directory:
sympress new my-site
Non-interactive examples:
sympress new customer-portal \
--type=app \
--name="Customer Portal" \
--package-name=acme/customer-portal
sympress new content-sync-service \ --type=microservice \ --no-setup \ --package=sympress/orm \ --package=sympress/migration
sympress new shop-platform \ --type=commerce \ --package=wpackagist-plugin/woocommerce
Use a repository-provided manifest:
sympress new my-site --template-version=<reviewed-tag-or-SHA> --allow-template-execution
The CLI also tries to discover a manifest in the selected template repository by default, from the same resolved immutable Git SHA used to materialize the template. Use --no-remote-manifest with an explicit local/offline catalog when discovery is unnecessary; creation still resolves a non-SHA selected version before download.
Update A Project
Projects created by the CLI contain .sympress/project.json. Run sympress update anywhere inside that project to update it later:
sympress update --level=patch
Update levels are intentionally conservative:
patch: refresh metadata and missing package recommendations for the current project type.minor: allow changing the project type, for example frommicroservicetoapporwebsite; missing recommendations for the new type are added.major: allow project type changes and starter template/repository changes.
Examples:
sympress update --level=minor --type=app sympress update --level=minor --type=website --no-install sympress update --level=major --template=sympress-starter --type=website
By default the update command patches composer.json, updates
.sympress/project.json and runs composer update for newly added packages. Use
--dry-run to inspect the plan and --no-install to skip Composer execution.
What It Does
- Resolves the selected version/ref once to an immutable Git SHA, clones without checkout and checks out that SHA detached with Git hooks disabled. Composer installation, root scripts and plugins are not executed during materialization.
- Writes project metadata and selected package suggestions to
composer.json. - Creates
.envfrom.env.exampleand fills first-run values:WP_HOME,WP_SITEURL,WP_ADMIN_USERNAME,WP_ADMIN_PASSWORD,DDEV_PROJECT_NAMEandDDEV_PROJECT_TLD. - Writes
.sympress/project.jsonso future update runs know the project type, starter template, repository and actual immutable template SHA. - Runs the setup command from the checked-out manifest only when --allow-template-execution explicitly authorizes it. --no-setup and dry-run never execute setup.
Project Types
The default catalog ships with these profiles:
website: editorial site with assets, consent and cache suggestions.app: portal or application with ORM, migrations, events and mail.microservice: lean service boundary with events, mail, ORM and migrations.commerce: WooCommerce-oriented project with operational tooling.
Useful Options
sympress project:create [directory] [options]
--template=sympress-starter--type=website|app|microservice|commerce--name="Acme Website"--project-slug=acme-website--package-name=acme/website--package=vendor/name[:constraint]--dev-package=vendor/name[:constraint]--no-suggested-packages--repository=https://github.com/SymPress/starter--template-version=1.1.8--manifest=./sympress-cli.json--manifest=https://github.com/SymPress/starter--manifest-ref=<40-character-Git-SHA>--no-remote-manifest--allow-template-execution--no-setup--dry-run
Update options:
--level=patch|minor|major--type=website|app|microservice|commerce--template=sympress-starter--repository=https://github.com/SymPress/starter--template-version=1.1.8--manifest=./sympress-cli.json--manifest-ref=<40-character-Git-SHA>--no-remote-manifest--no-install--dry-run
Repository Manifest
A starter repository can ship one of these files:
.sympress/cli.json.sympress-cli.jsonsympress-cli.json
When the starter changes, update this manifest in the starter repository. The CLI will pick it up on the next run, so setup commands, project types and package suggestions can evolve with the repository instead of being hardcoded in the CLI.
New projects default to the stable Starter 1.1.8 tag. An explicitly selected version and its verified commit remain fixed even when the catalog at that commit advertises a different default. Repository and Composer package identities must still match before any project is materialized.
Example:
{
"$schema": "https://raw.githubusercontent.com/sympress/cli/main/schema/repository-manifest.schema.json",
"schemaVersion": 1,
"templates": [
{
"id": "sympress-starter",
"label": "SymPress Starter",
"packageName": "sympress/starter",
"repositoryUrl": "https://github.com/SymPress/starter",
"description": "DDEV-ready SymPress WordPress starter.",
"defaultVersion": "1.1.8",
"setupCommand": ["bin/console", "setup", "{project_slug}"]
}
],
"profiles": [
{
"id": "website",
"label": "Website",
"description": "Editorial WordPress site with SymPress defaults.",
"exampleName": "acme-website"
}
],
"packageSuggestions": [
{
"name": "sympress/assets",
"label": "Assets",
"description": "Asset registration and output filtering.",
"recommendedProfiles": ["website"]
},
{
"name": "sympress/profiler",
"label": "Profiler",
"description": "Development profiler.",
"dev": true,
"recommendedProfiles": ["website"]
}
]
}
The canonical format is defined by
schema/repository-manifest.schema.json.
Malformed entries fail as a whole instead of being silently ignored.
Repository manifests are read from the same selected immutable SHA as template files; there is no fallback to main. A snapshot manifest cannot redirect the already selected package/repository/default ref. Explicit raw HTTPS JSON URLs and local files are independent catalogs with their own provenance; remote Git catalogs require a 40-character --manifest-ref. Materialization still inspects the checked-out manifest before setup.
--allow-template-execution authorizes setup commands and all executable behavior those commands invoke (including Composer scripts/plugins). Review the repository, SHA and argv before using it. Without the flag, setup refuses before cloning; --no-setup can be used to inspect the source first. No shell is used and command failures propagate. The initial Git clone/checkout stage disables Git hooks and does not run Composer. A created project records the immutable SHA; update catalog loading follows the selected target SHA, and changing source/version invalidates the previous recorded identity.
Dotenv literal values round-trip comments, dollars, quotes, backslashes, Unicode and whitespace. Only WP_SITEURL intentionally expands ${WP_HOME}/wp. The .env file is created/written with mode 0600. Completion and dry-run output never print an admin password; the credential is stored privately in .env.
Extending
The command is intentionally thin. Prefer changing repository manifests for starter-specific behavior. Built-in fallback defaults live in these catalog classes:
SymPress\Cli\Catalog\DefaultTemplateCatalogSymPress\Cli\Catalog\DefaultProfileCatalogSymPress\Cli\Catalog\DefaultPackageCatalog
The generator layer is split into:
ProjectGeneratorfor orchestration.ComposerJsonEditorfor package and metadata changes.EnvFileEditorfor first-run environment values.CommandRunnerfor process execution, so tests can swap it out.
Quality Checks
composer qa
The repository workflow calls the shared sympress/workflows QA workflow. Org
level issue templates, pull request template, security policy and contribution
guidelines are provided by the SymPress .github repository.
License
GPL-2.0-or-later. See LICENSE.