CLI

Commands and usage

λ phase --help
Keep Secrets.

             /$$
            | $$
    /$$$$$$ | $$$$$$$   /$$$$$$   /$$$$$$$  /$$$$$$
   /$$__  $$| $$__  $$ |____  $$ /$$_____/ /$$__  $$
  | $$  \ $$| $$  \ $$  /$$$$$$$|  $$$$$$ | $$$$$$$$
  | $$  | $$| $$  | $$ /$$__  $$ \____  $$| $$_____/
  | $$$$$$$/| $$  | $$|  $$$$$$$ /$$$$$$$/|  $$$$$$$
  | $$____/ |__/  |__/ \_______/|_______/  \_______/
  | $$
  |__/

Commands:
  auth                              💻 Authenticate with Phase
  init                              🔗 Link local project with Phase app
  run                               🚀 Run and inject secrets to your app
  shell                             🐚 Launch a sub-shell with secrets as environment variables
  apps list                         📋 List available apps and their environments
  secrets list                      📇 List all the secrets
  secrets get                       🔍 Fetch details about one or more secrets in JSON
  secrets create                    💳 Create a new secret
  secrets update                    📝 Update an existing secret
  secrets delete                    🗑️ Delete secrets
  secrets import                    📩 Import secrets from a .env file
  secrets export                    🥡 Export secrets in a specific format
  dynamic-secrets list              📇 List dynamic secrets & metadata
  dynamic-secrets lease generate    ✨ Generate a lease (create fresh dynamic secret)
  dynamic-secrets lease get         🔍 Get leases for a dynamic secret
  dynamic-secrets lease renew       🔁 Renew a lease
  dynamic-secrets lease revoke      🗑️ Revoke a lease
  ai enable                         🪄 Enable AI integrations and configure secret visibility
  ai disable                        🚫 Disable AI integrations
  ai skill                          📄 Print the Phase AI skill document
  users whoami                      🙋 See details of the current user
  users switch                      🪄 Switch between Phase users, orgs and hosts
  users logout                      🏃 Logout from phase-cli
  users keyring                     🔐 Display information about the Phase keyring
  console                           🖥️ Open the Phase Console in your browser
  docs                              📖 Open the Phase CLI Docs in your browser
  completion                        ⌨️ Generate the autocompletion script for the specified shell

Flags:
  -h, --help      help for phase
  -v, --version   version for phase

Use "phase [command] --help" for more information about a command.

Available commands

To use Phase CLI, simply run:

> phase [command] [sub-command] [options]

To view all available commands and their descriptions, run:

> phase --help
> phase secrets -h

💻 auth

Authenticate with Phase using the CLI on your own machine. The phase auth command lets you log in to either Phase Cloud or a Self-hosted instance of Phase.

Auth Methods:

  1. Webauth (Default): This automated method opens the Phase Console in your default browser for authentication. You'll simply enter your sudo password to authenticate the CLI seamlessly. For Self-Hosted instances, you'll be prompted to enter the host URL.

Note that during this process, an ephemeral X25519 keypair is generated and a crypto sealed box is used for enhanced security and no tokens or private keys are exchanged in plain text.

Example:

» phase auth
? Choose your Phase instance type: ☁️ Phase Cloud
Please authenticate via the Phase Console: https://console.phase.dev/webauth/OTM3MC00ZWViYmI1MGVlMTU3ZTliOWZk...

This opens the Phase Console in a new tab. Enter your sudo password when prompted. The CLI securely receives your credentials via encrypted POST requests to finalize authentication. If you are already authenticated, it will display your email address and provide instructions for switching accounts.

  1. Token: This allows you to authenticate to Phase directly uisng a Personal Access Token (PAT) or a Service Account Token that you may have manually created in the Phase Console.

For token mode, provide the following:

  • Host URL - Only for Self-hosted instances
  • Email
  • Personal Access Token (PAT) or a Service Account Token

Obtain a Personal Access Token (PAT) from the Phase Console by going to Access Control -> Authentication -> Personal Access Tokens -> + Create Token.

  1. AWS IAM: Authenticate using your current AWS identity from the standard AWS credential chain (env vars, shared config/credentials, SSO, role assumption, instance profile, etc). Optionally bind the external identity to a Phase Service Account and set a TTL for the issued token. You'll need to have configured an external identity to a service account in the Phase Console first.

See External Identities for more details.

Usage:

> phase auth --mode aws-iam [--service-account-id SERVICE_ACCOUNT_ID] [--ttl SECONDS] [--no-store]

Options:

  • --service-account-id (Required): Service Account ID to map this external AWS identity to a Phase Service Account.
  • --ttl (Optional): Token TTL in seconds for tokens created using external identities. Defaults to the configured Default TTL of the external identity.
  • --no-store (Optional): Print the authentication token to STDOUT without storing credentials in the keyring.

Examples:

# Log in using your current AWS identity and persist credentials
> phase auth --mode aws-iam --service-account-id 0f1a2b3c-4d5e-6789-abcd-ef0123456789
phase auth --mode aws-iam --service-account=2115a1fc-0a78-4a7b-ad8c-6fa6cc15f489 --ttl 60 --no-store
{
    "authentication": {
        "tokenType": "ServiceAccount",
        "token": "pss_service:v2:728a65904a8b66222e6488ee73d8b797391e8e54f0ed42af03a43b96a623b7a2:a7579d80027dddebb934f532ef6977a50d82dfbaa87f1b021cfef72086884605:d2f05a4bf13cea53a41d06fa2aad265ec9068aefa4609446b4c29743e6436e07:b17346b16aef0a2c25e05814a5a0f54555100965f1d6fb41e023989eab99c791",
        "bearerToken": "ServiceAccount 728a65904a8b66222e6488ee73d8b797391e8e54f0ed42af03a43b96a623b7a2",
        "TTL": 60,
        "maxTTL": 86400
    }
}
  1. Azure: Authenticate using your current Azure identity via DefaultAzureCredential (Managed Identity, Service Principal, Workload Identity, Azure CLI, etc). You'll need to have configured an Azure external identity on a service account in the Phase Console first.

See External Identities for more details.

Usage:

> phase auth --mode azure [--service-account-id SERVICE_ACCOUNT_ID] [--azure-resource RESOURCE] [--ttl SECONDS] [--no-store]

Options:

  • --service-account-id (Required): Service Account ID to map this external Azure identity to a Phase Service Account.
  • --azure-resource (Optional): Azure AD resource/audience for the token request. Must match the "Resource / Audience" configured on the Phase identity. Default: https://management.azure.com/.
  • --ttl (Optional): Token TTL in seconds. Defaults to the configured Default TTL of the external identity.
  • --no-store (Optional): Print the authentication token to STDOUT without storing credentials in the keyring.

Examples:

# Log in using your current Azure identity and persist credentials
> phase auth --mode azure --service-account-id 0f1a2b3c-4d5e-6789-abcd-ef0123456789
# Authenticate with a custom resource and print token to STDOUT
> phase auth --mode azure --service-account-id 0f1a2b3c-4d5e-6789-abcd-ef0123456789 --azure-resource "https://management.azure.com/" --ttl 3600 --no-store

Auth Options Summary

  • mode: Choose the mode of authentication (token, webauth, aws-iam, azure). Default: webauth
  • service-account-id (Required for external identities): Bind external identity to a Phase Service Account.
  • ttl (Optional): Only applicable when using external identities for authentication. TTL in seconds for the issued token.
  • no-store (Optional): Only applicable when using external identities for authentication. Print the authentication token response to STDOUT without storing credentials.
  • azure-resource (Optional, Azure only): Azure AD resource/audience. Default: https://management.azure.com/.

🔗 init

Link your local application or project to your Phase app. The phase init command creates a .phase.json file in the root of your projects which holds important contexts for the phase cli, so you don't have to pass arguments repetitively. This file does not contain any sensitive information and can be check into your git repo.

Usage:

# Interactive (prompts for app, environment, monorepo)
> phase init

# Non-interactive (for CI/CD or AI agents)
> phase init --app-id APP_ID --env ENVIRONMENT [--monorepo]
  • --app-id: (Optional) Application ID. When provided with --env, skips interactive prompts.
  • --env: (Optional) Environment name. When provided with --app-id, skips interactive prompts.
  • --monorepo: (Optional) Enable monorepo support. Default is false.

During interactive mode, you'll be asked to:

  1. Select an App previously created in the Phase Console
  2. Choose a default Environment
  3. Enable monorepo support (optional)
> phase init
? Select an App: [use arrow keys]
   ferrari
 » keyspace
   inception
   Exit

? Choose a Default Environment: Development
? 🍱 Monorepo support: Would you like this configuration to apply to subdirectories? (y/N)

Choosing an app will create a .phase.json configuration file in your project's working directory:

> phase init
? Select an App: keyspace
? Choose a Default Environment: Development
? 🍱 Monorepo support: Would you like this configuration to apply to subdirectories? y
✅ Initialization completed successfully.

> cat .phase.json
{
  "version": "2",
  "phaseApp": "keyspace",
  "appId": "511f26b7-5b56-47f3-920e-a4edb9cdbf3c",
  "defaultEnv": "Development",
  "envId": "679bf2bc-9353-4fe0-a84f-825f284c8f8d",
  "monorepoSupport": true
}

Tips:

  • Modify the defaultEnv in .phase.json to set the default environment context for the Phase CLI. For example, "defaultEnv": "production".
  • When monorepo support is enabled, the CLI will search parent directories for a .phase.json config up to a maximum depth of 8 directories (configurable via PHASE_CONFIG_PARENT_DIR_SEARCH_DEPTH). This allows you to have a single config at the root of your monorepo that applies to all sub-projects.

Example directory structure:

monorepo/
├── .phase.json (with monorepoSupport: true)
├── service-a/
│   └── src/
├── service-b/
│   └── src/
└── apps/
    └── web/
        └── src/

In this example, running Phase CLI commands from any subdirectory will use the root .phase.json config.


🚀 run

Run and inject secrets into your app with the ability to override default settings.

Usage:

> phase run [--env ENVIRONMENT] [--app APP_NAME] [--tags TAGS] [command_to_run]
  • command_to_run: The command you wish to run, such as yarn dev. You can also chain multiple command together by wrapping them in double quotes, example: phase run "printenv | grep secret"
  • --env: (Optional) Specify the environment (e.g., dev, staging, production). Supports partial string matching eg. prod for production Default is development
  • --path: (Optional) Specific path under which to fetch secrets from and inject into your application. Default is '/'. Pass an empty string "" to fetch secrets from all paths.
  • --app: (Optional) Name of your Phase application. Use this if you don't have a .phase.json file in your project directory or want to override it.
  • --app-id: (Optional) ID of your Phase application. Takes precedence over --app if both are provided.
  • --tags: (Optional) Comma-separated list of tags to filter secrets.
  • --generate-leases: (Optional) Whether to generate leases for dynamic secrets (true/false). Default: true.
  • --lease-ttl: (Optional) TTL in seconds to use when generating leases.

The run command executes your specified shell command, setting environment variables to the secrets fetched from Phase. It resolves cross-environment and local references in secrets.

Examples:

> phase run yarn dev
> phase run --env dev "printenv | grep DJANGO_SECRET_KEY"
DJANGO_SECRET_KEY=7842cc89c5a703acdf4797e0f063e1851734cea0677ad9382158cfcee26195df

Injecting Referenced secrets:

> phase secrets get PROD_AWS_KEY --env dev
{
    "key": "PROD_AWS_KEY",
    "value": "${prod.AWS_ACCESS_KEY_ID}",
    "comment": "",
    "path": "/",
    "application": "example-app",
    "environment": "Development",
    "tags": [],
    "overridden": false
}

> phase run --env dev "printenv | grep PROD_AWS_KEY"
PROD_AWS_KEY=AKIA2OGYBAH63UA3VNFG

Note that secrets get returns the raw, unresolved reference syntax (${prod.AWS_ACCESS_KEY_ID}), while phase run automatically resolves references and injects the actual secret value.

Chaining multiple commands:

> phase run --env prod "python manage.py migrate && python manage.py runserver backend:8000"

Additional Notes:

  • The phase run only exposes secrets to your applications runtime and not to the rest of your system for security reasons.
  • When specifying tags with --tags, only secrets matching these tags will be injected into the environment.
  • Cross-environment and local references in secrets are automatically resolved and injected. Warnings are issued if any references cannot be resolved.
  • Errors during the command execution or secret fetching process will result in an appropriate error message and termination of the process.
  • When dynamic secrets are configured, the CLI will automatically generate leases and inject the freshly created dynamic secrets along with static secrets. Control this behavior with --generate-leases and --lease-ttl.
  • AI mode: Commands that dump environment variables (printenv, env, export, set, declare, compgen) are blocked when the CLI detects an AI agent, to prevent secret exposure.

🐚 shell

Launch an ephemeral shell with secrets injected as environment variables.

Usage:

> phase shell [--env ENVIRONMENT] [--app APP_NAME] [--shell SHELL_TYPE] [--path PATH] [--tags TAGS]
  • --env: (Optional) Specify the environment (e.g., dev, staging, production). Default is development
  • --path: (Optional) Specific path under which to fetch secrets from and inject into your shell. Default is '/'. Pass an empty string "" to fetch secrets from all paths.
  • --app: (Optional) Name of your Phase application. Use this if you don't have a .phase.json file in your project directory or want to override it.
  • --app-id: (Optional) ID of your Phase application. Takes precedence over --app if both are provided.
  • --shell: (Optional) Specify the shell to launch. Supported shells: bash, zsh, fish, sh, powershell, pwsh, cmd. Default is your current shell.
  • --tags: (Optional) Comma-separated list of tags to filter secrets.
  • --generate-leases: (Optional) Whether to generate leases for dynamic secrets (true/false). Default: true.
  • --lease-ttl: (Optional) TTL in seconds to use when generating leases.

The shell command launches a new shell session with your Phase secrets loaded as environment variables. This is useful for local development workflows where you need to work with multiple commands, scripts, and tools, and running phase run for each command may not be practical.

Examples:

# Launch a zsh shell with secrets from the development environment
> phase shell
[15:32:00] 🐚 Initialized zsh with 15 secrets from Application: example-app, Environment: Development
           Remember: Secrets are only available in this session. Type exit or press Ctrl+D to exit.

> echo $POSTGRES_CONNECTION_STRING 
postgresql://postgres:dbc76c4d...@localhost:5432/mydb

# Exit the shell using Ctrl+D or by typing 'exit'
> exit
[15:33:29] 🐚 Shell session ended. Phase secrets are no longer available.

Notes:

  • When using zsh with modifications like powerline10k, command suggestions and tab completions might be affected in certain cases. This is not due to the Phase CLI - you can verify this by launching zsh directly.
  • Secrets are only available within the shell session and are automatically cleared when you exit.
  • Inside the shell, PHASE_ENV is set to the full environment name from the fetched secrets (e.g., "Development", "Production").
  • Inside the shell, PHASE_APP is set to the full application name from the fetched secrets. (e.g., "example-app")
  • When dynamic secrets are configured, the CLI can automatically generate leases and provision the freshly created dynamic secrets along with static secrets. Control this behavior with --generate-leases and --lease-ttl.
  • AI mode: phase shell is blocked entirely when invoked by an AI agent. Use phase run <command> instead.

📱 apps

📋 apps list

List all available applications and their environments as JSON. Useful for scripting, CI/CD, and AI agents that need to discover app IDs for non-interactive phase init.

Usage:

> phase apps list

Example:

> phase apps list
[
  {
    "id": "511f26b7-5b56-47f3-920e-a4edb9cdbf3c",
    "name": "my-app",
    "environments": [
      { "id": "679bf2bc-9353-4fe0-a84f-825f284c8f8d", "name": "Development", "env_type": "DEV" },
      { "id": "a1b2c3d4-e5f6-7890-abcd-ef0123456789", "name": "Production", "env_type": "PROD" }
    ]
  }
]

🗝️ secrets

Manage your secrets with various sub-commands.

📇 secrets list

List all the secrets in a specified environment, with options to show uncensored secrets, filter by app, and filter by tags.

Usage:

> phase secrets list [--show] [--env ENVIRONMENT] [--app APP_NAME] [--tags TAGS]
  • --show: Display secrets uncensored. If you have dynamic secrets configured, the CLI will automatically generate leases and display the values of the freshly created dynamic secrets along with static secrets in the table.
  • --env: (Optional) Specify the environment. Default is development
  • --path: (Optional) The path in which you want to list secrets. Default is '/'. Pass an empty string "" to list secrets from all paths.
  • --app: (Optional) Name of your Phase application. Use this to override the .phase.json file or when it's not present in your project directory.
  • --app-id: (Optional) ID of your Phase application. Takes precedence over --app if both are provided.
  • --tags: (Optional) Comma-separated list of tags to filter secrets.
  • --generate-leases: (Optional) Whether to generate leases for dynamic secrets. Defaults to the value of --show.
  • --lease-ttl: (Optional) TTL in seconds to use when generating leases.

Indicators:

  • 🔒: Sealed secret (write-only — value cannot be read back after creation).
  • 🔧: Config secret (non-sensitive configuration value, stored unencrypted).
  • 🔗: Secret references another secret in the same environment.
  • 🌐: Cross-environment reference (secret from another environment in the same or different application).
  • 🔖: Tag associated with the secret.
  • 💬: Comment associated with the secret.
  • 🔏: Personal secret override (visible only to you).
  • ⚡️: Dynamic secret.

AI mode behaviour: config-type secrets are always shown in plaintext (even without --show). When invoked by an AI agent, sealed secrets show as [REDACTED] and secret-type values are redacted based on ai.json configuration.

🔍 secrets get

Fetch details about one or more secrets in JSON, with the ability to specify the application and filter by tags.

Usage:

> phase secrets get KEY [KEY...] [--env ENVIRONMENT] [--app APP_NAME] [--tags TAGS]
  • KEY: One or more keys to fetch. Single key returns a JSON object; multiple keys returns a JSON array.
  • --env: (Optional) Specify the environment in which to search for the secret.
  • --path: (Optional) The path from which to fetch the secret from. Default is '/'
  • --app: (Optional) Name of your Phase application. Use this option to override the .phase.json file in your project directory or when it's not present.
  • --app-id: (Optional) ID of your Phase application. Takes precedence over --app if both are provided.
  • --tags: (Optional) Comma-separated list of tags to filter secrets.
  • --generate-leases: (Optional) Whether to generate leases for dynamic secrets (true/false). Default: true.
  • --lease-ttl: (Optional) TTL in seconds to use when generating leases.

Example:

> phase secrets get DJANGO_DEBUG

{
    "key": "DEBUG",
    "value": "True",
    "comment": "This is only for local development. NOT to be used in production.",
    "path": "/",
    "application": "example-app",
    "environment": "Development",
    "tags": [
        "local-development"
    ],
    "overridden": false
}

Dynamic secret example:

> phase secrets get AWS_IAM_USERNAME
{
    "key": "AWS_IAM_USERNAME",
    "value": "wwm6hwzpbpnvxs",
    "comment": "",
    "path": "/",
    "application": "example-app",
    "environment": "Development",
    "tags": [],
    "overridden": false,
    "is_dynamic": true,
    "dynamic_group": "AWS IAM credentials (aws)"
}

Multiple keys example:

> phase secrets get DATABASE_HOST DATABASE_PORT
[
    {
        "key": "DATABASE_HOST",
        "value": "localhost",
        ...
    },
    {
        "key": "DATABASE_PORT",
        "value": "5432",
        ...
    }
]

Notes:

  • Single key returns a JSON object (backwards compatible). Multiple keys returns a JSON array.
  • The get command provides a JSON-formatted output including key details such as the secret value, whether it's overridden, tags associated with it, and any comments.
  • Using the --tags option allows you to filter the secret based on specific tags.
  • If you have dynamic secrets configured and try to fetch one by key, the CLI will automatically generate a lease and return the value of the freshly created dynamic secret.
  • When invoked by an AI agent, sealed and secret-type values are redacted based on ai.json configuration.

💳 secrets create

Create a new secret with options to input the value manually, read from stdin, or generate a random value of specified type and length.

Usage:

> phase secrets create [KEY] [--env ENVIRONMENT] [--app APP_NAME] [--random TYPE] [--length LENGTH] [--override] [--type TYPE]
  • KEY: (Optional) The key for the new secret. It will be converted to uppercase. If the value is not provided as an argument, it will be read from stdin.
  • --env: (Optional) Specify the environment where the secret will be created.
  • --path: (Optional) The path in which you want to create a secret. You can create a directory by simply specifying a path like so: --path /folder/SECRET. Default is '/'
  • --app: (Optional) Name of your Phase application. Use this to override the .phase.json file or when it's not present in your project directory.
  • --app-id: (Optional) ID of your Phase application. Takes precedence over --app if both are provided.
  • --random: (Optional) Specify the type of random value to generate. Available types are hex, alphanumeric, base64, base64url, key128, key256. Example: --random hex.
  • --length: (Optional) Specify the length of the random value. Applicable for types other than key128 and key256. Default length is 32. Example: --length 16.
  • --override: (Optional) Update the personal override value.
  • --type: (Optional) Secret type. One of secret (default), sealed (write-only — value cannot be read back after creation), or config (non-sensitive configuration value).

Examples:

# Create a secret by reading the value from stdin
> cat ~/.ssh/id_rsa | phase secrets create SSH_PRIVATE_KEY

# Create a secret with a randomly generated hexadecimal value of 32 characters
> phase secrets create RAND --random hex --length 32

# Create a sealed secret (value cannot be read back)
> phase secrets create STRIPE_KEY --type sealed

# Create a config value (non-sensitive, stored unencrypted)
> phase secrets create APP_PORT --type config

Notes:

  • base64 : Random bytes, base64 encoded
  • base64url : Random bytes, base64url encoded (URL-safe)
  • key128 : 16 Byte high entropy base64 encoded symmetric key - suitable for AES-128
  • key256 : 32 Byte high entropy base64 encoded symmetric key - suitable for use with ChaCha20 or AES-256

📝 secrets update

Update an existing secret with options to input the new value manually, read from stdin, or generate a random value of specified type and length.

Usage:

> phase secrets update KEY [--env ENVIRONMENT] [--app APP_NAME] [--random TYPE] [--length LENGTH] [--override] [--toggle-override] [--type TYPE]
  • KEY: The key associated with the secret to update. If the new value is not provided as an argument, it will be read from stdin.
  • --env: (Optional) Specify the environment where the secret will be updated.
  • --path: (Optional) The current path of the secret to update. Default is '/'
  • --updated-path: (Optional) The new path for the secret, if changing its location. If not provided, the secret's path is not updated. Example usage: --updated-path "/folder/subfolder"
  • --app: (Optional) Name of your Phase application. Use this to override the .phase.json file or when it's not present in your project directory.
  • --app-id: (Optional) ID of your Phase application. Takes precedence over --app if both are provided.
  • --random: (Optional) Specify the type of random value to generate. Available types are hex, alphanumeric, base64, base64url, key128, key256. Example: --random hex.
  • --length: (Optional) Specify the length of the random value. Applicable for types other than key128 and key256. Default length is 32. Example: --length 16.
  • --override: (Optional) Update the personal override value.
  • --toggle-override: (Optional) Toggle the override state between active and inactive.
  • --type: (Optional) Change the secret type. One of secret, sealed, or config.

Examples:

# Update a secret by manually entering a new value
> phase secrets update DEBUG

# Update a secret by piping a value via stdin
> cat ~/.ssh/id_ed25519 | phase secrets update SSH_PRIVATE_KEY

# Update a secret with a randomly generated hexadecimal value of 32 characters
> phase secrets update MY_SECRET_KEY --random hex --length 32

# Update a secret with a personal override value
> phase secrets update POSTGRES_CONNECTION_STRING --override

# Toggle the override state of a secret
> phase secrets update POSTGRES_CONNECTION_STRING --toggle-override

# Change only the secret type (no value prompt)
> phase secrets update APP_PORT --type config
> phase secrets update API_KEY --type sealed

Notes:

  • base64 : Random bytes, base64 encoded
  • base64url : Random bytes, base64url encoded (URL-safe)
  • key128 : 16 Byte high entropy base64 encoded symmetric key - suitable for AES-128
  • key256 : 32 Byte high entropy base64 encoded symmetric key - suitable for use with ChaCha20 or AES-256

🗑️ secrets delete

Delete one or more secrets from a specified environment, with an option to specify the application.

Usage:

> phase secrets delete KEYS... [--env ENVIRONMENT] [--app APP_NAME]
  • KEYS...: One or more keys of the secrets to be deleted. Separate multiple keys with spaces.
  • --env: (Optional) Specify the environment from which the secrets will be deleted.
  • --path: (Optional) Path filter for deleting secrets. Default is /. Pass an empty string "" to delete from all paths.
  • --app: (Optional) Name of your Phase application. Use this to override the .phase.json file or when it's not present in your project directory.
  • --app-id: (Optional) ID of your Phase application. Takes precedence over --app if both are provided.

Example:

# Delete a single secret
> phase secrets delete DEBUG
Successfully deleted the secret.

# Delete multiple secrets
> phase secrets delete SECRET1 SECRET2 SECRET3
Successfully deleted the secrets.

Notes:

  • The delete command can be used to remove a single secret or multiple secrets at once by providing their keys as arguments.
  • If you have an .phase.json file in your project directory, it will be used to determine the default application. Use the --app option to override this behavior.

📩 secrets import

Import secrets into your Phase environment from a .env file, with an option to specify the application.

Usage:

> phase secrets import ENV_FILE [--env ENVIRONMENT] [--app APP_NAME] [--type TYPE]
  • ENV_FILE: The path to the .env file from which the secrets will be imported.
  • --env: (Optional) Specify the environment where the secrets will be imported.
  • --path: (Optional) The path to which you want to import secret(s). Default is '/'
  • --app: (Optional) Name of your Phase application. Use this to override the .phase.json file or when it's not present in your project directory.
  • --app-id: (Optional) ID of your Phase application. Takes precedence over --app if both are provided.
  • --type: (Optional) Secret type to apply to all imported secrets. One of secret (default), sealed, or config.

Example:

# View the contents of the .env file
> cat .env
AWS_ACCESS_KEY_ID="AKIA2OGYBAH63UA3VNFG"
AWS_SECRET_ACCESS_KEY="V5yWXDe82Gohf9DYBhpatYZ74a5fiKfJVx8rx6W1"

# Import secrets from the .env file into the 'prod' environment
> phase secrets import .env --env prod
Successfully imported and encrypted 2 secrets.
To view them please run: phase secrets list --env prod

# List imported secrets in the 'prod' environment
> phase secrets list --env prod

# Optional: Remove the .env file if no longer needed
> rm .env

Notes:

  • The import command reads key-value pairs from the specified .env file and imports them as secrets into the chosen environment.
  • If an .phase.json file exists in your project directory, it will determine the default application. The --app option can be used to override this behavior.

🥡 secrets export

Export secrets from your Phase environment, with options to filter by keys, tags, and to specify the export format.

Usage:

> phase secrets export [keys...] [--env ENVIRONMENT] [--app APP_NAME] [--tags TAGS] [--format FORMAT]
  • keys...: (Optional) One or more specific secret keys to export. If omitted, all secrets are exported.
  • --env: (Optional) Specify the environment from which the secrets will be exported.
  • --path: (Optional) The path from which you want to export secret(s). Default is '/'. Pass an empty string "" to export secrets from all paths.
  • --app: (Optional) Name of your Phase application. Use this to override the .phase.json file or when it's not present in your project directory.
  • --app-id: (Optional) ID of your Phase application. Takes precedence over --app if both are provided.
  • --tags: (Optional) Comma-separated list of tags to filter the secrets. Supports partial matching and treats underscores as spaces.
  • --format: (Optional) Specify the export format. Supported formats are dotenv, kv, json, csv, yaml, xml, toml, hcl, ini, java_properties. Default format is dotenv.
  • --generate-leases: (Optional) Whether to generate leases for dynamic secrets (true/false). Default: true.
  • --lease-ttl: (Optional) TTL in seconds to use when generating leases.

Examples:

# Export all the secrets in the 'prod' environment to dotenv format
> phase secrets export --env prod
AWS_ACCESS_KEY_ID="AKIA2OGYBAH63UA3VNFG"
AWS_SECRET_ACCESS_KEY="V5yWXDe82Gohf9DYBhpatYZ74a5fiKfJVx8rx6W1"
# Export all secrets in the 'dev' environment to a .env file
> phase secrets export --env dev > .env.example
# Export only specific keys
> phase secrets export AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY --env prod
AWS_ACCESS_KEY_ID="AKIA2OGYBAH63UA3VNFG"
AWS_SECRET_ACCESS_KEY="V5yWXDe82Gohf9DYBhpatYZ74a5fiKfJVx8rx6W1"
# Export secrets with specific tags in 'dev' environment to JSON format
> phase secrets export --env dev --tags "tag1,tag2" --format json
{
  "AWS_SECRET_ACCESS_KEY": "V5yWXDe82Gohf9DYBhpatYZ74a5fiKfJVx8rx6W1",
  "DB_NAME": "XP1_LM",

}

Notes:

  • The export command allows you to export secrets in various formats:
    • dotenv (.env): Key-value pairs in a simple text format with values wrapped in double quotes
    • kv: Simple key-value pairs with uppercase keys and raw values
    • json: JavaScript Object Notation, useful for integration with various tools and languages
    • csv: Comma-Separated Values, a simple text format for tabular data
    • yaml: Human-readable data serialization format, often used for configuration files
    • xml: Extensible Markup Language, suitable for complex data structures
    • toml: Tom's Obvious, Minimal Language, a readable configuration file format
    • hcl: HashiCorp Configuration Language, used in HashiCorp tools like Terraform
    • ini: A simple format often used for configuration files
    • java_properties: Key-value pair format commonly used in Java applications
  • Use the --tags option to filter secrets by tags, which supports partial matching and considers underscores as spaces.
  • If an .phase.json file exists in your project directory, it will determine the default application. The --app option can be used to override this behavior.
  • If you have dynamic secrets configured, the CLI will automatically generate leases and export the values of the freshly created dynamic secrets along with static secrets.
  • AI mode: When invoked by an AI agent, sealed and secret-type values are replaced with [REDACTED] in the exported output.

⚡️ dynamic-secrets

Manage dynamic secrets and their short-lived credentials (leases).

📇 dynamic-secrets list

List dynamic secret definitions (metadata) available to your app and environment.

Usage:

> phase dynamic-secrets list [--env ENVIRONMENT] [--app APP_NAME] [--app-id APP_ID] [--path PATH]
  • --env: (Optional) Specify the environment. Default is development.
  • --app: (Optional) Name of your Phase application.
  • --app-id: (Optional) ID of your Phase application. Takes precedence over --app.
  • --path: (Optional) Path to filter dynamic secrets. Default is /.

Examples:

> phase dynamic-secrets list
[
  {
    "id": "3d07788d-a32a-4d54-8d7d-cc11efdfe424",
    "name": "AWS IAM credentials - docs example",
    "type": "dynamic",
    "description": "",
    "environment": "febb85cd-561b-4d96-b20a-2cfd799586c1",
    "folder": null,
    "path": "/",
    "defaultTtl": "01:00:00",
    "maxTtl": "1 00:00:00",
    "provider": "aws",
    "keyMap": [
      {
        "id": "username",
        "masked": false,
        "keyName": "AWS_IAM_USERNAME",
        "keyDigest": "bff90b6333a7af45e6c78f1c880fa626b3f93545ab5f21489df825bb38fed672"
      },
      {
        "id": "access_key_id",
        "masked": false,
        "keyName": "AWS_ACCESS_KEY_ID",
        "keyDigest": "a2c461ab14cc191f084bd7dda3b566dee65c6a287cf33b29b07f42bf35107c19"
      },
      {
        "id": "secret_access_key",
        "masked": true,
        "keyName": "AWS_SECRET_ACCESS_KEY",
        "keyDigest": "3813f891ac1901d258b20b7aa2b3108949971bcbdce380bf537c9da195b7c166"
      }
    ],
    "createdAt": "2025-09-26T09:48:34.012281Z",
    "updatedAt": "2025-09-26T09:48:34.012301Z",
    "deletedAt": null,
    "lease": null
  },
]

📜 dynamic-secrets lease

Manage leases (ephemeral credentials) for dynamic secrets.

🔍 dynamic-secrets lease get

Get active leases for a dynamic secret.

Usage:

> phase dynamic-secrets lease get SECRET_ID [--env ENVIRONMENT] [--app APP_NAME] [--app-id APP_ID] [--path PATH]
  • SECRET_ID: The dynamic secret ID.
  • --env, --app, --app-id: Context flags as above.
  • --path: Present for parity; not required for lease operations.

Example:

> phase dynamic-secrets lease get 3d07788d-a32a-4d54-8d7d-cc11efdfe424
[
    {
        "id": "dc3e86c5-acb8-42ca-8dfc-cb2c28fc0498",
        "name": "AWS IAM credentials",
        "description": "",
        "secret": "3d07788d-a32a-4d54-8d7d-cc11efdfe424",
        "ttl": "01:00:00",
        "status": "expired",
        "owner": {
            "type": "organisation_member",
            "data": {
                "id": "f1a8ede5-c96b-4514-b4f2-2b88bcce0b2e",
                "username": "nimish-ks",
                "fullName": "Nimish",
                "email": "nimishk@phase.dev",
                "role": {
                    "id": "4bc0d6b1-8d3d-4dad-a2b2-cece14bd9ee4",
                    "name": "Owner"
                }
            }
        },
        "credentials": [],
        "createdAt": "2025-09-29T12:31:01.405885Z",
        "renewedAt": null,
        "expiresAt": "2025-09-29T13:31:01.405477Z",
        "revokedAt": "2025-09-29T13:31:28.963104Z",
        "deletedAt": null
    },
    {
        "id": "09624959-5907-40b8-8ae8-a0ab352b59fc",
        "name": "AWS IAM credentials",
        "description": "",
        "secret": "3d07788d-a32a-4d54-8d7d-cc11efdfe424",
        "ttl": "01:00:00",
        "status": "expired",
        "owner": {
            "type": "organisation_member",
            "data": {
                "id": "f1a8ede5-c96b-4514-b4f2-2b88bcce0b2e",
                "username": "nimish-ks",
                "fullName": "Nimish",
                "email": "nimishk@phase.dev",
                "role": {
                    "id": "4bc0d6b1-8d3d-4dad-a2b2-cece14bd9ee4",
                    "name": "Owner"
                }
            }
        },
        "credentials": [],
        "createdAt": "2025-09-29T11:27:56.206673Z",
        "renewedAt": null,
        "expiresAt": "2025-09-29T12:27:56.206276Z",
        "revokedAt": "2025-09-29T12:28:28.911349Z",
        "deletedAt": null
    }
]

🔁 dynamic-secrets lease renew

Renew an existing lease by a specified TTL (in seconds).

Usage:

> phase dynamic-secrets lease renew LEASE_ID TTL [--env ENVIRONMENT] [--app APP_NAME] [--app-id APP_ID]
  • LEASE_ID: Lease identifier to renew.
  • TTL: Renewal duration in seconds.

Example:

> phase dynamic-secrets lease renew ce6ebf1a-c008-4379-9ed6-351dd763f18b 3600
{
  "message": "Lease renewed successfully. Updated expiry: 2025-09-29 14:45:50.912286+00:00"
}

🗑️ dynamic-secrets lease revoke

Revoke an existing lease, immediately invalidating the credentials.

Usage:

> phase dynamic-secrets lease revoke LEASE_ID [--env ENVIRONMENT] [--app APP_NAME] [--app-id APP_ID]

Example:

> phase dynamic-secrets lease revoke ce6ebf1a-c008-4379-9ed6-351dd763f18b
{
  "message": "Lease revoked successfully"
}

dynamic-secrets lease generate

Generate a new lease (create fresh ephemeral credentials) for a dynamic secret.

Usage:

> phase dynamic-secrets lease generate SECRET_ID [--lease-ttl SECONDS] [--env ENVIRONMENT] [--app APP_NAME] [--app-id APP_ID]
  • SECRET_ID: The dynamic secret ID.
  • --lease-ttl: (Optional) TTL in seconds for the generated lease. If omitted, the default TTL is used.

Example:

> phase dynamic-secrets lease generate 3d07788d-a32a-4d54-8d7d-cc11efdfe424
[
  {
    "id": "3d07788d-a32a-4d54-8d7d-cc11efdfe424",
    "name": "AWS IAM credentials - docs example",
    "type": "dynamic",
    "description": "",
    "environment": "febb85cd-561b-4d96-b20a-2cfd799586c1",
    "folder": null,
    "path": "/",
    "defaultTtl": "01:00:00",
    "maxTtl": "1 00:00:00",
    "provider": "aws",
    "keyMap": [
      {
        "id": "username",
        "masked": false,
        "keyName": "AWS_IAM_USERNAME",
        "keyDigest": "bff90b6333a7af45e6c78f1c880fa626b3f93545ab5f21489df825bb38fed672"
      },
      {
        "id": "access_key_id",
        "masked": false,
        "keyName": "AWS_ACCESS_KEY_ID",
        "keyDigest": "a2c461ab14cc191f084bd7dda3b566dee65c6a287cf33b29b07f42bf35107c19"
      },
      {
        "id": "secret_access_key",
        "masked": true,
        "keyName": "AWS_SECRET_ACCESS_KEY",
        "keyDigest": "3813f891ac1901d258b20b7aa2b3108949971bcbdce380bf537c9da195b7c166"
      }
    ],
    "createdAt": "2025-09-26T09:48:34.012281Z",
    "updatedAt": "2025-09-26T09:48:34.012301Z",
    "deletedAt": null,
    "lease": {
      "id": "d43fa19b-9060-4acf-b6d9-36c1e832c1bb",
      "name": "AWS IAM credentials",
      "description": "",
      "secret": "3d07788d-a32a-4d54-8d7d-cc11efdfe424",
      "ttl": "01:00:00",
      "status": "active",
      "owner": {
        "type": "organisation_member",
        "data": {
          "id": "f1a8ede5-c96b-4514-b4f2-2b88bcce0b2e",
          "username": "nimish-ks",
          "fullName": "Nimish",
          "email": "nimish@phase.dev",
          "role": {
            "id": "4bc0d6b1-8d3d-4dad-a2b2-cece14bd9ee4",
            "name": "Owner"
          }
        }
      },
      "credentials": [
        {
          "key": "AWS_IAM_USERNAME",
          "value": "ybm0vi9yk"
        },
        {
          "key": "AWS_ACCESS_KEY_ID",
          "value": "AKIAVWFM2HYO*********"
        },
        {
          "key": "AWS_SECRET_ACCESS_KEY",
          "value": "ozznB6pSagoTalgG************"
        }
      ],
      "createdAt": "2025-09-29T13:47:24.199689Z",
      "renewedAt": null,
      "expiresAt": "2025-09-29T14:47:24.199283Z",
      "revokedAt": null,
      "deletedAt": null
    }
  }
]

Notes:

  • Leases are time-bound credentials. When they expire (or are revoked), the credentials stop working.
  • Commands like phase run, phase shell, phase secrets get, and phase secrets export can automatically generate leases when injecting or exporting dynamic secrets. Control this with --generate-leases and --lease-ttl. This will allow you to make use of dynamic secrets without having to make any changes to your application code.

🥷 ai

Configure AI integrations for Phase. The ai command group controls how AI coding agents interact with your Phase secrets. When enabled, the CLI installs a skill document to your AI tool's global skill directory and applies security guardrails automatically.

See AI agent integration pages for setup guides for each supported tool.

🪄 ai enable

Enable AI integrations: installs the Phase skill document for your chosen AI agent and configures secret visibility. This command cannot be run by AI agents — it must be run by the user directly.

Usage:

# Interactive — select AI agent and visibility
> phase ai enable

# Non-interactive
> phase ai enable --mask --path ~/.claude/skills/phase-cli/SKILL.md
> phase ai enable --no-mask --path ~/.cursor/skills/phase-cli/SKILL.md

Interactive mode first asks which AI agent to install for, then prompts for secret visibility:

🪄  Install Phase AI skill for
❯ Claude Code (global) → ~/.claude/skills/phase-cli/SKILL.md
  Cursor (global) → ~/.cursor/skills/phase-cli/SKILL.md
  VS Code Copilot (global) → ~/.copilot/skills/phase-cli/SKILL.md
  Codex (global) → ~/.agents/skills/phase-cli/SKILL.md
  OpenCode (global) → ~/.config/opencode/skills/phase-cli/SKILL.md
  Custom path...

🔒 Mask secret values from AI agents?
❯ Yes — mask secret values (recommended for production)
  No — allow AI to read secret values (e.g. development environments)

Value visibility by type and setting:

Secret TypemaskSecretValues: true (default)maskSecretValues: false
sealedHiddenHidden
secretHiddenVisible
configVisibleVisible

🚫 ai disable

Disable AI integrations. Removes ~/.phase/ai.json and uninstalls the skill document from all known AI agent directories.

> phase ai disable

📄 ai skill

Print the raw Phase AI skill document to stdout. Useful for piping to a custom location or inspecting the skill content.

> phase ai skill
> phase ai skill > /path/to/custom/SKILL.md

AI Security Guardrails

When the CLI detects it is being run by an AI agent:

  1. Output redaction: secrets list, secrets get, and secrets export automatically redact values based on secret type and ai.json settings. Redacted values show as [REDACTED].
  2. Blocked commands: phase run refuses to execute commands that dump environment variables (printenv, env, export, set, declare, compgen), since these would expose injected secrets.
  3. Shell blocked: phase shell is entirely blocked in AI mode to prevent unrestricted access to injected secrets.
  4. AI commands blocked: phase ai enable and phase ai disable cannot be run by AI agents.

AI agent detection works via environment variables set by supported tools:

  • Claude Code: CLAUDECODE=1
  • Cursor: CURSOR_AGENT=1
  • OpenAI Codex: CODEX=1
  • OpenCode: OPENCODE=1
  • Cross-tool convention: AGENT=<name> (Codex, Goose, Amp, etc.)

👥 users

Manage users and accounts in the Phase CLI. This command includes sub-commands for user management.

🙋 users whoami

See details of the current user.

Usage:

> phase users whoami

This command displays information about the currently logged-in user in the Phase CLI.

Example:

> phase users whoami
✉️ Email: rohan@spacex.com
🙋 User ID: c9324ace-4605-4017-9425-0632524f4750
🏢 Organization: spacex
☁️ Host: https://console.phase.dev

🪄 users switch

Switch contexts between Phase users, orgs and hosts.

Usage:

> phase users switch

This command displays a list of user accounts that the Phase CLI is authenticated to, across orgs and instances. Simply use the up/down arrow keys ( and ) and hit enter to switch the account context.

Example:

> phase users switch
? Choose a user to switch to: (Use arrow keys)
   🏢 Organization, ✉️ Email, ☁️ Phase Host, 🆔 User ID
 » spacex, rohan@spacex.com, https://console.phase.dev, g9624ace
   phasehq, rohan@phase.dev, https://console.internal.tailscale.phase.dev, f6s34az1

🏃 users logout

Logout from the Phase CLI.

Usage:

> phase users logout [--purge]
  • --purge: Purge all local data. This option will remove any local configuration and data related to the current user's session.

🔐 users keyring

Display information about the Phase keyring. The Phase keyring holds sensitive credentials such as user tokens.

Usage:

> phase users keyring

This command provides insights into the Phase keyring, which is used to securely store user credentials.


📖 docs

Open the Phase Docs in your web browser.

Usage:

> phase docs

This command is a shortcut to quickly access the Phase Docs in your default web browser.


🖥️ console

Open the Phase Console in your web browser.

Usage:

> phase console

This command is a shortcut to quickly access the Phase Console in your default web browser. If you have a .phase.json config in the current working directory, it will automatically open the Console for the app and environment that the config was initialized with.


⌨️ completion

Generate shell autocompletion scripts for the Phase CLI. This allows tab-completion of commands, flags, and arguments in your terminal.

Usage:

> phase completion [shell]

Available sub-commands:

  • bash — Generate the autocompletion script for bash
  • zsh — Generate the autocompletion script for zsh
  • fish — Generate the autocompletion script for fish
  • powershell — Generate the autocompletion script for powershell

Examples:

# Generate and load zsh completions
> phase completion zsh > "${fpath[1]}/_phase"

# Generate and load bash completions
> phase completion bash > /etc/bash_completion.d/phase

# Generate and load fish completions
> phase completion fish > ~/.config/fish/completions/phase.fish

Run phase completion [shell] --help for detailed instructions for each shell.


🔗 Secret referencing

You can set a value of a secret to a value of another by simply pointing to it via the following syntax.

Secret referencing syntax:

Value reference syntaxEnvironmentPathSecret Key Being ReferencedDescription
${KEY}same environment/KEYLocal reference in the same environment and path root (/).
${staging.DEBUG}staging/ (root of staging environment)DEBUGCross-environment reference to a secret at the root (/).
${production./frontend/SECRET_KEY}production/frontend/SECRET_KEYCross-environment reference to a secret in a specific path.
${/backend/payments/STRIPE_KEY}same environment/backend/payments/STRIPE_KEYLocal reference with a specified path within the same environment.
${backend_api::production.SECRET_KEY}production (in backend_api app)/ (root of backend_api app)SECRET_KEYCross-application reference to a secret at the root path within another application.
${backend_api::production./frontend/SECRET_KEY}production (in backend_api app)/frontend/SECRET_KEYCross-application reference to a secret in a specific path within another application.

For more information see: Phase Console Secrets

Values prefixed with a 🔗 indicate a local secret being referenced, whereas values prefixed with 🌐 indicate a cross-environment secret value being referenced ie. development, staging, prod.

Examples:

Local environment secret referencing:

> phase secrets list --env prod --show
KEY 🗝️                   | VALUE
-------------------------------------------------------------------------------------------------
DB_NAME                  | XP1_LM
DB_USER                  | j_mclaren
DB_PASSWORD              | 6c37810ec6e74ec3228416d2844564fceb99ebd94b29f4334c244db011630b0e
DB_HOST                  | mc-laren-prod-db.c9ufzjtplsaq.us-west-1.rds.amazonaws.com
DB_PORT                  | 5432
DATABASE_URL             | 🔗 postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}

> phase run "printenv | grep DATABASE_URL"
DATABASE_URL=postgresql://j_mclaren:6c37810ec6e74ec3228416d2844564fceb99ebd94b29f4334c244db011630b0e@mc-laren-prod-db.c9ufzjtplsaq.us-west-1.rds.amazonaws.com:5432/XP1_LM

The database connection string postgresql:// is referencing DB_USER, DB_PASSWORD, DB_HOST, DB_PORT and DB_NAME from the same environment (dev/development)

Local environment secret referencing inside a folder:

The following database credentials are inside of postgres folder

DB_NAME                  | XP1_LM
DB_USER                  | j_mclaren
DB_PASSWORD              | 6c37810ec6e74ec3228416d2844564fceb99ebd94b29f4334c244db011630b0e
DB_HOST                  | mc-laren-prod-db.c9ufzjtplsaq.us-west-1.rds.amazonaws.com
DB_PORT                  | 5432
> phase secrets list --env prod --show
KEY 🗝️                   | VALUE
-------------------------------------------------------------------------------------------------
DATABASE_URL             | 🔗 postgresql://${postgres/DB_USER}:${postgres/DB_PASSWORD}@${postgres/DB_HOST}:${postgres/DB_PORT}/${postgres/DB_NAME}

> phase run "printenv | grep DATABASE_URL"
DATABASE_URL=postgresql://j_mclaren:6c37810ec6e74ec3228416d2844564fceb99ebd94b29f4334c244db011630b0e@mc-laren-prod-db.c9ufzjtplsaq.us-west-1.rds.amazonaws.com:5432/XP1_LM

The database connection string postgresql:// is referencing DB_USER, DB_PASSWORD, DB_HOST, DB_PORT and DB_NAME from the same environment (dev/development)

Cross environment secret referencing:

> phase secrets list --env prod --show
KEY 🗝️                    | VALUE
----------------------------------------------------------------------------
DATABASE_URL              | 🌐 postgresql://${dev.DB_USER}:${dev.DB_PASSWORD}@${dev.DB_HOST}:${dev.DB_PORT}/${dev.DB_NAME}

> phase run --env prod "printenv | grep DATABASE_URL"
DATABASE_URL=postgresql://j_mclaren:6c37810ec6e74ec3228416d2844564fceb99ebd94b29f4334c244db011630b0e@mc-laren-prod-db.c9ufzjtplsaq.us-west-1.rds.amazonaws.com:5432/XP1_LM

Note: This is assuming an environment named dev/development exists and has a secrets with the keys AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.


Offline mode

The Phase CLI supports offline access to your secrets. After authenticating and fetching secrets at least once, encrypted copies of the API responses are cached locally. If the network becomes unavailable, the CLI can decrypt and serve secrets from this cache.

Behavior

PHASE_OFFLINECaches on successServes from cacheNetwork errors
unsetYesNoFail with PHASE_OFFLINE=1 hint
1 / trueNo (skips network)YesN/A
0 / falseYesNoFail with PHASE_OFFLINE=1 hint

How it works

  1. Automatic caching: Every successful phase secrets command transparently caches the encrypted API responses to ~/.phase/secrets/offline/.
  2. Explicit offline mode: Set PHASE_OFFLINE=1 to skip network requests entirely and serve directly from cache. This is useful in air-gapped environments or when you know you're offline.
  3. Network errors: If a network request fails and PHASE_OFFLINE is not set, the CLI will display an error with a hint to set PHASE_OFFLINE=1. It will not silently fall back to cached data.

Cache location

~/.phase/secrets/offline/{account_id}/
  userdata.json                                # encrypted user/app/environment metadata
  secrets/
    {hash}.json                                # encrypted secrets (one file per environment + path combination)

Running phase users logout will automatically delete the offline cache for that account.

Dynamic secrets

Dynamic secrets (e.g. short-lived database credentials) require server interaction to generate leases and cannot be served from cache. When offline, the CLI will skip dynamic secrets and log a warning:

⚠️ Offline mode: dynamic secret 'my-db-creds' requires network access, skipping

Write operations

Creating, updating, and deleting secrets require network access. These operations will return an error in offline mode:

> PHASE_OFFLINE=1 phase secrets create MY_KEY=my_value
Error: cannot create secrets in offline mode

Authentication requirement

Offline caching requires a persistent authenticated session via phase auth. This is because the CLI needs a locally stored account identity to scope the cache directory.

When using ad-hoc environment variables (PHASE_SERVICE_TOKEN / PHASE_HOST) without a prior phase auth, caching is not available and PHASE_OFFLINE=1 will have no effect. This is by design — ad-hoc env var authentication is intended for stateless environments like CI/CD where offline mode is not applicable.

To use offline mode with a service account, authenticate first:

> phase auth
# Enter your service account token when prompted
# This persists the identity and enables caching

> phase secrets list
# Secrets are now cached for offline use

Wrapped key share

Offline decryption requires a wrapped key share, which is stored locally after authentication. If you authenticated before this feature was available, simply re-run phase auth to store it****.****


Environment variables

PHASE_DEBUG

Type: Boolean

Description: Set to true to get full tracebacks for error messages

Example:

> PHASE_DEBUG=True phase secrets list

PHASE_HOST

Type: String

Description: A full URL to the REST API of the Phase Service

Example:

> export PHASE_HOST=https://phase.internal.company.domain.com

> phase secrets export
...

PHASE_SERVICE_TOKEN

Type: String

Description: A way to authenticate with the Phase Service via tokens, useful for running the cli in an headless environment like CI/CD, Docker containers etc.

Example:

> export PHASE_SERVICE_TOKEN=pss_service...

> phase secrets export
...

PHASE_VERIFY_SSL

Type: Boolean

Description: A way to temporarily disable TLS certificate verification checks

Note: Disable TLS certificate verification is dangerous and can expose you to risks of MITM attacks.

Example:

> export PHASE_VERIFY_SSL=False

> phase secrets export
...

PHASE_CONFIG_PARENT_DIR_SEARCH_DEPTH

Type: Integer

Description: Sets the maximum depth for searching parent directories for a .phase.json config file when monorepo support is enabled. Default is 8.

Example:

> export PHASE_CONFIG_PARENT_DIR_SEARCH_DEPTH=5

> phase secrets export
...

PHASE_OFFLINE

Type: Boolean

Description: Skip network requests entirely and serve secrets from the local offline cache. Requires that secrets have been fetched at least once while online. See Offline mode below for details.

Example:

> export PHASE_OFFLINE=1

> phase secrets list
...