Run and Check JavaScript with Node.js on Linux
Node.js does far more from the command line than just running app.js. It evaluates one-off expressions, checks syntax without executing anything, and runs its own test suite, all without a wrapper script. These examples use Node.js v24.21.0 from package version 24.21.0-1nodesource1, installed here as both node and nodejs. Allow about fifteen minutes if you already have a script to test.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need a shell and the nodejs package. None of these examples need sudo. Keep application files in a working directory you control, and never execute JavaScript you have not inspected: it can read files, open network connections or spawn child processes just like any other program.
1. Check the runtime you are about to use
Start with read-only checks. On this installation the two command names are aliases and the manpages are identical:
$ command -v node
/usr/bin/node
$ node --version
v24.21.0
$ nodejs --version
v24.21.0
$ dpkg-query -W -f='${Package} ${Version}\n' nodejs
nodejs 24.21.0-1nodesource1
Your path or package version may differ. The checkpoint that matters is that the command resolves to the runtime you expect. If a project pins a major version, compare this result against its documented requirement before installing dependencies or touching system packages.
2. Evaluate one expression without creating a file
Use --eval, or its short form -e, for a quick one-off action. The shell handles the outer quotes; Node.js only sees the JavaScript inside them:
$ node --eval 'console.log(JSON.stringify({ runtime: process.version, platform: process.platform }))'
{"runtime":"v24.21.0","platform":"linux"}
This is ordinary user-level execution: it does not touch Node.js configuration, but the JavaScript itself can still alter your files or contact a service. A common trap is confusing shell syntax with JavaScript syntax; keep the whole expression inside one quoted argument, using double quotes inside it when that makes the boundary clearer.
Use --print, or -p, when you want Node.js to print the expression's value automatically:
$ node --print '2 ** 8'
256
$ node -p 'process.arch'
x64
Checkpoint
Use --eval for actions such as console.log() and --print for an expression whose result you want displayed. Neither replaces reviewing a longer script.
3. Check a file without running it
From the directory containing your script, run --check (or -c):
$ node --check app.js
$ printf 'syntax check exit status: %s\n' "$?"
syntax check exit status: 0
A successful check prints no output and returns status 0. It only checks syntax, not whether imports resolve, files exist, or the application behaves correctly. Invalid syntax makes Node.js print an error and exit non-zero: fix the reported location and check again.
Do not use shell redirection to overwrite the original script while experimenting. Write a changed version to a new name, check it, and replace the old file only after reviewing the difference; replacement can discard work and is not automatically reversible.
4. Pass script arguments deliberately
Any words after a script filename get passed to the script as arguments. The first application argument lands at process.argv[2]:
$ node app.js --input '/path/to/data.json' --verbose
If an argument starts with a hyphen and must not be read as a Node.js option, put -- before the script filename or the remaining arguments, whichever fits your command shape:
$ node -- app.js --input '/path/to/data.json'
Quote paths and values that might contain spaces. Avoid building a command by concatenating untrusted text into a shell string; passing separate, quoted arguments keeps the shell from interpreting semicolons, dollar signs and wildcards on your behalf.
5. Run the built-in test runner
Node.js v24 ships a command-line test runner. Run it from the project directory:
$ node --test
Test names, counts and timing depend on your project's files. A passing summary should show zero failed tests. The runner discovers files by Node.js's own test-runner rules; if it reports none found, check file names and the current directory rather than assuming the application is tested.
Name a single known test file explicitly when you only need that one:
$ node --test test/basic.test.js
Do not add --watch to a command meant for automation. Watch mode restarts the process whenever the entry point or watched files change, and keeps the terminal occupied until you stop it with Ctrl-C:
$ node --watch app.js
Checkpoint
Use --test for a finite verification command. Use --watch only while actively developing; the restart it triggers is a process action, not a deployment.
6. Keep environment settings visible
NODE_OPTIONS prepends allowed Node.js options ahead of whatever you type on the command line, so an inherited environment can quietly change how a simple-looking command behaves. Inspect it when debugging a surprising result:
$ printf 'NODE_OPTIONS=%s\n' "${NODE_OPTIONS-}"
NODE_OPTIONS=
$ env | grep '^NODE_OPTIONS=' || true
For a one-off experiment, set a value explicitly so it disappears when the command exits:
$ NODE_OPTIONS='--trace-warnings' node app.js
Never put secrets in NODE_OPTIONS, shell history, or a shared service environment. The manpage also documents NODE_PATH for adding module-search directories, but it can make a script silently load a different module than you expect; prefer the project's normal dependency layout and check the working directory first when resolution fails.
Node's REPL history lives in ~/.node_repl_history by default. Set NODE_REPL_HISTORY to an empty value if commands typed interactively must not be persisted:
$ NODE_REPL_HISTORY='' node
This affects the REPL process only; it does not erase an existing history file. Check the exact path first if you need to remove that file, and make a deliberate decision before deleting it.
7. Avoid unsafe TLS shortcuts
Warning
Never use NODE_TLS_REJECT_UNAUTHORIZED=0 as a routine fix for certificate errors. The installed manpage says this disables TLS certificate validation entirely, letting an active network attacker impersonate a service. Fix the certificate chain, trust store or proxy configuration instead. Treat --insecure-http-parser the same way, as a compatibility exception only: the manpage warns that accepting invalid headers can enable request-smuggling attacks.
Done means
- Version checked:
node --versionreports the runtime your project expects. - Quoting verified: a small expression runs correctly with no accidental shell expansion.
- Syntax checked:
node --check app.jsreturns status 0 before the file runs. - Tests pass:
node --testreports zero failures, or you have investigated why none were found. - Environment inspected: you checked inherited
NODE_OPTIONSwhen behaviour looked wrong. - TLS left intact: you did not disable certificate validation or run untrusted JavaScript casually.