find-up

Find a file or directory by walking up (or down) parent directories from any path.

Library
npm
v8.0.0
644stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
39/100Needs Attention
Development Activity0
Maintenance20
Community56
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
59/100Fair
Architecture70
Code Quality82
Innovation55
Learning Curve30

find-up is a small, dependency-light Node.js library from Sindre Sorhus for locating a file or directory by walking up parent directories from a starting point, similar to how Node itself resolves node_modules. It exposes both async and sync APIs (findUp/findUpSync), a multi-match variant that returns every match up the tree (findUpMultiple/findUpMultipleSync), and a companion findDown/findDownSync pair added in v8 for searching descendant directories instead of ancestors.

Under the hood it delegates the per-directory existence check to its sibling package locate-path, so find-up’s own code is just the directory-walking loop, stop conditions, and matcher-function support. Callers can pass a plain filename, an array of candidate names (first match wins, in order), or a custom async/sync matcher function that receives each directory and can return a path, undefined to keep walking, or the findUpStop symbol to abort the search early — useful as a performance guard when the current working directory is deeply nested.

Because it’s ESM-only, has zero runtime dependencies beyond locate-path and unicorn-magic, and requires Node 20+, it’s commonly reached for when writing CLI tools, linters, and build tooling that need to discover a config file, a monorepo root, or a package.json relative to wherever the user invoked the command from.

What You Get

  • findUp/findUpSync — return the first matching path found while walking up from cwd, or undefined if nothing matches before hitting stopAt (default: the filesystem root)
  • findUpMultiple/findUpMultipleSync — return every matching path found across all visited ancestor directories, optionally capped with a limit option
  • findDown/findDownSync — walk descendant directories instead, with a configurable depth and a choice of breadth-first or depth-first strategy
  • Matcher-function support — pass a function instead of a name to run custom logic per directory and return a path, undefined, or the exported findUpStop symbol to abort early
  • type option (file | directory | both) and allowSymlinks to control exactly what counts as a match
  • Full TypeScript type definitions (index.d.ts) shipped in the package, validated against real usage via tsd

Common Use Cases

  • Config file discovery - CLI tools and linters call findUp(['app.config.js', 'app.config.json']) to locate a project’s config file starting from wherever the user ran the command.
  • Monorepo/package root resolution - build tooling uses findUp('package.json') or the matcher-function form to find the nearest (or a specific) package.json/workspace root relative to a file being processed.
  • Git repository root detection - tools that need to know if they’re inside a Git repo use findUp('.git', {type: 'both'}) to handle both regular repos and submodules, where .git can be a file instead of a directory.
  • Stopping search at a known boundary - passing stopAt lets a tool avoid walking past a known project boundary (e.g. the invoking user’s home directory) when looking for a file that may not exist.
  • Finding the closest match among children - findDown (new in v8) searches a directory’s descendants rather than its ancestors, useful for locating a nested entry point or fixture file below a known root.

Under The Hood

Architecture The entire module is a single flat index.js file with no internal layering: findUpMultiple/findUpMultipleSync implement the core upward-walk loop (resolve cwd, compute a stopAt boundary, repeatedly call a runMatcher closure and path.dirname until the root or a limit is hit), and findUp/findUpSync are thin wrappers that call the multiple-variant with limit: 1. The newer findDown/findDownSync pair reuses the same locatePath/locatePathSync primitive but walks fs.readdir entries recursively, offering breadth-first (queue-based) and depth-first (recursive) strategies behind a shared prepareFindDownOptions helper. The only external dependency actually doing work is locate-path, to which all per-directory existence/type checks are delegated — find-up’s own code is purely the walking and stopping logic, so changing the core loop would require touching all four public entry points identically since they share the same helpers.

Tech Stack Plain Node.js (>=20 required) with ESM-only exports ("type": "module"), zero build step — index.js ships directly, with hand-written index.d.ts type definitions rather than a TypeScript compilation step. Runtime dependencies are minimal: locate-path (path-existence checks with type/symlink filtering) and unicorn-magic (a toPath helper for normalizing URL-or-string cwd inputs). Dev tooling is Sindre Sorhus’s standard set: xo for linting, ava as the test runner, and tsd for type-definition testing, wired together in a single npm test script and run in GitHub Actions across Node 20/24 on Ubuntu and macOS.

Code Quality The test suite (test/findup.js, test/finddown.js) is extensive relative to the module’s size — well over 60 individual ava test cases covering sync/async parity, symlink handling, custom cwd types (string, relative, URL), stopAt boundaries, matcher-function throw/reject/early-stop behavior, and type: 'both' semantics, all exercised against a real temporary-directory fixture tree rather than mocks. Error handling is minimal but intentional — matcher-function exceptions propagate to the caller rather than being swallowed, and findDown’s recursive directory reads catch and ignore readdir errors (e.g. permission-denied) rather than failing the whole search. Naming is consistent and the code has almost no inline comments, relying instead on the shipped TypeScript definitions and README for documentation. CI runs the full lint/test/type-check pipeline on every push and PR.

What Makes It Unique find-up’s main technical distinction is offering symmetric up-and-down traversal (findUp/findDown) with matching sync variants and a shared type/symlink-matching contract, plus first-class support for passing a custom matcher function rather than only static filenames — including a dedicated findUpStop sentinel for early termination, which most comparable file-discovery utilities in the ecosystem don’t expose. It intentionally keeps the surface area and dependency graph small rather than pursuing novel algorithmic approaches, favoring predictability and composability (it explicitly recommends combining findUp and findDown for monorepo-root detection in its own README) over expanded scope.

Used by 8 apps in this directory

TypeScript
84%
Apache 2.0

Continue

Developer Tools · AI Development · AI Code Assistants

35,808

Open-source coding agent for VS Code, JetBrains, and CLI with support for 30+ LLM providers.

View details
81
Repo Health
88
Technical
62
Dependency
Built with
TypeScript84%
Updated yesterday
TypeScript
45%
Other

Convex Backend

Developer Tools · Databases

12,494

Open-source reactive database that lets developers build live-updating apps with pure TypeScript, strong consistency, and real-time subscriptions—no separate API layer required.

View details
87
Repo Health
82
Technical
68
Dependency
Built with
TypeScript45%
Rust43%
Updated 2 days ago
TypeScript
75%
Apache 2.0

Fern

Developer Tools

3,772

Fern turns a single OpenAPI, AsyncAPI, or Protobuf definition into type-safe SDKs for nine languages and a hosted API documentation site, all from one CLI and one source of truth.

View details
90
Repo Health
86
Technical
66
Dependency
Built with
TypeScript75%
Updated yesterday
TypeScript
97%
MPL 2.0

Logto

Authentication

14,510

Open-source auth infrastructure for SaaS and AI apps with OIDC, SAML, and RBAC

View details
91
Repo Health
83
Technical
63
Dependency
Built with
TypeScript97%
Updated yesterday
TypeScript
95%
MIT

melty

Developer Tools · AI Code Assistants · Code Editors

5,443

The AI code editor where every chat message is a git commit you can revert, branch, or squash

View details
35
Repo Health
75
Technical
67
Dependency
Built with
TypeScript95%
Updated 1 years ago
TypeScript
99%
Apache 2.0

Trigger.dev

Automation · AI Development · Developer Tools

16,223

Build and deploy fully-managed AI agents and background jobs in TypeScript — with no timeouts, durable retries, real-time observability, and elastic scaling built in.

View details
90
Repo Health
9
Technical
63
Dependency
Built with
TypeScript99%
Updated today
TypeScript
95%
Apache 2.0

Void

AI Code Assistants · Code Editors · Automation

28,810

Open-source AI code editor with direct LLM integration and data privacy

View details
46
Repo Health
84
Technical
68
Dependency
Built with
TypeScript95%
Updated 3 months ago
TypeScript
85%
Other

Webiny JS

Ecommerce · Blogging · CMS

8,032

Open-source, self-hosted CMS on AWS serverless — a TypeScript framework you extend with code, not a product you configure through a UI.

View details
90
Repo Health
86
Technical
62
Dependency
Built with
TypeScript85%
JavaScript14%
Updated yesterday

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search