process.cwd()

Returns the absolute path of the directory the Node.js process is currently working in.

Signature
process.cwd()
  • Added in Node.js v0.1.8

Return value

stringThe absolute path of the process's current working directory.

Errors

Throws an ENOENT error if the current working directory has been deleted or is no longer accessible.

process.cwd() returns the directory the process is anchored to right now. Every relative path you hand to fs, path.resolve() or require() of a runtime-computed path is resolved against it, so it quietly decides what half your file operations actually touch.

When to reach for it

Use it for anything that should follow the user: a config file discovered in the project root, an output directory a CLI writes into, a glob the caller typed. Those should be relative to where the command was invoked.

What trips people up

The working directory is a property of the invocation, not of the file. Running node scripts/build.js from the project root gives a cwd of the project root, while cd scripts && node build.js gives scripts — and every relative fs.readFile() in that script now looks somewhere else. When you want a path relative to the source file, use __dirname (CommonJS) or import.meta.dirname (ESM) instead.

It is also mutable: any call to process.chdir(), including one buried in a dependency, changes the answer for the whole process. Call process.cwd() at the point of use rather than caching it, or capture it once at startup and resolve everything against that snapshot.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Resolve a config file the user expects to be found in the directory they ran the command from.
  • Write CLI output into the caller's folder rather than next to the installed script.
  • Print the working directory in an error message so a failing relative path can be diagnosed.
  • Build an absolute path with path.resolve() before passing it to a library that requires one.

Frequently asked questions

What is the difference between process.cwd() and __dirname?

process.cwd() is the directory the command was run from and can change during the process, while __dirname is the directory of the source file and is fixed. Use cwd for user-supplied paths and __dirname (or import.meta.dirname in ESM) for files shipped alongside your code.

Why does my relative fs.readFile() path work in one terminal but not another?

Relative paths resolve against process.cwd(), which depends on where the command was launched, not where the file lives. Print process.cwd() in the failing case, or build the path with path.resolve(__dirname, 'file.txt') if it should always be found next to the script.

Can process.cwd() throw?

Yes — if the directory the process is running in is deleted or unmounted, the call fails with ENOENT because the process still holds a handle to a directory that no longer has a path. Recreating the directory does not help; the process must chdir somewhere valid.

More examples

Working directory versus script directory

The output shows the two anchors diverging for one single run. `data.csv` resolves next to where the user stood, which is what you want for their input; `template.html` resolves next to the source file, which is what you want for an asset shipped with the code. Running the same script as `cd /srv/app/scripts && node report.js` moves the first path and leaves the second untouched. In ESM the equivalent of `__dirname` is `import.meta.dirname`.

Example · javascript
const path = require('node:path');

// File on disk: /srv/app/scripts/report.js
console.log('cwd     :', process.cwd());
console.log('__dirname:', __dirname);
console.log('user file:', path.resolve('data.csv'));
console.log('bundled  :', path.join(__dirname, 'template.html'));

// $ cd /srv/app && node scripts/report.js
// cwd     : /srv/app
// __dirname: /srv/app/scripts
// user file: /srv/app/data.csv
// bundled  : /srv/app/scripts/template.html

Finding the project root by walking up

The output shows the search succeeding from a nested directory: the loop starts at the working directory and climbs until it finds a `package.json`. The `parent === dir` check is the important part — at the filesystem root `path.dirname('/')` returns `'/'`, so without it the loop never ends when the file is genuinely absent.

Example · javascript
const fs = require('node:fs');
const path = require('node:path');

function findProjectRoot(start = process.cwd()) {
  let dir = path.resolve(start);
  while (true) {
    if (fs.existsSync(path.join(dir, 'package.json'))) return dir;
    const parent = path.dirname(dir);
    if (parent === dir) return null; // reached the filesystem root
    dir = parent;
  }
}

const root = findProjectRoot();
console.log('project root:', root);
console.log('config path :', root && path.join(root, 'config', 'app.json'));
// project root: /srv/app
// config path : /srv/app/config/app.json

Discussion

  • Be the first to comment on this lesson.