Docs
Credentials
pncli authenticates with tokens you generate once and hand over. This page shows where those tokens rest under each option, which one wins when several are set, and how git gets a marketplace's credential. Every option is reversible, and none changes how commands behave.
Where pncli keeps your tokens
There are two storage options. The default, A, writes each token into
~/.pncli/config.json as plaintext — simple, and fine on a machine only you use.
B moves the secret into your operating system's credential store and leaves only
a reference like keychain:github.token in the file.
pncli config keychain migrate.
| A · Plaintext config | B · OS keychain | |
|---|---|---|
| Set up | pncli config init or pncli config set | pncli config keychain set github.token (prompts) |
In config.json | The token itself | "keychain:github.token" |
| Who can read it | Anything that can read your home directory — backups, dotfile sync, other tools | Your OS login; the OS may ask before another app reads it |
| Extra cost | None | One lookup per command — on Windows, starting PowerShell (under a second) |
| Needs | Nothing | macOS / Windows built-ins; secret-tool (libsecret-tools) on Linux |
Where to see it on your machine
Option B entries are ordinary items in your OS store, so you can inspect or delete them with the tools you already have:
| OS | pncli secrets (option B) | git-auth keychain mode |
|---|---|---|
| Windows | Credential Manager → Windows Credentials → generic credential pncli:github.token | Generic credential git:https://host/org/repo (Git Credential Manager) |
| macOS | Keychain Access → login → pncli github.token (service pncli) | Internet password for the repository's host |
| Linux | Passwords and Keys (Seahorse) → pncli github.token (attribute service=pncli) | The libsecret or Git Credential Manager item for the host |
Moving between A and B
pncli config keychain migrate --dry-run # preview
pncli config keychain migrate # A → B, every secret
pncli config keychain migrate github.token # A → B, one key
pncli config keychain migrate --to config # B → A, keep entries
pncli config keychain migrate --to config --purge # B → A, delete entries
pncli config keychain status # refs + whether they resolve - Nothing is ever held in only one place mid-move. A → B writes each secret, reads it back, and only then rewrites the config. B → A rewrites the config before
--purgedeletes anything. - A → B leaves
config.json.pre-keychain.bak— a plaintext copy for undo.pncli doctorreminds you until you delete it. - Marketplace tokens can start in the keychain:
pncli skills marketplace add <url> --token <token> --keychain.
Which value wins
A token can be set in more than one place. pncli takes the first one it finds, and environment variables always sit above anything on disk — which is what keeps CI predictable.
PNCLI_KEYCHAIN_BACKEND=none to ignore keychain references on a runner.
See CI Recipes for the full list of CI fallback variables. A keychain
reference that cannot be read is treated as not set — pncli never sends the literal
keychain:… string as a credential — and pncli doctor names it.
How git gets marketplace credentials
pncli's own marketplace add and sync hand git the marketplace's token for
each call, through the environment — never on the command line, never in the clone's
.git/config. But an agent host that clones a marketplace itself (Claude Code's
/plugin marketplace add, for instance) runs plain git, which knows nothing
about pncli. pncli skills git-auth enable bridges that, in one of two modes:
| A · Helper mode (default) | B · Keychain mode | |
|---|---|---|
| What is written | A credential.<repo-url>.helper entry in your global gitconfig | A copy of the token in git's credential store, plus a repo-scoped useHttpPath |
| Token rotation | Nothing to do — git always gets pncli's current token | Re-run enable --mode keychain; doctor flags a stale copy |
| Needs pncli on git's PATH | Yes | No — works for GUI clients and containers |
| If pncli can't answer | git falls through to your own helpers (gh, Git Credential Manager) | — |
| Undo | pncli skills git-auth disable restores exactly what was there before | |
A helper-mode entry looks like this — scoped to one repository, so nothing else on the host changes:
[credential "https://bitbucket.imagile.dev/scm/ai/skills.git"]
helper =
helper = !pncli skills git-credential --marketplace 'internal-ai'
helper = manager - The empty
helper =makes pncli the first helper asked; the helper after it (here Git Credential Manager) is whatever you used before, kept as the fallback. - Each marketplace uses its own token and username: its
--token, or the provider token pncli already has —github.token,bitbucket.pat,ado.pat. - The two options combine: helper mode plus option B means git asks pncli, pncli reads the OS keychain, and the token never sits in a file anywhere.
Checking what git actually sends
git has many places a credential can come from — insteadOf rewrites with a token in them,
a token in a remote URL, Git Credential Manager, the gh CLI, the Windows Credential
Manager. These commands show which one wins, never printing more than a fingerprint like
ghp_…a1b2:
# every remote of this clone, and whether it can read the repo
pncli git credentials inspect
# every clone under a folder that is unmapped or lacks access
pncli git credentials inspect --scan ~/src --problems-only
# insteadOf rewrites and URL-scoped helpers
pncli git credentials mappings
# what the credential stores hold, and what git actually sends
pncli git credentials stored
# drop a stale stored credential
pncli git credentials forget --host github.com --username octo
# per marketplace: mode, and whether git sends pncli's token
pncli skills git-auth status
# all of the above, with a fix for each problem
pncli doctor stored also flags a shadowed credential — one sitting in a store that git
never sends because another helper answers first — which is the usual answer to “why is git using the
wrong account?”.
More on the concepts behind skills and marketplaces: Skills guide.