cheat sheet
tsx
Daily-driver reference for the tsx CLI — run TS files, watch mode, ESM/CJS handling, Node loader integration.
tsx — CLI
What it is
tsx is the CLI that runs TypeScript and JSX files directly with Node — no separate compile step, no tsc invocation. Esbuild handles transpile per-file, the loader hook plugs into Node, and the result is a one-binary developer experience. It largely replaces ts-node for new projects.
For the package surface (peer deps, alternatives, security model), see packages-npm/npm-tsx. This page focuses on day-to-day CLI usage.
Install
# In a project
npm install -D tsx
# Global (rare)
npm install -g tsx
# One-off
npx tsx ./script.ts
Output: tsx binary on $PATH (project-local under node_modules/.bin/, or global).
Day-to-day commands
| Command | What it does |
|---|---|
tsx file.ts | Run a TS/TSX file once and exit |
tsx watch file.ts | Run with auto-restart on import-graph changes |
tsx watch --clear-screen file.ts | Same, clear terminal between runs |
tsx --no-cache file.ts | Bypass tsx's esbuild cache |
tsx --tsconfig path/to/tsconfig.json file.ts | Use a specific tsconfig |
tsx esm file.ts | Force ESM mode (rare — auto-detected) |
tsx cjs file.ts | Force CJS mode |
node --import tsx file.ts | Run tsx as a Node loader explicitly |
Common scenarios
Run a script with arguments
tsx ./scripts/migrate.ts --env=staging --dry-run
Output:
[migrate] env=staging, dry-run=true
[migrate] 3 migrations applied
Arguments after the script path are passed through to the script's process.argv.
Watch a dev server
tsx watch src/server.ts
Output:
[tsx] Starting watch mode for src/server.ts...
Server listening on http://localhost:3000
[tsx] File changed: src/api/users.ts
[tsx] Restarting...
Server listening on http://localhost:3000
Only files in the import graph trigger restart. To extend the watch scope, wrap with nodemon.
Pass env vars from a .env file
# Node 20.6+ has --env-file natively; combine with tsx via the node form
node --env-file=.env --import tsx ./src/server.ts
Output:
Server listening on http://localhost:3000
DB connected via DATABASE_URL=...
Or use dotenv-cli for older Node:
npx dotenv -e .env -- tsx ./src/server.ts
Output:
Server listening on http://localhost:3000
Pre-load a module (-r style)
node --require dotenv/config --import tsx ./src/server.ts
Output:
Server listening on http://localhost:3000
tsx's own CLI doesn't expose -r; reach for the explicit node --import tsx form when you need pre-loaders.
Resolve tsconfig.json paths aliases
npm install -D tsconfig-paths
node --import tsx --import tsconfig-paths/register ./src/server.ts
Output:
added 1 package in 1s
Server listening on http://localhost:3000
tsx does NOT resolve TS path aliases by default. The companion loader adds them.
Replace ts-node in npm scripts
- "dev": "ts-node-esm src/server.ts",
- "migrate": "ts-node --transpile-only ./scripts/migrate.ts",
+ "dev": "tsx watch src/server.ts",
+ "migrate": "tsx ./scripts/migrate.ts",
Side-effects to verify: --require hooks (replace with node --require ... --import tsx), tsconfig-paths (install + register).
Debug with Node inspector
node --inspect-brk --import tsx ./src/server.ts
Output:
Debugger listening on ws://127.0.0.1:9229/...
For help, see: https://nodejs.org/en/docs/inspector
Then attach VS Code or Chrome DevTools to chrome://inspect. Source maps make TS lines visible directly.
Useful flags
| Flag | What it does |
|---|---|
--watch | Watch import-graph files for changes |
--clear-screen | Clear terminal between runs in watch mode |
--no-cache | Skip the esbuild cache (forces recompile) |
--tsconfig <path> | Override tsconfig.json location |
--no-source-maps | Disable inline source maps (faster, harder to debug) |
--ignore <glob> | Add patterns to ignore in watch mode |
--conditions <name> | Add export conditions (for conditional exports in package.json) |
esm / cjs | Subcommands forcing module mode (auto-detected by default) |
Environment variables:
| Env var | Purpose |
|---|---|
TSX_TSCONFIG_PATH | Path to tsconfig.json (overrides default search) |
NODE_OPTIONS | Standard Node flags (e.g. --max-old-space-size=8192) |
Configuration
tsx reads tsconfig.json automatically. The relevant compiler options:
target— controls down-leveling (esbuild respects this)jsx—react,react-jsx,react-jsxdev,preserveexperimentalDecorators— supportedpaths— NOT respected by default; usetsconfig-pathsemitDecoratorMetadata— NOT supported (use ts-node or tsc for this)
Example tsconfig.json:
{
"compilerOptions": {
"target": "es2022",
"module": "esnext",
"jsx": "react-jsx",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"experimentalDecorators": true
}
}
Common pitfalls
Unknown file extension ".ts"when running plainnode. The tsx loader isn't registered. Usetsx file.tsdirectly ornode --import tsx file.ts.Cannot find module '@/utils'. TS path aliases aren't resolved. Addtsconfig-paths/registerto the loader chain.- Watch mode misses changes. Watch follows the static import graph. Files imported via dynamic
require()or computedimport()aren't tracked. Fall back tonodemon. - No type errors at runtime.
tsxstrips types; it doesn't type-check. Pair withtsc --noEmitin pre-commit or CI. - Memory leak after long watch sessions. Restart
tsx watchevery few hours during long dev cycles. The esbuild cache accumulates. SyntaxError: Cannot use import statement outside a module. File interpreted as CJS but contains ESM. Rename to.mtsor set"type": "module"in the nearestpackage.json.
See also
- Packages: npm-tsx — versioning, security, ecosystem
- Packages: npm-ts-node — predecessor
- JavaScript: typescript — language reference
- JavaScript: node-runtime — Node flags useful with tsx