# tsup: a zero-config TypeScript bundler that is no longer actively maintained

> tsup wraps esbuild to bundle TypeScript libraries with no configuration, writing output to ./dist. Its README now tells readers to migrate to tsdown, so the real question is whether to start a new project on it.

**egoist/tsup** — The simplest and fastest way to bundle your TypeScript libraries.

- Repository: https://github.com/egoist/tsup
- Website: https://tsup.egoist.dev
- Stars: 11,301 · Forks: 275
- Language: TypeScript
- License: MIT
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/egoist-tsup

## What tsup does for a TypeScript library author

A library author's build is a different job from an application's build. The output has to be importable by other people's toolchains, the type declarations have to ship alongside the JavaScript, and the whole thing has to run in a repository that may contain three source files. tsup targets exactly that case: point it at entry files, and it produces bundled output in ./dist with no configuration file required. The README describes it as bundling "your TypeScript library with no config, powered by esbuild".

The set of inputs is deliberately narrow. According to the README, tsup bundles anything Node.js supports natively, namely .js, .json and .mjs, plus TypeScript .ts and .tsx. CSS support exists but the README labels it experimental and links to a documentation section rather than describing the behaviour inline. If your library ships stylesheets as part of its public surface, that label is the honest description of where you stand.

The audience is therefore the package maintainer, not the web app developer. If you are building a site or an application bundle, tsup is the wrong shape of tool, and the README does not pretend otherwise.

## How tsup produces output: esbuild plus a thin orchestration layer

The bundling itself is esbuild's work. tsup's own contribution is the layer around it: reading entry arguments, resolving configuration, driving the build, and handling the parts esbuild does not do for a library. The dependency list in package.json shows that layer clearly. esbuild is a direct dependency, as are rollup, chokidar, sucrase, postcss-load-config, bundle-require and tinyglobby.

That mix explains the boundary of what tsup can do. Rollup's presence is the tell that declaration file generation and some output formats are not purely esbuild paths. Sucrase appears for transformation work esbuild does not cover. postcss-load-config is what stands behind the experimental CSS support, which means CSS handling depends on your project's PostCSS configuration being discoverable.

The peer dependencies are optional, and package.json marks all four that way: @microsoft/api-extractor at ^7.36.0, @swc/core at ^1, postcss at ^8.4.12 and typescript at >=4.5.0. Optional means tsup will start without them and only reach for them when a feature needs them. If you enable declaration output or CSS handling, you are opting into those peer installs, and a missing one surfaces as a build failure rather than at install time.

The package exposes two binaries, not one. package.json maps tsup to dist/cli-default.js and tsup-node to dist/cli-node.js. The two entry points exist as separate CLI files in the source tree, which is worth knowing before you assume a single build pipeline covers both.

## Installing tsup and bundling your first library

The README installs tsup as a local dev dependency and explicitly says a global install is not recommended. Any of the three package managers works.

```bash
npm i tsup -D
```

The Yarn and pnpm equivalents are `yarn add tsup --dev` and `pnpm add tsup -D`. After this, the tsup binary is available through your package manager's script runner.

Bundling is then a single command with the entry files as arguments:

```bash
tsup src/index.ts src/cli.ts
```

The README states that files are written into ./dist, and that this two-entry invocation produces dist/index.js and dist/cli.js. Run it in a scratch directory with one trivial export and you should see a dist folder appear with a JavaScript file next to it. Nothing else is required: no config file, no tsconfig changes mentioned in the README's usage section.

For a repeatable build, put the same command in a script entry in package.json so your release process and your local run use the same arguments. The repository's own build script shows the pattern it uses for itself, including flags like --clean and --splitting:

```bash
tsup src/cli-*.ts src/index.ts src/rollup.ts --clean --splitting
```

Those flags belong to that specific build. The README's usage section does not enumerate the full flag set; it points to the documentation site and to the API docs for configuration options.

## The maintenance warning is the first thing to read

The README opens with a warning block, before the project title, stating that the project is not actively maintained anymore and directing readers to tsdown with a link to a migration guide. That is unusual placement and it is the single most important fact about adopting tsup today. The last push to the repository was on 2026-09-20, so the code has not been abandoned in the sense of a frozen archive, but the maintainer's own stated position is that active maintenance has stopped.

This changes the risk profile rather than the tool's behaviour. An existing build keeps working; the bundler does not stop functioning because the README changed. What changes is what happens when esbuild ships a breaking change, when a Node.js release alters module resolution, or when one of the optional peer dependencies moves. None of those are hypothetical categories for a bundler whose core is a direct dependency on esbuild ^0.27.0.

The release cadence visible in the repository supports the same reading. v8.5.1 is dated 2025-11-12, v8.5.0 is dated 2025-05-16, and v8.4.0 is dated 2025-02-25. Those are real releases, spaced months apart, and the latest sits well behind the last push date. A reader deciding today should treat the README warning as the maintainer's answer to the question they are asking.

## Where tsup stops being the right tool

The narrow input set is the first boundary. The README lists .js, .json, .mjs, .ts and .tsx. If your library's public surface includes .vue, .svelte or another compiled format, tsup is not the bundler for it, and no configuration flag in the README changes that.

CSS is the second boundary, and it is a softer one. The README does not describe CSS as supported; it describes it as experimental and links out. Experimental support in a bundler means the failure mode is a build that succeeds in your environment and produces output consumers cannot use, because the PostCSS configuration resolution differed between the two. For a library where styles are incidental, this may never matter. For a component library where CSS is the product, the label should steer you elsewhere.

The third boundary is the one the README sets itself. When a project's own documentation recommends a successor, using it for a new greenfield library means accepting a migration you already know is coming. That is a defensible choice if your build is simple and you value the zero-config path, but it is a choice, not a default.

## tsdown and Vite: two different answers to the same question

tsdown is the successor the README names, and the migration guide lives at tsdown.dev. The difference in approach is architectural: tsdown is built on Rolldown, the Rust-based bundler from the same lineage as Vite's tooling, whereas tsup sits on esbuild with rollup pulled in for parts of the library-specific work. For a reader, the practical consequence is that tsdown is where the maintainer's attention went, and the migration guide exists specifically to move tsup users across. If you are choosing today, comparing tsup against tsdown first is the comparison the project itself invites.

Vite is the other name that comes up, and it solves a different problem. Vite's centre of gravity is the application and dev-server workflow; library mode is a mode within it. tsup has no dev server and no application story, only entry files and output. If your project is an app, Vite's library mode is not the thing you want either, but the point is that these tools are not interchangeable: one is a library bundler, the other is an application build tool that can also emit a library.

The repository also carries a rollup entry point in its own build command, src/rollup.ts, and lists rollup ^4.34.8 as a dependency. That does not make tsup a Rollup replacement for general use; it means Rollup is part of how tsup gets certain output built.

## Licence and the cost of staying on tsup

tsup is MIT licensed, with the copyright line naming EGOIST. MIT is permissive: you can use it commercially, modify it, and redistribute it, provided the licence and copyright notice travel with the code. The repository ships a LICENSE file at the top level, so the terms are in the tree rather than only on a website. Nothing in the repository suggests a dual licence or a commercial tier. This is a description of the licence text, not legal advice; if your organisation has a policy on third-party licences, the LICENSE file is the document to hand to whoever enforces it.

The upgrade cost is the more interesting number. tsup's dependencies are ordinary npm packages, and the optional peer dependencies mean a TypeScript version bump or a PostCSS major release can change your build without tsup itself changing. With active maintenance stopped, you own those bumps. Practically, that means pinning your lockfile, reading the esbuild changelog before moving the ^0.27.0 range, and accepting that a fix for a break caused upstream may not arrive. The alternative cost is the migration itself, and the project has published a guide for it, which is a lower cost than a migration with no documented path.

## Conclusion

Use tsup for an existing library whose build already works and whose output you have verified, and treat the README's own migration pointer as the signal that new adoption carries a maintenance question. Do not start a long-lived project on it without checking the tsdown migration guide first. Verify three things before deciding: that the emitted dist files match your package.json entry points, that any CSS import still behaves as documented under the experimental CSS support, and that a dry run of the tsdown migration guide covers the options you actually set.

## FAQ

### What are the differences between tsup and tsc?

tsc is the TypeScript compiler and emits per-file JavaScript plus declarations; tsup bundles entry files into output in ./dist using esbuild. The README describes tsup as bundling a TypeScript library with no config, and lists .tsx as an input alongside .ts.

### How do I install tsup?

Install it locally in your project folder with npm i tsup -D, or the Yarn and pnpm equivalents. The README says a global install is possible but not recommended.

### What does tsup output when I pass multiple entry files?

The README gives the example tsup src/index.ts src/cli.ts and states that this outputs dist/index.js and dist/cli.js. Files are written into ./dist.

### Can tsup bundle CSS?

The README links to a CSS support section and labels that support experimental. It does not describe the behaviour inline, so treat CSS output as something to verify in your own build before relying on it.

### Is tsup still maintained?

The README carries a warning stating the project is not actively maintained anymore and points readers to tsdown with a migration guide. The last push to the repository was on 2026-09-20.

## Sources

- [egoist/tsup on GitHub](https://github.com/egoist/tsup)
- [License: MIT](https://github.com/egoist/tsup/blob/main/LICENSE)
- [Project website](https://tsup.egoist.dev)
- [README](https://github.com/egoist/tsup/blob/main/README.md)
- [Releases](https://github.com/egoist/tsup/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/egoist-tsup
