Designed to make building in public easier
✅ Important! Install live-keys in a NEW FOLDER, as a NEW PROJECT. It is a separate codebase to your other project.
Once you establish your keys.json file treat it like any other key. Safely, securely, and offline unless you know what you're doing.
❌ Super Duper Important Details, Don't Worry It's Okay!
Did you read the note above? live-keys is a key in itself. It is a standalone, separate server and application to your main codebase. To present your system safely: turn off the electricity! Flick the switch off and don't zap yourself. So, DO NOT INSTALL live-keys in your main codebase. Start a new project with a new folder!
This separation is how your keys are obfuscated: a simple HTTP call, offline.
💁♀️ live-keys is an Express-based tool that helps you build in public more safely and show more of your process.
How:
- It runs as a separate local server, acting as a simple proxy for your API keys, preventing them from being exposed during live streams, videos, or presentations.
- This allows you to create a collection of API and environment keys for public building, store it one time with
live-keysand then use it repeatedly.
What:
- Keep environment secrets out of plain sight, from .env files to surprise terminal outputs.
- Outputs from
live-keysare designed to be informative, educational and reflect best practice by allowing people to expose environment secrets like .env files. Configure API fails to display either404or a friendliernullas you demonstrate full processes. - This is essentially an agnostic, open source, cross compatible version of "secrets" that anyone can use.
Made in Cursor by Josh Reinhardt (https://ezc.tech)
With thanks to winston and husky
Winston Dev Tool Summary:
- What: Simple and universal logging library with support for multiple transports for Node.js
- Created by: Charlie Robbins (GitHub: indexzero)
- Current maintainer: David Hyde
- Best contact: https://github.com/winstonjs/winston
live-keys uses winston to provide a more verbose output on API failures. Logging from winston creates context with simple JavaScript time stamps and sliced 15 record files, for extra sight on API fails. API failures are typically not verbose, so having a little extra sight from chronology is helpful in an educational or presentation setting especially.
Husky Dev Tool Summary:
- What: Modern native Git hooks tool - makes Git hooks easy and automates commit/push tasks
- Created by: Typicode (GitHub: typicode)
- Maintainer: Typicode
- Best contact: https://github.com/typicode/husky (GitHub issues) or typicode@gmail.com
live-keys uses husky to prevent developer users from accidentally committing the real secrets they put in their keys.json file inside live-keys.
live-keys. It prevents committing the keys.json file. You are circumventing standard best practice procedures to use live-keys because humans and AI know to guard .env files, and to store them in keys.json is unusual. This demonstrates the fundamentals of environment secrets.
| Feature / Aspect | Traditional .env Approach |
live-keys Approach |
|---|---|---|
.env File Content |
Contains the actual secret key.API_KEY="sk-real-xxxxxxxx" |
Contains the URL of the key server.LIVE_KEYS_SERVER_URL="http://localhost:3666" |
| Secret Storage | The real secret is stored in the .env file within your main project's directory. |
The real secret is stored in a separate keys.json file, managed only by the live-keys server. |
| Application Code | Synchronously reads the key directly from the environment.const key = process.env.API_KEY; |
Asynchronously fetches the key from the live-keys local server.const key = await getApiKey('API_KEY'); |
| Workflow for Streaming | Manual & Risky: 1. Manually edit .env to replace the real key with a fake one.2. Restart the application. 3. Remember to never show the .env file. |
Simple & Safe: 1. Run a single command: npm run stream:on.2. The application continues running without changes. |
| Risk of Exposure | High. If you accidentally show the .env file, console.log(process.env), or a debugger variable, the real secret is exposed. |
Low. The most you can expose is the placeholder value or the local server URL. |
| Complexity | Very Simple. This is the standard, built-in method for handling secrets in most frameworks. | Adds a layer. It requires running a second, separate server process alongside your main application. |
Your application code uses that single URL as a base. It then appends the name of the secret it needs to the end of the URL. Here is a code example of how your application would fetch two different keys:
const serverUrl = process.env.LIVE_KEYS_SERVER_URL;
// Fetch the OpenAI key
const openaiResponse = await fetch(`${serverUrl}/keys/OPENAI_API_KEY`);
const openaiData = await openaiResponse.json();
const openaiKey = openaiData.value; // This is the actual key/placeholder
// Fetch the Stripe key
const stripeResponse = await fetch(`${serverUrl}/keys/STRIPE_SECRET_KEY`);
const stripeData = await stripeResponse.json();
const stripeKey = stripeData.value; // This is the actual key/placeholderYou can use this tool any time your screen, terminal, or browser's developer tools might be visible to others. This includes live streams, recorded videos, pair programming sessions with external collaborators, or any situation where you are sharing your development environment publicly.
- Live Coding Streamers and YouTubers: The primary audience, who can code with real APIs without fear of accidental exposure.
- Developers Building in Public, Presentations and at Demos: Anyone giving a live talk or demo.
- Open-Source Developers: Anyone recording a GIF, streaming a feature build, or sharing their screen.
- Educators and Tutorial Creators: Teachers demonstrating authentic, end-to-end development workflows.
- Local Key Server: A simple Express server to fetch your keys.
- Streaming Mode Toggle: Instantly switch between serving real keys (dev mode) and placeholder keys (stream mode).
- Configurable Strict Mode: Choose whether the server returns a hard
404 Not Founderror or a friendlynullvalue for missing keys. - Pre-Commit Git Hook: Optional hook to prevent you from accidentally committing real keys.
- Request History Log: A persistent log of the last 15 key requests for easy debugging.
Of course. Here is a table outlining the 10 most important files in the live-keys codebase.
| File Path | Why It's Important | Key Dependencies | Purpose & Key Functions | Educational Value |
|---|---|---|---|---|
src/server.ts |
The application's core. | express, keys.json, .live-keys.state.json |
Runs the Express API server; serves keys based on streaming mode. | A stateful TypeScript API server. |
package.json |
Defines the project. | All scripts/*.js |
Manages dependencies and defines all user-facing npm commands. |
The project's command center. |
keys.json |
The user's secret vault. | src/server.ts, scripts/status.js |
Stores the user's real and placeholder key pairs. | A simple data/config separation model. |
docs/how-to-use.md |
The primary user guide. | N/A | Explains the concepts and how to integrate live-keys into another project. |
Best-practice technical documentation. |
scripts/status.js |
The main diagnostic tool. | src/server.ts |
Acts as a client to fetch and display the live server's status and history. | A Node.js-based client for a local API. |
live-keys.config.json |
Configures advanced features. | src/server.ts, scripts/pre-commit.js |
Enables/disables features like strictMode and the git hook. |
Feature-flagging and user configuration. |
scripts/setup.js |
The first user interaction. | *.template.json |
Runs on npm install to create the initial config files from templates. |
A basic project scaffolding script. |
scripts/toggle.js |
Controls the server state. | src/server.ts |
Sends the API request to turn streaming mode on, off, or toggle it. | A state-changing command-line client. |
README.md |
The project's front door. | docs/*.md |
Provides a high-level overview and directs users to detailed documentation. | A standard open-source project landing page. |
scripts/pre-commit.js |
The core security feature. | live-keys.config.json |
Runs automatically before a git commit to prevent accidentally committing real keys. |
An automated git hook for security scanning. |
This is a critical point!
You do need to write code differently in your main application to use live-keys.
It represents a fundamental shift from a synchronous, direct-access pattern to an asynchronous, request-based pattern for handling your secrets.
Don't use it for production development, use it for public development.
Here is a breakdown of the change:
Your code assumes the secret is immediately available in the environment.
- Logic: "Get the variable named
OPENAI_API_KEYfromprocess.envright now." - Code:
// The key is available instantly. const apiKey = process.env.OPENAI_API_KEY; // You can use it immediately. const openai = new OpenAI({ apiKey: apiKey });
Your code must now ask another service (the live-keys server) for the secret and wait for a response.
- Logic: "Send a network request to the
live-keysserver for the key namedOPENAI_API_KEY, and wait for it to reply with the value." - Code:
// You must use async/await because it's a network request. async function initializeApi() { const liveKeysUrl = process.env.LIVE_KEYS_SERVER_URL; const response = await fetch(`${liveKeysUrl}/keys/OPENAI_API_KEY`); const data = await response.json(); const apiKey = data.value; // The value can now be used. const openai = new OpenAI({ apiKey: apiKey }); } // You have to call the async function to start your app. initializeApi();
This change in code, while requiring an adjustment, is precisely what makes live-keys secure and effective:
- Decoupling: Your main application is no longer directly coupled to the secret. It doesn't know the value, only how to ask for it.
- Centralized Control: This allows the
live-keysserver to act as a central switch. When you runnpm run stream:on, it changes the value that gets sent back to your app, without your app ever needing to know or change. - No Leaks: Because the real secret is never loaded into your main application's
process.envwhen streaming, it's impossible for a strayconsole.logor debugger to accidentally expose it.
This section will guide you through setting up and running live-keys.
- Node.js: v18.0.0 or higher.
- npm: Included with Node.js.
-
Install the package
npm install
This command installs dependencies and creates
keys.jsonandlive-keys.config.jsonfrom templates. -
Configure Your Keys & Features
keys.json: Add your real and placeholder API keys.live-keys.config.json: Configure the server's features.strictMode(boolean): Iftrue, requests for missing keys return a404 Not Found. Defaults tofalse.gitHook(object): Configures the pre-commit hook.enabled(boolean): Iftrue, the hook will run. Defaults tofalse.mode(string): Can be'warn'or'block'. Defaults to'warn'.
-
Set Up the Git Hook (Optional, but Recommended) We recommend using
huskyto manage the git hooks reliably.npm install husky --save-dev npx husky install npx husky add .husky/pre-commit "node scripts/pre-commit.js"
npm run devThe server will start with a detailed banner confirming its status.
You can control the server and perform checks using the following commands:
npm run stream:on: Turns streaming mode ON.npm run stream:off: Turns streaming mode OFF.npm run stream:toggle: Toggles the current mode.
npm run status(ornpx status): Checks the live server's status, mode, and key request history.npm run check-keys(ornpx check-keys): Validates yourkeys.jsonfile.npm run key-commands(ornpx key-commands): Displays a list of all available commands.
For tighter integration, a client-side helper library is available in the /code-base-files directory. See the README.md in that directory for full instructions.
For detailed information on the server's endpoints, see the official API.md file in the project root.
GET /keys/:name: Fetches a key. Returns{ "key": "...", "value": "..." }on success.GET /health: Raw health check endpoint. Returns server status, mode, and request history.POST /stream-mode/toggle: Toggles streaming mode. Accepts an optional body ({ "mode": "on" }or{ "mode": "off" }) to set a specific state.GET /config-check: Validates thekeys.jsonfile.
You can perform a simple end-to-end test to validate the entire workflow.
1. fake-api.js (A mock of a real API)
const http = require('http');
// This key must match a 'real' key in your keys.json
const REAL_API_KEY = 'sk-real-openai-key-goes-here';
http.createServer((req, res) => {
if (req.headers['authorization'] === `Bearer ${REAL_API_KEY}`) {
res.writeHead(200, {'Content-Type': 'application/json'}).end(JSON.stringify({ message: '✅ Success!' }));
} else {
res.writeHead(401, {'Content-Type': 'application/json'}).end(JSON.stringify({ message: '❌ Unauthorized' }));
}
}).listen(4001, () => console.log('Fake API listening on http://localhost:4001'));2. run-test.js (A script that simulates your app)
async function runTest() {
const res = await fetch('http://localhost:3666/keys/OPENAI_API_KEY');
const { value: apiKey } = await res.json();
const apiRes = await fetch('http://localhost:4001', { headers: { 'Authorization': `Bearer ${apiKey}` } });
console.log(`Fake API responded with: ${await apiRes.text()}`);
}
runTest();Run node test-app/fake-api.js and npm run dev in separate terminals. Then run node test-app/run-test.js. Toggle streaming mode on and off to see the test succeed and fail.
For production environments, it is recommended to build the project and run the compiled JavaScript output.
-
Build the project:
npm run build
This command uses
tscto compile the TypeScript files fromsrc/into thedist/directory. -
Run the production server:
npm start
This command runs the compiled
dist/server.jsfile directly with Node.js.
Open to contribution or collaboration, also, feel free to fork or clone this repo.
If you wish to contribute, please fork the repository and use a feature branch. Pull requests are warmly welcome. Before submitting a pull request, please ensure your code adheres to the existing style by running:
npm run lintDistributed under the MIT License. See LICENSE for more information.
Josh Reinhardt - https://ezc.tech | https://ezc.app | https://ezcourier.com.au | https://linkedin.com/in/ezcourier Project Link: https://github.com/computerlegs/live-keys


