Give your agent a way to ask for a secret
An agent that needs a credential will ask for it the obvious way, and the obvious way puts the plaintext in the context window and the session transcript. PinchPass gives the agent a channel for getting the value out-of-band, straight to disk.
Pi native OpenClaw plugin 70+ agents via skills.sh MIT
The problem this solves for agents
Every credential an agent receives in conversation becomes part of its working state. It is stored in the transcript, replayed as context on later turns, echoed in logs, and often synced to a model provider. Rotating the key afterwards is the only real remedy, and by then the value has already been copied around.
The fix is not to teach the agent to be careful. It is to give it a different channel: the human types the value into a form whose contents the agent never sees, and the value lands in a file the agent reads as a path rather than as text.
Three ways to wire it up
Pi package
pi install npm:@pinchpass/cli
Registers the request_secret tool and the bundled skill, and
downloads the binary for link mode.
OpenClaw plugin
npm i -g @pinchpass/cli
The same package carries an OpenClaw plugin manifest exposing the same tool
name, backed by a $.raw runner.
Universal skill
npx skills add rubybear-lgtm/pinchpass
No plugin, no per-platform work: the skill teaches the agent when to call the CLI and how to read its output.
The request_secret tool
| Parameter | Meaning |
|---|---|
names |
One or more secret names to collect, written into
.env as keys. |
via |
How to collect: auto, modal, or
link. See the table below. |
out |
Output .env path. Defaults to .env. |
note |
Description shown to the human, so they know what is being asked for. |
ttl |
Minutes until the link expires. Applies to
link mode only; in modal mode it is ignored. |
tunnel |
Open a bore.pub tunnel so the human does not need to be on
your machine. Applies to link mode. |
via | Behaviour |
|---|---|
modal |
A Pi dialog collects each value from the keyboard straight into the
.env file. No server starts, nothing touches the network, and
the value never reaches the model or the transcript.
ttl does not apply. |
link |
Spawns the CLI, streams the one-time encrypted URL to the user immediately, and blocks until they submit or the TTL expires. |
auto |
Modal in the interactive TUI, link everywhere else. This is the default. |
Modal mode is pure dialog, so it works without the pinchpass binary
and without network access. Link mode resolves the binary from
PATH, ~/.local/bin, ~/.openclaw/bin, and
~/.pi/bin, so no PATH surgery is needed.
What the tool returns
Results render as small styled cards rather than raw JSON, and they report where the value went, not what it was:
- ✅ Secrets collected — with the saved file path and the key names that were written.
- ✋ Cancelled — the user dismissed the dialog. Nothing was written.
- ❌ Failed — the request timed out or the CLI could not run. Nothing was written.
The key names and the path are safe to keep in context. The values are not part of the result at all.
Teaching an agent when to reach for it
The skill is the integration. It tells the agent to use PinchPass when it needs a
value it does not have, when the user says they need to give it a secret, or when
a .env file needs credentials.
It also tells the agent when not to: for non-sensitive plaintext there is no reason to route the value through end-to-end encryption, and the agent should just ask for it directly. Keeping that rule in the skill is what stops the tool from being applied to every string an agent wants.
# teach every detected agent
npx skills add rubybear-lgtm/pinchpass
# target specific agents
npx skills add rubybear-lgtm/pinchpass -a opencode -a claude-code -a openclaw
# install globally, available in every project
npx skills add rubybear-lgtm/pinchpass -g
The skill works with opencode, Claude Code, OpenClaw, Cursor, Windsurf, Gemini, and 70 or so other agents — no platform-specific plugin required.
Working with the CLI directly
When an agent drives the CLI itself, the skill's first rule is to always pass
-json, so the output can be parsed rather than screen-scraped:
# one secret, machine-readable
pinchpass request SECRET_NAME -json
# several at once, into a chosen file
pinchpass request KEY_A KEY_B KEY_C -out config/secrets.env -json
# the human is not on this machine
pinchpass request SECRET_NAME -tunnel -json
Consuming that output correctly takes three rules:
- The first object carries the
url. Present it to the human verbatim, including the#k=fragment, and keep waiting. - The second object carries the outcome. Read
successandmessagefrom it. It does not containurl, so do not look there for the link. - A timeout exits non-zero with
successfalse. Handle it as a failure to collect, not as an empty secret.
The CLI reference shows both objects in full.
A safe agent loop
-
Detect that a step needs a credential the agent does not have.
-
Decide that the value is genuinely sensitive. If it is not, ask for it directly and skip all of this.
-
Choose the channel: modal if the human is present in an interactive session, link otherwise, adding
tunnelwhen they are on another machine. -
Relay the URL verbatim, complete with the fragment. Do not shorten it, wrap it, or reformat it.
-
Never write the value into the transcript, a log line, a commit, or a summary. The agent's job is to know the key name, not the value.
-
Wait for the blocking call to finish rather than polling or retrying concurrently, which would waste the one-time link.
-
On failure, surface the failure and offer a fresh link; on success, continue with the file path. Never echo the contents of
.envback to the user.
Next
- CLI reference — flags, the two JSON objects, and
.envwriting rules. - Security model — what the agent can and cannot observe, and what the relay sees.
- Install — every channel, including the prebuilt binary for link mode.
- FAQ — short answers to the obvious follow-ups.