Skip to content
Integrations

Phantom Secrets

Stack is the control plane; Phantom is the vault. Understanding the split is the single most important mental model for operating Stack safely.

Sister product
Phantom Secrets — E2E-encrypted vault. Credential storage and execution require supported setup.
phm.dev ↗

The split

Setup handles supplied and materialized credential values in memory and attempts persistence through installed Phantom. Dedicated secrets in .stack.toml record the slot name; manual fields and freeform metadata can contain user data and must be reviewed before sharing.

Stack (control plane)
  • ● Drives provider OAuth / API flows
  • ● Creates or attaches resources according to the adapter
  • ● Tracks which secrets each service needs (slot names)
  • ● Exports empty-key .env.example skeletons separately; writes available .mcp.json descriptors
  • ○ Handles credential values during setup
Phantom (vault)
  • ● Provides the installed credential-persistence interface
  • ● Owns supported execution; phm_* strings are not generally resolved by Stack
  • ● Requires separately qualified sync and CI configuration
  • ● Controls credential access through its installed interface
  • ○ Has no opinion on what the keys mean

Why Stack refuses to run without Phantom

When you run stack add, stack import, or stack doctor, Stack calls phantom via its CLI. If Phantom setup is missing or its project metadata is unavailable, the credential-writing path refuses before provider contact. Illustrative refusal:

$ stack add supabase
Phantom Secrets isn't installed.

Blank stack init can write split config without provider setup. Selected template init attempts setup by default; use --noProvision for config only. Other read-only commands have their own requirements.

The flow of a single secret

Take SUPABASE_SERVICE_ROLE_KEY as an example:

  1. You run stack add supabase.
  2. Where the OAuth branch is configured, Stack opens Supabase authorization and listens on http://127.0.0.1:8787/callback — register that exact URI as the allowed redirect in your OAuth app so no wildcard matching is needed.
  3. The adapter can create a project through the Management API or attach an existing resource; access and outcomes must be checked (example ref: abcdefghijklmnop).
  4. The adapter attempts to fetch the service_role key. Setup processes credential values in memory.
  5. Stack submits SUPABASE_SERVICE_ROLE_KEY through the supported create-only Phantom stdin interface. Existing names, missing setup or refused persistence can stop the operation.
  6. Stack writes secrets = ["SUPABASE_SERVICE_ROLE_KEY"] into .stack.toml. Earlier credential and MCP writes can remain if later writes fail.
  7. Run stack env export --example separately for an empty SUPABASE_SERVICE_ROLE_KEY= skeleton; Stack does not regenerate populated env files.
Check phm_ strings before sharing. Stack does not establish their safety or general substitution behavior. phantom exec is an installed-product interface that stack exec forwards to; follow its supported configuration and verify the actual consumer.

Runtime injection — stack exec

Configure the application inputs required by process.env using the installed Phantom guidance. The Stack wrapper alone does not establish that they are supplied:

# Ordinary app startup; configure required inputs first
bun dev

# Forward through installed Phantom exec; verify the app receives its inputs
stack exec -- bun dev

stack exec forwards everything after -- to phantom exec. Use it for dev servers, test runners, migrations — only after the app and installed execution path are configured and verified.

Syncing the vault

Sync and CI bootstrap belong to the installed Phantom product. Check its current capabilities and configuration before transferring any credentials:

# Inspect the installed interface before planning sync
phantom --version
phantom --help

stack ci init (see CI integration) now refuses workflow generation with exit 1 before creating a workflow directory or writing a file. Its config and existing-file guards remain; stack ci init --force also refuses without overwriting. Phantom Secrets 0.7.9 requires a trusted terminal for Cloud pull; --force does not bypass it, and PHANTOM_CLOUD_TOKEN is not a supported bearer-token input. The local vault passphrase is separate from the Cloud encryption key. No unattended Cloud bootstrap is provided.

Which Stack commands talk to Phantom

Command Needs Phantom? What it does with the vault
stack init Config-only: no; service setup: required Blank/config-only init writes split config; selected templates attempt setup.
stack add Yes Writes provisioned secrets into the vault.
stack import Yes Attempts nonempty parsed values; existing vault names are skipped and writes can fail.
stack remove Yes Attempts named-secret cleanup; headless or refused cleanup can keep keys.
stack env show / diff Yes Reads the vault's key list (never the values).
stack doctor Yes Runs available adapter checks; some are absent or limited.
stack exec Yes Forwards to phantom exec — verify installed execution and the app separately.
stack list, stack info Command-dependent requirements List reads config; info checks slot presence and may run an adapter health check.
stack providers, stack templates list, stack projects list No Static catalog / registry data.

Installing Phantom

Follow the Phantom Secrets setup guidance for your platform and verify its credential and execution interfaces. Stack source and this example do not establish an installed version or completed vault setup.

# Inspect the installed product before configuring Stack
phantom --version
phantom --help

For the full Phantom story, see Phantom phm.dev ↗ .