CLI
The CLI is the primary way to sync secrets between your terminal and Shelve. Use it to inject variables at runtime (shelve run), push local changes upstream, or pull secrets to disk when you really need a .env file.
npx skills add https://shelve.cloudInstallation
Install @shelve/cli in your project or globally. See the Quickstart guide.
pnpm add -D @shelve/cli
Command overview
| Command | Description |
|---|---|
run | Inject secrets into a child process (preferred) |
init | Agent-safe ignore files + .gitignore block |
login / logout | Manage stored credentials |
me | Show the logged-in user |
push / pull | Sync secrets with Shelve |
diff / sync | Compare or apply sync policy |
create | Create a project + shelve.json |
config | Show merged configuration |
generate | Generate .env.example or ESLint config |
upgrade | Update the CLI package |
doctor | Validate config, auth, API, and cache |
agents-automation | Global flags, JSON output, CI & agents |
troubleshooting | Error codes and common fixes |
Global flags
Available on every command (before or after the subcommand):
| Flag | Alias | Description |
|---|---|---|
--json | Machine-readable stdout; structured errors on stderr | |
--quiet | -q | No spinners or clack UI |
--yes | -y | Skip confirmation prompts |
--non-interactive | Fail instead of prompting | |
--debug | Verbose logs (SHELVE_DEBUG=1) |
Configuration
Configuration is loaded from the current working directory. Supported filenames: shelve.json, shelve.config.json, .shelverc.json. If none exists and a command requires config, the CLI can create shelve.json interactively (or fail in non-interactive mode).
JSON Schema: shelve.cloud/schema.json
{
"$schema": "https://shelve.cloud/schema.json",
"slug": "nuxtlabs",
"project": "@nuxt/ui",
"defaultEnv": "development",
"confirmChanges": false,
"autoCreateProject": true
}
Monorepo support
Shelve detects monorepo roots and merges the root shelve.json with the local one. Put the settings every package shares in the root file and the project in each package:
{
"slug": "nuxtlabs",
"defaultEnv": "development"
}
The package config wins wherever the two disagree.
Running from the root
push, pull, diff and sync run once per package that has its own config file:
shelve pull
That writes apps/app/.env and apps/api/.env. Packages without a config file are skipped, as is the root itself.
Target a single package with --path:
shelve pull --path apps/app
To treat the root as a project of its own instead, give it a project in the root shelve.json. A bare command then runs in the root instead of fanning out. --path still targets a single package.
Inside a package, commands behave as they always have and only touch that package:
shelve pull
run is the exception: it executes your command in the current directory and never fans out.
Configuration options
| Option | Type | Default | Description |
|---|---|---|---|
project | string | SHELVE_PROJECT or nearest package.json name | Project name |
slug | string | SHELVE_TEAM_SLUG | Team slug |
token | string | Keychain / $XDG_CONFIG_HOME/.shelve / SHELVE_TOKEN | API token |
url | string | https://app.shelve.cloud | Shelve instance URL |
defaultEnv | string | — | Default environment for run, push, pull, diff, sync |
confirmChanges | boolean | false | Confirm before push/pull writes |
envFileName | string | .env | Local env file name |
autoUppercase | boolean | true | Uppercase keys on push |
autoCreateProject | boolean | true | Create project if missing |
sync | object | — | Sync policies (per-env push/pull rules) |
Environment variables
| Variable | Description |
|---|---|
SHELVE_PROJECT | Project name |
SHELVE_TEAM_SLUG | Team slug |
SHELVE_TOKEN | Authentication token |
SHELVE_URL | Shelve instance URL |
SHELVE_DEFAULT_ENV | Default environment |
SHELVE_DEBUG=1 | Enable debug logging |
AI_AGENT | Force AI-agent shell detection |
Credentials are stored in the OS keychain when available, with an XDG file fallback (~/.config/.shelve, mode 0600).