Node.js › CLI Tools & Scripting with Node.js

How do you correctly set an exit code from a Node.js CLI script to signal success or failure to the calling shell or CI pipeline?

Intermediate

Answer

process.exitCode = n sets the exit code the process will use once it naturally finishes all pending work, without abruptly terminating the process (letting any pending I/O, like a final console.log flush, complete first); process.exit(n) forces immediate termination with that code, which can risk truncating unflushed output if called too early -- setting process.exitCode is generally the safer, more correct approach, with process.exit() reserved for cases needing genuinely immediate termination.
async function main() {
  try {
    await runTask();
    process.exitCode = 0; // success, but lets the process exit naturally
  } catch (err) {
    console.error(err.message);
    process.exitCode = 1; // signals failure to the calling shell/CI without forcing an abrupt exit
  }
}
main();
Real-world example A CI pipeline running a custom Node.js validation script checks the script's exit code to decide whether to fail the build; the script sets process.exitCode = 1 on any validation failure, correctly signaling failure to the CI system while still letting any final buffered log output flush properly before the process actually exits.

Common follow-ups: What's the specific risk of calling process.exit() immediately after an async console.log(), given stdout can be asynchronous in some environments?;What exit code conventions (0 for success, non-zero for various failure types) are commonly followed by CLI tools?