@kolatts/pncli 1.26.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,19 +4,21 @@ import {
4
4
  loadConfig,
5
5
  loadJsonFile,
6
6
  maskConfig,
7
+ normalizeBaseUrl,
7
8
  setConfigValue,
8
9
  setRepoConfigValue,
9
10
  writeGlobalConfig,
10
11
  writeRepoConfig
11
- } from "./chunk-JOAWUILY.js";
12
+ } from "./chunk-LH7WBP7W.js";
12
13
  export {
13
14
  getGlobalConfigPath,
14
15
  loadConfig,
15
16
  loadJsonFile,
16
17
  maskConfig,
18
+ normalizeBaseUrl,
17
19
  setConfigValue,
18
20
  setRepoConfigValue,
19
21
  writeGlobalConfig,
20
22
  writeRepoConfig
21
23
  };
22
- //# sourceMappingURL=config-SQ3YHJHI.js.map
24
+ //# sourceMappingURL=config-JGBUUXQX.js.map
@@ -2,9 +2,10 @@
2
2
  import {
3
3
  HttpClient,
4
4
  createHttpClient
5
- } from "./chunk-AGELHQKO.js";
5
+ } from "./chunk-ZDJYOI3W.js";
6
+ import "./chunk-HZF6WQPU.js";
6
7
  export {
7
8
  HttpClient,
8
9
  createHttpClient
9
10
  };
10
- //# sourceMappingURL=http-WCDXXCKQ.js.map
11
+ //# sourceMappingURL=http-6QJU2SWP.js.map
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ debug,
4
+ fail,
5
+ isDebugEnabled,
6
+ log,
7
+ setGlobalOptions,
8
+ setGlobalUser,
9
+ success,
10
+ warn,
11
+ writeRawOutput
12
+ } from "./chunk-HZF6WQPU.js";
13
+ export {
14
+ debug,
15
+ fail,
16
+ isDebugEnabled,
17
+ log,
18
+ setGlobalOptions,
19
+ setGlobalUser,
20
+ success,
21
+ warn,
22
+ writeRawOutput
23
+ };
24
+ //# sourceMappingURL=output-XT3WT5L5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kolatts/pncli",
3
- "version": "1.26.0",
3
+ "version": "3.0.0",
4
4
  "description": "The Paperwork Nightmare CLI — One command does what three meetings couldn't.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,8 +15,7 @@
15
15
  "lint": "eslint src/",
16
16
  "typecheck": "tsc --noEmit",
17
17
  "test": "vitest run",
18
- "test:watch": "vitest",
19
- "prepare": "husky"
18
+ "test:watch": "vitest"
20
19
  },
21
20
  "dependencies": {
22
21
  "@inquirer/checkbox": "^5.2.1",
@@ -32,7 +31,6 @@
32
31
  "@typescript-eslint/eslint-plugin": "^8.31.0",
33
32
  "@typescript-eslint/parser": "^8.31.0",
34
33
  "eslint": "^9.25.1",
35
- "husky": "^9.1.7",
36
34
  "tsup": "^8.4.0",
37
35
  "tsx": "^4.19.3",
38
36
  "typescript": "^5.8.3",
@@ -57,7 +55,6 @@
57
55
  "skills",
58
56
  "LICENSE",
59
57
  "NOTICE",
60
- "README.md",
61
- "copilot-instructions.md"
58
+ "README.md"
62
59
  ]
63
60
  }
@@ -9,7 +9,38 @@ metadata:
9
9
  services: config
10
10
  ---
11
11
 
12
- pncli gives AI agents and humans unified CLI access to enterprise tools: Jira, Bitbucket, Confluence, SonarQube, SDElements, Azure DevOps, Jenkins, Artifactory, IBM UrbanCode Deploy, Checkmarx, ServiceNow, Contrast Security IAST, Sonatype IQ Server, OpenShift / Kubernetes, Dynatrace, and LogScale.
12
+ pncli gives AI agents and humans unified CLI access to enterprise tools: Jira, Bitbucket, GitHub, Confluence, SonarQube, SDElements, Azure DevOps, Jenkins, Artifactory, Checkmarx, ServiceNow, Contrast Security IAST, Sonatype IQ Server, OpenShift / Kubernetes, Dynatrace, LogScale, Split.IO, and Figma.
13
+
14
+ Every service authenticates the same way: a personal access token you generate in that tool's own UI and put in an env var or the config file. If a tool you need is missing from the table below, it is not out of scope by default — pncli covers enterprise tooling broadly, and the only hard requirement is personal-access-token auth.
15
+
16
+ ## Output and errors
17
+
18
+ All commands return JSON to stdout — parse it rather than scraping text.
19
+
20
+ - Success: `{ "ok": true, "data": { ... }, "meta": { "service": "...", "action": "...", "timestamp": "...", "duration_ms": N } }`
21
+ - Error: `{ "ok": false, "error": { "status": N, "message": "...", "url": "..." }, "meta": { ... } }` (`url` is null when the failure was not an HTTP call)
22
+
23
+ Always check `ok` before reading `data`. Errors are JSON too, so a non-zero exit still gives you a structured reason.
24
+
25
+ Run commands from the repository root — project and repo are auto-detected from git remotes.
26
+
27
+ ## Provider detection
28
+
29
+ Before running provider-specific commands, establish which tools the repo actually uses:
30
+
31
+ 1. **Work item tracking** — Jira or Azure DevOps? Determines `pncli jira ...` vs `pncli ado work ...`.
32
+ 2. **Source control** — GitHub, Bitbucket, or Azure DevOps? Determines `pncli github ...`, `pncli bitbucket ...`, or `pncli ado repo ...`.
33
+
34
+ Ask the user and cache the answers for the session. If they don't know, run `git remote -v`: a URL containing `/_git/` is Azure DevOps, `/scm/` is Bitbucket, `github.com` (or a GitHub Enterprise host) is GitHub.
35
+
36
+ ## Useful flags
37
+
38
+ - `--dry-run` — print the API request without executing it
39
+ - `--verbose` — extra progress detail on stderr (stdout stays pure JSON)
40
+ - `--debug` — trace every API call (method, URL, status) on stderr; never logs credentials
41
+ - `--pretty` — human-readable output when running by hand
42
+ - `--output-file <path>` — write JSON to a file instead of stdout; use it for large payloads (search, logs, `--all` pagination) so they don't flood agent context
43
+ - Defaults from `.pncli.json` are applied automatically — you rarely need `--project`, `--repo`, `--type`, or `--priority`
13
44
 
14
45
  ## Two config levels
15
46
 
@@ -34,7 +65,7 @@ For commands with long rich-text fields (Jira `create-issue`/`update-issue`, ADO
34
65
 
35
66
  ## Available services
36
67
 
37
- For detailed setup of any service, read the included file for that service.
68
+ Each service has its own file in this skill with the config keys and example values for it.
38
69
 
39
70
  | Service | File | Commands unlocked |
40
71
  |---------|------|-------------------|
@@ -47,7 +78,6 @@ For detailed setup of any service, read the included file for that service.
47
78
  | SonarQube | `sonarqube.md` | Code quality issues |
48
79
  | SDElements | `sde.md` | Threat model tasks |
49
80
  | Checkmarx | `checkmarx.md` | SAST findings |
50
- | IBM UrbanCode Deploy | `udeploy.md` | Component versions, deployments |
51
81
  | Jenkins | `jenkins.md` | Builds, job status |
52
82
  | Artifactory | `artifactory.md` | Packages, repos |
53
83
  | ServiceNow | `servicenow.md` | Change requests, incidents |
@@ -56,8 +86,16 @@ For detailed setup of any service, read the included file for that service.
56
86
  | OpenShift / Kubernetes | `openshift.md` | Pod health, events, logs, metrics |
57
87
  | Dynatrace | `dynatrace.md` | Services, entities, problems, traces, Kubernetes workloads |
58
88
  | LogScale | `logscale.md` | Log queries, repository listing |
89
+ | Split.IO | `splitio.md` | Feature flag discovery, targeting updates, Change Requests |
90
+ | Figma | `figma.md` | Design files, comments, version history |
59
91
  | Skills Marketplace | `marketplace.md` | Install org-internal skills |
60
92
 
93
+ ## Installing skills
94
+
95
+ The skills bundled with pncli install into a repo with `pncli skills install` (default target `.agents/skills/`, which GitHub Copilot and Codex both read; add `--agent claude-code` for `.claude/skills`). Add `--scope user` to install them globally instead.
96
+
97
+ Org-internal skills come from a git-hosted marketplace: `pncli skills marketplace setup <git-clone-url>` registers one, and `pncli skills marketplace sync` keeps everything installed from it current. `pncli skills status` and `pncli skills locations` show what is installed and where. The full workflow is in the `marketplace.md` file that ships inside the installed skill.
98
+
61
99
  ## Setup walkthrough
62
100
 
63
101
  **Step 1 — Identity**
@@ -4,6 +4,8 @@ pncli uses Dynatrace's REST APIs directly; no Dynatrace CLI is required.
4
4
 
5
5
  ## Configuration
6
6
 
7
+ ### Single environment (legacy)
8
+
7
9
  | Key | Environment variable | Purpose |
8
10
  |---|---|---|
9
11
  | `dynatrace.baseUrl` | `PNCLI_DYNATRACE_BASE_URL` | Classic environment URL, such as `https://abc12345.live.dynatrace.com` |
@@ -27,8 +29,48 @@ pncli config test
27
29
  When platform credentials are present, `config test` and `config check` also run a minimal Grail
28
30
  spans query and report it separately as `dynatrace_platform`.
29
31
 
32
+ ### Multiple named environments
33
+
34
+ Dynatrace is commonly deployed per-environment (e.g. QA and PROD), each with its own base URL and
35
+ API token. pncli supports named environment profiles so you can switch between them with a flag rather
36
+ than rewriting `dynatrace.baseUrl` and `dynatrace.apiToken` before every command.
37
+
38
+ ```bash
39
+ # Set up named environments
40
+ pncli config set dynatrace.environments.qa.baseUrl https://abc11111.live.dynatrace.com
41
+ pncli config set dynatrace.environments.qa.apiToken dt0c01...
42
+ pncli config set dynatrace.environments.prod.baseUrl https://abc22222.live.dynatrace.com
43
+ pncli config set dynatrace.environments.prod.apiToken dt0c01...
44
+
45
+ # Optional: include Grail platform credentials per environment
46
+ pncli config set dynatrace.environments.prod.platformUrl https://abc22222.apps.dynatrace.com
47
+ pncli config set dynatrace.environments.prod.platformToken dt0s16...
48
+
49
+ # Optional: set a default named environment (used when --env is omitted)
50
+ pncli config set dynatrace.defaultEnvironment prod
51
+ ```
52
+
53
+ `config test` and `config check` report the connectivity status of each named environment
54
+ separately as `dynatrace.<name>` (and `dynatrace.<name>_platform` when platform credentials are set).
55
+
56
+ Environment variables (`PNCLI_DYNATRACE_BASE_URL`, etc.) continue to apply to the legacy flat config
57
+ and take precedence over stored values, but do not override named environments.
58
+
30
59
  ## Commands
31
60
 
61
+ ```bash
62
+ # Using the default (legacy flat config or defaultEnvironment)
63
+ pncli dynatrace services --from now-2h
64
+
65
+ # Targeting a named environment
66
+ pncli dynatrace --env qa services --from now-2h
67
+ pncli dynatrace --env prod problems list --from now-24h
68
+
69
+ # Compare QA and PROD in one session
70
+ pncli dynatrace --env qa entities list --selector 'type("SERVICE")'
71
+ pncli dynatrace --env prod entities list --selector 'type("SERVICE")'
72
+ ```
73
+
32
74
  ```bash
33
75
  pncli dynatrace services --from now-2h
34
76
  pncli dynatrace workloads --from now-2h
@@ -44,3 +86,7 @@ pncli dynatrace trace --id 0123456789abcdef0123456789abcdef
44
86
 
45
87
  Entity and problem list commands automatically follow Dynatrace pagination. Use Dynatrace selector
46
88
  syntax for advanced filtering.
89
+
90
+ The `--env <name>` option is available on the `dynatrace` parent command and applies to all
91
+ subcommands: `entities list`, `entities get`, `services`, `workloads`, `problems list`,
92
+ `problems get`, and `trace`.
@@ -0,0 +1,62 @@
1
+ # Figma
2
+
3
+ pncli uses the Figma REST API directly; no external CLI is required.
4
+
5
+ ## Configuration
6
+
7
+ | Key | Environment variable | Purpose |
8
+ |---|---|---|
9
+ | `figma.baseUrl` | `PNCLI_FIGMA_BASE_URL` | Figma API base URL — always `https://api.figma.com` |
10
+ | `figma.token` | `PNCLI_FIGMA_TOKEN` | Personal access token |
11
+
12
+ Generate a personal access token in Figma under **Account Settings → Personal access tokens**.
13
+
14
+ ```bash
15
+ pncli config set figma.baseUrl https://api.figma.com
16
+ pncli config set figma.token <your-token>
17
+ pncli config test
18
+ ```
19
+
20
+ ## Finding a Figma file key
21
+
22
+ The file key is the alphanumeric segment in a Figma URL. Both URL formats are accepted:
23
+
24
+ ```
25
+ https://www.figma.com/design/ABCDEFGH1234/My-Design-Name
26
+ ^^^^^^^^^^^^
27
+ https://www.figma.com/file/ABCDEFGH1234/My-Design-Name
28
+ ^^^^^^^^^^^^
29
+ ```
30
+
31
+ You can pass either the raw file key or the full URL to any `figma` command.
32
+
33
+ ## Commands
34
+
35
+ ```bash
36
+ # Get current user — useful for verifying credentials
37
+ pncli figma me
38
+
39
+ # Get file metadata and structure summary (component and style counts)
40
+ pncli figma file ABCDEFGH1234
41
+ pncli figma file "https://www.figma.com/design/ABCDEFGH1234/My-Design"
42
+
43
+ # Include the full document node tree (can be large)
44
+ pncli figma file ABCDEFGH1234 --document
45
+
46
+ # Get all comments on a file
47
+ pncli figma comments ABCDEFGH1234
48
+
49
+ # Get comments as of a specific point in time
50
+ pncli figma comments ABCDEFGH1234 --as-of 2026-08-01T00:00:00Z
51
+
52
+ # Get version history
53
+ pncli figma versions ABCDEFGH1234
54
+
55
+ # List files in a Figma project (project ID is visible in the project URL)
56
+ pncli figma project-files 123456789
57
+ ```
58
+
59
+ ## Notes
60
+
61
+ - `figma file` returns a summary by default: name, last-modified, version, thumbnail URL, role, editor type, schema version, and counts of components and styles. Pass `--document` to include the full document node tree (this can be very large for complex designs).
62
+ - Passing a Figma image (screenshot or export) rather than a link is **not supported** — pncli works with the Figma REST API only, not image analysis. Use the file key or URL instead.
@@ -49,3 +49,50 @@ pncli config set --repo defaults.jenkins.baseUrl https://jenkins.myteam.imagile.
49
49
  ```
50
50
 
51
51
  Resolution order (highest to lowest): project `.pncli.json` → global config → `PNCLI_JENKINS_BASE_URL` env var.
52
+
53
+ ## Multiple Jenkins instances
54
+
55
+ When you work with more than one Jenkins controller (e.g. a stable production instance plus ephemeral pipeline-as-code instances), add a `jenkinsInstances` array to your global config:
56
+
57
+ ```json
58
+ {
59
+ "jenkinsInstances": [
60
+ {
61
+ "name": "prod",
62
+ "baseUrl": "https://jenkins.imagile.dev",
63
+ "username": "you@example.com",
64
+ "apiToken": "abc12345"
65
+ },
66
+ {
67
+ "name": "ephemeral",
68
+ "baseUrl": "https://jenkins-tmp.imagile.dev",
69
+ "username": "you@example.com",
70
+ "apiToken": "abc12345"
71
+ }
72
+ ]
73
+ }
74
+ ```
75
+
76
+ Manage the array with the `instance` subcommands, which append rather than replace:
77
+
78
+ ```
79
+ pncli jenkins instance add --name prod --base-url jenkins.imagile.dev --username you@example.com --api-token abc12345
80
+ pncli jenkins instance add --name ephemeral --base-url jenkins-tmp.imagile.dev --username you@example.com
81
+ pncli jenkins instance list
82
+ pncli jenkins instance remove --name ephemeral
83
+ ```
84
+
85
+ Omit `--api-token` on an interactive terminal and pncli prompts for it, which keeps the token out of your shell history. `instance list` masks every token as `***`. Adding a name that already exists is rejected unless you pass `--force`, which overwrites that entry in place.
86
+
87
+ `pncli config set jenkinsInstances '[...]'` also works, but it **replaces** the whole array — you must re-supply every instance you want to keep, including tokens that `config check` masks. Prefer `instance add`.
88
+
89
+ Then select an instance at run-time with `--instance`:
90
+
91
+ ```
92
+ pncli jenkins --instance ephemeral pipeline list
93
+ pncli jenkins --instance prod pipeline run --name my-job --wait
94
+ ```
95
+
96
+ When `--instance` is omitted, pncli uses the default `jenkins.*` config as usual.
97
+
98
+ **Note:** Per-instance credentials are read only from the global config file — there is no env-var override for a named instance. To override Jenkins credentials at runtime (CI/CD, GitHub Actions), use the default `jenkins.*` config with `PNCLI_JENKINS_BASE_URL`, `PNCLI_JENKINS_USERNAME`, and `PNCLI_JENKINS_API_TOKEN`, and omit `--instance`.
@@ -26,11 +26,11 @@ pncli skills marketplace list
26
26
  pncli skills marketplace plugins <name>
27
27
  ```
28
28
 
29
- `list` shows every registered marketplace. `plugins` shows the plugins available inside one of them, without installing anything.
29
+ `list` shows every registered marketplace, including `upstreamRemote` — the `origin` fetch URL read from the local clone, with any injected token scrubbed. It is `null` when the clone is missing or has no `origin`, which is the quickest way to spot a marketplace whose local path has drifted from the URL it was registered with. `plugins` shows the plugins available inside one of them, without installing anything.
30
30
 
31
31
  ## Sync (pull + install)
32
32
 
33
- Install to `~/.agents/skills` (GitHub Copilot / Codex):
33
+ Install to `~/.agents/skills` (Codex / GitHub Copilot — the default):
34
34
  ```
35
35
  pncli skills marketplace sync
36
36
  ```
@@ -64,6 +64,16 @@ pncli skills marketplace sync --marketplace all
64
64
 
65
65
  `sync` skips reinstalling when a marketplace has no new upstream changes (single-plugin and `all` installs alike). Pass `--force` to reinstall anyway.
66
66
 
67
+ ### Update what you already have, without picking up new plugins
68
+
69
+ By default an `all` sync installs every plugin the marketplace offers, including ones added upstream since you last synced. Pass `--installed-only` to update just the plugins already on disk:
70
+
71
+ ```
72
+ pncli skills marketplace sync --marketplace all --installed-only
73
+ ```
74
+
75
+ Plugins are matched by the marketplace name recorded at install time, falling back to the clone URL — so a marketplace you have since renamed still resolves. Disabled plugins count as installed and are refreshed in place, staying disabled. If a marketplace has no installed plugins at all, it is reported as `skipped` with `installedOnly: true` rather than silently installing everything.
76
+
67
77
  ## Enable / disable installed plugins
68
78
 
69
79
  Temporarily switch a plugin's skills off without deleting them (no re-download needed to switch back on):
@@ -93,6 +103,47 @@ It loops through a menu until you're done:
93
103
 
94
104
  Everything the session changed is emitted as one JSON summary at the end. Agents should use the scriptable equivalents instead: `enable`, `disable`, `add`, `remove`.
95
105
 
106
+ ## Where skills are installed
107
+
108
+ Every command that installs or reads skills takes `--agent` and `--scope`. Those resolve to:
109
+
110
+ | `--agent` | `--scope project` | `--scope user` |
111
+ |---|---|---|
112
+ | `codex` (default) | `.agents/skills` | `~/.agents/skills` |
113
+ | `github-copilot` | `.github/skills` | `~/.copilot/skills` |
114
+ | `claude-code` | `.claude/skills` | `~/.claude/skills` |
115
+
116
+ `.agents/skills` is the cross-tool convention — both Codex and GitHub Copilot read it — which is why it is the default. Use `--agent github-copilot` only when you specifically want Copilot's own directories, and `--agent claude-code` (or the `--claude` shorthand) for Claude Code.
117
+
118
+ Project-scope paths resolve against the repository root, so you get the same directory whichever subdirectory you run from. Outside a git repository they fall back to the current working directory.
119
+
120
+ `--target <dir>` overrides all of this and installs wherever you point it. `skills install --target` records the directory in your global config so it still shows up in the commands below; `pncli skills forget-target <dir>` stops tracking it (it deletes nothing).
121
+
122
+ ### List the install paths
123
+
124
+ ```
125
+ pncli skills locations
126
+ ```
127
+
128
+ Reports every path pncli knows about — each agent host at both scopes, plus any recorded custom targets — with whether the directory exists and how many skills are in it. The `marketplaceSkills`, `bundledSkills`, and `untrackedSkills` counts are mutually exclusive and always add up to `totalSkills`; anything in `untrackedSkills` was dropped in by hand or installed before pncli recorded provenance.
129
+
130
+ `disabledStashMissing` names disabled skills whose stashed copy has been deleted out from under pncli — those cannot be re-enabled and need a fresh `sync`.
131
+
132
+ ### Trace a skill back to its repository
133
+
134
+ ```
135
+ pncli skills status
136
+ ```
137
+
138
+ Walks every known location and emits one record per installed skill joining it to the plugin, marketplace, clone URL, and the live `origin` remote of the local clone. This is the command to reach for when you need to know where a skill actually came from rather than just where it sits.
139
+
140
+ Narrow it with `--marketplace <name-or-url>`, `--plugin <name>`, `--source marketplace|bundled|untracked`, `--agent`, or `--scope`:
141
+
142
+ ```
143
+ pncli skills status --source untracked
144
+ pncli skills status --marketplace internal-ai
145
+ ```
146
+
96
147
  ## Remove a marketplace
97
148
 
98
149
  ```
@@ -3,13 +3,54 @@
3
3
  pncli connects to the OpenShift / Kubernetes REST API using a service account bearer token.
4
4
  No `kubectl` or `oc` CLI is required.
5
5
 
6
- ## Required config keys
6
+ ## Configuration
7
+
8
+ pncli supports two configuration models for OpenShift clusters, which can be used together:
9
+
10
+ ### Legacy flat config (single cluster)
7
11
 
8
12
  | Key | Env var | Description |
9
13
  |-----|---------|-------------|
10
14
  | `openshift.baseUrl` | `PNCLI_OPENSHIFT_BASE_URL` | API server URL, e.g. `https://api.cluster.imagile.dev:6443` |
11
15
  | `openshift.token` | `PNCLI_OPENSHIFT_TOKEN` | Service account bearer token |
12
16
 
17
+ ### Named two-level config (multiple environments and instances)
18
+
19
+ | Key | Description |
20
+ |-----|-------------|
21
+ | `openshift.environments.<env>.instances.<instance>.baseUrl` | API server URL for this cluster |
22
+ | `openshift.environments.<env>.instances.<instance>.token` | Bearer token for this cluster |
23
+ | `openshift.defaultEnvironment` | Default environment name (used when `--env` is omitted) |
24
+ | `openshift.defaultInstance` | Default instance name (used when `--instance` is omitted) |
25
+
26
+ Example:
27
+
28
+ ```bash
29
+ pncli config set openshift.environments.non-prod.instances.us-east.baseUrl https://api.np-us-east.imagile.dev:6443
30
+ pncli config set openshift.environments.non-prod.instances.us-east.token eyJhbGciOiJSUzI1NiI...
31
+ pncli config set openshift.environments.non-prod.instances.eu-west.baseUrl https://api.np-eu-west.imagile.dev:6443
32
+ pncli config set openshift.environments.non-prod.instances.eu-west.token eyJhbGciOiJSUzI1NiI...
33
+ pncli config set openshift.environments.prod-us.instances.primary.baseUrl https://api.prod-us.imagile.dev:6443
34
+ pncli config set openshift.environments.prod-us.instances.primary.token eyJhbGciOiJSUzI1NiI...
35
+
36
+ # Set defaults so --env / --instance can be omitted
37
+ pncli config set openshift.defaultEnvironment non-prod
38
+ pncli config set openshift.defaultInstance us-east
39
+ ```
40
+
41
+ ## Selecting a target cluster
42
+
43
+ All `pncli openshift` subcommands accept `--env` and `--instance` to choose a named cluster:
44
+
45
+ ```bash
46
+ pncli openshift --env non-prod --instance us-east pods --namespace my-namespace
47
+ pncli openshift --env prod-us --instance primary events --namespace my-namespace
48
+ ```
49
+
50
+ If `--env`/`--instance` are omitted, pncli resolves the cluster in this order:
51
+ 1. `openshift.defaultEnvironment` + `openshift.defaultInstance`
52
+ 2. Legacy flat `openshift.baseUrl` / `openshift.token`
53
+
13
54
  ## Getting your service account token
14
55
 
15
56
  **Inside a pod** (recommended for CI):
@@ -46,11 +87,21 @@ pncli config init
46
87
 
47
88
  ## Commands
48
89
 
90
+ ### List configured clusters
91
+
92
+ ```bash
93
+ pncli openshift cluster list
94
+ ```
95
+
96
+ Returns all configured environments/instances and the flat legacy cluster (if set), plus the
97
+ configured defaults.
98
+
49
99
  ### List pod health summary
50
100
 
51
101
  ```bash
52
102
  pncli openshift pods --namespace my-namespace
53
103
  pncli openshift pods --namespace my-namespace --label-selector app=my-app
104
+ pncli openshift --env non-prod --instance us-east pods --namespace my-namespace
54
105
  ```
55
106
 
56
107
  Returns a pre-processed summary with phase counts (running/pending/failed), restart counts,
@@ -62,6 +113,7 @@ CrashLoopBackOff/OOMKilled/ImagePullBackOff indicators, and per-pod container st
62
113
  pncli openshift events --namespace my-namespace
63
114
  pncli openshift events --namespace my-namespace --field-selector involvedObject.name=my-pod
64
115
  pncli openshift events --namespace my-namespace --all # include Normal events
116
+ pncli openshift --env prod-us --instance primary events --namespace my-namespace
65
117
  ```
66
118
 
67
119
  Returns Warning events sorted by count (highest-frequency first), filtered to surface problems.
@@ -85,15 +137,40 @@ pncli openshift pod-metrics --namespace my-namespace
85
137
  Returns per-pod, per-container CPU and memory usage. Requires the metrics-server to be
86
138
  installed in the cluster (`GET /apis/metrics.k8s.io/v1beta1/...`).
87
139
 
140
+ ### Get combined resource usage, limits, and requests
141
+
142
+ ```bash
143
+ pncli openshift resource-usage --namespace my-namespace
144
+ pncli openshift resource-usage --namespace my-namespace --label-selector app=my-app
145
+ pncli openshift resource-usage --namespace my-namespace --csv
146
+ ```
147
+
148
+ Fetches pod specs (limits/requests) and metrics-server usage in parallel, joins them by
149
+ pod + container, and normalizes all values to **millicores (m)** for CPU and **mebibytes (Mi)**
150
+ for memory. Pods without metrics (e.g. not Running) appear with empty usage columns.
151
+
152
+ Use `--csv` to emit a spreadsheet-ready CSV suitable for Excel:
153
+
154
+ ```
155
+ Pod,Container,CPU Usage (m),Memory Usage (Mi),CPU Limits (m),Memory Limits (Mi),CPU Requests (m),Memory Requests (Mi)
156
+ my-pod-abc,app,45,128,500,256,100,128
157
+ ```
158
+
159
+ Requires the metrics-server (`GET /apis/metrics.k8s.io/v1beta1/...`) — same as `pod-metrics`.
160
+
88
161
  ## Test connectivity
89
162
 
90
163
  ```bash
91
- pncli config test
164
+ pncli config test # tests flat config + all named clusters
165
+ pncli config check # structured status per cluster
92
166
  ```
93
167
 
168
+ Named clusters appear in `config check` output with keys like `openshift:non-prod/us-east`.
169
+
94
170
  ## Minimum RBAC permissions
95
171
 
96
- The service account needs read access to pods, events, logs, and metrics in the target namespace:
172
+ The service account needs read access to pods, events, logs, and metrics in the target namespace.
173
+ `resource-usage` requires the same metrics-server permission as `pod-metrics`:
97
174
 
98
175
  ```yaml
99
176
  rules: