Claude Code can inspect files that its workspace permissions allow. If those permissions include a dotenv file with real values, the credentials can enter agent context, transcripts, tool logs, or generated code.
Phantom removes real values from managed dotenv files, keeps dotenv read permissions closed, and exposes value-blind MCP metadata instead. Application and test processes load phm_ placeholders. On supported HTTP paths, the authenticated proxy matches an exact route and injects only that route's vault value into its fixed auth header; client headers and bodies never resolve placeholders.
The MCP integration goes further: Claude gains the release-schema-verified tool
catalog for value-free secret workflows. The current release contract enforces
54 unique tools; runtime tools/list is canonical.
Install the reviewed v0.7.9 binary using the platform-specific, checksum-
verified path in getting started, then run
phantom init in the project.
phantom setup --client claudeIn v0.7.9, this merges the phantom MCP server
into the project's .mcp.json. Separately, it removes only the legacy Phantom
MCP entry and Phantom-managed dotenv read grants from
.claude/settings.local.json, preserving unrelated servers and permission
rules. Dotenv denies remain a defense-in-depth boundary.
Release compatibility: v0.7.9 is the first release with this correction.
v0.7.8 and earlier binaries (including installs made with the former v0.7.8
Homebrew formula) wrote MCP registration into .claude/settings.local.json,
which is not Claude Code's supported MCP registration location. After upgrading to
v0.7.9, rerun phantom setup --client claude to migrate the legacy entry. If
you must stay on v0.7.8, run phantom setup --client claude --print and
manually merge only its mcpServers.phantom entry into .mcp.json. Keep
permission settings in .claude/settings.local.json; do not copy them into
.mcp.json or overwrite unrelated server entries.
The corrected setup validates both files before writing and uses exact before-images to avoid overwriting concurrent edits. It attempts rollback after an observed later write failure; separate file replacements are not a crash-atomic filesystem operation. If setup reports a partial or uncertain result, inspect both files locally before retrying.
Claude Code uses .mcp.json for project-scoped registration. In interactive
sessions, review and approve the server when Claude prompts; Phantom setup
does not grant that approval. Headless client behavior differs, so inspect the
configuration before starting automated sessions. See the
Claude Code MCP scope documentation.
The generated command is a machine-local executable path; review it before
sharing .mcp.json with teammates, whose installed paths may differ.
Install both v0.7.9 release binaries before setup. Version 0.7.9 records the
running phantom executable with mcp serve when it can resolve that runtime,
otherwise it looks for a local phantom-mcp. Setup has no network
package-runner fallback and fails closed when neither local runtime is
executable. Keep both verified binaries installed and inspect the generated
entry.
Verify it registered:
claude mcp list
claude mcp get phantomCheck that phantom is connected, not merely listed or pending approval.
phantom exec -- claudeThe proxy starts on 127.0.0.1, *_BASE_URL environment variables are set, and Claude launches with the full Phantom environment. When your code runs API calls inside the Claude Code session, the proxy handles credential injection.
phantom agent doctor
phantom agent report --jsonUse this before giving Claude broad autonomy. It checks the repo's .env files, Phantom config, vault access, unprotected secrets, MCP wiring, package script wrapping, pre-commit protection, cloud login, team state, audit status, and sync targets. The report returns one state: unsafe, protected, verified, team-ready, or compliance-ready.
Once phantom is registered, Claude can call the full runtime
catalog. The following table highlights the core workflows; use MCP
tools/list for the canonical catalog.
Status tools return three forms: a short human summary text block, the same
value-blind report as JSON text, and that report as MCP structuredContent.
Reports carry names, counts, and states only, never secret values or phantom
tokens, and include next_step where the agent has something to do next.
Tools whose whole answer was already JSON (phantom_capability, phantom_do,
phantom_setup_workspace, the audit, leak-incident,
compliance, validation, expiry, and rotation-schedule tools)
keep that JSON as their only text block and now also attach it as
structuredContent.
Errors the user can fix come back as MCP error -32600 with the next step in
the message; -32603 is kept for real server faults.
- Locked vault. When the project's secrets are in an encrypted-file vault
and the MCP server's environment has no
PHANTOM_VAULT_PASSPHRASE, the server opens the OS keychain instead. Tools that would answer from that empty view (phantom_secrets_expiry_check,phantom_secret_rotation_due,phantom_validate_secret,phantom_rotation_schedule_next) refuse with "Vault locked: ..." and the unlock step. When the keychain holds some entries, they answer but add avault_notesaying the answer covers only the keychain. Fix it by settingPHANTOM_VAULT_PASSPHRASEin the server's env config and restarting the server. - Wrong passphrase. A decryption failure names both causes: a wrong
PHANTOM_VAULT_PASSPHRASEin the server's env, or a corrupt vault file. - Not initialized.
phantom_why,phantom_status,phantom_check,phantom_list_secrets,phantom_list_with_expiry, andphantom_compliance_statusstill answer beforephantom init. Other vault tools return thephantom initnext step.
| Tool | What it does |
|---|---|
phantom_init |
Apply one exact-before transaction across config, managed dotenv, gitignore, hook, generated client files, and vault CAS operations. |
phantom_env |
Generate .env.example from current .env — secrets replaced with placeholders, non-secrets preserved. |
Claude must ask for explicit user consent before calling any of these. Calling
without confirm: true and a valid one-use approval_token returns an error.
The token comes from a separate attached-terminal phantom mcp-approve
ceremony that displays the exact value-blind effect; keep that command outside
Claude's shell and PTY authority.
Provider requests and other effectful operations are disabled by default.
They can reach both confirm: true and one-use approval_token gates only
when PHANTOM_MCP_EFFECTS=trusted-terminal is configured outside Claude's
authority. phantom mcp-approve requires attached stdin/stderr, shows the
value-blind effect and exact parameters, and requires a fresh typed challenge.
A same-user shell or Claude-controlled PTY can defeat the ceremony; leave MCP
effects disabled unless approval command and storage are outside its authority.
This includes phantom_cloud_status, phantom_team_list,
phantom_team_members, and phantom_validate_all. Conditional operations keep
their inspection mode read-only, but require both gates for schedule updates,
alert backfill/dispatch, hotspot acknowledgement, and saved reports. Runtime
tools/list is the exact parameter contract; every tool whose schema takes
approval_token says so in its description.
With PHANTOM_MCP_EFFECTS unset (the default), every approval-gated tool
refuses with a message naming the variable. To enable them:
- Set
PHANTOM_MCP_EFFECTS=trusted-terminalin the environment that launches the Phantom MCP server, somewhere Claude cannot edit, for example a user-scoped registration:claude mcp add --scope user -e PHANTOM_MCP_EFFECTS=trusted-terminal phantom -- phantom mcp serve. A project.mcp.jsonthat Claude can write is not outside its authority. - Claude calls the tool with
confirm: trueafter asking you. The first call has noapproval_token; the server prints a nonce on its stderr and the call fails with "requires out-of-band approval". - In your own trusted terminal (not Claude's shell or PTY), run
phantom mcp-approve <NONCE>, review the value-blind effect and exact parameters, and type the challenge. - Claude retries the identical call with
approval_token: "<nonce>:<token>". The token is one-use and bound to those exact parameters.
You never need this to add a secret: phantom_add_secret_interactive is
effect-free, and phantom add NAME in your terminal does the actual write.
Here is a typical conversation that shows how the tools compose in practice.
You: I need to add a Stripe secret key to this project.
Claude: [calls phantom_add_secret_interactive with name STRIPE_SECRET_KEY;
no value, no approval needed because it stores nothing]
Run `phantom add STRIPE_SECRET_KEY` in your terminal and enter the
real value at the prompt. Do not paste it into chat.
You: can you check our vault is healthy?
Claude: [calls phantom_doctor]
All checks pass. Config valid, .env fully protected, .env is in
.gitignore, .env.example exists.
You: after our hosted pilot is commissioned, back up this vault so I can restore
it on this keychain machine later
Claude: I first need to verify that the hosted deployment and your entitlement
are commissioned. If they are, the push overwrites the existing cloud copy.
Approve the exact effect outside my shell authority. [calls
phantom_cloud_push with confirm: true and the one-use approval_token]
[Only after provider acceptance: reports the value-free push result.]
- Tell Claude the secret name, not the value. Claude calls
phantom_add_secret_interactive(effect-free, no approval) and gives youphantom add NAME; you run it in your terminal and enter the value at the prompt. - Claude writes the integration code using the env var name (
process.env.MY_API_KEY). phantom exec -- claudeensures API test calls during the session go through the proxy.
In the supported path, Claude uses value-blind MCP status and reviewed proxy
routes rather than receiving provider credentials. That boundary does not cover
unmanaged files, external tools, provider responses outside configured
scrubbing, or processes launched outside phantom exec.
Claude can call phantom_sync (read-only mode) to show which secrets and targets are configured, then guide you to run phantom sync --platform vercel --project prj_xxx in the terminal to execute the actual push.
You: I'm on a new laptop. Help me get set up.
Claude: [calls phantom_status — sees no .phantom.toml]
Phantom isn't initialized here. Do you have authorized access to the
project's secrets in Vercel? Personal Phantom Cloud backups cannot be
decrypted here without the original machine's cloud key.
You: Vercel, project ID is prj_abc123
Claude: Run this to pull secrets from Vercel:
phantom pull --from vercel --project prj_abc123
Then I'll run phantom_doctor to verify everything looks good.
To run Claude Code through a local LiteLLM gateway that holds no real keys, see Connect an agent in the LiteLLM guide. Without the gateway, nothing changes: the direct Phantom route above stays the default.
These limits are intentional and enforced at the protocol level.
Phantom's MCP does not return real secret values. phantom_list_secrets
returns names only, the deprecated plaintext add tool refuses values, and
interactive entry happens in the trusted terminal. This is a statement about
the Phantom MCP surface, not about unrelated files, shell commands, providers,
or tools that may grant the agent broader access.
Cannot call listed effectful tools without both gates. phantom_init,
phantom_remove_secret, phantom_rotate,
phantom_cloud_push, phantom_cloud_pull, phantom_copy_secret,
phantom_env, phantom_wrap, phantom_unwrap, phantom_doctor (when
fix=true), authenticated provider reads, and team write tools hard-fail if
confirm: true or the one-use out-of-band approval is absent. These are tool
gates, not a general prompt-injection defense; keep the approval command and
deployment/provider authority outside the agent's control.
Cannot receive real secret values through MCP. Plaintext values passed to phantom_add_secret are rejected. New secrets must be entered through the terminal prompt started by phantom_add_secret_interactive.
Cannot execute sync or pull against platforms. phantom_sync is informational only — it shows configuration but does not call Vercel or Railway APIs. Actual sync requires a CLI command you run directly.
Cannot start or stop the proxy. There is no MCP tool for proxy lifecycle.
Use phantom exec for a child-owned session, or run foreground phantom start
in a trusted terminal and press Ctrl-C in that same terminal to stop. Detached
--daemon mode and current external process control fail closed; phantom stop
authenticates legacy v0.7.3 state only to report manual migration guidance and
never kills a process or deletes the record.
- MCP setup:
phantom setup --client claudeafter installing bothv0.7.9binaries - Full command list: getting-started.md
- Troubleshooting: troubleshooting.md
- GitHub: https://github.com/ashlrai/phantom-secrets
- Site: https://phm.dev
