This tool works with both Expo and React Native CLI projects. Just install and go.
An env var bug never shows up where you look for it. The .env file is right, the CI secret is set, and the build still ships with EXPO_PUBLIC_API_URL pointing at staging — because what matters is what got inlined into the bundle, and nothing on your machine can tell you that.
The Environment Inspector reads the values the running build actually resolved, on the device, and checks them against a contract you declare in code. You find out on the TestFlight build instead of from a support ticket.
Vars stream in as discovered, a declared contract lights up what never shipped, you read exactly what's wrong, compare two builds' health, and land the fix.
Not a video — this is the shipped tool on a mock build. Every EXPO_PUBLIC_ var the binary actually resolved streams in: auto-discovered, auto-typed, zero config.
npm install @buoy-gg/envAfter installation, the Environment Inspector will be auto-detected and appear in your FloatingDevTools menu.
For more control, use createEnvTool with the envVar builder to define required variables and validation rules:
import { createEnvTool, envVar } from "@buoy-gg/env";
const envTool = createEnvTool({
requiredEnvVars: [
envVar("EXPO_PUBLIC_API_URL").exists(),
envVar("EXPO_PUBLIC_DEBUG_MODE").withType("boolean").build(),
envVar("EXPO_PUBLIC_ENVIRONMENT").withValue("development").build(),
envVar("EXPO_PUBLIC_MAX_RETRIES")
.withType("number")
.withDescription("Maximum API retry attempts")
.build(),
],
});
import { createEnvTool, envVar } from "@buoy-gg/env";
const envTool = createEnvTool({
requiredEnvVars: [
envVar("EXPO_PUBLIC_API_URL").exists(),
envVar("EXPO_PUBLIC_DEBUG_MODE").withType("boolean").build(),
envVar("EXPO_PUBLIC_ENVIRONMENT").withValue("development").build(),
envVar("EXPO_PUBLIC_MAX_RETRIES")
.withType("number")
.withDescription("Maximum API retry attempts")
.build(),
],
});
envVar BuilderThe fluent builder API makes it easy to define environment variable requirements:
envVar("API_KEY")
.withType("string") // Set expected type
.withValue("sk_test_123") // Or set expected value
.withDescription("API Key") // Add documentation
.build() // Finalize config
// Shorthand for just checking existence
envVar("API_KEY").exists()
envVar("API_KEY")
.withType("string") // Set expected type
.withValue("sk_test_123") // Or set expected value
.withDescription("API Key") // Add documentation
.build() // Finalize config
// Shorthand for just checking existence
envVar("API_KEY").exists()
type EnvVarType = "string" | "number" | "boolean" | "array" | "object" | "url";
type EnvVarType = "string" | "number" | "boolean" | "array" | "object" | "url";
createEnvTool OptionscreateEnvTool({
name?: string; // default: "ENV"
description?: string;
colorPreset?: "orange" | "cyan" | "purple" | "pink" | "yellow" | "green"; // default: "green"
id?: string; // default: "env"
requiredEnvVars?: RequiredEnvVar[];
enableSharedModalDimensions?: boolean;
});
createEnvTool({
name?: string; // default: "ENV"
description?: string;
colorPreset?: "orange" | "cyan" | "purple" | "pink" | "yellow" | "green"; // default: "green"
id?: string; // default: "env"
requiredEnvVars?: RequiredEnvVar[];
enableSharedModalDimensions?: boolean;
});
EXPO_PUBLIC_ prefixed variables| Status | Description |
|---|---|
required_present | Required var is set and correct |
required_missing | Required var is not set |
required_wrong_value | Set but doesn't match expected value |
required_wrong_type | Set but wrong type |
optional_present | Optional var that is set |
Use the interactive builder below to create your environment validation config. Add variables, configure checks (type, value, description), and export the code directly.
import { envVar, createEnvTool } from "@buoy-gg/env";
const envTool = createEnvTool({
requiredEnvVars: [
envVar("API_URL").withType("url").build(),
envVar("AUTH_TOKEN").exists(),
envVar("DEBUG").withType("boolean").build(),
envVar("SECRET_KEY").withValue("sk_*").build(),
envVar("ENVIRONMENT").withValue("production or development").build(),
],
});import { envVar, createEnvTool } from "@buoy-gg/env";
const envTool = createEnvTool({
requiredEnvVars: [
envVar("API_URL").withType("url").build(),
envVar("AUTH_TOKEN").exists(),
envVar("DEBUG").withType("boolean").build(),
envVar("SECRET_KEY").withValue("sk_*").build(),
envVar("ENVIRONMENT").withValue("production or development").build(),
],
});Auto-discovery only sees EXPO_PUBLIC_ variables. Anything else has to be declared in your contract to appear — which is deliberate: a devtool that enumerated every value in scope would be a way to read secrets off a device.
It reads the build, not your .env file. The values shown are the ones inlined into the running bundle. That is the entire point — it is how you catch a build that shipped with the wrong value — but it means editing .env changes nothing until you rebuild.
Install @buoy-gg/env and open the Env tool — it auto-discovers EXPO_PUBLIC_ variables and shows the value each one resolved to in the running build.
Yes — attach expected types and custom validators, and failures show the current value, expected value, and context.