Skip to main content
Use the Barekey SDK when your code should read variables directly instead of shelling out to the CLI or depending on a pulled .env file. For most server-side code, import from @barekey/sdk/server.

Install

npm install @barekey/sdk

Package entrypoints

ImportUse for
@barekey/sdk/serverserver-side reads, CLI-session auth, API-backed mode, standalone .env mode, and typegen
@barekey/sdk/publicpublic variables only, including browser-facing reads
@barekey/sdkcombined root export, but the explicit subpaths are clearer in app code

The simplest server client

import { BarekeyClient } from "@barekey/sdk/server";

export const barekey = new BarekeyClient();
This works when:
  • barekey.json can be found in the current directory or a parent directory
  • the runtime can authenticate with either BAREKEY_ACCESS_TOKEN or a stored CLI login

How the server SDK resolves configuration

BarekeyClient supports three configuration styles.

Option 1: rely on barekey.json

const client = new BarekeyClient();
This is usually the best local-development setup.

Option 2: pass the scope explicitly

const client = new BarekeyClient({
  organization: "acme",
  project: "web",
  environment: "production",
});

Option 3: pass a json object

const client = new BarekeyClient({
  json: {
    organization: "acme",
    project: "web",
    environment: "production",
  },
});
You must provide either:
  • all of organization, project, and environment
  • or json
  • or nothing, in which case Barekey tries to load barekey.json
Do not mix explicit fields with json.

barekey.json reference

This file is used by both the SDK and CLI.
{
  "organization": "acme",
  "project": "web",
  "environment": "development",
  "config": {
    "typegen": "semantic",
    "mode": "centralized"
  }
}

Top-level keys

KeyTypeRequiredNotes
organizationstringYes in centralized modeCanonical organization key
projectstringYes in centralized modeProject slug
environmentstringYes in centralized modeStage name
orgstringNoAlias for organization
stagestringNoAlias for environment
configobjectNoExtra SDK and runtime behavior

config keys

KeyAllowed valuesDefaultWhat it does
config.mode"centralized" or "standalone""centralized"Chooses API-backed Barekey mode or local .env file mode
config.typegen"semantic" or "minimal""semantic" in centralized mode, "minimal" in standalone modeControls the style of generated SDK types

Search behavior

The SDK and CLI search for barekey.json starting from the current working directory and walking upward through parent directories. That means one repo-level file can cover a whole monorepo.

How auth is resolved

In centralized mode, BarekeyClient resolves credentials in this order:
  1. BAREKEY_ACCESS_TOKEN
  2. a stored CLI session created by barekey auth login

BAREKEY_ACCESS_TOKEN

If BAREKEY_ACCESS_TOKEN is set, the SDK uses it directly. Optional:
  • BAREKEY_API_URL overrides the default API base URL
Example:
export BAREKEY_ACCESS_TOKEN="bk_at_..."
export BAREKEY_API_URL="https://api.barekey.dev"
This is the best fit for production deploys and CI.

CLI session fallback

If BAREKEY_ACCESS_TOKEN is not set, the SDK tries to reuse the local CLI login. That is convenient for local development because you can log in once with:
barekey auth login
Then your app can usually run without extra token wiring.

Reading values

get() returns a promise-like handle. If the variable has a known generated type, await returns the parsed value directly.
const url = await barekey.get("DATABASE_URL");
const featureEnabled = await barekey.get("FEATURE_ENABLED");
Batch reads preserve input order:
const [databaseUrl, redisUrl] = await barekey.get([
  "DATABASE_URL",
  "REDIS_URL",
] as const);

Use inspect() when you need metadata

const result = await barekey.get("DATABASE_URL").inspect();

result.value;
result.rawValue;
result.name;
result.kind;
result.declaredType;
result.visibility;
result.decision;
result.selectedArm;
This is especially useful for:
  • debugging
  • logging resolution metadata
  • checking ab_roll decisions

Dynamic reads and caching

get() accepts BarekeyGetOptions:
type BarekeyGetOptions = {
  dynamic?: true | { ttl: number | Date | { epochMilliseconds: number } };
  seed?: string;
  key?: string;
};

dynamic

Use dynamic when a value should be refreshed instead of coming from the static definition cache.
const value = await barekey.get("PUBLIC_MESSAGE", {
  dynamic: true,
});
With a TTL:
const value = await barekey.get("PUBLIC_MESSAGE", {
  dynamic: { ttl: 5_000 },
});
ttl means:
  • numbers are milliseconds
  • Date uses its timestamp
  • objects with epochMilliseconds are also accepted

seed and key

Use these for deterministic ab_roll evaluation:
const checkoutVariant = await barekey.get("CHECKOUT_FLOW", {
  seed: user.id,
  key: "checkout-v1",
});
The same seed and key pair gives the same result for the same variable.

Typegen

Barekey can write generated types into your installed @barekey/sdk package. Run:
barekey typegen
Then known keys become typed in the SDK.

Typegen modes

semantic

This is the centralized default. It preserves Barekey metadata in the generated types, including:
  • mode
  • visibility

minimal

This is the standalone default. It generates simpler value types, which is useful when types are inferred from local .env files.

SDK-side typegen refresh

BarekeyClient also accepts:
const client = new BarekeyClient({
  typegen: false,
});
Or:
const client = new BarekeyClient({
  typegen: {
    ttl: 5_000,
  },
});
Notes:
  • automatic typegen refresh only runs in development
  • it only applies when filesystem access is available
  • set typegen: false to disable it

Requirements validation

You can validate the resolved configuration against a Standard Schema v1 validator before reads proceed.
const client = new BarekeyClient({
  requirements: {
    "~standard": {
      validate(value) {
        return { value };
      },
    },
  },
});
Use this when you want startup-time guarantees that required Barekey values form a valid config object.

Standalone mode

Standalone mode makes the server SDK read local .env* files instead of calling the Barekey API. Set:
{
  "config": {
    "mode": "standalone"
  }
}
In this mode:
  • filesystem access is required
  • organization, project, and environment may be omitted
  • typegen becomes minimal
  • values are inferred from local .env content
This is useful when you want one SDK API for local and centralized setups. Read more in Local development.

Public client

Use PublicBarekeyClient for public variables:
import { PublicBarekeyClient } from "@barekey/sdk/public";

const client = new PublicBarekeyClient({
  organization: "acme",
  project: "web",
  environment: "production",
});

const title = await client.get("PUBLIC_TITLE");

Important public-client rules

  • it only reads public variables
  • it does not use CLI auth
  • it supports baseUrl
  • it does not support standalone mode
If config.mode is "standalone", PublicBarekeyClient throws.

Errors you should expect

The SDK throws BarekeyError subclasses. Common ones:
Error codeMeaning
NO_CONFIGURATION_PROVIDEDBarekey could not find explicit config or a barekey.json file
INVALID_CONFIGURATION_PROVIDEDConfig shape is incomplete or invalid
NO_CREDENTIALS_PROVIDEDNo access token and no CLI session were available
INVALID_CREDENTIALS_PROVIDEDThe stored or provided credentials are invalid
VARIABLE_NOT_FOUNDThe named variable does not exist
UNAUTHORIZEDThe API rejected the current token
REQUIREMENTS_VALIDATION_FAILEDYour requirements schema rejected the resolved config
Example:
import { BarekeyError } from "@barekey/sdk/server";

try {
  const value = await barekey.get("DATABASE_URL");
} catch (error) {
  if (error instanceof BarekeyError) {
    console.error(error.code, error.requestId);
  }
  throw error;
}

Practical patterns

  • Create one shared client module and import it where needed.
  • Use CLI-session auth locally and BAREKEY_ACCESS_TOKEN in production.
  • Run barekey typegen after config changes.
  • Use inspect() when you need metadata, not just the value.
  • Use standalone mode only on the server side.
For CLI-driven local workflows, read CLI and Local development.