# Paperclip

[Paperclip](https://docs.paperclip.ing) is a control plane for the AI agents you
run at work: it hires them, assigns them issues, and holds their budgets and
approvals. It also has its own secret store — and that is where seekrit fits,
because the two answer different questions. Paperclip decides *which agent may
do what*; seekrit decides *what a credential is worth if the agent leaks it*.

```bash
npx paperclipai plugin install @seekrit/paperclip-plugin
```

One install adds four agent tools, the three seekrit skills, and a secrets panel
under the company. The rest of this page is what to configure and why the design
is shaped the way it is.

## Why a seekrit secret is not a Paperclip `secret_ref`

Start here, because it is the thing people look for and do not find.

Paperclip resolves an adapter's `secret_ref` through its own provider system,
and that provider list is **closed**: `local_encrypted`, `aws_secrets_manager`,
`gcp_secret_manager`, `vault`. There is no seekrit provider to select, so there
is no honest way to express a seekrit secret as a Paperclip secret.

The dishonest way — copying a value out of seekrit into Paperclip's store — is
worse than it looks. It creates a second plaintext copy under a different
lifecycle, so a rotation in seekrit silently leaves Paperclip serving the old
value, and a revocation in seekrit revokes nothing. The plugin does not do it,
and neither should you.

Instead, values reach a run at the moment of use, two ways.

> **Note:** Paperclip's **execution policy** governs review and approval stages. It does not cover network egress or sandboxing — that gap is exactly what the [egress proxy](/docs/guides/agent-proxy) fills.

## The two paths

| Path | Use it when | What the run holds |
| --- | --- | --- |
| **Inject and exec** — `seekrit:run_command` | The run is your own tooling: a build, a test suite, a migration, a dev server | The real value, in one child process's environment |
| **Egress proxy** — `{{seekrit:NAME}}` placeholders | The credential is going to a model, a sandbox, generated code, or a subagent whose output you cannot predict | Never a value — only a placeholder |

Default to the first for tooling you wrote and the second for anything an agent
is about to hand onward. When both would work, the proxy is stronger: it also
bounds *where* the credential can go.

## Configure the plugin

One field is required: a **seekrit service token**, chosen with Paperclip's own
secret picker in Settings → Plugins → seekrit. This is the one credential that
*should* live in Paperclip's store — it is Paperclip's token, and it is the
ceiling on everything its agents can reach, so scope it narrowly with
[`seekrit access grant`](/docs/guides/service-tokens).

The rest are defaults so a tool call needs no arguments:

| Field | Default | What it does |
| --- | --- | --- |
| `app` / `env` / `group` | | The target tools use when a call names none. |
| `allowRunCommand` | on | Turn off execution, leaving the read-only and write-only tools. |
| `cliPath` | `seekrit` | Where the CLI is, if not on the host's `PATH`. |
| `timeoutSeconds` | `300` | Hard cap on one tool invocation. |

The [seekrit CLI](/docs/guides/cli) must be installed on the Paperclip host: the
plugin shells out to it rather than reimplementing the crypto, which is also how
it avoids ever holding a plaintext itself.

## What the agent gets

| Tool | Does |
| --- | --- |
| `seekrit:list_secrets` | Names, versions, and when each last changed. Never a value. |
| `seekrit:run_command` | Runs a command with secrets injected into that child only; returns exit code and output. |
| `seekrit:store_secret` | Encrypts and stores a value. Write-only — nothing reads one back. |
| `seekrit:proxy_config` | Generates a `seekrit-proxy.toml` for the upstreams a workload calls. |

There is deliberately **no** `get_secret`. Reading a value is the local MCP
server's job, next to your key; a Paperclip tool that returned one would put
plaintext into a run transcript by design. A test in the package enforces the
absence.

The plugin also installs the three seekrit skills into the company's library, so
an agent knows *when* to reach for those tools — including
`seekrit-paperclip`, which covers the Paperclip-specific traps: never put a
value in an adapter env map, a project env map, an approval payload, or an issue
comment.

## MCP servers, per adapter

Paperclip is the control plane; the **adapter's runtime** speaks MCP. So MCP
config is per-runtime and lives next to the agent's working directory, not in
Paperclip's database. For the Claude Code adapter — and the Codex, Cursor,
Gemini CLI, and OpenCode adapters, which inherit their CLI's own MCP support the
same way — that is a project-scoped `.mcp.json`:

```bash
seekrit paperclip init --dir /srv/paperclip/workspaces/storefront
```

An existing file is merged, not replaced. See
[`seekrit paperclip init`](/docs/reference/cli#seekrit-paperclip-init) for the
flags.

## Wiring the proxy

For runs you do not trust, generate a config and run the proxy beside Paperclip:

```bash
seekrit proxy init --mode forward \
  --preset anthropic --preset openai --preset gemini
SEEKRIT_TOKEN=skt_… seekrit proxy run
```

Then paste the placeholder environment into the agent's **Configuration →
Environment variables**. `seekrit paperclip init --preset …` prints exactly this
table for the presets you name:

| Variable | Value |
| --- | --- |
| `ANTHROPIC_API_KEY` | `{{seekrit:ANTHROPIC_API_KEY}}` |
| `OPENAI_API_KEY` | `{{seekrit:OPENAI_API_KEY}}` |
| `GEMINI_API_KEY` | `{{seekrit:GEMINI_API_KEY}}` |
| `HTTPS_PROXY` | `http://127.0.0.1:8081` |
| `NODE_EXTRA_CA_CERTS` | absolute path to `seekrit-proxy-ca.pem` |

Every value is a plain string. A placeholder is not a secret, so none of it needs
a `secret_ref` and none of it trips `PAPERCLIP_SECRETS_STRICT_MODE` — which is
the practical reason this path is the one to reach for. Use `SSL_CERT_FILE` or
`REQUESTS_CA_BUNDLE` instead of `NODE_EXTRA_CA_CERTS` for a non-Node runtime.

A run wired this way holds no key. The proxy refuses any host not in its config,
and that config is not something the run can edit.

## The secrets panel

The plugin adds a page at `/:company/seekrit` listing what the configured
environment holds — names, versions, last changed. It reads live and falls back
to its last snapshot when seekrit is unreachable, saying which it is showing: an
empty table would read as "no secrets", which is a different and wrong answer to
"we could not ask".

## Skills without the plugin

Paperclip installs skills straight from a GitHub repository, pinned to a commit.
If you want the instructions but not the plugin, paste this into the source field
on the Skills page:

```
https://github.com/seekritdev/agent-plugin
```

That is the same [agent plugin](/docs/guides/ai-agents/plugin) package every
other coding agent installs, so the guidance your Paperclip agents follow matches
the guidance your local ones do.

## Where the boundary sits

Paperclip is self-hosted, so its server is a process **you** run. A plugin that
decrypts there is in the same position as [`seekrit run`](/docs/guides/run) or
the [SDKs](/docs/guides/sdks) — the customer's own side of the line — and
seekrit's API still never sees a plaintext, a private key, or a data key.

What the plugin adds on top of that is narrower than it needs to be, on purpose:
it holds no network capability of its own (the CLI subprocess makes the calls),
posts no issue comments, caches no resolved value, and writes the service token
to no log, no activity row, and no error message.

One honest caveat: because the plugin never sees the values `run_command`
injects, it cannot redact them from that command's output. A program that prints
its own credential has leaked it — the tool description tells the agent so
before it pipes stdout into a comment.
