@kolatts/pncli 5.3.0 → 5.4.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.
- package/README.md +1 -1
- package/dist/chunk-L6OY2546.js +984 -0
- package/dist/chunk-L6OY2546.js.map +1 -0
- package/dist/cli.js +2396 -385
- package/dist/cli.js.map +1 -1
- package/dist/{config-Y6IE6GY7.js → config-OH2O5E3P.js} +4 -2
- package/package.json +1 -1
- package/skills/pncli/SKILL.md +7 -2
- package/skills/pncli/ado.md +4 -0
- package/skills/pncli/bitbucket.md +4 -0
- package/skills/pncli/github.md +37 -0
- package/skills/pncli/jira.md +45 -1
- package/skills/pncli/marketplace.md +53 -1
- package/skills/pncli/skills-guide.md +169 -0
- package/dist/chunk-QHJ2HM5J.js +0 -466
- package/dist/chunk-QHJ2HM5J.js.map +0 -1
- /package/dist/{config-Y6IE6GY7.js.map → config-OH2O5E3P.js.map} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
envOverriddenSecretPaths,
|
|
3
4
|
getGlobalConfigPath,
|
|
4
5
|
loadConfig,
|
|
5
6
|
loadJsonFile,
|
|
@@ -9,9 +10,10 @@ import {
|
|
|
9
10
|
setRepoConfigValue,
|
|
10
11
|
writeGlobalConfig,
|
|
11
12
|
writeRepoConfig
|
|
12
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-L6OY2546.js";
|
|
13
14
|
import "./chunk-HRNOAQDN.js";
|
|
14
15
|
export {
|
|
16
|
+
envOverriddenSecretPaths,
|
|
15
17
|
getGlobalConfigPath,
|
|
16
18
|
loadConfig,
|
|
17
19
|
loadJsonFile,
|
|
@@ -22,4 +24,4 @@ export {
|
|
|
22
24
|
writeGlobalConfig,
|
|
23
25
|
writeRepoConfig
|
|
24
26
|
};
|
|
25
|
-
//# sourceMappingURL=config-
|
|
27
|
+
//# sourceMappingURL=config-OH2O5E3P.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kolatts/pncli",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.4.0",
|
|
4
4
|
"description": "The Paperwork Nightmare CLI — structured JSON access to Jira, Bitbucket, GitHub, Confluence, Azure DevOps, SonarQube, Jenkins, and more, built for AI coding agents. Connectivity without MCP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/skills/pncli/SKILL.md
CHANGED
|
@@ -108,6 +108,7 @@ Each service has its own file in this skill with the config keys and example val
|
|
|
108
108
|
| Figma | `figma.md` | Design files, comments, version history |
|
|
109
109
|
| Alation | `alation.md` | Data catalog metadata (data sources, schemas, tables, columns), search, Document Hubs |
|
|
110
110
|
| Skills Marketplace | `marketplace.md` | Org plugins and shipped AGENTS.md / CLAUDE.md from git marketplaces |
|
|
111
|
+
| Skills guide | `skills-guide.md` | How skills management fits together: sources, agent hosts, scopes, sync, private-repo auth, OS keychain |
|
|
111
112
|
|
|
112
113
|
## Installing skills
|
|
113
114
|
|
|
@@ -115,7 +116,7 @@ The skills bundled with pncli install into a repo with `pncli skills install` (d
|
|
|
115
116
|
|
|
116
117
|
Installed skills are a copy — after upgrading pncli, re-run `pncli skills install` to refresh them. `skills list` and `skills status` warn when the installed copy came from a different pncli version.
|
|
117
118
|
|
|
118
|
-
Org-internal plugins come from a git-hosted marketplace: `pncli skills marketplace add <git-clone-url> --all-agents` registers one and installs every plugin into all three agent hosts, and `pncli skills marketplace sync --marketplace all --all-agents` keeps them current. A marketplace can also ship an `instructions/AGENTS.md` and `instructions/CLAUDE.md`; `add` and `sync` merge those into each agent's user-level instructions file (`~/.codex/AGENTS.md`, `~/.copilot/copilot-instructions.md`, `~/.claude/CLAUDE.md`) as a marked block that leaves your own content untouched — `pncli skills marketplace instructions list|install|remove` manages them. `pncli skills status`, `pncli skills locations`, and `pncli doctor` show what is installed and where. The full workflow is in the `marketplace.md` file that ships inside the installed skill, and `pncli skills marketplace --help` summarises it.
|
|
119
|
+
Org-internal plugins come from a git-hosted marketplace: `pncli skills marketplace add <git-clone-url> --all-agents` registers one and installs every plugin into all three agent hosts, and `pncli skills marketplace sync --marketplace all --all-agents` keeps them current. A marketplace can also ship an `instructions/AGENTS.md` and `instructions/CLAUDE.md`; `add` and `sync` merge those into each agent's user-level instructions file (`~/.codex/AGENTS.md`, `~/.copilot/copilot-instructions.md`, `~/.claude/CLAUDE.md`) as a marked block that leaves your own content untouched — `pncli skills marketplace instructions list|install|remove` manages them. `pncli skills status`, `pncli skills locations`, and `pncli doctor` show what is installed and where. The full workflow is in the `marketplace.md` file that ships inside the installed skill, and `pncli skills marketplace --help` summarises it. For the concepts behind all of this — where skills come from, how they stay current, and how private marketplaces authenticate — run `pncli skills guide` (or read `skills-guide.md`).
|
|
119
120
|
|
|
120
121
|
## Setup walkthrough
|
|
121
122
|
|
|
@@ -159,10 +160,14 @@ Review results. If any service shows `ok: false`, help troubleshoot the URL or c
|
|
|
159
160
|
pncli config show
|
|
160
161
|
```
|
|
161
162
|
|
|
163
|
+
**Keeping tokens out of plaintext** — `pncli config keychain migrate` moves every secret in `~/.pncli/config.json` into the OS keychain (macOS Keychain, Windows Credential Manager, Secret Service) and leaves `keychain:` references in their place; `--to config` moves them back. `PNCLI_*` environment variables still take precedence.
|
|
164
|
+
|
|
162
165
|
**Troubleshooting** — when any command fails unexpectedly, run:
|
|
163
166
|
|
|
164
167
|
```
|
|
165
168
|
pncli doctor
|
|
166
169
|
```
|
|
167
170
|
|
|
168
|
-
It reports config-file health, credential validity per service, and skill install state (including stale skills) in one JSON envelope, with a `problems` array listing suggested fixes. Add `--offline` to skip the network checks.
|
|
171
|
+
It reports config-file health, credential validity per service, keychain references that do not resolve, git authentication for marketplace hosts (GitHub token scope, expiry, and SSO authorization), and skill install state (including stale skills) in one JSON envelope, with a `problems` array listing suggested fixes. Add `--offline` to skip the network checks.
|
|
172
|
+
|
|
173
|
+
When a clone fails with "repository not found" or an auth error, `pncli git credentials inspect` shows which credential git actually uses for each remote (after `insteadOf` rewriting, or from Git Credential Manager / the `gh` CLI / the OS keychain), and whether it can read the repo; `--scan <dir>` checks every clone under a folder, and `pncli git credentials stored` lists what the credential stores hold. See `github.md`.
|
package/skills/pncli/ado.md
CHANGED
|
@@ -51,3 +51,7 @@ pncli ado work schema --example-only > wi.json
|
|
|
51
51
|
pncli ado work create --type Bug --input-file wi.json
|
|
52
52
|
pncli ado work update --id 123 --input-file wi.json --field Priority=1 # flag wins, and it's reported
|
|
53
53
|
```
|
|
54
|
+
|
|
55
|
+
## Skills marketplaces on this host
|
|
56
|
+
|
|
57
|
+
A skills marketplace repository on this host (see `marketplace.md`) with no `--token` of its own uses `ado.pat` (`PNCLI_ADO_PAT`) for clone and pull, and for `pncli skills git-auth`. The PAT needs the Code (Read) scope.
|
|
@@ -38,3 +38,7 @@ pncli bitbucket --project MYPROJ create-repo --name my-new-repo
|
|
|
38
38
|
# With a description and explicit project flag
|
|
39
39
|
pncli bitbucket create-repo --project MYPROJ --name my-new-repo --description "My project"
|
|
40
40
|
```
|
|
41
|
+
|
|
42
|
+
## Skills marketplaces on this host
|
|
43
|
+
|
|
44
|
+
A skills marketplace repository on this host (see `marketplace.md`) with no `--token` of its own uses `bitbucket.pat` (`PNCLI_BITBUCKET_PAT`) for clone and pull, and for `pncli skills git-auth`. Bitbucket Data Center personal access tokens are usually sent with your Bitbucket username: add the marketplace with `--username <you>`, or set it later with `pncli skills marketplace update <name> --username <you>`.
|
package/skills/pncli/github.md
CHANGED
|
@@ -65,3 +65,40 @@ pncli github resolve-thread --thread-id PRT_kwDOHfWCIM4APCA
|
|
|
65
65
|
`list-review-threads` returns the first 100 threads with their resolution status,
|
|
66
66
|
file path/line, and first 10 comments. If a PR has more than 100 threads, a warning
|
|
67
67
|
is written to stderr.
|
|
68
|
+
|
|
69
|
+
## Which token does a clone use? (`pncli git credentials`)
|
|
70
|
+
|
|
71
|
+
Classic-PAT setups usually put the token in a gitconfig rewrite such as
|
|
72
|
+
`url."https://<classic-PAT>@github.com/acme/".insteadOf "https://github.com/acme/"`, while Git Credential
|
|
73
|
+
Manager, the `gh` CLI, or the Windows Credential Manager may hold other tokens for the same host. A repo outside
|
|
74
|
+
every mapping silently clones anonymously and fails as "repository not found"; a mapped token may be valid but
|
|
75
|
+
unable to see a particular repo; a stored token may be shadowed by another helper. These commands work on any
|
|
76
|
+
clone, not just skills marketplaces, and never print a token — only its type and a fingerprint (`ghp_…a1b2`):
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
pncli git credentials inspect # every remote of the current clone
|
|
80
|
+
pncli git credentials inspect ~/src/tools --remote upstream
|
|
81
|
+
pncli git credentials inspect https://github.com/acme/tools.git
|
|
82
|
+
pncli git credentials inspect --scan ~/src --problems-only # clones that are unmapped or lack access
|
|
83
|
+
pncli git credentials mappings # every insteadOf rewrite and URL-scoped helper, tokens checked
|
|
84
|
+
pncli git credentials stored # what the credential stores hold, and what git actually sends
|
|
85
|
+
pncli git credentials forget --host github.com --username octo # drop a stale stored credential
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- **`inspect`** — per remote: the URL as configured, the URL git uses after `insteadOf` rewriting, the mapping
|
|
89
|
+
that applied, and where the credential comes from (`insteadOf`, the `url` itself, a `helper`, or `none`). For a
|
|
90
|
+
helper it names the kind — Git Credential Manager, wincred, osxkeychain, libsecret, store, `gh`, pncli — and
|
|
91
|
+
GCM's backing store (`wincredman`, `dpapi`, `keychain`, `secretservice`, …). Online it runs an authenticated
|
|
92
|
+
`git ls-remote`, and for GitHub reports the account, a classic token missing `repo`, SAML SSO authorization,
|
|
93
|
+
expiry, and whether the token can see **this** repository — each problem with a concrete fix, such as the exact
|
|
94
|
+
`insteadOf` line to add for an unmapped org.
|
|
95
|
+
- **`stored`** — the Windows Credential Manager's `git:` entries (Git Credential Manager and wincred), the plaintext
|
|
96
|
+
`~/.git-credentials` file, and the macOS Keychain's git entries (metadata only), plus what git actually sends per
|
|
97
|
+
host and per stored path. Flags stored tokens that GitHub rejects or that expire soon, several accounts for one
|
|
98
|
+
host, plaintext storage, and **shadowed** entries — a stored credential git never sends because another helper
|
|
99
|
+
(typically `gh auth setup-git`) answers first.
|
|
100
|
+
- **`forget`** — `git credential reject` for one host (and optionally account or path), which every helper
|
|
101
|
+
implements; it reports the fingerprint before and after. A shadowed Windows entry cannot be reached this way —
|
|
102
|
+
`stored` gives the exact `cmdkey /delete:` command instead.
|
|
103
|
+
|
|
104
|
+
`--offline` skips every network check.
|
package/skills/pncli/jira.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Jira
|
|
2
2
|
|
|
3
|
-
Enables: `pncli jira get-issue`, `create-issue`, `update-issue`, `search`, `list-boards`, `list-sprints`, `set-sprint`, and more — get, create, and update issues, transitions, comments, attachments, custom fields, and
|
|
3
|
+
Enables: `pncli jira get-issue`, `create-issue`, `update-issue`, `search`, `list-boards`, `list-sprints`, `set-sprint`, `log-work`, and more — get, create, and update issues, transitions, comments, attachments, custom fields, sprints, and worklogs.
|
|
4
4
|
|
|
5
5
|
## Required config
|
|
6
6
|
|
|
@@ -42,6 +42,17 @@ pncli jira set-sprint --key ACME-123 --sprint <sprint-id>
|
|
|
42
42
|
|
|
43
43
|
`list-sprints` output includes `startDate`/`endDate`/`state`/`goal` for each sprint.
|
|
44
44
|
|
|
45
|
+
## Worklogs
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
pncli jira log-work --key ACME-123 --time-spent "2h 30m" --comment "Investigated the failing build"
|
|
49
|
+
pncli jira log-work --key ACME-123 --time-spent "1d" --started 2024-01-15T09:00:00.000+0000
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`--time-spent` uses Jira's own duration format (`1d`, `2h 30m`, `45m`, ...). `--started` takes
|
|
53
|
+
Jira's datetime format (`yyyy-MM-dd'T'HH:mm:ss.SSSZ`, e.g. `2024-01-15T09:00:00.000+0000`) and
|
|
54
|
+
defaults to now when omitted.
|
|
55
|
+
|
|
45
56
|
## Custom fields
|
|
46
57
|
|
|
47
58
|
Register a custom field once so `--field <Name>=value` and `--input-file` can address it by
|
|
@@ -60,6 +71,36 @@ mangle nested double quotes inside a single-quoted argument, which silently stor
|
|
|
60
71
|
value. `pncli jira fields` prints what's currently registered; `pncli jira fields --discover`
|
|
61
72
|
fetches field metadata straight from the Jira API instead.
|
|
62
73
|
|
|
74
|
+
Registration is only needed to address a field by **friendly name**, or to get automatic
|
|
75
|
+
value shaping from `type`. Both `--field` and `--fields-file` accept an unregistered raw
|
|
76
|
+
Jira field id or name directly (e.g. `--field fixVersions=@versions.json`,
|
|
77
|
+
`{"fixVersions": [...]}` in a `--fields-file` JSON file) — nothing needs to be pre-registered
|
|
78
|
+
just to use a standard field like `fixVersions` or a custom field you already know the
|
|
79
|
+
`customfield_NNNNN` id for. Registration only fails for a key that still has whitespace in
|
|
80
|
+
it and isn't a registered friendly name — that's almost always a typo.
|
|
81
|
+
|
|
82
|
+
Some select-type fields (a "Crew" picker, for example) reject the display text you see in
|
|
83
|
+
Jira's UI and only accept the option's numeric key. Run `pncli jira fields --discover
|
|
84
|
+
--project <key>` to see each field's `allowedValues`; if a field's values are `{id, value}`
|
|
85
|
+
pairs rather than plain strings, register it with `"type":"option-id"` and pass the numeric
|
|
86
|
+
`id`, not the display text. **Sprint** is not a custom field at all — don't try to set it
|
|
87
|
+
via `--field` or `--fields-file`; use `pncli jira set-sprint --key <key> --sprint <id>` after
|
|
88
|
+
the issue exists, with the id from `pncli jira list-sprints`.
|
|
89
|
+
|
|
90
|
+
### PowerShell-safe JSON values
|
|
91
|
+
|
|
92
|
+
Passing JSON inline in `--field Name={"a":1}` is unreliable in PowerShell — its argument
|
|
93
|
+
parser mangles embedded quotes before pncli ever sees them. Use the `@file` form instead,
|
|
94
|
+
which sidesteps shell quoting entirely:
|
|
95
|
+
|
|
96
|
+
```powershell
|
|
97
|
+
'{"steps":[{"action":"click"}]}' | Out-File -Encoding utf8 steps.json
|
|
98
|
+
pncli jira create-issue --project ACME --summary "..." --field "Test Steps=@steps.json"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
This also applies to `--jql` and any other flag that would otherwise need inline JSON or
|
|
102
|
+
nested quotes on Windows.
|
|
103
|
+
|
|
63
104
|
## Large fields via --input-file
|
|
64
105
|
|
|
65
106
|
`create-issue` and `update-issue` accept `--input-file <path>` (`-` for stdin) instead of, or alongside, individual flags — useful for a long description or many custom fields at once. Run `pncli jira schema` to print the JSON Schema plus a runnable example. Any string value in `fields` may be `@path/to/file` to pull that field's content from a file (e.g. a big HTML description) instead of inlining it. Custom fields resolve by friendly name (if registered — see **Custom fields** above) or by raw id (`customfield_10032`) with no registration required. Individual flags (`--summary`, `--description`, `--field`, ...) override matching keys from the file; overridden keys are printed to stderr and included in the output's `meta.overrides`.
|
|
@@ -79,3 +120,6 @@ pncli jira create-issue --input-file issue.json --priority Low # --priority wi
|
|
|
79
120
|
- `--assignee` on `create-issue`, `update-issue`, and `assign` takes a **username**, as does
|
|
80
121
|
any `user`-typed custom field passed via `--field`
|
|
81
122
|
- Custom fields discovered with `pncli jira fields --discover`
|
|
123
|
+
- `create-issue` does not check for duplicates before submitting. If a request times out or
|
|
124
|
+
the response is otherwise ambiguous, run `pncli jira search` for the exact summary before
|
|
125
|
+
retrying — a timeout does not tell you whether the issue was actually created.
|
|
@@ -27,7 +27,59 @@ pncli skills marketplace add https://bitbucket.imagile.dev/scm/ai/skills.git --n
|
|
|
27
27
|
|
|
28
28
|
You can register as many marketplaces as you like — just run `add` again with a different URL. `marketplace setup` is kept as an alias of `add` for backward compatibility.
|
|
29
29
|
|
|
30
|
-
For a private repo, pass `--token <token>` (a Bitbucket or GitHub access token) — it's stored with that marketplace's entry and
|
|
30
|
+
For a private repo, pass `--token <token>` (a Bitbucket or GitHub access token) — it's stored with that marketplace's entry and supplied to git for each clone and pull; it is not left in the clone's `.git/config`. For a marketplace hosted on `github.com` (or the host configured as `github.baseUrl`), you can omit `--token` if you already have a working GitHub credential configured (`PNCLI_GITHUB_TOKEN`, `GITHUB_TOKEN`, or `pncli config set github.token`) — `marketplace add` and `marketplace sync` fall back to it automatically. An explicit `--token` on the marketplace always takes priority over that fallback. To rotate a marketplace's own token, re-run `marketplace add <url> --token <new-token>` (repeat `--keychain` if the old one was stored there, or use `pncli config keychain set marketplaces.<name>.token`); a rejected or expired token surfaces as a clear error naming the marketplace rather than raw git output.
|
|
31
|
+
|
|
32
|
+
Add `--keychain` to store the token in the OS keychain (macOS Keychain, Windows Credential Manager, Secret Service) instead of plaintext config; the marketplace entry then holds a `keychain:marketplaces.<name>.token` reference.
|
|
33
|
+
|
|
34
|
+
### Providers: GitHub, Bitbucket, Azure DevOps
|
|
35
|
+
|
|
36
|
+
A marketplace can live on any HTTPS git host. pncli detects the provider from your configured service hosts and the URL shape (`/_git/` is Azure DevOps, `/scm/` is Bitbucket Data Center), and uses it to pick a fallback token when the marketplace has none of its own:
|
|
37
|
+
|
|
38
|
+
| Provider | Example clone URL | Fallback token (when no `--token`) |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| GitHub / GitHub Enterprise | `https://ghe.imagile.dev/ai/skills.git` | `PNCLI_GITHUB_TOKEN` / `GITHUB_TOKEN` / `github.token` (github.com or the host of `github.baseUrl`) |
|
|
41
|
+
| Bitbucket Data Center | `https://bitbucket.imagile.dev/scm/ai/skills.git` | `PNCLI_BITBUCKET_PAT` / `bitbucket.pat` (the host of `bitbucket.baseUrl`) |
|
|
42
|
+
| Azure DevOps Server | `https://ado.imagile.dev/DefaultCollection/Platform/_git/skills` | `PNCLI_ADO_PAT` / `SYSTEM_ACCESSTOKEN` / `ado.pat` (the host of `ado.baseUrl`) |
|
|
43
|
+
| anything else | `https://git.imagile.dev/ai/skills.git` | none; pass `--token` |
|
|
44
|
+
|
|
45
|
+
Each marketplace keeps its own `--token`, so marketplaces on the same host (or on different providers) can use different secrets. Pass `--provider github|bitbucket|ado|git` if detection guesses wrong.
|
|
46
|
+
|
|
47
|
+
The token is sent with a username: `x-access-token` on github.com, `x-token-auth` everywhere else (unchanged from earlier versions; Azure DevOps accepts any username with a PAT). **Bitbucket Data Center personal access tokens are usually sent with your Bitbucket username** — set it per marketplace:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
pncli skills marketplace add https://bitbucket.imagile.dev/scm/ai/skills.git --token <token> --username jdoe --all-agents
|
|
51
|
+
pncli skills marketplace update internal-ai --username jdoe # for one you already added
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Rotate a token or change credentials (`update`)
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
pncli skills marketplace update internal-ai --token <new-token> [--keychain]
|
|
58
|
+
pncli skills marketplace update internal-ai --username jdoe
|
|
59
|
+
pncli skills marketplace update internal-ai --clear-token # use the provider fallback instead
|
|
60
|
+
pncli skills marketplace update internal-ai --provider bitbucket
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`update` changes the stored entry only — no re-clone, no reinstall. A keychain entry the marketplace no longer points at is deleted.
|
|
64
|
+
|
|
65
|
+
### Let git itself authenticate (`git-auth`)
|
|
66
|
+
|
|
67
|
+
pncli's own clone and pull are covered above, but an agent host that clones a marketplace itself (e.g. Claude Code's `/plugin marketplace add`) runs plain `git`, which has no credential for it. Give it one:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
pncli skills git-auth enable # every marketplace that has a credential
|
|
71
|
+
pncli skills git-auth enable --marketplace internal-ai --mode keychain
|
|
72
|
+
pncli skills git-auth status # per marketplace: mode, username, token source, match
|
|
73
|
+
pncli skills git-auth disable [--marketplace internal-ai] [--forget-keychain]
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- Entries are **scoped to each marketplace's repository URL** (with and without `.git`), for example `credential.https://bitbucket.imagile.dev/scm/ai/skills.git.helper`. git consults them only for that repository, so every other repo on the same host keeps using your own login, untouched.
|
|
77
|
+
- `--mode helper` (default) writes an empty reset entry, `!pncli skills git-credential --marketplace '<name>'`, then whatever helpers git used for that repo before (the host's `gh auth setup-git` entry, Git Credential Manager, osxkeychain). pncli answers with that marketplace's own credential — the same username and token its clone and pull use — resolved from env → config → keychain, so nothing is copied into gitconfig and rotation needs no re-run. If pncli cannot answer, git falls through to your helpers as before.
|
|
78
|
+
- `--mode keychain` stores the credential in git's own credential store via `git credential approve`, keyed to the repository (a repo-scoped `useHttpPath`). It works where pncli is not on git's `PATH`, but must be re-run after rotating the token; `pncli doctor` detects the stale copy.
|
|
79
|
+
- `--host <host>` writes a whole-host entry instead, answered with the provider token pncli has for that host. Use it deliberately: it puts that token in front of every repo on the host.
|
|
80
|
+
- `disable` restores exactly what `enable` replaced; pncli records it under `gitAuth.scopes` in its global config. `enable` also rewrites any clone whose `origin` still carries an embedded token.
|
|
81
|
+
|
|
82
|
+
`pncli doctor` reports a `gitAuth` entry per marketplace: provider, mode, username, token source, whether git's credential matches pncli's, and clones with embedded tokens. Online, it runs an authenticated `git ls-remote` with exactly that username and token — which catches a wrong Bitbucket username as reliably as an expired token — and, for GitHub, reports the token kind (classic `ghp_` vs fine-grained), a missing `repo` scope, SSO authorization, and expiry within 14 days.
|
|
31
83
|
|
|
32
84
|
If you upgrade pncli from a version that only supported a single marketplace, your existing config is migrated to the multi-marketplace format automatically the first time you run any `marketplace` command — no manual steps required.
|
|
33
85
|
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: How skills management works
|
|
3
|
+
description: The mental model behind pncli skills — where skills come from, where they go, how they stay current, and how private marketplaces authenticate.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# How skills management works
|
|
7
|
+
|
|
8
|
+
pncli puts **skills** — folders of instructions an AI coding agent loads on demand — where your agents will find them, and keeps them current. Read this once; after that, `pncli skills --help` and `pncli doctor` cover the day-to-day.
|
|
9
|
+
|
|
10
|
+
Print any section on its own with `pncli skills guide <section>` (for example `pncli skills guide auth`). `pncli skills guide --sections` lists them all.
|
|
11
|
+
|
|
12
|
+
## The big picture
|
|
13
|
+
|
|
14
|
+
Skills reach your machine from two sources, and both end up in the same place:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
pncli (npm package) your org's marketplace repo (git)
|
|
18
|
+
└─ bundled "pncli" skill └─ plugins/<plugin>/skills/<skill>/SKILL.md
|
|
19
|
+
│ │ + instructions/AGENTS.md, CLAUDE.md
|
|
20
|
+
│ pncli skills install │ pncli skills marketplace add | sync
|
|
21
|
+
▼ ▼
|
|
22
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
23
|
+
│ agent skills directories (.agents/skills, .claude/skills, …) │
|
|
24
|
+
│ each skill carries a provenance record: source, plugin, marketplace │
|
|
25
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
26
|
+
▲
|
|
27
|
+
└── Codex, GitHub Copilot, and Claude Code read from here
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
- The **bundled skill** is pncli's own command reference. It ships inside the npm package, so it changes when pncli does.
|
|
31
|
+
- **Marketplace plugins** are your org's skills, published in a git repository. pncli clones the repo once and pulls it whenever you sync.
|
|
32
|
+
- Every skill pncli installs is stamped with **provenance** — where it came from and which pncli version put it there. That is how `status`, `sync`, and `doctor` can tell your org's skills, pncli's own, and anything you dropped in by hand apart.
|
|
33
|
+
|
|
34
|
+
## Agent hosts and where skills live
|
|
35
|
+
|
|
36
|
+
Each agent host reads its own directories. `--agent` picks one; `--all-agents` covers every host in one run.
|
|
37
|
+
|
|
38
|
+
| `--agent` | Project scope | User scope | Read by |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| `codex` (default) | `.agents/skills` | `~/.agents/skills` | Codex and GitHub Copilot |
|
|
41
|
+
| `github-copilot` | `.github/skills` | `~/.copilot/skills` | GitHub Copilot |
|
|
42
|
+
| `claude-code` (`--claude`) | `.claude/skills` | `~/.claude/skills` | Claude Code |
|
|
43
|
+
|
|
44
|
+
**Project scope** lives in the repository — commit it and everyone who clones the repo gets the skills. **User scope** lives in your home directory and applies to every repository on the machine.
|
|
45
|
+
|
|
46
|
+
- The bundled skill installs at project scope by default. Add `--scope user` to have it everywhere.
|
|
47
|
+
- Marketplace plugins always install at user scope. They are org-wide, not repo-specific.
|
|
48
|
+
|
|
49
|
+
`pncli skills locations` prints every one of these paths with a count of what's in it.
|
|
50
|
+
|
|
51
|
+
## The bundled pncli skill
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
pncli skills install --all-agents # this repo, every agent host
|
|
55
|
+
pncli skills install --all-agents --scope user # every repo on this machine
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The bundled skill is versioned with pncli. After `npm update -g @kolatts/pncli`, the copies on disk are one version behind; `pncli doctor` flags them as stale, and re-running `pncli skills install` refreshes them.
|
|
59
|
+
|
|
60
|
+
## Marketplaces
|
|
61
|
+
|
|
62
|
+
A marketplace is a git repository your org publishes plugins from. The lifecycle is:
|
|
63
|
+
|
|
64
|
+
1. **Add** — register, clone, and install every plugin:
|
|
65
|
+
`pncli skills marketplace add https://ghe.imagile.dev/ai/skills.git --all-agents`
|
|
66
|
+
2. **Sync** — pull the latest and refresh what you already have. With no arguments this is non-interactive, which makes it safe for a login script or a scheduled task:
|
|
67
|
+
`pncli skills marketplace sync --all-agents`
|
|
68
|
+
3. **Browse** — see what's there without installing anything:
|
|
69
|
+
`pncli skills marketplace plugins internal-ai`
|
|
70
|
+
4. **Pick up something new** — plain `sync` only refreshes plugins you already have. Run `sync --force` for the interactive picker, or name the plugin:
|
|
71
|
+
`pncli skills marketplace sync new-plugin --all-agents`
|
|
72
|
+
|
|
73
|
+
You can register as many marketplaces as you like. Clones live in `~/.agents/marketplaces/`, and `marketplace remove` unregisters one without deleting its clone.
|
|
74
|
+
|
|
75
|
+
**What a marketplace repo looks like:** `.claude-plugin/marketplace.json` (or a `plugins/` directory), with each plugin holding a `skills/` folder of skill directories. That's the same layout Claude Code's own plugin marketplaces use, so one repo serves both.
|
|
76
|
+
|
|
77
|
+
## Turning plugins on and off
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
pncli skills marketplace disable some-plugin
|
|
81
|
+
pncli skills marketplace enable some-plugin
|
|
82
|
+
pncli skills marketplace manage # interactive: checkbox list of every plugin
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`disable` moves a plugin's skills into a hidden `.pncli-disabled/` folder next to them, so agents stop loading them. Nothing is deleted and nothing needs re-downloading. A disabled plugin stays disabled across syncs, but it still gets refreshed while it sits there.
|
|
86
|
+
|
|
87
|
+
To remove a plugin for good, use `marketplace purge-plugin`. `skills purge-user` clears an agent's whole user-level skills folder.
|
|
88
|
+
|
|
89
|
+
## Shipped instructions (AGENTS.md / CLAUDE.md)
|
|
90
|
+
|
|
91
|
+
A marketplace can also ship org-wide agent instructions in `instructions/AGENTS.md` and `instructions/CLAUDE.md`. `add` and `sync` merge them into each agent's **user-level** instructions file (`~/.codex/AGENTS.md`, `~/.copilot/copilot-instructions.md`, `~/.claude/CLAUDE.md`).
|
|
92
|
+
|
|
93
|
+
They go in as a marked block. Your own content in that file is never touched, the block is replaced in place on every sync, and `marketplace instructions remove` strips it cleanly. Don't edit inside the markers, because the next sync overwrites them.
|
|
94
|
+
|
|
95
|
+
## Where did this skill come from?
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
pncli skills status # every skill → plugin → marketplace → clone URL
|
|
99
|
+
pncli skills status --source untracked # skills pncli did not install
|
|
100
|
+
pncli skills locations # every path, with counts
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The counts in `locations` always add up: `marketplaceSkills + bundledSkills + untrackedSkills = totalSkills`.
|
|
104
|
+
|
|
105
|
+
## Private repos and auth
|
|
106
|
+
|
|
107
|
+
A private marketplace needs a credential in two places, and they're easy to confuse:
|
|
108
|
+
|
|
109
|
+
1. **pncli's own clone and pull.** Pass `--token` to `marketplace add`, or let pncli fall back to the token it already has for the provider: `github.token` for GitHub and GitHub Enterprise, `bitbucket.pat` for your Bitbucket host, `ado.pat` for your Azure DevOps host. pncli hands the token to git through the environment for each call, so it never shows up on git's command line and is never left in the clone's `.git/config`.
|
|
110
|
+
2. **Everyone else's git.** An agent host that clones a marketplace itself — Claude Code's `/plugin marketplace add`, for instance — runs plain `git`, and plain git has no idea about pncli's token. `git-auth` fixes that:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
pncli skills git-auth enable # every marketplace that has a credential
|
|
114
|
+
pncli skills git-auth status # per marketplace: mode, and whether git sends pncli's token
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`git-auth` has two modes:
|
|
118
|
+
|
|
119
|
+
| Mode | How it works | After a token rotation |
|
|
120
|
+
|---|---|---|
|
|
121
|
+
| `helper` (default) | git asks `pncli skills git-credential --marketplace <name>` on each operation | Nothing to do — git always gets pncli's current token |
|
|
122
|
+
| `keychain` | the token is stored in git's own credential store (Git Credential Manager, macOS Keychain, libsecret) | Re-run `git-auth enable --mode keychain`; `doctor` flags the stale copy |
|
|
123
|
+
|
|
124
|
+
Use `helper` unless something runs git without pncli on its `PATH`. Some GUI git clients and containers do that, and for those `keychain` is the right mode.
|
|
125
|
+
|
|
126
|
+
Entries are scoped to each marketplace's own repository URL, so every other repo on the same host keeps your usual login (`gh`, Git Credential Manager, the macOS Keychain), untouched. `git-auth disable` puts your previous setup back exactly. A whole-host entry (`--host`) is available, but only when you ask for it.
|
|
127
|
+
|
|
128
|
+
**Which GitHub token?** A classic personal access token (`ghp_…`) with the `repo` scope works across every repository your account can see, which suits a marketplace. A fine-grained token (`github_pat_…`) also works, but only for the repositories you selected when you created it. If your org uses SAML single sign-on, authorize the token for the org (Settings → Developer settings → Tokens → Configure SSO). `pncli doctor` checks the scope, the SSO authorization, and the expiry date for you.
|
|
129
|
+
|
|
130
|
+
**Several marketplaces, several secrets.** Each marketplace keeps its own `--token` (and `--username`), and every git path — pncli's clone and pull, the git helper, doctor's access check — uses exactly that pair. Rotate one with `pncli skills marketplace update <name> --token <new-token>`.
|
|
131
|
+
|
|
132
|
+
**Bitbucket and Azure DevOps.** Both work like GitHub. Bitbucket Data Center personal access tokens are usually sent with your Bitbucket username, so give the marketplace `--username <you>`. Azure DevOps PATs need the Code (Read) scope and accept any username. `pncli doctor` tries an authenticated `git ls-remote` for each marketplace, so a wrong username shows up the same way an expired token does.
|
|
133
|
+
|
|
134
|
+
## Keeping credentials in the OS keychain
|
|
135
|
+
|
|
136
|
+
Diagrams of both storage options, and of both git-auth modes, are on the website: https://kolatts.github.io/pncli/credentials/
|
|
137
|
+
|
|
138
|
+
Any secret in `~/.pncli/config.json` can live in your operating system's credential store instead: the macOS Keychain, Windows Credential Manager, or the Secret Service on Linux. The config file then holds only a reference such as `"token": "keychain:github.token"`.
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
pncli config keychain migrate --dry-run # what would move
|
|
142
|
+
pncli config keychain migrate # config → keychain, every plaintext secret
|
|
143
|
+
pncli config keychain set github.token # store one (prompts; or pipe it with --stdin)
|
|
144
|
+
pncli config keychain status # every reference, and whether it resolves
|
|
145
|
+
pncli config keychain migrate --to config # keychain → config (entries kept)
|
|
146
|
+
pncli config keychain migrate --to config --purge # …and delete the keychain entries
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
- `PNCLI_*` environment variables still win over everything, so CI is unaffected. Set `PNCLI_KEYCHAIN_BACKEND=none` on a machine that should ignore references altogether.
|
|
150
|
+
- `migrate` reads each secret back before it rewrites your config, and leaves a `config.json.pre-keychain.bak` behind. Delete that file once `pncli config check` passes.
|
|
151
|
+
- `marketplace add --token … --keychain` stores a marketplace token the same way from the start.
|
|
152
|
+
- Lookups cost a little time. On Windows each pncli command that needs a keychain secret starts PowerShell once (typically well under a second); macOS and Linux are faster.
|
|
153
|
+
- The keychain and `git-auth` helper mode work together. Git asks pncli, pncli reads the keychain, and the token never sits in a file anywhere.
|
|
154
|
+
|
|
155
|
+
## Troubleshooting
|
|
156
|
+
|
|
157
|
+
| Symptom | Try |
|
|
158
|
+
|---|---|
|
|
159
|
+
| The agent doesn't see a skill | `pncli skills status`, then check the host's directory in `pncli skills locations` |
|
|
160
|
+
| "I ran marketplace add but nothing shows up" | `pncli doctor` — it flags marketplaces with nothing installed from them |
|
|
161
|
+
| `sync` fails with "Invalid username or token" | `pncli doctor`: look for an expired token, a missing `repo` scope, or SSO not authorized |
|
|
162
|
+
| Claude Code's `/plugin marketplace add` can't clone | `pncli skills git-auth enable --host ghe.imagile.dev` |
|
|
163
|
+
| The bundled skill is out of date after an upgrade | `pncli skills install` (add `--all-agents` / `--scope user` as before) |
|
|
164
|
+
| A plugin added upstream never arrived | `pncli skills marketplace sync --force`, or name it explicitly |
|
|
165
|
+
| A command says "not configured" but the token is in the keychain | `pncli config keychain status` — the reference may point at a missing entry |
|
|
166
|
+
| Some ordinary clone (not a marketplace) says "repository not found" | `pncli git credentials inspect` in that clone, or `pncli git credentials inspect --scan ~/src --problems-only` |
|
|
167
|
+
| git keeps using the wrong account or an old token | `pncli git credentials stored` — shows shadowed and stale stored credentials, then `pncli git credentials forget` |
|
|
168
|
+
|
|
169
|
+
`pncli doctor` runs every one of these checks at once and prints a fix command next to each problem it finds.
|