mrkeyoor.com_
Sat 08 Aug 20:59 UTC
npmUtilsupdated 08 Aug 2026

find-pkg

find-pkg is a tiny CommonJS utility that starts at a directory, walks toward the filesystem root, and returns the path of the first package.json it encounters. It exposes promise, callback, and synchronous forms, plus an optional search-depth limit. It finds the manifest path only: it does not read JSON, resolve an installed dependency, search downward, or accept arbitrary filenames and glob patterns.

Verdict

A focused compatibility utility that still works for old CommonJS tooling, but its frozen 2018 surface and missing types make it a poor new dependency. Current projects should usually use find-up or pkg-dir.

API stability5/5The public API is two functions and has not moved since version 2.0.0: the default export accepts a start directory, optional limit or callback, and findPkg.sync mirrors it. The implementation simply binds package.json to find-file-up, so there is little surface to churn. Stability here comes from being frozen, not from an active compatibility policy.
Docs3/5The README clearly shows promise, async-await, callback, and sync calls and states that the package searches only for package.json. Important behavior is left to tests and source: undefined on a miss, the default current directory, the numeric depth limit, the absolute return path, and the lack of JSON parsing are not explained together in the user-facing guide.
Maintenance1/5The GitHub repository is not archived, but its last push was March 28, 2018, the current npm version is still 2.0.0, and the README says it was generated on that same date. One open issue or pull request is a small queue, yet there is no recent release, CI evidence, or maintenance activity to show modern Node and ESM concerns are being addressed.
Ecosystem3/5The package recorded 5,132,262 downloads in the measured week and remains embedded in dependency trees, which gives it substantial installed reach. Direct community signals are much smaller: the repository has 9 stars, the package has one runtime dependency, and modern neighboring packages such as find-up and pkg-dir cover broader, better-typed use cases.

Use it if

  • You maintain older CommonJS tooling that needs the nearest package.json path from an arbitrary nested directory
  • You need the same upward search in promise, Node-style callback, and synchronous code
  • You need to cap how many parent directories the lookup may inspect
  • Node 8 compatibility matters more than modern module syntax or bundled TypeScript declarations
Skip it if

Setup reality

Installation is only npm install find-pkg, with no native compilation, configuration file, credentials, or peer dependency. The compatibility cost is age and module shape. Version 2.0.0 declares Node 8 or newer, exports CommonJS from index.js, and does not ship a TypeScript declaration. In CommonJS, require('find-pkg') is the documented path; in ESM, use createRequire or test your runtime's CommonJS default-import interop instead of assuming named exports. The async function resolves to an absolute package.json path or undefined when no manifest exists, so a missing result is normal and must be handled before readFile. It does not parse the manifest. Reading and JSON.parse remain your responsibility, including malformed JSON errors. The start argument is treated as a directory and defaults to the current working directory; when processing a source filename, pass path.dirname(filename). A second numeric argument limits the number of levels searched, but that overload is documented by tests rather than the README. The synchronous form blocks filesystem work and belongs in startup or CLI code, not a request hot path. Symlinks, permission errors, and unexpected parent manifests still deserve tests in your deployment layout.

Patterns

Find the nearest package.jsonfind-nearest-manifest

const findPkg = require('find-pkg');

const manifestPath = await findPkg(process.cwd());
if (!manifestPath) throw new Error('No package.json found');
console.log(manifestPath);

The result is an absolute filename, or undefined when the search reaches the root without finding a manifest.

Start from the current working directoryuse-default-directory

const findPkg = require('find-pkg');

const manifestPath = await findPkg();

Omitting the start argument uses process.cwd(), which may differ from the directory containing the current module.

Search from a source file's directoryfind-from-file

const path = require('path');
const findPkg = require('find-pkg');

const sourceFile = '/workspace/app/src/index.js';
const manifestPath = await findPkg(path.dirname(sourceFile));

Pass a directory. Converting a filename with path.dirname avoids treating the filename itself as a search directory.

Find and parse the nearest manifestread-package-json

const fs = require('fs/promises');
const findPkg = require('find-pkg');

const manifestPath = await findPkg();
if (!manifestPath) return null;
const pkg = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
console.log(pkg.name, pkg.version);

find-pkg returns a path only. File access and JSON parsing errors are yours to catch or propagate.

Derive the package root directoryget-package-directory

const path = require('path');
const findPkg = require('find-pkg');

const manifestPath = await findPkg('/workspace/app/src');
const packageDir = manifestPath ? path.dirname(manifestPath) : undefined;

Use pkg-dir instead if the directory is the only result you ever need.

Stop after a fixed number of parent levelslimit-search-depth

const findPkg = require('find-pkg');

const manifestPath = await findPkg('/workspace/app/src/deep', 3);

The numeric second argument is covered by the project's tests but omitted from its main README examples.

Use the Node-style callback APIuse-callback

const findPkg = require('find-pkg');

findPkg('/workspace/app/src', (error, manifestPath) => {
  if (error) throw error;
  if (!manifestPath) return console.log('not inside a package');
  console.log(manifestPath);
});

A missing package is reported as an undefined path, not as an error.

Find a manifest synchronouslyuse-sync

const findPkg = require('find-pkg');

const manifestPath = findPkg.sync(__dirname);
if (!manifestPath) throw new Error('No package.json found');

The sync form blocks filesystem work; reserve it for CLI startup, configuration loading, or build scripts.

Load metadata for the containing packageload-own-metadata

const fs = require('fs');
const findPkg = require('find-pkg');

const manifestPath = findPkg.sync(__dirname);
const metadata = manifestPath
  ? JSON.parse(fs.readFileSync(manifestPath, 'utf8'))
  : { name: 'unknown', version: 'unknown' };

Starting at __dirname follows the installed module location; starting at process.cwd() follows the caller's launch directory.

Treat no manifest as a normal branchhandle-missing-manifest

const findPkg = require('find-pkg');

async function packageContext(start) {
  const manifestPath = await findPkg(start);
  return manifestPath ? { manifestPath } : { manifestPath: null };
}

Do not pass an undefined result straight to readFile; the library intentionally resolves rather than rejects on a clean miss.

Load the CommonJS package from ESMimport-from-esm

import { createRequire } from 'node:module';

const require = createRequire(import.meta.url);
const findPkg = require('find-pkg');
const manifestPath = await findPkg(new URL('.', import.meta.url).pathname);

Version 2.0.0 is CommonJS and has no exports map; createRequire avoids depending on default-import interop details.

Declare the untyped module locallyadd-typescript-shim

// types/find-pkg.d.ts
declare module 'find-pkg' {
  type Callback = (error: Error | null, path?: string) => void;
  function findPkg(start?: string, limit?: number): Promise<string | undefined>;
  function findPkg(start: string, callback: Callback): void;
  namespace findPkg {
    function sync(start?: string, limit?: number): string | undefined;
  }
  export = findPkg;
}

The package does not publish declarations. Keep a local shim small and validate overloads against the installed version.

Alternatives

PackageRegistryPick it when
find-upnpmYou want a maintained ESM utility that can search for arbitrary names or use a matcher
pkg-dirnpmYou want the nearest package root directory rather than its package.json path
find-package-jsonnpmYou want to iterate through multiple package.json files while walking upward