Running scripts, the REPL and --watch

Node.js · Essentials · 8 min

These are the commands you use every day while writing and debugging Node code.

The simplest way to run code is node app.js. Node executes the file top to bottom, then keeps the process alive as long as there is pending work — an open server, a timer, an unfinished read. When nothing is left, the process exits on its own.

Running node with no arguments opens the REPL (read–eval–print loop). It is ideal for poking at an API:

  • _ holds the last result; .help lists commands; .editor lets you paste multi-line code; .exit or Ctrl+D quits.
  • Top-level await works, and built-in modules are preloaded: type fs. and press Tab.

For quick one-offs use -e (evaluate) or -p (evaluate and print):

node -p "os.cpus().length"
node -e "console.log(process.versions.v8)"

During development, node --watch app.js restarts the process whenever the file or anything it imports changes — no nodemon needed. Combine it with --watch-path=./src to watch a directory.

Useful companions:

  • node --run dev runs the dev script from package.json, faster than npm run because it skips npm's startup.
  • node --check file.js only parses the file, catching syntax errors.
  • node --env-file=.env app.js loads environment variables (covered later).

Since 22.18 Node can also run TypeScript files directly by stripping type annotations (node app.ts); it does not type-check, so keep tsc in your workflow for that.

Finally, a Unix script can start with the shebang #!/usr/bin/env node; mark it executable (chmod +x) and it runs like any other command.

Example

#!/usr/bin/env node
// greet.js — try: node greet.js, then node --watch greet.js and edit the text
const name = process.argv[2] ?? "world";
console.log(`Hello, ${name}!`);

// Pending timers keep the process alive; it exits after this fires
setTimeout(() => console.log("bye"), 500);

/* In a terminal:
   $ node greet.js Ada      -> Hello, Ada!  (then "bye")
   $ node -p "2 ** 10"      -> 1024
   $ node                   -> opens the REPL; try: await fetch('https://example.com').then(r => r.status)
*/

Remember

  • node file.js runs a script; the process exits when no work is pending
  • The REPL supports top-level await and has built-in modules preloaded
  • --watch restarts on changes; --run runs package.json scripts quickly

Watch out for

  • Thinking --watch or type stripping type-checks or bundles code — they only restart and strip.

Check yourself

  1. A script calls setInterval and nothing else. What happens when it reaches the last line?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: nodejs.org/learn/command-line/run-nodejs-scripts-from-the-command-line