Programmatic Usage

Use the SecretStash Node module as a project dependency for programmatic access to the SecretStash API.

When installed as a project dependency, the SecretStash Node module exposes a full TypeScript API for managing variables, device keys, envelopes, and applications programmatically. This is ideal for custom build scripts, server-side integrations, and automation workflows.

Installation

npm install @secret-stash/cli --save

Client Setup

All API interactions go through the SecretStashClient class. By default, it reads credentials from environment variables or your .env file:

import { SecretStashClient } from "@secret-stash/cli";

// Uses SECRET_STASH_API_TOKEN and SECRET_STASH_API_URL from the environment
const client = new SecretStashClient();

You can also pass configuration directly:

const client = new SecretStashClient(
  "https://secretstash.cloud",  // API URL
  "your_api_token_here"         // API token
);

Managing Variables

The VariablesManager handles listing, pulling, and pushing environment variables.

import { SecretStashClient, VariablesManager } from "@secret-stash/cli";

const client = new SecretStashClient();
const variables = new VariablesManager();

Listing Variables

Retrieve a masked list of variables for an environment:

const result = await variables.list(client, "your-app-id", "production");

console.log(`Total variables: ${result.total}`);
for (const v of result.variables) {
  console.log(`${v.name} = ${v.maskedValue}`);
}

Returns ListVariablesResult:

PropertyTypeDescription
variablesArrayList of variables with id, name, maskedValue, and created_at.
totalnumberTotal number of variables.

Pulling Variables

Decrypt and merge remote variables into a local .env file:

const result = await variables.pull(client, "your-app-id", "production", ".env");

console.log(`Pulled ${result.variableCount} variables into ${result.filePath}`);

Parameters:

ParameterTypeDefaultDescription
clientSecretStashClientThe API client.
applicationIdstringYour application ID.
environmentSlugstringThe environment slug (e.g., production).
filePathstring".env"Path to the .env file to update.

Returns PullVariablesResult:

PropertyTypeDescription
filePathstringThe path to the updated .env file.
variableCountnumberNumber of variables written.

Pushing Variables

Encrypt and upload local .env variables to SecretStash:

const result = await variables.push(client, "your-app-id", "production", ".env");

console.log(`Pushed ${result.created} variables. Failed: ${result.failed}`);

Parameters:

ParameterTypeDefaultDescription
clientSecretStashClientThe API client.
applicationIdstringYour application ID.
environmentSlugstringThe environment slug.
filePathstring".env"Path to the .env file to read.

Returns PushVariablesResult:

PropertyTypeDescription
creatednumberNumber of variables successfully pushed.
failednumberNumber of variables that failed to push.

Managing Device Keys

The KeyManager handles local RSA key pair generation, registration, and recovery.

import { SecretStashClient, KeyManager } from "@secret-stash/cli";

const client = new SecretStashClient();
const keys = new KeyManager();

You can optionally pass a custom key directory:

const keys = new KeyManager("/path/to/custom/key/dir");

Initializing a Device Key

Generate and register a new RSA-4096 key pair:

const result = await keys.init(client, {
  label: "My Node Server",
  force: false,
});

console.log(`Key ID: ${result.deviceKeyId}`);
console.log(`Fingerprint: ${result.fingerprint}`);
console.log(`Key directory: ${result.keyDirectory}`);

Options (KeyInitOptions):

PropertyTypeDefaultDescription
labelstringhostnameA human-readable label for this device.
forcebooleanfalseForce regeneration of existing keys.
temporarybooleanfalseCreate a short-lived key for CI/CD.
ttlMinutesnumber15TTL in minutes for temporary keys.

Returns KeyInitResult:

PropertyTypeDescription
deviceKeyIdnumberThe server-assigned device key ID.
labelstringThe device label.
fingerprintstringSHA-256 fingerprint of the public key.
keyDirectorystringPath to the key storage directory.
isTemporarybooleanWhether this is a temporary key.
expiresAtstring | nullExpiration timestamp for temporary keys.

Checking Key Status

const status = await keys.status(client);

console.log(`Local key found: ${status.hasLocalPrivateKey}`);
console.log(`Registered on server: ${status.isRegisteredOnServer}`);
console.log(`Server keys: ${status.serverKeyCount}`);

Syncing Device Metadata

const meta = await keys.sync(client);

console.log(`Key ID: ${meta.device_key_id}`);
console.log(`Fingerprint: ${meta.fingerprint}`);

Generating a Recovery Key

const recovery = await keys.generateRecoveryKey(client, {
  outputDir: "./recovery",
  force: false,
});

console.log(`Recovery share saved to: ${recovery.sharePath}`);

Managing Environments

The EnvironmentsManager handles listing and creating environments.

import { SecretStashClient, EnvironmentsManager } from "@secret-stash/cli";

const client = new SecretStashClient();
const environments = new EnvironmentsManager();

Listing Environments

const result = await environments.list(client, "your-app-id");

for (const env of result.environments) {
  console.log(`${env.name} (${env.slug}) — ${env.type}`);
}

Creating an Environment

const result = await environments.create(
  client,
  "your-app-id",
  "Staging",      // name
  "staging",      // slug
  "development"   // type
);

console.log(`Created: ${result.name} (${result.slug})`);

Managing Envelopes

The EnvelopeManager handles envelope rewrapping, repair, and reset operations.

import { SecretStashClient, EnvelopeManager } from "@secret-stash/cli";

const client = new SecretStashClient();
const envelopes = new EnvelopeManager();

Rewrapping an Envelope

Migrate access from an old device key to your current device key:

await envelopes.rewrap(client, {
  applicationId: "your-app-id",
  environmentSlug: "production",
  oldPrivateKeyPath: "/path/to/old/device_private_key.pem",
  oldDeviceKeyId: 42,
});

Resetting Envelopes

Generate a new DEK and create envelopes for all registered devices:

const result = await envelopes.reset(client, "your-app-id", "production");

console.log(`Created ${result.envelopeCount} envelopes`);

Repairing an Envelope

Attempt a rewrap; if that fails, fall back to a full reset:

await envelopes.repair(client, {
  applicationId: "your-app-id",
  environmentSlug: "production",
  oldPrivateKeyPath: "/path/to/old/device_private_key.pem",
  oldDeviceKeyId: 42,
});

Managing Applications

The ApplicationsManager provides read access to your available applications.

import { SecretStashClient, ApplicationsManager } from "@secret-stash/cli";

const client = new SecretStashClient();
const apps = new ApplicationsManager();

const result = await apps.list(client);

for (const app of result.applications) {
  console.log(`${app.name} (${app.id})`);
}

Error Handling

The module throws typed errors that you can catch and handle:

Error ClassDescription
InvalidApiTokenThe API token is invalid or expired.
MissingApiTokenNo API token was configured.
InvalidEnvironmentConfigurationRequired configuration is missing or invalid.
NoEnvironmentsFoundThe specified environment does not exist.
DeviceKeyNotRegisteredNo local device key found or key not registered on server.
PrivateKeyNotFoundThe local private key file is missing.
PrivateKeyFailedToSaveFailed to save the private key to disk.
MetaKeyFailedToSaveFailed to save the device metadata file.
import { SecretStashClient, VariablesManager, InvalidApiToken, NoEnvironmentsFound } from "@secret-stash/cli";

try {
  const client = new SecretStashClient();
  const variables = new VariablesManager();
  await variables.pull(client, "app-id", "production");
} catch (error) {
  if (error instanceof InvalidApiToken) {
    console.error("Check your SECRET_STASH_API_TOKEN");
  } else if (error instanceof NoEnvironmentsFound) {
    console.error("Environment not found:", error.message);
  } else {
    throw error;
  }
}

Exported Types

The module also exports the following TypeScript types for use in your application:

TypeDescription
KeyInitOptionsOptions for KeyManager.init().
KeyStatusResultReturn type of KeyManager.status().
KeyInitResultReturn type of KeyManager.init().
RecoveryKeyResultReturn type of KeyManager.generateRecoveryKey().
ListVariablesResultReturn type of VariablesManager.list().
PullVariablesResultReturn type of VariablesManager.pull().
PushVariablesResultReturn type of VariablesManager.push().
ListEnvironmentsResultReturn type of EnvironmentsManager.list().
CreateEnvironmentResultReturn type of EnvironmentsManager.create().
ListApplicationsResultReturn type of ApplicationsManager.list().
RewrapOptionsOptions for EnvelopeManager.rewrap() and repair().
ResetResultReturn type of EnvelopeManager.reset().
DeviceMetadataDevice key metadata structure.
EnvelopePayloadEncrypted envelope structure.
ApplicationDataApplication record from the API.
EnvironmentDataEnvironment record from the API.
EnvironmentTypeEnum of environment types.