untracked turns your dependency tree into an ignore file
Ignore common junk files in zip/lambda/webpack bundles with a universal untracked file list.
At a glance
- What is it?
- untracked is a CLI that prints gitignore style patterns for the files you do not want in a production bundle, and it decides what to keep by reading your production dependencies with npm ls --prod. The catch is that it protects dependencies, not your own runtime assets.
- Who is it for?
- untracked suits Node projects that ship to Docker, Heroku or Vercel and currently deploy their whole working tree, and it is at its best when your production dependencies are declared in package.json and installed from a lockfile so npm ls --prod returns a clean tree.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 80 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem is the deploy tarball, not the repository
Every Node deployment platform copies a directory into a build image. Whatever is in that directory at the wrong moment ends up in the artifact you ship, including the Markdown files nobody reads at runtime, the test fixtures, the coverage report from your last CI run, the source maps you meant to keep out, and the type definitions that only your editor reads.
untracked exists to shrink that payload. The project description says it ignores common junk files in zip, lambda and webpack bundles using a universal untracked file list, and the README frames the goal as creating the smallest production bundle possible.
The audience is a JavaScript developer who deploys with a platform that copies the working tree rather than a build step that packages only what is needed. That is the Heroku slug compiler case, the Vercel deployment case and the Docker build context case. If your build already copies a dist directory and nothing else, this tool has nothing to do. If your deploy step is a zip of the repository root, it has a lot to do.
The output format is the key design decision. untracked emits gitignore pattern syntax rather than a bespoke format, which means the result works with any tool that understands ignore files, including the ones that are not the platform you had in mind when you generated it.
npm ls --prod decides what survives
The mechanism has two halves. The first is a built-in catalogue of files that are never needed in production. The project groups it into four categories.
- Documentation: README, LICENSE, CHANGELOG, CONTRIBUTING, and the same names across all markup formats. - Tooling: Makefile, Gruntfile, Gulpfile, karma.conf.js, jest.config.js and similar build configuration. - Assets: source maps, type definitions and Flow types, matched as *.map, *.d.ts and *.flow. - Artifacts: coverage/, docs/, examples/ and test* directories.
The second half is the dependency check. The README states that untracked reads your dependencies from npm ls --prod and generates ignore rules that exclude everything unnecessary while preserving your production dependencies. In other words, the tool does not just subtract a fixed list from your tree. It asks npm what the production dependency graph actually is, and it keeps the paths those packages occupy, so a bundled dependency that has to be present at runtime is not caught by a broad rule such as node_modules or a wildcard on a common directory name.
That is the interesting part of the design, and it is also where the tool inherits npm's behaviour. If npm ls --prod cannot resolve the tree cleanly, or if dependencies are hoisted, installed globally, vendored by hand or linked through a workspace, the answer it produces is only as good as what npm reports.
Writing to a file, or updating one in place
The simplest use prints the patterns to standard output, and the README describes that as the files to ignore being detected automatically.
npx untrackedRedirect that output into whatever ignore file your platform reads.
npx untracked > .dockerignore
npx untracked > .slugignore
npx untracked > .vercelignoreThe interesting case is the second one, because a plain redirect destroys whatever was in the file before. If you already keep a .dockerignore with your own rules, the --write flag updates only the auto-generated section, delimited by ### start and ### finished markers, and leaves everything else alone.
npx untracked --write .dockerignoreThat marker convention is what makes the tool safe to run repeatedly in CI. The hand written part of the file survives, the generated part is replaced on each run, and a diff between two runs shows only what changed in the generated block.
The README also shows a per platform mapping. Heroku reads .slugignore, written during a prebuild step.
{
"scripts": {
"heroku-prebuild": "npx untracked > .slugignore"
}
}Vercel reads .vercelignore, and Docker reads .dockerignore. For Yarn there is a three step sequence that installs production dependencies, generates .yarnclean and then runs the autoclean command with --force.
The untracked field in package.json is where you correct it
No list of common junk files is right for every project, so untracked exposes a configuration block in package.json with three fields.
{
"untracked": {
"whitelist": ["bin"],
"blacklist": ["node_modules/puppeteer/.local-chromium"]
}
}The whitelist field lists files to include in the bundle, that is, files that would otherwise be ignored and should not be. The blacklist field adds extra paths to ignore, which is how you handle the case where a dependency ships something large that your build never touches, such as the Chromium download that Puppeteer keeps inside its package directory. The write field takes either true, in which case the default target is .dockerignore, or an explicit file path to update in place.
The configuration is not limited to package.json. The README points at cosmiconfig support, so the same settings can live in .untrackedrc, .untrackedrc.json, .untrackedrc.js or untracked.config.js. That matters for monorepo setups where the ignore file lives at the root and package.json belongs to a workspace package.
The project reads its own configuration through joycon and parses command line arguments with mri, so the CLI surface is small and the configuration lookup is delegated to a library that already knows how to find config files in the places you would expect.
Where untracked will not help
The first limitation is the most important one and it follows from the mechanism. untracked protects your production dependencies. It does not know which of your own files are needed at runtime. A hand written script in the repository root, a template directory, a fixture your server reads at request time, a static file your server serves: none of these are dependencies, so the tool has no reason to keep them and no way to know they matter. The whitelist field is the escape hatch, and the more of your runtime assets you need to list there, the less you are really getting from an automated tool.
The second limitation is that it reads npm, so it inherits npm's model. A project that installs dependencies with pnpm, yarn with Plug'n'Play, or bun has a different tree shape, and the README documents only the npm path with npm ls --prod. A workspace monorepo with hoisted packages is another case where the shape of node_modules decides the answer.
The third is that untracked ignores files, it does not prune them. Nothing is deleted from your working tree or from the deploy artifact by the tool itself. On Yarn that distinction is handled by pairing it with the autoclean command, as the README shows, but on Docker and Heroku the ignore file is read by the platform, and the savings only appear if the platform honours the file you generated.
The related project listed in the README, lambda-prune, works on the other side of the same problem: it cleans up old AWS Lambda functions, whereas untracked decides what goes into the bundle in the first place.
Maintenance, packaging and the shape of the CLI
The releases show a project in steady maintenance. v1.6.5 shipped on 2026-07-15, v1.6.6 on 2026-07-30 and v1.6.7 on 2026-08-03, and the last push to the repository was on 2026-08-03. The repository is not archived.
The package itself is small by design. The main entry is src/index.js and the executable is bin/index.js, with the published files limited to those two directories. The runtime dependencies are four: joycon for configuration discovery, mri for argument parsing, tinyspawn for running child processes such as npm ls, and update-notifier to tell you about newer versions. The engines field accepts Node 6 or newer, which tells you the runtime dependency versions were chosen for a very old Node floor.
The repository uses ava with c8 for coverage, standard for linting, conventional-changelog-cli and standard-version for releases, and a set of commit and publish hooks managed through simple-git-hooks and nano-staged.
The licence is MIT, with Kiko Beats named as author and maintainer and Lucas Bento listed as a contributor. Read the LICENSE file in the repository for the exact terms before shipping it in a build pipeline.
Editorial conclusion
untracked suits Node projects that ship to Docker, Heroku or Vercel and currently deploy their whole working tree, and it is at its best when your production dependencies are declared in package.json and installed from a lockfile so npm ls --prod returns a clean tree. It does not suit a project whose runtime assets live outside dependency directories, because the tool reasons about dependencies rather than about your own source files, and it does not replace a per service ignore list that a platform already manages. Before adopting, run npx untracked and read the generated patterns line by line, check that any file listed in the untracked whitelist field in package.json is actually restored, and confirm that the files the platform excludes by default are not the ones you are relying on untracked to remove.
Frequently asked questions
What does untracked do and how do I install it?
It generates ignore patterns for files you do not want in a production bundle, using gitignore pattern format so any ignore file tool can read the result. Install it with npm install untracked -g, or run it without installing using npx untracked.
How does untracked decide which files to keep?
It reads your production dependencies from npm ls --prod and generates rules that exclude unnecessary files while preserving those dependencies. The built-in list covers documentation, tooling files, assets such as *.map and *.d.ts, and artifact directories such as coverage/, docs/ and test*.
How do I update an existing .dockerignore without losing my own rules?
Use the --write flag with the file name, for example npx untracked --write .dockerignore. It updates only the section between the ### start and ### finished markers and preserves everything else in the file.
Can I exclude a file from being ignored in untracked?
Yes. Declare an untracked field in your package.json with a whitelist array of files to include in the bundle, and a blacklist array of additional paths to ignore. The same settings can go in .untrackedrc, .untrackedrc.json, .untrackedrc.js or untracked.config.js since the project supports cosmiconfig formats.
Which deploy platforms does untracked support?
The README shows examples for Heroku through a .slugignore written in a heroku-prebuild script, for Vercel through a .vercelignore, for Docker through a .dockerignore, and for Yarn through a .yarnclean paired with the autoclean command.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/kikobeats-untracked)Was this useful?