npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@yourfam/yf-tree

v0.1.1

Published

Write a directory tree as Markdown or one self-contained HTML page

Readme

yf-tree

Write a directory tree. Markdown is a fenced tree. HTML is one self-contained dark page with expand and collapse.

This does not write file contents. That is yf-dump. Node 20+.

  • Source / README: https://github.com/YourFam/yf-tree
  • npm: https://www.npmjs.com/package/@yourfam/yf-tree
  • Unscoped alias: https://www.npmjs.com/package/yf-git-tree
  • Issues: https://github.com/YourFam/yf-tree/issues

Install

npm install -g @yourfam/yf-tree

Then from any directory:

yf-tree

The command is yf-tree. No install:

npx @yourfam/yf-tree
npx yf-git-tree

npx yf-git-tree is the unscoped alias of @yourfam/yf-tree (same CLI, same version). npm rejects unscoped yf-tree as too similar to existing rc-tree. After -g, the command is yf-tree.

| | npm install -g @yourfam/yf-tree | npm install -D @yourfam/yf-tree | |---|---|---| | Where it goes | Global npm prefix | node_modules/ of the current repo | | Command | yf-tree from any folder | npx yf-tree in that repo | | Typical use | A CLI you want everywhere | A tool this repo runs in scripts |

With -D, plain yf-tree is not on your PATH. Use npx yf-tree.

Usage

yf-tree [path]

path defaults to .. yf-tree apps/web scans that folder. The output file is still written relative to where you ran the command.

yf-tree
yf-tree apps/web --format html
yf-tree --depth 2 --out docs
yf-tree --out - 
yf-tree --stamp --ignore dist --ignore "*.log"

| Option | Default | What it does | |---|---|---| | path | . | Directory to scan | | --format | md | md or html. The file extension does not change the format | | --depth | No limit | Positive integer. --depth 1 is the root plus its immediate children. Deeper levels are omitted | | --out | ./yf-tree-out/tree.md or tree.html | A file, a directory, or - | | --stamp | Off. The same file is replaced | On. The name gains a local timestamp: tree-2026-11-05-143022.md | | --ignore | Nothing extra | Repeatable name or glob, on top of the built-in skips | | --no-default-ignore | Built-in skips are on | Turn those skips off | | --no-gitignore | .gitignore in the scanned tree is honored | Also list paths that Git ignores | | --gitignore | Off. The repository is not changed | Add yf-tree-out/ to the repository root .gitignore. Creates that file when it is missing | | --dirs-only | Files and directories | Directories only | | --max-children | No cap | Max entries kept per folder. The rest become one line, N more | | --help, -h | | Usage | | --version, -V | | Package version |

--out docs/tree.md writes that file. --out docs writes docs/tree.md or docs/tree.html. A path that already exists as a directory is a directory. A new path whose last segment has an extension is a file. --out - prints to the terminal and does not write a file. --stamp applies to the default folder and to --out. It does not change stdout.

If the output file sits inside the scanned tree, that file is left out of the listing.

yf-tree --gitignore adds yf-tree-out/ to the .gitignore at the git root, the directory that contains .git. The pattern has no leading slash, so the folder is ignored wherever you run the command. A line that is already yf-tree-out/ or /yf-tree-out/ is left as it is. Without a git repository, the flag fails and does not create a .gitignore.

What is skipped

A .gitignore in the scanned tree is honored, including nested ones. .gitignore files above the path you scanned are not read. An ignored directory is not opened, so a negation inside it cannot bring files back.

These directory names are always hidden, including when there is no Git ignore:

| Kind | Names | |---|---| | Version control | .git, .svn, .hg | | JavaScript | node_modules, bower_components, .pnp | | Python | __pycache__, .venv, venv, .tox, .pytest_cache, .mypy_cache, .ruff_cache | | JS framework cache | .next, .nuxt, .turbo, .cache, .parcel-cache, .expo | | Test output | coverage, htmlcov, .nyc_output |

These files are hidden anywhere: .DS_Store, Thumbs.db, desktop.ini, *.pyc.

dist, build, out, output, public, target, bin, obj, vendor, Pods, .vscode, .idea, .github, and .env are not hardcoded. Those names are source in some projects. .gitignore and --ignore cover them. A tree still shows that .env exists. Hiding file contents belongs to yf-dump.

Dotfiles other than the skips above stay visible. --no-default-ignore turns the built-in names off. .gitignore and --ignore still apply.

Listing

Directories first, then files, A to Z, case insensitive. Symlinks are listed (name -> target) and not followed.

Markdown:

```text
.
├── src
│   └── index.js
└── README.md
```

HTML is one page: dark background, directories expand and collapse, buttons for expand all and collapse all. It does not color or badge files by type. The page has no external assets.

Development

git clone https://github.com/YourFam/yf-tree.git
cd yf-tree
npm test
node ./bin/yf-tree.js --help

Maintainer: YourFam (kamal-yourfam on npm). MIT.

Publish the unscoped alias (maintainers)

The GitHub repo publishes two npm packages at the same version:

  1. npm publish --access public from the repo root → @yourfam/yf-tree
  2. Then from alias/, with matching version and dependencies["@yourfam/yf-tree"]:
cd alias
npm publish --access public

That second package is named yf-git-tree and only shims the scoped CLI so npx yf-git-tree cannot be squatted. npm will not accept unscoped yf-tree (too similar to rc-tree).

License

MIT © 2026 YourFam. See LICENSE.