@seekrit/paperclip-plugin
v0.2.1
Published
seekrit for Paperclip — agent tools that inject end-to-end encrypted secrets into a run without the run ever holding a value, plus the seekrit skills and a company secrets panel.
Maintainers
Readme
@seekrit/paperclip-plugin
seekrit for Paperclip — end-to-end encrypted secrets for the agents you run at work, without a credential ever coming to rest in Paperclip.
npx paperclipai plugin install @seekrit/paperclip-pluginWhat it adds
| | |
| --- | --- |
| 4 agent tools | seekrit:list_secrets, seekrit:run_command, seekrit:store_secret, seekrit:proxy_config |
| 3 skills | seekrit-secrets, seekrit-agent-keys, seekrit-paperclip, installed into the company's library |
| 1 page | A secrets panel at /:company/seekrit — names, versions, last changed. No values. |
Configure it
One field is required: a seekrit service token, picked with Paperclip's secret picker in Settings → Plugins → seekrit. Scope it to the environments these agents should reach; it is the ceiling on everything the tools can do.
The optional fields set defaults so a tool call needs no arguments: app,
env, group, plus allowRunCommand (turn off execution and leave the
read-only and write-only tools), cliPath, and timeoutSeconds.
The seekrit CLI must be on the
Paperclip host's PATH — the plugin shells out to it rather than reimplementing
the crypto. npm i -g @seekrit/cli, or point cliPath at it.
Why a seekrit secret is not a Paperclip secret_ref
Paperclip's secret provider list is closed — local_encrypted,
aws_secrets_manager, gcp_secret_manager, vault — so there is no seekrit
provider to select, and this plugin does not pretend otherwise. It does not copy
values into Paperclip's store either: that would create a second plaintext copy
under a different lifecycle, where a rotation in seekrit silently leaves
Paperclip serving the old value and a revocation revokes nothing.
Instead the tools keep resolution at the moment of use, two ways:
run_commandinjects secrets into one child process and returns its exit code and output. The plugin worker never sees a value;seekrit rundecrypts inside the child it execs.proxy_configgenerates aseekrit-proxyconfiguration so an untrusted workload sends{{seekrit:NAME}}placeholders and the proxy — which holds the credentials — swaps them in on the way out, toward allowlisted hosts only.
Paperclip's database ends up holding exactly one credential: this plugin's own service token.
What it deliberately cannot do
- Read a secret value. There is no
get_secrettool, and a test enforces the absence. Reading a value is the local MCP server's job, next to the key. - Reach the network. No
http.outboundcapability — the CLI subprocess makes the API calls, in its own process. - Post to an issue. No
issue.comments.create. Tools return results to the agent, which writes its own comment in its own voice. - Redact a command's output. Because the plugin never sees the injected
values, it cannot scan for them. A program that prints its own credential has
leaked it, and the
run_commanddescription says so to the agent.
Development
pnpm --filter @seekrit/paperclip-plugin test # regenerates skills, then runs vitest
pnpm --filter @seekrit/paperclip-plugin build # dist/manifest.js, dist/worker.js, dist/ui/
npx paperclipai plugin install ./apps/paperclip-pluginsrc/skills.generated.ts is generated from agent-plugin/skills/** by
gen-skills.mjs and gitignored — Paperclip installs managed skills from inline
content, so the manifest has to carry the bytes. test/skills.test.ts re-reads
the originals, so a stale generated file fails rather than shipping.
Tests run the real worker against a fake seekrit binary that records how it
was called, which is what pins the properties that matter: a stored value travels
on stdin and never in argv, and the service token reaches the child as an
environment variable and appears in no activity row, log line, or error message.
MIT licensed. Docs: https://seekrit.dev/docs/guides/ai-agents/paperclip
