tmp: temporary files that clean up after themselves in Node
Temporary file and directory creator for node.js
At a glance
- What is it?
- tmp is a small dependency-free Node library for creating temporary files and directories, with a synchronous and an asynchronous API and cleanup on process exit. It suits tools that need scratch space without leaking files, though its random naming falls back to pseudo random numbers when the system entropy pool is low, and its path rules constrain where files may be created.
- Who is it for?
- Use tmp when your Node tool creates scratch files or working directories and you want them removed on process exit without wiring up your own cleanup, and when the promise-style API is acceptable through tmp-promise.
- 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 149 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 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A small library with both an async and a sync API
tmp is a temporary file and directory creator for Node.js, described in the README as a widely used library for that job. The whole surface is small: create a file, create a directory, or just generate a unique name, in a callback flavour and a synchronous flavour.
The design choice that makes it pleasant is that all parameters are optional in every API call. A caller who wants nothing more than a scratch file writes tmp.file and gets a path and a file descriptor. A caller who wants a file with mode 0644, a prefix of prefix- and a postfix of .txt passes those and gets the same thing back in a different shape.
The package manifest confirms the shape of the dependency. The runtime dependencies object is empty, the entry point is lib/tmp.js, the published files list is lib/ only, and the engines field requires node >=14.14. A library with no runtime dependencies is a low-stakes decision in a dependency tree, and it is also the reason the package can be trusted to keep working after an ecosystem upgrade.
The one exception to the JavaScript API is a separate project. A promisified version of the API exists as tmp-promise, so applications that prefer async and await do not have to wrap the callbacks themselves.
Random names from crypto, with a pseudo random fallback
The naming mechanism is where a reader should slow down, because the README describes a fallback that matters.
Tmp uses crypto for determining random file names, or, when using templates, a six letter random identifier. And then the sentence that deserves attention: just in case that you do not have that much entropy left on your system, Tmp will fall back to pseudo random numbers.
That fallback is the kind of detail that is usually left out of a library README, and it changes the threat model. If you are using tmp to name a file that holds a secret, and the system entropy pool is exhausted, the name becomes predictable to anyone who can observe the directory. The name is not the secret, and the file permissions do the real work, but predictability of a temp path is the classic pattern behind symlink and file-displacement attacks on shared machines.
The six letter identifier is the same order of magnitude as a random suffix used in many other tools, which is to say it is fine for collision avoidance and fine for uniqueness, and not fine as a secrecy primitive.
The practical advice is to treat tmp as a convenience for uniqueness and lifecycle, not as a random name generator for security decisions, and to check the operating system entropy state if you are creating files in a container that starts with a cold pool.
Graceful cleanup and the setGracefulCleanup contract
The cleanup story is the reason most people reach for this library rather than calling fs.mkdtemp directly. You can set whether you want to remove the temporary file on process exit or not, and the option is enforced by calling a method:
const tmp = require('tmp');
tmp.setGracefulCleanup();Once graceful cleanup is set, tmp removes all controlled temporary objects on process exit. Otherwise the temporary objects remain in place, waiting to be cleaned up on system restart or by whatever scheduled temporary object removal the operating system runs.
That second half of the sentence is the honest part of the design. Without the call, tmp is no better than the operating system's janitor, and on a busy machine those files can sit around for a long time. The library hands you the choice, and the choice is opt-in.
The callbacks expose the cleanup function as well, so a caller can remove the object early when it is finished with it. In the asynchronous file example the callback receives a cleanupCallback, and the README notes that calling it manually is not necessary if the keep option was not passed, because the library will clean after itself.
The synchronous API mirrors this with a removeCallback on the returned object, and the same rule applies: removeCallback is available for manual cleanup, and the library handles it on exit otherwise.
The path rules that still constrain where files can go
The README devotes a long section to breaking changes, and the reason is instructive: several restrictions on paths are still in force, and they are easy to trip over.
A set of changes was reverted in v0.2.2, and tmp should now behave as it did before they were introduced. The reverted items were that tmpdir had to be located under the system defined tmpdir root, that spaces were collapsed into single spaces, and that all single and double quote characters were removed. Those three are history.
The restrictions that remain are these: template must be relative to tmpdir, name must be relative to tmpdir, and the dir option must be relative to tmpdir. In other words, everything tmp creates has to sit inside the temporary root it has chosen.
There is an escape hatch, and it is the tmpdir option, which the README describes as newly introduced for the purpose of overriding the system's tmpdir. So if you need your temporary objects somewhere else, you do not pass a dir outside the root, you change the root itself.
That design is defensible. A library that keeps every file it creates inside one known directory can clean up reliably, cannot be tricked into writing outside it by a crafted option, and gives the caller a single place to look for leftovers. It is a constraint, but it is a constraint with a purpose.
Node version support and the rimraf dependency going away
The compatibility section is a short list of dropped Node versions, and it is the kind of list that tells you how old the package is.
Since version 0.0.33, support for Node versions below 0.8 was dropped, and anyone on 0.8 has to pin below 0.0.33. Since version 0.1.0, support for Node versions below 0.10.0 was dropped, and applications that still need those must limit the dependency to versions below 0.1.0. Since version 0.2.2, all support for Node 14 and below was dropped. Then in version 0.2.3, Node versions at or below 14.4 were dropped and rimraf was removed from the dependencies.
The rimraf removal is the more interesting entry for a modern reader. rimraf is the recursive delete package that was one of the most depended-upon transitive dependencies in the Node ecosystem for years. The manifest now shows an empty dependencies object, so this library is no longer pulling a recursive delete implementation into every project that touches it, which removes a supply chain surface and a source of permission-related warnings from installers.
The package version in the manifest is 0.2.7, and the README points to CHANGELOG.md for more detail on compatibility. The repository has no GitHub releases, so the version in package.json and the published npm version are the only reference points.
Directory creation, unsafeCleanup and the descriptor question
Directory creation has one behaviour that trips people up, and it is documented: if the directory still contains items on process exit, then it will not be removed.
The reason is straightforward. A temporary directory that a child process wrote files into cannot be deleted by the parent without risking data loss, so tmp leaves it alone. If you want the directory removed even when it has entries in it, you can pass the unsafeCleanup option when creating it. The name is the warning.
The file side has an extra wrinkle that the README mentions. As a side effect of creating a unique file, tmp gets a file descriptor, and the returned object exposes it as fd. The examples log both the path and the descriptor, and the asynchronous example also receives the descriptor as a callback argument.
The other half of that is the mode, prefix and postfix handling. The advanced example creates a file with mode 0o644, a prefix of prefix- and a postfix of .txt, and the same options work in the synchronous call, where they are passed to fileSync. The prefix and postfix are what make a temp file recognisable to a human scanning a directory, and the mode is what decides who can read it before you write to it.
Note that both the synchronous and the asynchronous directory calls are documented as throwing an exception if the maximum limit of retries for creating a temporary name fails, or if you lack permission to write to the directory where the object should be created. A failed temp name is not a rare theoretical case on a full or misconfigured tmpfs.
Why not just call fs.mkdtemp yourself
The honest alternative to this library is two calls from the Node standard library: os.tmpdir for the root, and fs.mkdtemp or fs.mkdtempSync for a unique name. That is two lines and it has no dependencies, which is exactly the point of asking why tmp exists.
The differences are in the lifecycle and the ergonomics rather than in the creation itself. Node's own API gives you a directory and leaves the removal entirely to you. tmp adds removal on process exit once you call setGracefulCleanup, it gives you the removeCallback and cleanupCallback handles, it offers the prefix, postfix and mode options in one call, and it exposes tmpName and tmpNameSync when you want a name for a file that you will create and manage yourself.
The counter-argument is the constraint we already covered. tmp requires templates, names and the dir option to be relative to the tmpdir root, so you cannot use it to place a temporary object in an arbitrary directory of your choosing, only under a root you nominate with the tmpdir option.
For a script that creates one file and exits, the standard library is enough. For a long-running service that opens scratch files continuously across many modules, the shared cleanup registry is the part you would end up writing yourself, and tmp has already written it.
Editorial conclusion
Use tmp when your Node tool creates scratch files or working directories and you want them removed on process exit without wiring up your own cleanup, and when the promise-style API is acceptable through tmp-promise. Do not use it as a source of unpredictable names for anything security sensitive, because the library states that it falls back to pseudo random numbers when system entropy is low, and do not fight its path model, since templates, names and the dir option must all be relative to the tmpdir root. Before you adopt it, check that your Node version satisfies the >=14.14 engine requirement, read CHANGELOG.md for the compatibility notes, and plan for the 0.2.x path rules, noting that the last push to this repository was on 2026-05-27.
Frequently asked questions
How do I install tmp in a Node project?
The README gives the install command as npm install tmp. The package has no runtime dependencies and the manifest requires node >=14.14.
Does tmp delete the files it creates?
Only if you ask it to. You can set whether to remove the temporary file on process exit, and enforcing that requires calling tmp.setGracefulCleanup(). Otherwise the files remain until the operating system cleans them up.
Are the random names tmp generates safe for security use?
Not for secrecy. The README states that tmp uses crypto for random file names, but falls back to pseudo random numbers if the system has little entropy left, and a six letter identifier is used with templates. Use it for uniqueness and lifecycle, not as a source of unpredictable secret names.
Why does my tmp directory not get removed?
If the directory still contains items on process exit it will not be removed. You can pass the unsafeCleanup option when creating the directory to remove it even when it has entries in it.
Can I put temporary files in a directory other than the system temporary directory?
You have to change the root rather than the target, because template, name and the dir option must all be relative to tmpdir. To override the system's tmpdir, use the newly introduced tmpdir option.
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/raszi-node-tmp)Was this useful?