Appearance
plexctl support bundle
plexctl support bundle writes an offline diagnostics tar.gz archive to a caller-supplied path. The archive carries a small, fixed inventory of files harvested from the local environment and from the configured plexsphere server, suitable for handing to support without leaking secrets.
The contract is fixed:
- The archive ships REDACTED config — no bearer token, no password fields, no OAuth2 client secrets. The masking rule is the same
(?i)secret|key|tokenregex thatdomain-idpuses for output masking, so the two surfaces stay consistent. - The archive lists environment variable names only — values are never read or printed. Only variables whose names start with
PLEXSPHERE_are listed. - Collection is pure Go: no shell pipeline, no
curl, notarsubprocess. The bundle works the same way on macOS, Linux, and Windows. - The bundle path is supplied via
--output <path>. There is no default — running the command without--outputfails with exit2, so an interactive shell never accidentally receives binary data on stdout. The file is written with mode0600, matching the persisted-profile mode contract.
The archive contains exactly seven members, in this on-tape order:
| Member | Source | Purpose |
|---|---|---|
version.txt | local CLI build metadata | Matches plexctl --version byte-for-byte (wire shape: version=<semver> commit=<sha> date=<rfc3339>). |
server-version.json | GET /v1/version | Server build metadata. |
health.json | GET /v1/health | Server health snapshot. |
openapi.json | GET /v1/openapi.json | The exact OpenAPI document the server is currently serving. |
whoami.json | GET /v1/auth/whoami | The principal id and relations the configured token resolves to. |
config-redacted.json | persisted profile (file in CONFIG dir) | Profile with secret-shaped fields rewritten to ***. The token field is always rewritten. |
env-redacted.txt | local process env | Names — never values — of PLEXSPHERE_* env vars visible to the CLI. |
Synopsis
shell
plexctl support bundle --output <PATH>Invocation
plexctl support is the parent command; the only subcommand today is bundle. Future levels can hang additional support tools (e.g. support env) off the same parent without touching the root command's registration.
plexctl support bundle
Flags
| Flag | Type | Required | Default | Description |
|---|---|---|---|---|
--output | path | yes | — | Destination path for the diagnostics tar.gz. The path is resolved with filepath.Abs and written with mode 0600. |
Persistent flags inherited from root: see plexctl.md.
DECISION: the persistent
--outputflag at the root level selects the format (text/json/yaml) for every other subcommand. The leaf-level--outputonsupport bundleis a separate path flag with the same name. Cobra's flag set merges the two, but the dispatcher reads the format from the root's persistent-flag bag explicitly so the leaf path flag never shadows the format. Seecmd/plexctl/app.go(preRun) for the wiring.
Exit codes
| Code | Reachable from | Meaning |
|---|---|---|
0 | success | Archive written to --output path. |
1 | runtime/API error | A /v1/version, /v1/health, /v1/openapi.json, or /v1/auth/whoami call failed; the local file write failed; the destination path could not be resolved. The bundler collects every member before writing — a partial failure leaves nothing on disk so callers can safely retry. |
2 | flag-parse | Missing --output. |
3 | credentials | Missing or insecure credentials. |
4 | permission denied | HTTP 403 from one of the GETs. |
64 | none | Not a deferred command. |
Examples
Build a support bundle
shell
plexctl support bundle \
--server "${PLEXSPHERE_URL}" \
--output /tmp/plexsphere-support-$(date -u +%Y%m%dT%H%M%SZ).tar.gz
# Wrote support bundle to /tmp/plexsphere-support-20260501T100000Z.tar.gz (12345 bytes).Inspect the archive contents
shell
tar -tzf /tmp/plexsphere-support-20260501T100000Z.tar.gz
# version.txt
# server-version.json
# health.json
# openapi.json
# whoami.json
# config-redacted.json
# env-redacted.txtshell
tar -xzf /tmp/plexsphere-support-20260501T100000Z.tar.gz -O config-redacted.jsonjson
{
"name": "default",
"server": "https://plexsphere.example.com",
"token": "***"
}shell
tar -xzf /tmp/plexsphere-support-20260501T100000Z.tar.gz -O env-redacted.txt
# PLEXSPHERE_TOKEN
# PLEXSPHERE_URLThe redaction rule is enforced before any byte reaches the archive: config-redacted.json is built by walking the JSON-marshalled profile and rewriting every key matching (?i)secret|key|token to ***; env-redacted.txt lists names of variables present in the process environment without ever reading their values.
Refusal: missing --output (exit 2)
shell
plexctl support bundle
# stderr: Error: required flag(s) "output" not set
echo "exit=$?" # exit=2Refusal: missing credentials (exit 3)
shell
plexctl support bundle --output /tmp/bundle.tar.gz
# stderr: plexctl: profile resolved without a token
echo "exit=$?" # exit=3Cross-references
../../../api/openapi/plexsphere-v1.yaml— OpenAPI 3.1 source of truth for/v1/version,/v1/health,/v1/openapi.json, and/v1/auth/whoami.../../contexts/audit/index.md— bounded-context reference for the platform audit chain (the bundle does NOT include audit data; that surface lives behindplexctl audit).../../../cmd/plexctl/commands/support.go— source of truth for the cobra subcommand wiring, the--outputflag, and the0600file write.../../../cmd/plexctl/internal/support/bundle.go— source of truth for the seven-member inventory, the(?i)secret|key|tokenredaction rule applied toconfig-redacted.json, thePLEXSPHERE_*allowlist used forenv-redacted.txt, and the deterministic tar header layout.plexctl.md— root command reference (persistent flags, profile resolution, shared exit-code taxonomy).