stackbone secrets

stackbone secrets targets a running agent installation. With no --agent it uses the local-dev installation linked to the current project, so stackbone dev must be running. See target resolution. Every verb accepts --json and emits the standard envelope.

Manage environment-scoped secrets bound to the targeted installation. The CLI has no reveal verb: it never prints a plaintext value, on any verb or in any output mode. Reading a stored secret back is a human-only action in Studio. That rule holds across the whole CLI; see secrets are never printed. set is idempotent on the name (create and rotate are the same call).

Command Purpose
stackbone secrets list List secret names (values always masked) and their last-rotated time.
stackbone secrets set <name> Create or rotate a secret. Value from --value <v> or stdin; --description.
stackbone secrets remove <name> Delete a secret. Requires --yes.

remove is destructive and refuses to run without --yes, described under destructive verbs.

A name is SHOUTY_SNAKE_CASE. It starts with an uppercase letter, then carries uppercase letters, digits and underscores, up to 128 characters. A value is at most 4 KiB, and a --description at most 256 characters.

When set refuses a name or a value, it names the field. It prints one sentence, then one indented field: rule line per offending field. Three lines at most, then a (+N more) count for the rest:

$ stackbone secrets set openai_api_key --value sk-...
stackbone: The secret is not valid.
  - name: secret name must be SHOUTY_SNAKE_CASE (A-Z, 0-9, _)
  → Fix the field(s) above and run the command again.

Those lines read the same whether the CLI caught the problem before the request or the installation refused the body. Under --json the whole text rides in error.message, and either way the command exits 1. A refusal the CLI caught itself carries the error.code invalid_input.

set and remove reject any name that starts with STACKBONE_, and these as well: DATABASE_URL, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, S3_ENDPOINT, S3_BUCKET, MODEL_PROVIDER_API_KEY, MODEL_PROVIDER_BASE_URL, OPENROUTER_API_KEY, OPENROUTER_BASE_URL, BROWSER_MODE, BROWSERBASE_API_KEY, BROWSERBASE_PROJECT_ID. The install owns them. The runtime injects them itself, and an operator writes the model provider and the browser provider from their own Studio screens. list leaves them out too.

JSON payload

// secrets list: value_preview is a mask, never the plaintext
{
  "schema_version": 1,
  "items": [
    {
      "name": "OPENAI_API_KEY",
      "description": "Billing account key",
      "value_preview": "••••••",
      "created_by_email": "[email protected]",
      "created_at": "2026-05-20T09:00:00Z",
      "last_rotated_at": "2026-06-01T10:00:00Z",
    },
  ],
}

// secrets set: the same masked row, one level down under `secret`
{
  "schema_version": 1,
  "secret": {
    "name": "OPENAI_API_KEY",
    "description": "Billing account key",
    "value_preview": "••••••",
    "created_by_email": "[email protected]",
    "created_at": "2026-05-20T09:00:00Z",
    "last_rotated_at": "2026-06-05T11:30:00Z",
  },
}

// secrets remove
{ "schema_version": 1, "name": "OPENAI_API_KEY", "status": "deleted" }

Note

A deployed box locks each secret with the per-agent STACKBONE_SECRET_KEY in its .env, the same key the agent decrypts with. See what you set on the deployed container. A box running an image older than CLI 0.3.3 wrote them under a different key, so the agent read them as missing. You cannot recover those values: set them again once the box runs a 0.3.3 image or newer. stackbone dev never had this problem.

Exit codes: 0 ok · 4 not found (unknown secret, or a name remove cannot parse) · 5 permission (remove without --yes) · 1 generic (empty value, a set name or value that breaks a shape rule, a reserved name). See exit codes.

BUILT WITH ❤️ FROM CANADA AND SPAIN