Installer CLI
The tooling package pyplines-installer exposes these commands:
| Command | Purpose |
|---|---|
init | Write a reviewable YAML document; no installation occurs |
validate [FILE] | Validate structure, target settings, paths, references, and dependency cycles |
run [FILE] | Review and execute the selected targets in dependency order |
status [FILE] | Inspect installed targets and readiness |
doctor [FILE] | Also check service configuration drift, mounts, HTTPS, and NATS TLS |
uninstall [FILE] | Remove managed resources; --purge also deletes persistent data |
version | Show installer version and packaged default platform version |
FILE defaults to installation.yml in the current directory.
Global --json precedes the command and disables interactive prompts.
run accepts --dry-run, --yes/-y, and repeatable --target NAME.
status and doctor also accept --target NAME; dependencies are included.
Exit codes are 0 for success, 1 for validation/prerequisite errors or failed
target operations, and 2 for incomplete readiness such as pending approval.
CLI argument parsing also uses code 2. A run can report completed, failed, and
blocked targets together; inspect targets, ready, and failed in JSON output.
pyplines-installer --json validate installation.yml
pyplines-installer --json run installation.yml --dry-run
pyplines-installer --json run installation.yml --target runner --yes
pyplines-installer --json status installation.yml
init accepts --preset local|server|runner|action|custom, --output/-o, --name,
--platform-version, and --tooling-version. --from-directory DIR instead writes
an explicit reference to an existing managed service installation, preserving its
version. It cannot be combined with a preset or version changes. Existing output
files are never overwritten. Interactive init starts with your goal, then asks for relevant paths, ports,
and endpoint/TLS settings. Local setup includes the operator CLI and offers the
Action CLI as an option. Custom automation selects components with repeatable
--component pyplines-server|pyplines-runner|pyplines-cli|pyplines-action.
Generated YAML includes comments explaining version groups, paths, and credentials. Review generated example endpoints before installation.
For a noninteractive tools-only configuration:
pyplines-installer init --preset custom --component pyplines-cli --component pyplines-action --tooling-version "$TOOLING_VERSION" --output tools.yml
Packaged examples include local.yml, server.yml, runner.yml, action.yml,
and tools.yml in pyplines_installer/data/examples.
Document contract
The authoritative schema is contracts/installer/v1/installation.schema.json,
packaged with the installer and distributed in the release contract bundles.
It uses apiVersion: pyplines.installer/v1. JSON Schema establishes structural
validity; validate additionally checks dependency graphs, component settings,
and destination/port conflicts without contacting services.
| Field | Meaning |
|---|---|
name | Installation identity; 1–25 lowercase letters, digits, or hyphens, starting with a letter |
state_directory | Private installation state; relative to the YAML file |
profile | explicit (default) or local |
versions.platform | Required when installing server or runner targets |
versions.tooling | Required when installing Action or operator CLI targets |
credentials | Default credential references, never literal secrets |
targets | Mapping of unique instance names to component-specific settings |
Targets use component: pyplines-server|pyplines-runner|pyplines-action|pyplines-cli.
depends_on adds dependencies. A runner's server: {target: NAME} references a
server target and automatically adds a dependency; server: {url: HTTPS_ORIGIN}
connects to an external server. Separate runner hosts each run their own document.
Unknown fields, YAML aliases, duplicate keys, missing references, dependency cycles,
and unsupported settings are rejected. Target identifiers use the same format as
name. Relative paths resolve against the configuration file; environment expansion
is supported only through explicit credential references, not arbitrary YAML strings.
Endpoint settings
| Setting | Meaning |
|---|---|
server_url | Explicit server's host-facing HTTPS origin and published HTTPS port |
container_server_url | Runner HTTPS origin inside Docker; defaults to its host endpoint unless supplied by a referenced server's control network |
nats_url | Explicit server's advertised TLS origin, reachable by runners |
host_nats_url | Host NATS diagnostic origin; also selects the server's published NATS port |
control_network | Existing bridge network for service connectivity |
action_network | Runner Action-container bridge network, created if absent |
The local profile generates endpoint, certificate, and control-network settings.
Local server targets accept api_port (8443) and nats_port (4222); ports must be
distinct and between 1024 and 65535. Explicit servers supply server_url, nats_url,
certificate, and private_key, with optional ca_file, admin_username,
bind_address, host_nats_url, and control_network.
Runners support ca_file, max_concurrent (1–64), and the networking settings
above. Only runners referencing a generated local server are enrolled and approved
automatically. Explicit runner enrollment and approval remain administrator actions.
CLI targets and credentials
CLI targets accept directory, defaulting to ~/.local/bin. Action binaries are
selected for the host and downloaded directly over HTTPS, checksum-verified, and
version-checked. The operator CLI and its matching SDK are installed into a managed
Python environment; pyplines links to that environment. Existing unmanaged operator
executables and Action destination symlinks are rejected.
Credential references are either {env: NAME} or {file: PATH}. Supported root
keys are administrator_password, enrollment_token, and github_token. Targets
can override the credentials applicable to their component. Files require mode
600 and must not be symlinks. Values are resolved only when needed and never saved
in installer state or plans. Required unavailable credentials can be prompted for
in interactive runs; unattended runs need their configured source. Known credentials
are collected before installation starts. New administrator passwords require
confirmation. Progress pauses for any later credential prompt. --yes never waits
for input. Component progress shows the current operation and elapsed wait time;
errors include diagnosis and resume commands.
GitHub release downloads also recognize PYPLINES_GITHUB_TOKEN and GITHUB_TOKEN.
No GitHub CLI or curl subprocess is used. Docker/Compose, Python environment/package
installation, and executable verification remain subprocess operations.
State and compatibility
installation-state.json is private bookkeeping, not a configuration interface.
It records each target's desired settings, phase, successful artifact identity,
and last result. Resource receipts also track managed files, environment contents,
and cleanup progress. Removed targets are retained. Changes to a saved target's settings
or version are rejected until explicit upgrade support is added.
existing_installation: PATH explicitly references an old managed server/runner
directory and cannot be mixed with new service settings. Keep the original directory
and its referenced files. init --from-directory generates these references.
Hidden compatibility commands remain available: install server, install runner,
install action, install --config FILE, and local. status/doctor --directory
inspect their original directories. Their pyplines.installation/v1 schema remains
supported; it is distinct from the new multi-target document.
See the guided installer for complete configurations, private download credentials, migration, and the operator login handoff.
Uninstall and purge
pyplines-installer uninstall --dry-run
pyplines-installer uninstall
pyplines-installer uninstall --purge
pyplines-installer uninstall --target runner
pyplines-installer uninstall --directory ./development-state --purge --dry-run
pyplines-installer --json uninstall --directory ./development-state --purge --yes
uninstall accepts --dry-run, --purge, --yes/-y, repeatable --target,
and --directory. Use a YAML path or --directory, not both. The YAML supplies
only the state location; saved ownership controls cleanup even when targets or
versions have changed. --directory also supports original managed local and
single-service installations. Unknown or ambiguous ownership blocks removal.
Ordinary uninstall removes owned containers/networks, Action executables, and operator environments/links. It retains data volumes, generated development TLS, and service state for reinstalling with the original YAML. Purge also removes those volumes, generated certificates, and managed service files. State is deleted only after every recorded target is purged and no unknown files remain.
Full cleanup includes targets previously removed from YAML. Targeted cleanup does not implicitly select dependencies: include dependents explicitly before removing their server. Runners stop before their owned Action containers are removed. Supplied networks, certificates, credential files, user YAML, shared image/package caches, Docker, and the installer itself are retained. CLI configuration and tokens created by using the operator CLI are outside installer ownership. External-server runner registrations remain; revoke them using the operator CLI when appropriate.
Interactive purge requires typing the installation name. Automation requires
--purge --yes. Missing resources count as already removed; daemon access failures
do not. Partial cleanup preserves ownership receipts and reports the exact retry
command. Finish a failed cleanup before running installation again. Unknown files
or replaced executables must be moved aside or restored before retrying; cleanup
never recursively deletes unknown state-directory contents.

