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.
| Export | Signature | Notes |
|---|---|---|
join | join(...parts) -> string | Collapses . and .. segments. |
resolve | resolve(...parts) -> string | Resolves to an absolute path against cwd. |
relative | relative(from, to) -> string | |
normalize | normalize(p) -> string | |
dirname / basename / extname | (p[, suffix]) -> string | |
isAbsolute | isAbsolute(p) -> boolean | |
parse | parse(p) -> { root, dir, base, ext, name } | |
format | format(obj) -> string | Inverse of parse. |
matchesGlob | matchesGlob(p, pattern) -> boolean | |
toNamespacedPath | identity on POSIX | |
_makeLong | legacy alias | |
sep | "/" | |
delimiter | ":" | |
posix | full namespace | Same functions; canonical POSIX implementation. |
win32 | partial namespace | See 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.
| Export | Returns | Notes |
|---|---|---|
platform() / arch() | string | e.g. linux / x64. |
type() / release() / version() / machine() | string | Kernel identity. |
hostname() | string | |
tmpdir() / homedir() | string | Honor 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 name | Entries 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 | |
devNull | string | |
constants | object | errno (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
| Property | Notes |
|---|---|
argv | [0] executable, [1] script, rest user args. |
argv0, execPath, execArgv, title | Strings. |
env | Live environment as a string-valued object. |
platform, arch | String properties (e.g. linux, x64). |
version, versions | Node-compatible version string (v20.10.0) + versions object. |
pid, ppid | Numbers. |
release, features, allowedNodeEnvironmentFlags | Present 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
| Method | Notes |
|---|---|
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:
| Event | Behavior |
|---|---|
'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.win32is POSIX-backed (see caveat); no drive-letter or UNC semantics.process.memoryUsage()reports realrss,heapTotal, andheapUsed;externalandarrayBuffersare still0.process.stdout/stderrare minimal shapes, not full Writable streams (nocork,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.offon a signal is not wired). - Anything not listed above (e.g.
process.send,process.channel,os.setPrioritybeyond the basic form, worker-related process surface) is not present.