Your coding agent can run the migration. It can never be handed the password.
A credential vault in the editor you already have open — SSH hosts and keys, database connections, VPN profiles, terminal commands, config files and secrets — with a broker that lets an AI coding agent act on them over SSH, database and VPN protocols, which no HTTP proxy can broker.
Marketplace · How the broker works · Security model · Self-host the team server · Security reviews
Your SSH keys are in ~/.ssh, your connection strings are in appsettings.Development.json, your
.ovpn files are somewhere in Downloads — and the moment you point a coding agent at any of them,
it can read all of it.
- SSH hosts, keys, jump hosts and port forwards — connect in one click, never retype
- Databases — Postgres, MySQL, SQL Server, MongoDB
- VPN profiles — WireGuard and OpenVPN, up and down from the tree
- Terminal commands and scripts, arguments as rows, variables through the environment
- Config files kept out of git, read back from code in twenty languages
- Payment instruments, one-time codes, seed phrases
- A broker for AI agents — act on a credential, never receive it
- Ten permission switches, every one off by default, and a prompt as often as you say — every call, once every 12 hours, or never; creating and deleting always ask
- A single-binary CLI, 6.8 MB, no runtime to install first
- Optional self-hosted team sync the server cannot decrypt
Act on it, never receive it. The broker protocol has no field a raw secret could travel in — a
structure, not a policy. The source says it plainly
(brokerProtocol.ts:7): "no shape it could arrive in exists".
That is a guarantee about the protocol, not about everything an approved command may print: a
command you approve which writes a credential to its own output is masked on the way out, and that
masking is best-effort. The whole edge is under
Your agent, and what it may do, because a claim with no edge
stated is a claim nobody should believe.
Protocols, not just HTTP. The credential brokers built for AI agents that this was measured against on 2026-09-06 — Infisical's Agent Vault, Anthropic's Managed Agents Vaults, 1Password for Claude, Bitwarden's Agent Access SDK — all mediate HTTP: a forward proxy, egress substitution, browser autofill, an SDK. This one performs SSH commands, database queries, VPN connections and saved terminal commands on the agent's behalf, on the machine where the secret already lives.
One qualification, on corporate servers only. A company can mark somebody a developer, and a developer's vault is additionally sealed to a 32-byte login key the server holds and hands over only while their account is active — so the file plus the PIN stops opening once they are deactivated. That is one factor of two: the server still never sees the PIN and never sees the key that decrypts the payload, so it cannot read a vault with what it holds, and an operator with the login key and a stolen file can attack the PIN offline exactly as they already could. Nothing changes for a personal server, where no such key exists.
Local-first. Secrets sit in the OS keychain. The team server is optional and stores ciphertext — there is no decryption routine in it to call. On a corporate server it holds one FACTOR of a developer's key (above), and never the key that decrypts a payload.
Install from the Marketplace, or build it:
cd src_vs_code
npm ci && npm run package # produces creds-for-devs-<version>.vsix
code --install-extension creds-for-devs-*.vsixAdd an account, add a credential, press Connect. Creating the account profile signs in once with your existing Microsoft or Google account — that identity is the profile's name, and nothing is stored with them. After that there is no server and no network in daily use: nothing leaves the machine.
cd deploy
cp .env.example .env # edit: your domain, your identity provider, your TLS mode
docker compose up -dThat is the whole deployment: the API, an nginx that terminates TLS, and a certbot that obtains and renews the certificate. Everything that must survive an update — vault blobs, share inboxes, certificates — lives in host directories the containers only borrow. Full operator guide, including the four TLS modes and what to choose for an internal network: deploy/README.md.
The server cannot read anything it stores.
Secrets are encrypted on your machine: AES-256-GCM, under a random master key that is itself wrapped once per unlock method — a sync PIN, a security key (YubiKey / FIDO2 through WebAuthn PRF), a printed recovery code, or your organisation's recovery escrow. The PIN wrap is derived with scrypt at N = 2¹⁷, about 128 MiB and a second of work per attempt. What travels to the server is ciphertext, and what the server writes to disk is that same ciphertext. It has no key, and there is no code path that would let it acquire one.
What it adds is the thing a shared folder cannot:
| A shared NAS folder | This server | |
|---|---|---|
| Who may read your ciphertext | everyone with folder access | only you — GET /api/vault is scoped to your token's verified email |
| Sender of a shared secret | claimed by the sender, unverifiable | stamped by the server from a verified token, so it cannot be set by the sender |
| Joining and leaving | someone edits ACLs, eventually | whatever your identity provider already does |
Without a server, sharing through a folder or a NAS is signed with Ed25519 instead — trust on first use plus key continuity, which is strong against someone who arrives later and weak against someone already in place when you first exchanged. That is why a team that needs sender authenticity uses the server transport.
Nine kinds of entry, each with the action it exists for: credentials, SSH connections and
SSH keys (connect, install, serve from an agent with a prompt per signature), VPN configs
(start and stop the tunnel), database connections (open in your client, or run a query),
terminal commands (arguments as rows, each with its own note), scripts (a highlighted editor,
variables pulled out as ${NAME} rows and delivered through the environment rather than pasted into
the body), config files (the whole .env or appsettings.Development.json, kept out of git and
read back from code), and payment instruments (cards, bank details, seed phrases, read back the
way they are printed). Any entry can also carry one encrypted file and one encrypted image, 4 MiB
each; executables are refused, including as a double extension.
Any entry can be given a lifetime, for the staging tokens and one-off keys nobody ever gets round to deleting: one hour, one day, until VS Code closes, or until an agent has used it once. When the time comes the entry is really deleted — secret, revision history and a tombstone that carries the deletion to every machine that syncs — never merely flagged as spent.
Any entry, or a whole folder, can also take a PIN of its own — a real second wrap inside the vault, not a prompt in front of it. A protected entry disappears from every agent-facing surface rather than refusing on use, and a shared one asks its recipient to choose a PIN of their own, because your PIN was never sent and cannot be. An entry PIN needs at least four characters, anything you like — it is a second lock behind an open vault, not the vault's own, whose PIN keeps its stricter rules.
Around them: folders with types, project folders that create the whole set at once, multi-select for bulk delete, export and share, per-entry created and changed dates, the last three versions of each entry, and an export for people outside your organisation — password-sealed, or plain JSON if you deliberately ask for it.
The extension is one half; creds is the other — the same broker, reached from a terminal, a script,
or a host you are connected to over Remote-SSH.
curl -fsSL https://raw.githubusercontent.com/oleksandrdubyna88/dew_flow_creds_for_devs/main/install.sh | shNative AOT: one file, no runtime to install first — 6.8 MB on disk, about 3 MB to download, built for
six platforms. It picks the build for the machine it runs on, verifies the release checksum, and
refuses to install on a mismatch. CREDS_PREFIX chooses somewhere other than /usr/local/bin;
CREDS_VERSION pins a release instead of taking the newest.
Piping a script into sh is worth being deliberate about, on a tool about credentials most of all.
install.sh is short enough to read in a minute and does exactly what is written above —
download it and look before you run it on anything you care about.
What it does NOT install is a credential. creds holds none and can obtain none: it relays a
request to the VS Code window that minted the grant token, that window performs the action, and only
the output comes back.
An AI agent reaches this vault through MCP — and reaches nothing until you say so. Every entry is invisible to an agent until you turn a switch on for it, including every entry that existed before the feature.
Ten switches on two ladders, all off by default — six over entries, four over folders. Deleting implies creating implies replacing implies using implies seeing, so "may change it but may not see it" is not a state you can assemble by clicking. Set them on a folder and the entries in it inherit, including ones created there later.
| Switch | What an agent may do |
|---|---|
| Visible to agents | see the entry's non-secret half — name, host, user, port, and a connection string with the password removed |
| Usable by agents | ask to run a command, a query, a saved script; open a terminal or bring a VPN up |
| Agents may replace the secret | rotate it, without seeing the old value or the new one |
| Agents may create entries | store a credential in a folder you opened for it |
| Agents may delete what they created | move an entry to the Trash — never permanently |
| Agents may delete anything here | the same, over entries it did not create |
| Agents may rename and move folders | reorganise inside what you opened |
| Agents may create folders | make a folder to put things in |
| Agents may delete folders they created | to the Trash, never permanently |
| Agents may delete any folder here | the same, over folders it did not create |
Two things hold at every level. A secret is never handed over: the window holds the value, uses it, and answers with the result — there is no field in the protocol one could travel in. And the switch is not consent: a call asks you, in your editor, showing the real entry, the real command — and who is asking: the agent and its version, which of its sessions — for Claude Code, by the title on its tab — and the folder it works in (Claude Code 2.1.281 · session "creds old issues" (98bf9f23) · in ClaudeRag wants to…), as the caller reports them. That name is a label, and the dialog says so in its own sentence; a caller that reports nothing is An agent, never a product by default.
How often it asks is yours to set, on the entry or on a folder it inherits from: ask every time (the default), ask once every 12 hours, or never ask. It covers USING an entry only — creating and deleting always ask, whatever it says — and never-ask makes the switches the whole gate, which the form says in those words beside the option. The twelve-hour window is remembered on this machine alone and is never synced or shared; Forget Agent Consents on This Machine takes every such window back at once. Every call is recorded either way, in ⋯ → MCP logs.
Where that guarantee ends, stated rather than glossed. The structural half — no response field can carry a secret — holds absolutely. The second half is different: if an approved command prints a credential, the value appears in that command's own output, and a masker replaces this entry's stored values on the way out. That masker fails open by design — if it cannot build its table it lets the answer through rather than turning a working command into an outage — and it can only mask values it knows, so a secret the vault has never seen passes through unchanged. It is a second line, not the first. Approve commands you would be willing to see the output of.
Rotation is the one that sounds impossible. To change a password somebody must know the new one — so the agent never writes it. It writes a placeholder:
ALTER USER app IDENTIFIED BY '{{creds:new}}'The window generates the value, substitutes it, runs the statement, snapshots the old value into that entry's history, and stores the new one. Only a statement that succeeded updates the vault. You approve the statement with the placeholder still in it, which is what makes it safe to show you. This is wired to database and SSH entries; other kinds cannot be rotated this way.
Note the two syntaxes are different things and both are real: {{creds:new}} means "a value that
does not exist yet, mint it", while creds://you@example.com/prod-db/password is a reference to the
value stored today, resolved into a child process's environment and masked out of its output.
There is exactly one call where a secret travels toward the vault: an agent that provisioned something and holds the key can store it. ⋯ → MCP logs counts those by name — along with everything an agent asked for and did not get. Install the server from ⋯ → Install the MCP Server…; it is a separate binary, and the extension still has zero runtime dependencies.
Linux without a Secret Service. VS Code stores secrets in the OS keychain. On a Linux box with no Secret Service running, it silently falls back to an obfuscated file store — which is not encryption. The extension warns, and the fix is to install a keyring, not to ignore it.
Agents in containers. Share with Claude Code reaches an agent running beside the editor. An agent inside a container cannot reach the broker socket, and the Remote Bridge exists for the cases where a bridge is possible.
| What it is | Ships as | |
|---|---|---|
src_vs_code |
CredsForDevs, a VS Code extension | a .vsix on the Marketplace |
src_minimalapi_server |
Cred Vault Server, a .NET 10 minimal API, Native AOT | a 50 MB container image |
They version separately, on separate tags, and each half has its own CI workflow — ci · extension and ci · server — because a change to one should never be blocked by the other's toolchain.
- research/architecture.md — how the two halves fit together, the trust boundary, and the sequence of a sync
- research/module_extension.md — the extension's layers, crypto, and sync algorithm
- research/module_server.md — every endpoint, its authorization rule, and the storage layout
- research/module_deployment.md — the container stack, TLS, updates and backups
- research/PLAN_agent_ssh_broker.md — the broker, end to end
- research/PLAN_mcp_server.md — the MCP surface, the switches, the journal
- research/PLAN_org_recovery.md — corporate break-glass, and why the server still cannot open a vault alone
- research/SECURITY_REVIEW_2026-08-24.md — the pre-launch review of the whole product, three critical findings and their fixes
- research/SECURITY_REVIEW_2026-08-23.md — the security, reliability and architecture review, with what was fixed and what was not
- todo/ — what is still open, as executable plans
- CLAUDE.md — the rules a contributor, human or agent, works under here
git submodule update --init .claude/rules/shared # shared conventions
dotnet build dew_flow_creds_for_devs.slnx
./src_minimalapi_server/tests/bin/Debug/net10.0/CredVaultServer.Tests.exe
cd src_vs_code && npm ci && npm run typecheck && npm testOpen a security advisory
rather than a public issue. Everything in research/ that begins SECURITY_REVIEW_ is a
past pass over this code, findings and all, including the ones that were not fixed and why.
MIT — see LICENSE. Use it, fork it, ship it.