What Node.js projects usually do
Node.js applications normally read runtime configuration from process.env:
const databaseUrl = process.env.DATABASE_URL
const apiKey = process.env.PAYMENTS_API_KEY
During development, the values often live in .env. Node.js added its native --env-file option in version 20.6.0:
node --env-file=.env app.js
Many existing projects use dotenv instead:
import "dotenv/config"
const databaseUrl = process.env.DATABASE_URL
Both approaches end with the same interface. The application reads environment variables. The difference is who loads them and where the plaintext values are stored.
A hidden file is still a project file.
.gitignore helps prevent .env from being committed. The file remains unencrypted inside the workspace, where editors, scripts, plugins and coding agents may be able to read it.
Each developer also needs a copy. Someone has to communicate changes, remove old credentials and know which local files still contain them.
Kimen does not replace process.env. It replaces the project-local secret storage and the step which loads it.
Start the same Node.js application through Kimen.
This example assumes Node.js and Kimen are installed. Create a minimal application which verifies the variable without printing its value:
// app.mjs
if (!process.env.DATABASE_URL) {
throw new Error("DATABASE_URL is missing")
}
console.log("DATABASE_URL is available")
Initialize the local encrypted vault once, if you do not already have one, then store the values:
kimen vault init
kimen secret set node_dev.database_url
kimen secret set node_dev.payments_api_key
Commit a profile containing the names and local references:
# .kimen/profiles/dev.kmap
env DATABASE_URL=node_dev.database_url
env PAYMENTS_API_KEY=node_dev.payments_api_key
Validate the profile, then use the normal application command:
kimen doctor --profile dev
kimen run --profile dev -- node app.mjs
The second command should print:
DATABASE_URL is available
The application still receives process.env.DATABASE_URL. It does not need a Kimen package or a different configuration API.
With no active session, both doctor and run ask for the vault passphrase. If you expect several invocations, start a short session with kimen session start --ttl 30m and finish with kimen session lock.
Existing dotenv projects can migrate gradually.
You do not have to remove dotenv before trying Kimen. Start the existing command through Kimen and move one name at a time into the profile:
kimen run --profile dev -- npm run dev
The selected values already exist in the process environment when Node.js starts. dotenv preserves existing variables by default, so Kimen's values win in the normal configuration. Check projects which enable dotenv's override option or use custom framework loading.
Keep non-sensitive convenience settings in .env if that is useful, or move the whole runtime shape into Kimen profiles.
When dotenv no longer supplies anything, remove it from the startup path. The rest of the application can keep using process.env.
Server variables and browser variables are not the same.
Frameworks add another boundary. Next.js loads .env* files and inlines names prefixed with NEXT_PUBLIC_ into browser JavaScript. Vite exposes names prefixed with VITE_ through import.meta.env.
Those prefixes mean public, not protected. Kimen cannot keep a value secret after a build tool deliberately includes it in code sent to the browser. The Next.js documentation and Vite documentation both describe this build-time behavior.
# server-side secret
DATABASE_URL
# public browser value
NEXT_PUBLIC_API_ORIGIN
VITE_API_ORIGIN
Use Kimen for server processes, trusted build tools and private deployment credentials. Never put a secret behind a public framework prefix.
What this protects, and what it does not
- No secret value needs to be stored in the Node.js project.
- The committed profile can document the variables the application expects.
- The parent shell does not need a permanent export.
- The Node.js child process receives the selected values and can copy them.
- Client-side bundling still makes public variables public.