Learn how to determine if a Node.js file is executed directly from the CLI or imported as a module, with examples for CommonJS, ESM, and cross-module detection.
CommonJS
CommonJS modules can use the require.main
object to determine whether the module is executed directly or imported. The require.main
object is the main module that started your Node.js application.
// CommonJS
// main.js
if (require.main === module) {
// This script is being run directly
console.log('This script is the main module.');
} else {
// This script is being imported as a module
console.log('This script is being imported as a module.');
}
In this example, if you run main.js
directly using the main.js
node, you will see the output This script is the main module. When I import main.js
into another script or module using require('./main')
I get the output This script will be imported as a module.
Note that this approach works with Node.js versions that support ES Module (ESM) syntax.
If you are using CommonJS
syntax, you may want to use the require.main === module
check.
ESM
In the ECMAScript Module (ESM), you can use the "import.meta" object to determine whether a module is executed directly or imported. In particular, you can check the import.meta.url
property.
// main.mjs
import { fileURLToPath, pathToFileURL } from 'url';
import path from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
if (import.meta.url === pathToFileURL(process.argv[1]).href) {
// This module is being run directly
console.log('This module is the main module.');
} else {
// This module is being imported as a module
console.log('This module is being imported as a module.');
}
or you can using module es-main:
// ESM
import esMain from 'es-main';
if (esMain(import.meta)) {
console.log('called directly');
} else {
console.log('required as a module');
}
Support ESM and CJS
If you're writing Node.js code that should behave differently when run directly vs. imported as a module, you need a reliable way to detect how it's being executed.
The following snippet works across all module formats: .cjs
, .mjs
, and .js
(depending on your project setup). It checks whether the file was invoked via the CLI (node file.js
) or imported (require()
or import
).
// Detect if the script is run directly in both CommonJS and ESM
let isMain = false;
try {
// CommonJS detection
if (
typeof require !== "undefined" &&
typeof module !== "undefined" &&
require.main === module
) {
isMain = true;
}
} catch (_e) {
// Ignore errors in ESM environments
}
try {
// ES Module detection
const mainArg = process.argv[1] && path.resolve(process.argv[1]);
if (mainArg && import.meta.url === pathToFileURL(mainArg).href) {
isMain = true;
}
} catch (_e) {
// Ignore errors in CommonJS environments
}
if (isMain) {
console.log("Invoked from CLI");
} else {
console.log("Not invoked from CLI");
}
✅ This approach works seamlessly in both CommonJS and ES Modules, making it ideal for packages or scripts that support multiple module systems.
In this example, if you run main.mjs
directly using the main.mjs
node, you will see the output: "This module is the main module.
" If you import main.mjs
into another ESM module using import './main.mjs';
, you will see the output This module will be imported as a module. Note the ESM file extension.
Modules are usually .mjs
. If you want to use CommonJS syntax, you can use the approach described in the previous answer ("require.main === module")
.