> ## Documentation Index
> Fetch the complete documentation index at: https://docs.barekey.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript SDK

> Full guide to the Barekey SDK, including server reads, React/public reads, requirements schemas, typegen, and standalone local mode.

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

<Tabs>
  <Tab title="npm">
    ```bash theme={null}
    npm install @barekey/sdk
    ```
  </Tab>

  <Tab title="pnpm">
    ```bash theme={null}
    pnpm add @barekey/sdk
    ```
  </Tab>

  <Tab title="yarn">
    ```bash theme={null}
    yarn add @barekey/sdk
    ```
  </Tab>

  <Tab title="bun">
    ```bash theme={null}
    bun add @barekey/sdk
    ```
  </Tab>
</Tabs>

## Package entrypoints

| Import                | Use for                                                                                   |
| --------------------- | ----------------------------------------------------------------------------------------- |
| `@barekey/sdk/server` | server-side reads, CLI-session auth, API-backed mode, standalone `.env` mode, and typegen |
| `@barekey/sdk/public` | public variables only, including browser-facing reads                                     |
| `@barekey/sdk`        | combined root export, but the explicit subpaths are clearer in app code                   |

## The simplest server client

```ts theme={null}
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`

```ts theme={null}
const client = new BarekeyClient();
```

This is usually the best local-development setup.

### Option 2: pass the scope explicitly

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

### Option 3: pass a `json` object

```ts theme={null}
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.

```json theme={null}
{
  "$schema": "./node_modules/@barekey/sdk/dist/barekey.schema.json",
  "organization": "acme",
  "project": "web",
  "environment": "development",
  "config": {
    "mode": "centralized",
    "typegen": "semantic",
    "disallow_ambigious_keys": true
  }
}
```

### Top-level keys

| Key            | Type     | Required                | Notes                                                   |
| -------------- | -------- | ----------------------- | ------------------------------------------------------- |
| `organization` | `string` | Yes in centralized mode | Canonical organization key                              |
| `project`      | `string` | Yes in centralized mode | Project slug                                            |
| `environment`  | `string` | Yes in centralized mode | Stage name                                              |
| `org`          | `string` | No                      | Alias for `organization`                                |
| `stage`        | `string` | No                      | Alias for `environment`                                 |
| `$schema`      | `string` | No                      | JSON Schema path for editor autocomplete and validation |
| `config`       | `object` | No                      | Extra SDK and runtime behavior                          |

### `config` keys

| Key                              | Allowed values                    | Default                                                          | What 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 mode | Controls the style of generated SDK types                 |
| `config.disallow_ambigious_keys` | `boolean`                         | `true`                                                           | Makes non-generated keys a type error unless you opt out  |

### 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 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:

```bash theme={null}
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:

```bash theme={null}
barekey 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.

```ts theme={null}
const url = await barekey.get("DATABASE_URL");
const featureEnabled = await barekey.get("FEATURE_ENABLED");
```

Batch reads preserve input order:

```ts theme={null}
const [databaseUrl, redisUrl] = await barekey.get([
  "DATABASE_URL",
  "REDIS_URL",
] as const);
```

## Use `inspect()` when you need metadata

```ts theme={null}
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`:

```ts theme={null}
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.

```ts theme={null}
const value = await barekey.get("PUBLIC_MESSAGE", {
  dynamic: true,
});
```

With a TTL:

```ts theme={null}
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:

```ts theme={null}
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:

```bash theme={null}
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:

* kind
* visibility
* rollout state

#### `minimal`

This is the standalone default.

It only generates the resolved value type, such as `string`, `boolean`, or an inferred object shape from local `.env` files.

### SDK-side typegen refresh

`BarekeyClient` also accepts:

```ts theme={null}
const client = new BarekeyClient({
  typegen: false,
});
```

Or:

```ts theme={null}
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 any Standard Schema v1 validator before reads proceed.

Pass the schema directly. You do not need to wrap `~standard` yourself.

```ts theme={null}
import { z } from "zod";
import { BarekeyClient } from "@barekey/sdk/server";

const client = new BarekeyClient({
  requirements: z.object({
    DATABASE_URL: z.string().url(),
    STRIPE_SECRET_KEY: z.string().min(1),
    DEBUG_MODE: z.boolean(),
  }),
});
```

This works with any library that exposes Standard Schema v1 metadata, including Zod and ArkType-compatible schemas.

Use this when you want startup-time guarantees that your resolved 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:

```json theme={null}
{
  "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](/integrations/local-development).

## Public client

Use `PublicBarekeyClient` for public variables:

```ts theme={null}
import { PublicBarekeyClient } from "@barekey/sdk/public";

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

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

## React `.tsx`

Use `@barekey/react` when you want public values to feel like normal React data reads.

Install it alongside the SDK:

```bash theme={null}
bun add @barekey/react
```

```tsx theme={null}
import { PublicBarekeyClient } from "@barekey/sdk/public";
import { BarekeyProvider, useBarekey } from "@barekey/react";
import barekeyConfig from "../barekey.json";

const client = new PublicBarekeyClient({
  json: barekeyConfig,
});

function HeroBanner() {
  const env = useBarekey();
  const [title, tagline] = env.get([
    "PUBLIC_TITLE",
    "PUBLIC_TAGLINE",
  ] as const);

  return (
    <section>
      <h1>{title}</h1>
      <p>{tagline}</p>
    </section>
  );
}

export function App() {
  return (
    <BarekeyProvider client={client}>
      <HeroBanner />
    </BarekeyProvider>
  );
}
```

You can also pass a public client directly to `useBarekey()` when you want to bootstrap values before rendering a provider tree:

```tsx theme={null}
import { PublicBarekeyClient } from "@barekey/sdk/public";
import { useBarekey } from "@barekey/react";
import barekeyConfig from "../barekey.json";

function Bootstrap() {
  const env = useBarekey(new PublicBarekeyClient({
    json: barekeyConfig,
  }));

  return <div>{env.get("PUBLIC_TITLE")}</div>;
}
```

### 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 code                       | Meaning                                                         |
| -------------------------------- | --------------------------------------------------------------- |
| `NO_CONFIGURATION_PROVIDED`      | Barekey could not find explicit config or a `barekey.json` file |
| `INVALID_CONFIGURATION_PROVIDED` | Config shape is incomplete or invalid                           |
| `NO_CREDENTIALS_PROVIDED`        | No access token and no CLI session were available               |
| `INVALID_CREDENTIALS_PROVIDED`   | The stored or provided credentials are invalid                  |
| `VARIABLE_NOT_FOUND`             | The named variable does not exist                               |
| `UNAUTHORIZED`                   | The API rejected the current token                              |
| `REQUIREMENTS_VALIDATION_FAILED` | Your `requirements` schema rejected the resolved config         |

Example:

```ts theme={null}
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](/integrations/cli) and [Local development](/integrations/local-development).
