Install
bun add @goenvless/envPreload (recommended)
Add the loader to your bunfig.toml:
preload = ["@goenvless/env/register"]/register runs the loader with a top-level await, so the preload does not resolve until the variables are fetched, decrypted and in place. Every bun run and bun test that picks up this bunfig.toml boots with variables already loaded, requiring no source changes.
Direct import
If you prefer code-side, import /register first, then read env:
import '@goenvless/env/register';
import { env } from '@goenvless/env/server';
import { serve } from 'bun';
serve({ port: env.PORT, fetch: handler });/register is a dependency of this module, so its top-level await resolves before the file body runs and env is loaded by the time serve is called. The file has to be ESM. require('@goenvless/env/register') throws instead of loading anything, because a require cannot block on the fetch and decrypt.
Use it
import { env } from '@goenvless/env/server';
const db = new Bun.SQL(env.DATABASE_URL);This snippet assumes the bunfig.toml preload above. Without that preload, or an awaited load(), the first read throws Envless env is not loaded yet. Import '@goenvless/env/register' or await load() first.
/server exposes every variable, server and client visibility alike, and coerces a value to a number or a boolean when the variable declares that type. Everything else stays a string.
Bun-specific notes
Bun.envmirrorsprocess.env, so loaded values show up there too, with one exception. A variable whose name changes how a process or its children execute code is decrypted and readable throughenv, but deliberately never written into the process environment:NODE_OPTIONS,NODE_PATH,NODE_REPL_EXTERNAL_MODULE,ELECTRON_RUN_AS_NODE,LD_PRELOAD,LD_LIBRARY_PATH,LD_AUDIT,DYLD_INSERT_LIBRARIES,DYLD_LIBRARY_PATH,DYLD_FRAMEWORK_PATH,PATH,BUN_INSPECT,BUN_INSPECT_CONNECT_TO,RUBYOPT,RUBYLIB,BUNDLE_GEMFILE,GEM_HOME,GEM_PATH,PYTHONPATH,PYTHONHOME,PYTHONSTARTUP,PYTHONUSERBASE,PHPRC,PHP_INI_SCAN_DIR,ENVLESS_CLIENT_ENVandENVLESS_INJECTED. The loader prints a warning naming the ones it refused.- Native Web Crypto is used for decryption, so no polyfill is needed.
- Loaded values never clobber variables already set in the ambient environment.
process.envkeeps the ambient value, whileenvreturns the Envless one.
CI with Bun
On a runner, provide the machine credential set before bun run: ENVLESS_TOKEN, ENVLESS_KEY (or ENVLESS_PASSPHRASE), ENVLESS_PROJECT, and ENVLESS_ENV. ENVLESS_TOKEN has to be a machine key starting with ev_sk_, anything else is refused. ENVLESS_PROJECT and ENVLESS_ENV can come from a committed .envless file instead. See Machine & CI access.