Plone deployment CLI.
plonex is a helper tool designed to simplify everyday project operations with Plone.
Note
At the moment plonex is in early development and may have breaking changes. Use with caution and report issues.
If you just want to test plonex, you can initialize a new project and run the ZEO server and client with these commands:
plonex project init myproject
cd myproject
plonex supervisor startThe generated configuration starts ZEO and the WSGI client under Supervisor in
the background. Use plonex supervisor status to check them. Runtime files are
generated from your YAML configuration.
Your site will be available at http://localhost:8080.
When you run a command, plonex does more than simply spawn a process:
- it finds the correct project root (a parent folder containing a file named
etc/plonex.yml) - it loads and merges configuration from all supported files
- it prepares temporary/generated config files when needed
- it exports environment variables defined in configuration
- it runs the appropriate executable from your virtualenv
This means commands are reproducible and configuration-driven.
You change behavior in YAML files (or CLI flags), and plonex applies that
consistently across services.
Use plonex RESOURCE ACTION [options] across the CLI:
plonex project compile
plonex sources list
plonex sources update
plonex dependencies install --update-sources
plonex dependencies sync
plonex instance debug
plonex db backup
plonex test pytest my.package -k loginproject, dependencies, sources, instance, supervisor, db, cron, and test
provide command families. shell and options provide interactive access and
inspection. Each operation has one built-in spelling. Removed shortcuts and flags are listed
in the CLI structure and migration guide. Bare command families show help.
Add this to your shell startup file:
eval "$(register-python-argcomplete plonex)"Start a prompt for your current project with plonex shell, or choose a project:
plonex shell --target /path/to/projectEnter the same commands and arguments you use at the command line, without the
plonex prefix:
plonex[myproject]> supervisor status
plonex[myproject]> dependencies sync
plonex[myproject]> sources list "plone.*"
plonex[myproject]> test robot tests/robot/example.robot --test "Login works"
plonex[myproject]> help dependencies
plonex[myproject]> exit
- Tab completes commands, subcommands, flags, and paths when readline is available.
- Up/Down recall commands from this project's current and previous sessions.
historylists remembered commands. History is stored invar/plonex-shell-historyunder the target project with owner-only permissions. Commands with recognizable credentials are omitted, but avoid placing secrets in command arguments: detection cannot recognize every possible secret.helplists commands;help COMMANDandCOMMAND --helpshow command help.exit,quit, or Ctrl-D leave the shell. Ctrl-C cancels the current input or interrupts a running command and returns to the prompt.- In an interactive terminal, Ctrl-Z returns to the prompt without stopping the current command. The server stays available for requests and upgrades.
- Blank lines and lines beginning with
#are ignored. - Quoting, escaped spaces, and
--work as they do in the CLI. Arguments are passed directly to plonex; pipes, redirects, variable expansion, and wildcard expansion are not interpreted by this prompt.
The shell uses the selected project as its working directory. Each command runs in a fresh process using the same Python installation as plonex, so configuration is reloaded and command-specific environment variables do not leak into later commands. Errors leave the prompt open.
Startup --verbose or --quiet flags become session defaults. An explicit -v
or -q on a command overrides those defaults for that command. To run a command
against another project without changing the session target, use
--target /other/project COMMAND. The optional plonex prefix is also accepted.
You can return to the prompt to run an upgrade, then reconnect to the same instance:
plonex[myproject]> instance debug
... instance starts; press Ctrl-Z ...
plonex[myproject]> instance upgrade
plonex[myproject]> fg
... back to the same instance and its live output ...
The shell keeps detached commands running and records their output under
var/log/shell/ (or your configured var_folder). Background logs do not print
over the prompt. On reconnect, the shell shows up to 64 KiB of output you missed,
then streams live output. Full logs remain on disk.
jobs: show a Markdown-style table of job IDs, service names, coloured states, process IDs, commands, and log locations. Running jobs are green, successful exits cyan, failures red, and signal exits yellow. Terminal colour settings, includingNO_COLOR, are respected.jobs --markdown: export a plain Markdown table without ANSI colour codes.fgorattach: reconnect to the most recent running job.fg %1orattach %1: reconnect to a specific job.logs %1: show that job's latest output without reconnecting.options %1: inspect the resolved service options captured when that job started.bg %1: leave or resume a job in the background.kill %1: stop the job and its foreground process group.instance debug &: start an instance directly in the background. A trailing, unquoted&preceded by a space works with other plonex commands too.
Job IDs also accept plain numbers. Commands that take a job ID default to the
most recent running job. instance debug --port 8081 starts another instance.
Ctrl-C while attached stops the foreground command; Ctrl-Z detaches it.
Exiting the shell stops jobs it owns, including detached instances. Job control
requires an interactive terminal; piped shell commands retain their usual behavior.
Preview a service using the same defaults, merged configuration, aliases, and argument handling as normal execution:
plonex options instance debug --port 8081
plonex options instance start --name worker --config etc/worker.yml
plonex options test pytest my.package -k login
plonex options --markdown dependencies syncThe report includes service constructor arguments, command flags, configuration file locations, and resolved options, including nested environment settings. The service is constructed but not entered or run: inspection does not launch the service, install dependencies, or render runtime files. Existing constructors may create directories, and normal configuration resolution still applies, including fetching remote Git profiles when configured.
In the shell, use a job ID to see its startup snapshot, or a command to preview current configuration:
plonex[myproject]> jobs
plonex[myproject]> options %1
plonex[myproject]> options %1 --markdown
plonex[myproject]> options instance debug --port 8082
Job snapshots are captured by the service process before it exports environment variables or runs helper services. They remain available after the job exits and do not change when YAML files are edited. A snapshot may be unavailable while a job is starting, or if it fails before entering its service. Help/version jobs do not have service options.
Inspection masks conventional password, token, and secret keys, known credential arguments, and passwords in URLs. Snapshots are stored with owner-only file permissions next to job logs. Ordinary process output in log files is unchanged.
Define shortcuts in etc/plonex.yml:
aliases:
start: supervisor start
stop: supervisor stop
test_whatever: pytest my.package
test_unit: [pytest, my.package, -k, "not integration"]Then run them as ordinary commands:
plonex start
plonex test_whatever -k login -x
plonex --target /path/to/project test_unit -qAn alias is one command, expressed as a quoted command string or a list of
argument tokens. Extra arguments are appended to its expansion. In the examples,
test_whatever -k login -x runs pytest my.package -k login -x. Values may
optionally start with plonex. Quotes preserve arguments containing spaces;
commands are not evaluated as shell code.
Aliases can refer to other aliases, but loops produce an error. Built-in command
names and shell commands such as help, history, exit, jobs, and attach cannot be replaced.
Aliases appear in project help and Tab completion, work in plonex shell, and can
be used by default_action or default_actions. Edits take effect on the next
shell command or completion.
Aliases use the same profile and local configuration precedence as other
options. To extend or override individual aliases inherited from a profile, use
the existing + mapping syntax:
+aliases:
test_whatever: pytest my.other_packageAll commands accept these options:
plonex [--target PATH] [--verbose] [--quiet] [--version] <command> ...
-t, --target: target project folder (defaults to current directory).-v, --verbose: set log level toDEBUG.-q, --quiet: reduce log output (WARNINGand above).-V, --version: print installed plonex version.
For all commands except init, plonex resolves the target by walking upward until it finds etc/plonex.yml.
If you run plonex without a command, it displays the help message unless a
default action is configured in etc/plonex.yml.
plonex separates intent from implementation.
You declare intent with simple commands such as plonex instance start or
plonex db pack, and plonex translates that into the correct low-level command,
with the correct paths, environment variables, and generated configuration files.
This approach has a few practical benefits:
- You do not need to remember long binary paths or many flags.
- Team members can share the same commands while keeping local overrides in YAML.
- Automation in CI can reuse exactly the same command set used locally.
In other words, plonex behaves like an orchestration layer over project runtime
tools, while still letting you control details through configuration.
You can still see what happens when you run a command passing the -v/--verbose flag or setting log_level: debug in YAML.
This is useful for troubleshooting and understanding the underlying behavior.
You can configure what happens when you run plonex with no explicit command.
By default, plonex shows the command help.
If you want a different behavior, set either default_action or
default_actions in etc/plonex.yml.
For example, to ensure supervisor is started and then run WSGI client is run in the foreground, you can set:
default_actions:
- supervisor start
- supervisor status
- instance debugYou can extend a project from one or more profiles declared in etc/plonex.yml.
Example:
profiles:
- /path/to/plonex-profile
- https://github.com/example/plonex-profile.git
http_port: 8081Profile configuration is loaded before the local project configuration, so the
local etc/plonex.yml remains the highest-precedence place for site-specific
overrides such as ports, hostnames, and service settings.
Profiles can themselves declare profiles, which allows a profile to extend
another profile before the local project overrides both.
Relative profile paths in the project etc/plonex.yml are resolved from the
project root. Relative profile paths declared inside a profile are resolved from
that profile root.
One practical way to organize profiles inside a repository is:
myproject/
├── etc/
│ └── plonex.yml
└── profiles/
├── default/
│ └── etc/
│ └── plonex.yml
├── production/
│ └── etc/
│ └── plonex.yml
└── development/
└── etc/
└── plonex.yml
For example, profiles/default/etc/plonex.yml can hold shared defaults used by
every environment:
plone_version: 6.2.0
http_address: 0.0.0.0
zeo_address: var/zeo.sock
environment_vars:
TZ: Europe/RomeThen profiles/production/etc/plonex.yml can extend default and add
production-specific values:
profiles:
- ../default
http_port: 8080
debug_mode: falseAnd profiles/development/etc/plonex.yml can also extend default but keep
more developer-friendly settings:
profiles:
- ../default
http_port: 8081
debug_mode: true
log_level: debugFinally, the project etc/plonex.yml chooses which profile to inherit from and
keeps the final local overrides:
profiles:
- profiles/development
http_port: 8082In this example the resulting http_port is 8082, because the local
etc/plonex.yml overrides profiles/development, which overrides
profiles/default.
plonex generates a merged var/constraints.txt for installation.
By default it starts from the Plone release constraints selected by
plone_version. The generated etc/plonex.yml does not include a
plonex_base_constraint entry unless you decide to add one.
Default behavior:
plone_version: 6.2.0This means the base constraint is effectively:
https://dist.plone.org/release/{{ plone_version }}/constraints.txtIf you want to override that base, add
plonex_base_constraint.
Supported values are:
- remote URLs
- local files relative to the project root
resource://package:pathreferences
Examples:
plonex_base_constraint: https://example.org/constraints/base.txtplonex_base_constraint: etc/constraints/base.txtplonex_base_constraint: resource://my.package:constraints/base.txtUse a plain URL in YAML, without Markdown link syntax. For GitHub files, copy the
Raw URL from raw.githubusercontent.com, rather than the /blob/ page URL.
Remote constraints, including nested -c and -r references, are merged into
var/constraints.txt. Local pins override remote pins, and packages installed in
editable mode are excluded. HTML responses and invalid remote requirements cause
a warning and stop generation, preserving the previous constraints file.
Generated package names use lowercase and replace runs of dots, underscores, or
hyphens with a single hyphen: zope.sendmail==7.2 becomes
zope-sendmail==7.2. This also applies to suggested and saved pins, added packages,
and direct pip_requirements. Versions, environment markers, paths, and URLs keep
their original spelling.
Note
If an old etc/constraints.d/000-plonex.txt file still exists, plonex warns
that it is ignored and suggests removing it. For compatibility, if neither
plone_version nor plonex_base_constraint is configured, plonex still tries
to infer plone_version from that legacy file.
Single action examples:
default_action: project describedefault_action: instance startEquivalent list form:
default_action:
- instance startIf you want to run multiple commands in sequence, use default_actions:
default_actions:
- supervisor start
- instance startThis is useful when you want plain plonex to bootstrap a common local
workflow, for example starting Supervisor first and then bringing up the client.
Notes:
default_actionsruns in order.- each action can be written as a shell-like string or a list of tokens.
- command-line global options such as
-vand-qstill apply.
plonex project init myproject
cd myproject
plonex supervisor start
plonex supervisor statusSupervisor starts the generated ZEO and WSGI programs in the background. For interactive development, the shell workflow below gives direct debugger input.
plonex shell
plonex[myproject]> db start &
plonex[myproject]> instance debug
... press Ctrl-Z to return to the prompt ...
plonex[myproject]> options %2
plonex[myproject]> instance upgrade
plonex[myproject]> fg %2
Ctrl-Z detaches without stopping the server. jobs lists the actual IDs;
logs %2 reads output and kill %2 stops that job. fg only reattaches jobs;
start new instances with instance debug. Exiting the shell stops its jobs.
Use an already-running ZEO server instead of starting a second one when your
project is configured with a shared database.
Declare its repository and editable installation together:
sources:
my.addon:
repo: git@github.com:example/my.addon.git
rev: main
install: true
extras: [test]plonex sources clone
plonex dependencies install
plonex sources listEditable installs use the checkout directly. A monorepo can add subdirectory;
path selects a custom checkout folder. Remove corresponding manual -e entries
when migrating. Distribution names such as my-addon are canonicalized, while
Python import names such as my.addon retain their dots.
Check both the declaration and actual installation:
plonex project describe sources
plonex project describe dependenciesThe source should have install: true, and its installed metadata should identify
the expected checkout as editable. A running process can still hold imported
Python modules; restart the instance after code changes when required. Dependency,
extra, or packaging changes need another dependencies install. An ordinary
editable: false installation contains built code rather than live source files.
plonex sources update
plonex dependencies install
plonex dependencies sync
plonex dependencies outdatedinstall preserves unrelated installed packages. sync resolves the declared
requirements and removes packages outside that environment. To combine checkout
updates with installation, use dependencies install --update-sources.
Output reports actual changes; an unchanged run prints No package changes.
Use pip_requirements or etc/requirements.d/*.txt for requirements and
etc/constraints.d/*.txt for pins. These can also come from profiles.
When constraint fragments in the same directory pin the same package, the first
filename in alphabetical order takes precedence. Project constraints take
precedence over profile constraints.
dependencies add 'my-addon[test]' records a requirement and installs it.
Save missing pins with dependencies install --persist-local; the local pin file
stays separate from shared constraints. Use a raw text URL for
plonex_base_constraint, rather than a GitHub /blob/ HTML page.
plonex project describe configuration --key http_port
plonex project describe configuration --key http_port instance debug --port 8081
plonex project describe analytics instance debug
plonex project describe profilesThe configuration report shows the resolved value, winning definition, earlier
values, and Jinja references. Adding a command inspects that command's defaults,
service-specific files, extra files, and CLI overrides. Analytics shows override
chains and configuration dependencies. Sensitive fields and derived secrets are
redacted. Use --format json for automation.
Put machine-specific overrides in etc/plonex.local.yml. Mappings and lists
normally replace earlier values. +sources adds or replaces complete source
entries, and +pip_requirements appends requirements. A source entry is itself
replaced, so include its repository and other settings when overriding it.
Use project describe configuration --key sources to inspect the result.
plonex project describe --format html --browse
plonex project describe runtime --browse
plonex project describe jobs --browseThe complete report is var/plonex_description/index.html. It has responsive
layout, section navigation, search, file links, and definition history. Markdown
and JSON exports sit alongside it. Focused reports use their section name and
preserve the complete report. Existing file paths in the HTML report are clickable,
including configuration history. Open the report on the project host: browsers may
block local file links from a web server, and they decide whether to display or
download each file. Inspection does not install, compile, export the configured
environment, or start application services.
plonex project doctor
plonex project doctor --format json
plonex supervisor start --planThe doctor reports configuration, virtualenv, source installation, constraint,
preparation, and local service problems with suggested next steps. It does not
install packages or change the project. Use --strict to make warnings fail a CI
check. See the doctor reference for its scope and
limitations.
plonex project snapshot create --output deployment.json
plonex project snapshot compare deployment.json
plonex project snapshot prepare deployment.json --to /path/to/new-venvSnapshots capture installed versions, source revisions, and dependency inputs. Preparation verifies supported inputs before creating a separate environment. See project snapshots for limitations and reproducibility.
Run plonex --target /path/to/project project inspect-legacy. The report reads
local configuration without running recipes or modifying the project. The
CLI reference shows how to consume mxdev's
generated files while leaving mxdev in charge of generating them.
plonex dependencies add pytest
plonex test pytest my.addon -k login -x --pdb
plonex test zope my.addon -t Login
plonex test robot tests/robot/login.robot --browser firefoxInstall the add-on's testing extras and the runner it needs. Use Python import
names for package-based tests. Arguments after the package in test pytest
go to pytest, including -k, -x, and --pdb. The shell preserves terminal input
for interactive debugging.
plonex instance run -- scripts/maintenance.py --argument value
plonex instance consoleThe console provides app. To establish a Plone site context:
from Testing.makerequest import makerequest
from zope.component.hooks import setSite
from zope.globalrequest import setRequest
app = makerequest(app)
setRequest(app.REQUEST)
site = app["Plone"]
setSite(site)Use plone.api.env.adopt_user(username="your-user") for an explicit application
user context when needed. Commit intended database changes with
transaction.commit(); abort discarded changes with transaction.abort().
See Plone's console documentation.
Keep the configured application running, then run plonex instance upgrade.
Install and enable collective.ftw.upgrade in the target project and site. Set
upgrade_tempfile_auth: true in YAML and restart the instance to enable private
temporary-file authentication for the same OS account. The default instance URL
uses the configured HTTP port; select another running instance with
plonex instance upgrade --url http://127.0.0.1:8081/. Alternatively configure
the upgrade tool's authentication and URL environment variables explicitly.
In the shell, detach the instance with Ctrl-Z, run the upgrade, and reattach.
Review and back up the database before planned deployment upgrades.
plonex supervisor start ensures that declared dependencies and generated runtime
files are current before starting Supervisor. It skips unchanged work. Requirement
and constraint changes trigger installation checks; changing an HTTP port only
regenerates affected runtime files.
plonex supervisor start --plan
plonex project describe preparationThe plan explains stale tasks and their prerequisites without executing them.
Preparation never implicitly updates Git sources, removes unused packages, runs
Plone upgrades, or restarts existing instances. Use dependencies sync for package
removal and explicit Supervisor commands to apply changes to running services.
See incremental preparation for caching, failures, and
remote profile behavior.
plonex supervisor reread
plonex supervisor update
plonex supervisor statusupdate applies changed program declarations. restart restarts all managed
programs; graceful --interval 2 restarts them sequentially. Neither should be
confused with editing the currently running process's configuration in memory.
options %JOB reports a shell job's startup snapshot even after YAML changes.
cron_timezone: Europe/Rome
cron_jobs:
StoreSessionStats:
schedule: "15 2 * * *"
callable: my.addon.jobs:store_session_stats
site: /Plone
context: sectors
user: scheduler
timeout: 900
lock: zope
lock_timeout: 300
enabled: falseMove the business logic into the callable, installed in the project virtualenv.
Create the named Plone user with the roles it needs; no password belongs in this
job declaration. Test with cron run StoreSessionStats, inspect cron logs and
cron history, then enable the schedule and apply Supervisor configuration.
Job runtimes are installed into the target virtualenv through the optional
plonex[jobs] requirement. The CLI itself does not need Huey. Supervisor launches
the target interpreter directly. Manual-only job declarations still keep a worker
for explicitly queued tasks.
A protected browser view can call the same function after POST and authenticator checks. The job runs through a dedicated ZEO client and owns its transaction; it does not invoke the browser view or disable CSRF. See the complete scheduled-job guide, including a protected view example.
plonex cron list
plonex cron status
plonex cron queue
plonex cron history StoreSessionStats
plonex cron logs StoreSessionStats --tail 100
plonex project describe jobs --browseSchedules use explicit IANA timezones, defaulting to UTC. Common lock names serialize related jobs; manual and daemon runs share those locks. Timeouts stop the job subprocess group and record the outcome. Retries default to zero; enable them only for work that tolerates repeating after a failure. The queue survives restarts, but missed periodic schedules are not replayed.
plonex cron status
plonex cron queue
plonex cron inspect TASK_ID
plonex cron retry TASK_ID
plonex cron revoke TASK_ID
plonex project describe queueMonitoring uses Huey's statistics extension in the target environment. Task IDs
link events to individual attempts and logs. retry creates a new task using the
current definition; revoke prevents a queued execution and does not kill a
running process. Add --format json for complete task IDs and structured output.
See the queue guide.
There are no built-in synonyms such as both --sync and sync. Use
dependencies sync, dependencies outdated, instance debug, and
project describe. Update aliases, default command lists, deployment scripts,
and Supervisor command values from older projects. Configuration identities
such as run_for: fg and etc/plonex-runwsgi.yml retain their meaning.
The CLI migration table lists every removed form.
plonex project init .
plonex supervisor start
plonex shellWhat happens:
initcreates project skeleton and base config.initcreates.venvand installs the configured dependencies.supervisor startstarts the configured ZEO and WSGI services in the background.shellopens a prompt for project commands. Usesupervisor statusthere to check managed services.jobslists processes launched by the current shell; Supervisor services are managed separately.
plonex db pack --days N
plonex db backupWhat happens:
db packreadszeo_addressfrom merged options and callszeopack.db backuprunsrepozoagainst the project Data.fs location.
plonex supervisor start
plonex supervisor status
plonex supervisor restart
plonex supervisor graceful --interval 2.0What happens:
plonexgeneratestmp/supervisor/etc/supervisord.confand service templates if needed.- it runs
supervisordandsupervisorctlfrom your project virtualenv. plonex supervisor gracefulrestarts each configured service one by one in the order reported bysupervisorctl status.--intervalcontrols the pause between service restarts. The default interval is1second.
You can also set the default interval in YAML:
supervisor_graceful_interval: 10Put that in etc/plonex.yml or another merged plonex config file.
The CLI flag
still wins over YAML when both are provided.
shell [--target PATH]
- Open the interactive project shell, including aliases, completion, job control, logs, and startup option inspection. See Interactive shell.
options [--markdown] <command> [arguments ...]
- Preview effective service arguments and options without running the service.
- In the interactive shell,
options [JOB]inspects a recorded job snapshot; omitting the job ID selects the most recent running job.
project init [target]
- Initialize project folders and base config.
- If
targetis omitted,plonexprompts for a folder and suggests the current directory as the default.
project compile
- Compile merged configuration into
var/plonex.yml. - If
sourcesis configured, compile also generatesvar/gitman.yml. - The default checkout location is
srcwhensources_locationis omitted.
Example:
sources:
my.package:
repo: https://github.com/example/my.package.git
rev: mainproject describe
- Render a project description from current configuration.
- Always export responsive HTML, Markdown, and JSON under
var/plonex_description/. - Select a section:
overview,configuration,analytics,profiles,environment,sources,dependencies,services,runtime,files,jobs, orpreparation. --format terminal|markdown|html|jsoncontrols stdout;--browseopens HTML.configuration --key OPTION [COMMAND ...]explains definitions and overrides.- Inspection does not compile configuration, install packages, or start services.
dependencies {install|sync|outdated} [options]
- Install from merged requirements/constraints.
sync: compile requirements/constraints and runuv pip syncusing the compiled requirements file as positional input.outdated: runuv pip list --outdated. Use this explicit action instead of an installation flag.-p, --persist: save auto-detected missing constraints into the project'setc/constraints.d/.--persist-local: save auto-detected missing constraints into a local (git-ignored)etc/constraints.d/999-autoinstalled.local.txt.--persist-profile: save auto-detected missing constraints into the first configured profile'setc/constraints.d/.--update-sources: update sources before installing dependencies (uses Gitman under the hood).
Dependency installation prints only package changes and relevant diagnostics:
Added my-package==1.0
Upgraded zope-sendmail: 7.2 → 7.3
Removed unused-package==2.0
An unchanged environment prints No package changes. Reinstalls, downgrades,
and source changes are reported as well. Use --verbose to see full uv output.
The internal package inventory used for checking pins is captured silently;
missing-pin suggestions and resolver/build failures remain visible.
To enable source updates by default in project configuration:
sources_update_before_dependencies: true
sources:
my.package:
repo: https://github.com/example/my.package.git
rev: mainTo install a checkout in the project virtualenv, set install: true. Installs
are editable by default, so Python code changes are available without reinstalling:
sources:
ploneintranet:
repo: git@github.com:quaive/ploneintranet.git
rev: master
install: true
extras: [test]
pas.plugins.oidc:
repo: git@github.com:collective/pas.plugins.oidc.git
install: true
reference.package:
repo: https://github.com/example/reference.package.git
install: falseRun plonex sources clone followed by plonex dependencies install, or use
plonex dependencies install --update-sources to update checkouts and install in one step.
plonex dependencies sync also supports these selections. Source declarations
without install: true remain checkout only. sources list shows each source's
installation selection alongside checkout health; it does not inspect the virtualenv.
Each selected source also accepts:
extras: [test, debug]: optional dependency extras, with canonical package naming.editable: false: build and install the local project normally; rerun dependencies after changing its code.path: vendor/my-checkout: override the checkout path, relative to the project (an absolute path is also supported). Otherwise usesources_location, defaultsrc.subdirectory: packages/backend: install a Python project inside a repository. This must be a relative path within the checkout.
Package names come from static pyproject.toml, setup.cfg, or literal setup.py
metadata, falling back to the project directory name. Selected packages are removed
from both base and local constraints, so release pins cannot override the local
checkout. Missing checkouts and directories without pyproject.toml or setup.py
produce an actionable error before installation. Source updates regenerate the
dependency files after reading the updated metadata.
uv currently cannot resolve editable checkout paths containing # or ?; move
the checkout or use editable: false in that case.
Put machine-specific selections in etc/plonex.local.yml. Configuration uses the
normal mapping replacement rules: if you override sources, include the entries
you want to keep; +sources adds or replaces complete source entries. Remove old
-e src/... entries from pip_requirements and etc/requirements.d/ when migrating
to source declarations, including their extras. Those requirement mechanisms remain
supported. Disabling a source stops requesting it; use dependencies sync to
remove it if nothing else requires it.
See development next steps for proposed environment checks, test selection, and debugging improvements.
dependencies add <package> [<package> ...]
- Add one or more packages and run dependency installation.
sources {list|clone|update|missing|tainted|suggest} [options]
- Manage configured source checkouts (uses Gitman under the hood).
update: run a regular sources update (executed by Gitman).update --force: run a forced update (--force), asking for confirmation by default.update --force --yes: skip confirmation.tainted: list checkouts with local changes.list: show configured checkouts and whether each is clean, tainted, or missing.missing: show configured checkouts that are not present on disk.clone: clone missing configured checkouts (usingrepoand optionalrev).clone --yes: skip confirmation prompt before cloning.suggest: inspect existing unmanaged checkouts and print a ready-to-paste YAML snippet foretc/plonex.ymlwith inferredrepoandrev.suggest --apply: write inferred entries intoetc/plonex.yml.suggest --apply-local: write inferred entries intoetc/plonex-sources.local.yml.suggest --apply-profile: write inferred entries into theetc/plonex.ymlof the first configured profile.
When unmanaged existing checkouts are detected, sources list and sources tainted
also print a suggested sources section to add into etc/plonex.yml.
sources list includes unmanaged checkouts in the table, marked unmanaged with
their branch, repository, and checkout health. The highlighted YAML suggestion
appears in a separate panel. Name filters apply to both rows and suggestions;
Git inspection output stays inside the report.
instance upgrade
- Run Plone upgrade steps.
There is a dedicated plonex project edit command to help you edit the configuration files for your plonex project.
You can use --all to open all discovered config files in your editor, otherwise you can select which files to edit interactively.
The selected editor:
- with the
--editoroption in the command line - with the
editoroption if specified in theetc/plonex.ymlconfiguration file - can be configured with the
EDITORenvironment variable - use the
opencommand as a fallback if none of the above is specified.
You can of course edit the configuration files manually, but plonex project edit helps you discover and open them quickly.
db start
- Start ZEO server.
instance start [options] [args ...]
- Options:
-n, --name: service name (default:runwsgi)-c, --config: extra config file (repeatable)-p, --port: HTTP port--host: HTTP host
instance console [options]
- Options:
-n, --name: service name (default:zconsole)-c, --config: extra config file (repeatable)-p, --port: HTTP port--host: HTTP host
- Open an interactive Zope console. Use
instance runfor scripts.
instance run [args ...]
- Run a script through
zconsole runwith generated runtime config.
instance add-user [-c FILE] <username> [password]
- Create a Zope user (password can be omitted to auto-generate one).
supervisor {status|start|stop|restart|graceful|reread|update}
- Manage supervisord for project services.
gracefulaccepts--interval SECONDSand falls back tosupervisor_graceful_intervalfrom YAML, defaulting to1.0.rereaddetects changed program declarations;updateapplies them.restart PROGRAM ...restarts selected programs; omit names to restart all.
db backup
- Create a verified offline snapshot of FileStorage and blob storage.
db pack [--days DAYS]
- Pack ZODB revisions older than
DAYS(default:7). - Uses merged
zeo_addressfrom your config files.
db restore --to NEW_DIRECTORY [--from SNAPSHOT_DIRECTORY]
- Recover into a new directory without replacing the live database. See database backup and recovery.
test pytest <package-or-path> [pytest arguments ...]
- Runs
.venv/bin/python -m pytest --pyargs PACKAGEin the target project, with its configured environment and pytest settings. Install pytest in that project's virtualenv first. - Accepts importable Python package names, test directories, files, and node IDs.
- Arguments after the package are passed to pytest, including
-k,-m,-x,-q,-v, and plugin flags. An optional--after the package is accepted. - Put plonex logging flags before
pytest; for example,plonex -v test pytest my.package -qenables plonex diagnostics and quiet pytest output. Test failures preserve pytest's exit status.
plonex test pytest my.package -k login -x
plonex test pytest src/my.package/tests -q
plonex test pytest tests/test_login.py::test_login -vtest zope <package> [-t TEST]
- Run
zope-testrunnerfor a package.
test robot-server [--layer LAYER]
- Start robot test server.
test robot <paths...> [--browser BROWSER] [-t TEST]
- Run Robot Framework tests.
Options are merged in this order (higher wins):
- CLI options
- Files passed with
-c/--config etc/plonex-<service>.*.ymletc/plonex-<service>.ymletc/plonex.*.yml(alphabetical precedence)etc/plonex.yml- Profiles declared by
etc/plonex.ymland nested profileplonex.ymlfiles - Service defaults
Why this matters:
- you can keep sane defaults in
etc/plonex.yml, - inherit shared defaults from one or more profiles,
- add machine- or developer-specific overrides in
etc/plonex.local.yml, - and still force one-off values from the command line when needed.
This is especially useful for paths like zeo_address, ports, or feature flags
that can vary by environment.
Useful settings include:
log_level:DEBUG,INFO,WARNING,ERROR,CRITICALenvironment_vars: environment variables exported before service executionzeo_address: socket/host used by runtime services anddb packblobstorage: blob storage pathhttp_port,http_address
Example:
zeo_address: /srv/components/zeo/var/zeo.socket
blobstorage: /srv/components/zeo/var/blobstorage
environment_vars:
TZ: Europe/RomeService-specific overrides are useful when one command needs different settings. For example:
etc/plonex.yml: shared defaults.etc/plonex.local.yml: local machine overrides (socket paths, local ports).etc/plonex-runwsgi.yml: runwsgi-only adjustments.
Because these files are merged with precedence, you can keep common settings in one place and make only small targeted overrides where needed.
Before running a command, plonex reads the optional .env and .env.local files
in the project root (the directory containing etc/plonex.yml). Both supply
variables to plonex and the services it starts, including Supervisor and its
child processes. .env.local overrides .env, so it can hold machine-specific
values. Other names, such as .env.production, are not loaded automatically.
Each file contains one NAME=value assignment per line. Empty lines, comments,
optional export, and shell-style single or double quotes are supported. Quote
values containing spaces or #. Values are literal: variable expansion, command
substitution, and multiline values are not supported. Either file may be absent.
When the same variable is defined in multiple places, the highest applicable setting wins:
- A job's
environmentsettings, for that job. A managed process may also define its own environment settings. - The service's resolved
environment_varsin YAML or configuration overrides. YAML files and-c/--configfollow the configuration precedence above. - Variables already exported in the shell that starts plonex (including an explicitly exported empty value).
- The project root
.env.local. - The project root
.env.
For example, start with these files in the project root:
.env:
COLOR=blue
TZ=Europe/Rome.env.local:
COLOR=greenWith no other definition of COLOR, a service receives COLOR=green and
TZ=Europe/Rome. Remove COLOR from .env.local and the service receives
COLOR=blue. To override both files for one command, run:
COLOR=red plonex instance startThe service now receives COLOR=red. To override it for a particular service,
add the following to etc/plonex-runwsgi.yml:
environment_vars:
COLOR: purpleThat service receives COLOR=purple, even when COLOR=red is exported in the
shell. Other services use their own resolved configuration. To override a YAML
setting for one invocation, create etc/one-off.yml:
environment_vars:
COLOR: yellowThen run plonex instance start --config etc/one-off.yml; that invocation
receives COLOR=yellow.
A scheduled job can override the service value for its own process. For example, in the applicable cron configuration:
cron_jobs:
example:
schedule: "*/15 * * * *"
command: ["/usr/bin/env"]
environment:
COLOR: orangeThis job receives COLOR=orange. Other jobs retain their own resolved values.
The environment files supply process environment variables; they do not
substitute values into YAML options. YAML environment_vars is an option mapping:
a higher-priority definition normally replaces the mapping, while +environment_vars can extend it in profile and additional project
configuration files that support + merges.
Plonex does not automatically load separate service-specific .env files.
Services may implement their own environment handling.
Keep files containing secrets out of version control and give them appropriate permissions; plonex does not create or configure the project's ignore rules. Restart running processes to pick up changes. The interactive shell reloads the files for each command.
plonex supports declarative helper services in etc/plonex.yml.
These services are not intended to be run directly as a top-level command.
Instead, they run automatically as dependencies of runtime commands.
This is useful when a command needs generated files before execution, for example Supervisor program snippets or other rendered templates.
Example:
services:
- template:
run_for: supervisor
source_path: resource://plonex.services.supervisor.templates:program.conf.j2
target_path: tmp/supervisor/etc/supervisor/runwsgi.conf
options:
program: runwsgi
command: plonex instance start
process_name: runwsgi
directory: "{{ target }}"
priority: 2In this example:
- the template is rendered only when running a command mapped to
supervisor, - the rendered file is prepared before
supervisord/supervisorctlis called, - and the dependency is fully controlled from YAML.
run_for accepts either a string or a list of command names:
services:
- template:
run_for: [supervisor, runwsgi]
source: etc/templates/runtime.conf.j2
target: tmp/runtime.confNotes:
- service entries must be a list of single-key mappings,
- unknown service names raise a configuration error,
- relative
source/targetpaths are resolved from the project target folder, resource://...template sources are supported.
Recommended pattern:
- keep long-lived defaults in
etc/plonex.yml, - keep machine-specific path overrides in
etc/plonex.local.yml, - add
run_foronly where generation must be scoped to specific commands.
More examples:
- Add extra ZCML includes for runtime services:
zcml_additional:
- etc/zcml/010-my-package-meta.zcml
- etc/zcml/020-my-package-configure.zcml
- etc/zcml/030-my-package-overrides.zcmlThese files are rendered or copied into tmp/runwsgi/etc/package-includes/
before plonex instance start ... runs. File names matter: plonex expects the
usual -meta.zcml, -configure.zcml, or -overrides.zcml suffixes.
- Add extra
zope.confsnippets for runtime services:
zope_conf_additional:
- etc/zopeconf/cache.j2
- etc/zopeconf/instancesettings.confFor example, etc/zopeconf/cache.j2 could contain:
<product-config my.package>
some-setting value
</product-config>
Each listed file is appended to the generated runtime zope.conf file.
Jinja templates can use the current service context.
- Generate a Supervisor program for an auxiliary service such as a websocket worker, Celery worker, or custom script:
services:
- template:
run_for: supervisor
source_path: resource://plonex.services.supervisor.templates:program.conf.j2
target_path: tmp/supervisor/etc/supervisor/worker.conf
options:
program: worker
command: .venv/bin/python -m mypackage.worker
process_name: worker
directory: "{{ target }}"
priority: 20That way plonex supervisor start manages not only zeoserver and
runwsgi, but also your additional long-running process.
- Combine service dependencies and runtime extras in the same project:
zcml_additional:
- etc/zcml/020-my-package-configure.zcml
zope_conf_additional:
- etc/zopeconf/cache.j2
services:
- template:
run_for: supervisor
source: etc/templates/worker.conf.j2
target: tmp/supervisor/etc/supervisor/worker.confThis keeps all project-specific runtime wiring in etc/plonex.yml while still
letting the generated files live under tmp/.
Services remain dataclasses based on BaseService. Commands resolve the project,
merge configuration, enter the service (including helper services), then run the
appropriate executable from the project virtualenv.
| Command | Main service | Execution |
|---|---|---|
instance debug, instance start |
RunWSGI |
.venv/bin/runwsgi tmp/<name>/etc/wsgi.ini |
instance console, instance run |
ZConsole |
.venv/bin/zconsole ACTION tmp/<name>/etc/zope.conf ... |
db start |
ZeoServer |
.venv/bin/runzeo -C tmp/zeoserver/etc/zeo.conf |
supervisor start |
Supervisor |
.venv/bin/supervisord -c tmp/supervisor/etc/supervisord.conf |
supervisor status |
Supervisor |
.venv/bin/supervisorctl -c tmp/supervisor/etc/supervisord.conf status |
dependencies install |
InstallService |
uv pip install -r var/requirements.txt -c var/constraints.txt |
dependencies sync |
InstallService |
uv pip compile ... --output-file var/compiled-requirements.txt, then uv pip sync var/compiled-requirements.txt |
dependencies outdated |
InstallService |
uv pip list --outdated |
test pytest PACKAGE |
PytestService |
.venv/bin/python -m pytest --pyargs PACKAGE ... |
test zope PACKAGE |
ZopeTest |
.venv/bin/zope-testrunner --all --quiet -pvc --package PACKAGE --auto-path ... |
db pack |
ZeoServer |
.venv/bin/zeopack -u <zeo_address> -d <days> |
options COMMAND |
Inspection | Construct the same service and read its resolved options |
Paths shown above use default folder and service names. Dependency inspection
uses uv pip freeze with the target project's Python, so printed package names
are canonical. Runtime templates and configured helper services can add other
preparation steps.
The shared service registry and invocation binding are also used by inspection. The shell owns terminal-backed jobs; services continue to run in isolated CLI processes. Tables and inspection reports share a Markdown-capable presenter. See Project decisions for ownership boundaries, snapshot semantics, and how to add commands while preserving these patterns.
plonex looks for etc/plonex.yml by walking up from the target directory.
Use one of these approaches:
- run commands from inside your project tree,
- pass
--target /path/to/project, - or initialize a project first with
plonex project init.
Use plonex options COMMAND with the same flags as the command you are
troubleshooting. For a running or completed shell job, options %1 shows the
options it actually started with. Use jobs to find the job ID.
plonex project compile also writes merged configuration to var/plonex.yml, but that
file is not a substitute for inspecting a particular service and its CLI flags.
Typical causes:
- a higher-priority config file overrides your value,
- a command-line option is overriding YAML,
- or a service-specific file exists and takes precedence for that service.
Check zeo_address in your merged config and ensure the socket/host exists.
If needed, set it in etc/plonex.local.yml for machine-specific environments.
If commands fail because binaries are missing, run:
plonex dependencies installThis recreates or updates environment-installed tooling used by runtime commands.
- Database snapshots require stopped FileStorage writers and a coordinated blob store; legacy repozo backups require their original restore procedure.
- Interactive job control requires a Unix terminal. Piped commands run without terminal job control.
- Jobs and snapshots belong to one shell session. Job logs and snapshots remain on disk, but a new shell does not adopt old processes or job IDs.
- Option previews construct services and may create directories; they do not run services. Startup snapshots are not live views into a process's Python state.
Parts of this project were developed with the assistance of AI-based tools.
All generated content was reviewed, tested, and modified by human maintainers before inclusion in the repository.