Core modules: path, os, and process

Reference for three Node core modules: node:path (string path manipulation), node:os (live host reporting), and node:process (the running process, also the global process). Lists exactly which functions, properties, and lifecycle events are implemented and which are not.

This page is the reference for three focused-tier core modules. All three are substantially implemented and safe to rely on for the surfaces listed here: node:path is pure string manipulation (POSIX-canonical, with a partial win32 namespace); node:os reports the live host; node:process (also the global process) reports and controls the running process, including the lifecycle events. Anything not listed in the tables below is not present.

Import forms

const path = require("node:path");      // or "path"
import path from "node:path";
const os = require("node:os");          // or "os"
import os from "node:os";
const process = require("node:process"); // rarely needed: `process` is a global

node:path

String-only path manipulation; no filesystem is touched. The top-level module is the POSIX implementation.

ExportSignatureNotes
joinjoin(...parts) -> stringCollapses . and .. segments.
resolveresolve(...parts) -> stringResolves to an absolute path against cwd.
relativerelative(from, to) -> string
normalizenormalize(p) -> string
dirname / basename / extname(p[, suffix]) -> string
isAbsoluteisAbsolute(p) -> boolean
parseparse(p) -> { root, dir, base, ext, name }
formatformat(obj) -> stringInverse of parse.
matchesGlobmatchesGlob(p, pattern) -> boolean
toNamespacedPathidentity on POSIX
_makeLonglegacy alias
sep"/"
delimiter":"
posixfull namespaceSame functions; canonical POSIX implementation.
win32partial namespaceSee caveat below.

Example:

$ cruft -e 'const p = require("node:path");
console.log(p.join("a", "b", "..", "c"));
console.log(p.resolve("/foo", "bar"));
console.log(p.relative("/a/b", "/a/c"));
console.log(p.dirname("/a/b/c.txt"));
console.log(p.basename("/a/b/c.txt"));
console.log(p.extname("/a/b/c.txt"));'
a/c
/foo/bar
../c
/a/b
c.txt
.txt

path.win32 caveat

path.win32 exists and exposes the Windows sep (\), and win32.join now emits backslash-separated paths. It is still backed by POSIX logic underneath, so do not rely on full drive-letter / UNC normalization semantics:

$ cruft -e 'const p = require("node:path");
console.log(p.win32.sep);
console.log(p.win32.join("C:\\a", "b"));'
\
C:\a\b

Treat path.win32 as POSIX logic exposing a Windows sep. It is not a faithful Windows path engine.

node:os

Host reporting. Note the Node convention: os.platform()/os.arch() are functions, while process.platform/process.arch are string properties.

ExportReturnsNotes
platform() / arch()stringe.g. linux / x64.
type() / release() / version() / machine()stringKernel identity.
hostname()string
tmpdir() / homedir()stringHonor TMPDIR / HOME.
cpus()array of { model, speed, times }
availableParallelism()number
totalmem() / freemem()number (bytes)
uptime()number (seconds)
loadavg()[1m, 5m, 15m]
networkInterfaces()object keyed by interface nameEntries carry address, netmask, family, mac, internal, cidr, scopeid.
userInfo(){ username, uid, gid, shell, homedir }
endianness()"LE" or "BE"
getPriority() / setPriority()number / undefined
EOL"\n" on this host
devNullstring
constantsobjecterrno (EACCES … EXDEV), signals (SIGHUP … SIGXFSZ), priority (PRIORITY_LOW … PRIORITY_HIGHEST).

Example:

$ cruft -e 'const os = require("node:os");
console.log(os.platform());
console.log(os.arch());
console.log(os.tmpdir());
console.log(os.homedir());'
linux
x64
/tmp
/home/jaredef

node:process (and the global process)

process is a global, no import needed.

Identity and environment

PropertyNotes
argv[0] executable, [1] script, rest user args.
argv0, execPath, execArgv, titleStrings.
envLive environment as a string-valued object.
platform, archString properties (e.g. linux, x64).
version, versionsNode-compatible version string (v20.10.0) + versions object.
pid, ppidNumbers.
release, features, allowedNodeEnvironmentFlagsPresent with Node-shaped values.
$ cruft -e 'console.log(process.platform);
console.log(process.arch);
console.log(process.version);
console.log(process.cwd());'
linux
x64
v20.10.0
/home/jaredef/Developer/cruftless-r8

argv, running a script file:

$ cat /tmp/argvtest.mjs
console.log(process.argv.slice(2).join(","));

$ cruft /tmp/argvtest.mjs alpha beta
alpha,beta

Methods

MethodNotes
cwd() / chdir(dir)Real working directory.
exit([code])Terminates immediately; emits 'exit' listeners first; honors process.exitCode.
nextTick(cb, ...args)Defers past current synchronous code; ticks run in order.
memoryUsage(){ rss, heapTotal, heapUsed, external, arrayBuffers }. rss is real resident memory (read from /proc/self/statm), and heapTotal/heapUsed report real non-zero values; external/arrayBuffers are currently 0. memoryUsage.rss() shorthand exists.
hrtime() / hrtime.bigint()High-resolution time.
uptime(), umask(), kill(pid[, signal])kill is a real kill(2): default SIGTERM, signal 0 is an existence probe, unknown names throw, dead pid throws ESRCH.
getuid(), getgid(), getegid(), availableMemory()
emitWarning()Present (no-op shape).
cpuUsage(), resourceUsage()Present; resourceUsage().maxRSS is real.

process.exit example:

$ cruft -e 'process.exit(3); console.log("after");'; echo "exit: $?"
exit: 3

stdout / stderr

process.stdout and process.stderr are minimal writable shapes: .write(str) (capability-gated per stream), .isTTY (false), .fd, .columns, .rows, and a no-op .on. They are enough for the module-load isTTY color probes real libraries do; they are not full streams. process.stdin is a real Readable EventEmitter.

Lifecycle events

process is a real EventEmitter for non-signal events. These listener methods are all functional:

ononceaddListenerprependListeneroffremoveListenerremoveAllListenersemitlistenersrawListenerslistenerCount
EventBehavior
'exit'Fired on normal completion and inside process.exit().
'beforeExit'Fired when the loop drains; a bounded re-drain loop supports rescheduling work. Not fired on process.exit() or an uncaught exception (Node parity).
'uncaughtException'Fires for both synchronous top-level throws and async throws (setTimeout(() => throw …)); the listener is called and the process does not crash on its own. Partial: the event loop does not resume after the handler the way Node's does.
'unhandledRejection'A listener replaces the default diagnostic; unhandled paths without a listener still diagnose and exit 1.
'SIGINT', 'SIGTERM', …Signal names install a real sigaction; the listener replaces the default disposition. No process.off for signal listeners yet.

Not implemented / gaps

  • path.win32 is POSIX-backed (see caveat); no drive-letter or UNC semantics.
  • process.memoryUsage() reports real rss, heapTotal, and heapUsed; external and arrayBuffers are still 0.
  • process.stdout/stderr are minimal shapes, not full Writable streams (no cork, pipe, backpressure, or 'drain').
  • 'uncaughtException' handlers fire for both synchronous and async throws, but do not resume the event loop afterward the way Node's do.
  • Signal listeners cannot be removed (process.off on a signal is not wired).
  • Anything not listed above (e.g. process.send, process.channel, os.setPriority beyond the basic form, worker-related process surface) is not present.