✨ A smarter build tool that starts like tsc and grows with you. Enable dual-format output, automatic package.json exports, and a robust watch mode with just a few lines of configuration. ✨
# initialize tship in your project
npx tship init
# build for both CJS and ESM
npx tship build
# watch mode during development
npx tship watchTShip is built on top of the TypeScript compiler API and delivers:
- Dual-format output – produce CommonJS and ES modules from a single codebase (opt-in)
- Smart extension handling – automatically renames files when output directories collide, keeps standard extensions otherwise
- Auto-exports – updates
package.jsonwith conditionalexports,main,module,types, andtypesVersionsfor maximum ecosystem compatibility - Robust watch mode – uses chokidar for reliable file watching (falls back to
tsc --watchwhen not configured) - Plugin system – hook into
onPostEmitandonBuildEndto extend the build pipeline - Zero config – runs as standard
tscby default; advanced features are activated only when you addtshipsettings - Fast – compiles each format in parallel using the TypeScript API
All features are configurable via tsconfig.json, a dedicated tship.config.ts, or CLI flags.
Install the package and its peer dependency typescript:
npm install -D @jstility/tship typescriptAdd a tship section to your tsconfig.json or run the init command to create a standalone config file:
npx tship initIf your tsconfig.json already has outDir defined, you can enable dual-format output with a single line:
{
"compilerOptions": {
"target": "ES2022",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"declaration": true,
"sourceMap": true
},
"tship": {
"formats": ["cjs", "esm"]
},
"include": ["src/**/*.ts"]
}Both formats will be written to ./dist and file extensions will be renamed to .cjs/.mjs automatically.
If you prefer to keep the formats in different folders, specify outDirs:
{
"compilerOptions": { ... },
"tship": {
"formats": ["cjs", "esm"],
"outDirs": {
"cjs": "./dist/cjs",
"esm": "./dist/esm"
},
"autoExports": {
"generate": true,
"typesVersions": true
}
}
}This will automatically populate main, module, types, exports, and typesVersions in your package.json.
If no tship property is present in tsconfig.json and no tship.config.ts exists, tship behaves exactly like tsc:
npx tship buildOnce you add formats (or any other tship option), the multi-format pipeline kicks in:
npx tship buildThis will output:
✔ Build completed in 234ms
ℹ CJS → dist/cjs
ℹ ESM → dist/esm
Inside dist/cjs you'll find CommonJS files (require/exports) and inside dist/esm you'll find ES modules (import/export). Both folders contain declaration files (.d.ts), source maps, and declaration maps.
Watch your source files and rebuild automatically:
npx tship watchOverride the format or output directories via CLI:
npx tship build --formats cjs,esm --cjs-out dist/commonjs --esm-out dist/moduleFor a complete list of commands and options, run:
npx tship --helpFull documentation is available at jstility.github.io/tship. You'll find guides on configuration, dual-format output, declaration files, auto-exports, watch mode, monorepo integration, and the plugin API.
If you encounter any issues or have questions, please open an issue with a clear description and, if possible, a minimal reproducible example.
Contributions are very welcome! Whether it's a bug report, feature request, or a pull request, please follow the guidelines in here. All contributions are appreciated.
@jstility/tship was created by Rangga Fajar Oktariansyah (@FajarKim) and is maintained by the JStility (@jstility) organization.
It builds upon the excellent TypeScript compiler API and is inspired by tools like tsup and tsc.
This project is licensed under the Apache License 2.0.
We stand with the innocent people of Palestine.
Learn more ➜