all repos — dot @ f5d9efe3a80ae1bdfbcf082ac9cb69f4d322d150

Shell, editor and terminal configuration, and the tools that go with them

pi: the siliconflow key is a reference, not a name

models.json gave the provider an apiKey of "SILICONFLOW_API_KEY", which pi
sends verbatim as the credential: it interpolates "$NAME" and "${NAME}", runs
"!command", and treats anything else as a literal. So that provider has been
authenticating with the 19-character string "SILICONFLOW_API_KEY" and getting a
401 for as long as it has existed.

Confirmed by calling pi's own resolver: "SILICONFLOW_API_KEY" resolves to
itself, "$SILICONFLOW_API_KEY" to the value. Nothing catches this --
isConfigValueConfigured returns true for both and reports no missing variables,
so `pi auth check` says ready either way, and only a real request fails. Hence
the note in CLAUDE.md beside the models.d row: the rule is invisible in the
file, and the next provider added would repeat it.

Reported as a change request from the machine that hit it; the sweep for other
instances found none.
Igor Soarez igor@soarez.org
Mon, 28 Sep 2026 12:45:14 +0300
commit

f5d9efe3a80ae1bdfbcf082ac9cb69f4d322d150

parent

bf177c58da897dbd084cc1fe8e6ebd9b61b85830

2 files changed, 8 insertions(+), 1 deletions(-)

jump to
M CLAUDE.md → CLAUDE.md

@@ -51,6 +51,13 @@ | `~/.config/claude/mcp-servers.d/*.json` | MCP servers, registered by `link/claude.sh` |

| `~/.claude/rules/*.md` | extra Claude Code user memory, loaded next to `config/claude/CLAUDE.md` | | `~/.config/pi/settings.d/*.json` | pi settings merged into the generated `~/.pi/agent/settings.json` by `link/pi.sh` | | `~/.config/pi/models.d/*.json` | pi providers merged into the generated `~/.pi/agent/models.json` by `link/pi.sh` | + +A credential in a pi provider -- `apiKey`, or anything under `headers` -- is a +**reference**, not a name: `"$SILICONFLOW_API_KEY"`, not `"SILICONFLOW_API_KEY"`. +A bare name is sent verbatim as the credential, and nothing warns: pi reports +such a provider as configured and `pi auth check` says `ready`, because a +literal counts as a value. Only a real request fails, with a 401. `!command` +runs a command and uses its output, and `$$` escapes a literal `$`. | `~/.config/agent-skills.d/*` | agent skills, linked into every installed agent by `link/skills.sh` | | `~/.local/share/szecret/{store,id.pub}` | the szecret store; the tool is here, its secrets are not | | `~/.config/shell/dir-hashes.zsh` | more zsh named directories, sourced by `config/zshrc` |
M config/pi/models.json → config/pi/models.json

@@ -3,7 +3,7 @@ "providers": {

"siliconflow-anthropic": { "baseUrl": "https://api.siliconflow.com/anthropic", "api": "anthropic-messages", - "apiKey": "SILICONFLOW_API_KEY", + "apiKey": "$SILICONFLOW_API_KEY", "authHeader": true, "models": [ {