The REPL & Quick Experiments
The Node.js REPL is an interactive shell for probing APIs, inspecting objects, and validating assumptions before you commit code to a file.
Recipe
Quick-reference recipe card - copy-paste ready.
node # start REPL
node --env-file=.env # preload env vars into REPL context
node -e "console.log(process.version)"
node --input-type=module -e "import { ok } from 'node:assert'; ok(1)"When to reach for this:
- Exploring an unfamiliar npm package's return shapes
- Verifying regex, date math, or Buffer encoding quickly
- Debugging a one-off
fetchresponse before wiring it into a service - Teaching teammates how
processorimport.metabehave
Working Example
# Start REPL with env file (Node 20+)
node --env-file=.env.development> const { readFile } = await import('node:fs/promises')
> const raw = await readFile('package.json', 'utf8')
> const pkg = JSON.parse(raw)
> pkg.engines
{ node: '>=24.18.0 <25' }
> // Inspect built-in fetch headers
> const res = await fetch('https://httpbin.org/headers')
> [...res.headers.entries()].slice(0, 3)
[
[ 'content-type', 'application/json' ],
[ 'content-length', '...' ],
[ 'date', '...' ]
]
> .save repl-session.js
> .exitWhat this demonstrates:
- Top-level
awaitworks in the REPL without wrapping in an async function - Dynamic
import()loads ESM built-ins inside the REPL session .savewrites every evaluated expression to a file for later cleanup--env-filemirrors production config loading during experiments
Deep Dive
How It Works
- The REPL compiles each line with V8, maintains a persistent context (
global), and prints expression results. - Multi-line input opens when braces are unclosed - paste async functions or object literals freely.
_holds the last evaluated result;_errorholds the last thrown error (Node REPL convention).- Dot-commands (
.help,.break,.clear) are meta-commands and not sent to V8.
Useful Dot-Commands
| Command | Action |
|---|---|
.help | List all dot-commands |
.save file | Write session history to disk |
.load file | Execute a file in the current context |
.break | Abort multi-line input |
.editor | Open multi-line editor mode |
TypeScript Notes
# Run TypeScript in REPL-like one-liners with tsx
npx tsx -e "const x: number = 42; console.log(x)"
# Or start tsx REPL for typed experiments
npx tsxFor typed exploration, tsx REPL is preferable to plain node when you need interfaces and generics.
Gotchas
- Shipping
.saveoutput directly - saved sessions include>prompts and may lack imports. Fix: refactor into a proper module and add tests. - Secrets in REPL history - pasted API keys persist in
.node_repl_history. Fix:.clearsensitive lines; never.savesessions with secrets. - Assuming REPL === production module scope -
requireis not defined in ESM-first projects. Fix: useawait import()or start with--input-type=module. - Large object dumps -
console.log(hugeArray)blocks the terminal. Fix: useutil.inspect(obj, { depth: 2, maxArrayLength: 10 }). - No test coverage from REPL checks - experiments validate intuition, not regressions. Fix: copy validated snippets into
node:testcases.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
node -e / tsx -e | Single-expression checks in CI or scripts | Multi-step exploration |
Scratch .mjs file + --watch | Repeatable experiments you will commit | Throwaway 10-second checks |
node:test + watch mode | Experiments that should become regression tests | Pure object inspection |
Debugger (node inspect) | Stepping through existing code | Prototyping new APIs from scratch |
FAQs
Does the REPL support top-level await?
Yes in Node 24. You can await fetch(...) directly at the prompt without an async wrapper.
How do I load a .env file in REPL?
Start with node --env-file=.env (Node 20+). Variables appear on process.env immediately.
Can I use TypeScript in the REPL?
The built-in REPL is JavaScript. Use npx tsx for a TypeScript-aware REPL.
What is the difference between node -p and node -e?
-p evaluates and prints the expression (implies -e). node -p "2+2" outputs 4.
How do I exit multi-line mode?
Press .break or Ctrl+C twice. .break aborts without killing the REPL session.
Where is REPL history stored?
~/.node_repl_history by default. Set NODE_REPL_HISTORY to change the path.
Can I require CommonJS modules in REPL?
In a project with "type": "module", use await import('pkg') instead of require.
How do I inspect the last error?
After a thrown error, _error references it. console.error(_error) prints the stack.
Is REPL safe for production debugging?
No. Never open REPL on production servers - use read-only logs, metrics, and local reproduction instead.
How do I experiment with import.meta?
node --input-type=module
> import.meta.url
'file:///...'Can I customize the REPL prompt?
Yes via NODE_REPL_HISTORY, custom repl servers, or programmatic repl.start({ prompt: 'api> ' }).
How do I turn a REPL experiment into a test?
Copy the validated logic into a node:test file and replace manual console.log assertions with assert.equal.
Related
- Node.js Basics - first
nodecommands - Running Scripts & Shebang - when experiments become scripts
- Reading the Official Docs & Diagnostics - dig deeper after REPL surprises
- node:test - graduate experiments to tests
Stack versions: This page was written for Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, and NestJS 11.