mrkeyoor.com_
Thu 06 Aug 01:00 UTC
npmCLI & Toolingupdated 05 Aug 2026

tsx

tsx runs TypeScript files in Node.js directly: tsx ./file.ts works like node ./file.ts but strips and transforms the types on the fly with esbuild. It handles both ESM and CommonJS without you thinking about it, respects tsconfig.json (including paths), ships a watch mode that reruns your script when imports change, and exposes hooks (node --import tsx, tsImport) so the same transform can power test runners and scripts. It deliberately does zero type checking; it is an execution tool, not a compiler replacement.

Verdict

The current default answer to 'how do I just run this TypeScript file', because it removed the loader and module-format ceremony that made ts-node painful. Keep tsc --noEmit in CI since tsx checks nothing, and reconsider once Node's native type stripping covers your codebase.

API stability4/5The 4.x line has been current since late 2023 with a steady stream of patch releases; the notable churn was Node's own loader API forcing the --loader to --import migration, which tsx tracked cleanly.
Docs4/5tsx.hirok.io covers CLI, watch mode, the register and tsImport APIs, and VSCode debugging with concrete snippets; the GitHub README is just a pointer to it, and some advanced pages sit behind sponsor-only help content.
Maintenance4/5Pushed August 2026 with a release the same day; it is a sponsor-funded solo project by privatenumber with 88 open issues (122 counting PRs), responsive but bus-factor one.
Ecosystem4/5Around 82M weekly downloads and it is the de facto dev runner wired into countless package.json scripts and docs; it has no plugin ecosystem of its own, it rides esbuild's.

Use it if

  • You want npm run dev to just execute src/server.ts with restart-on-change: tsx watch is the whole setup
  • You keep hitting ESM/CJS friction with ts-node: tsx's main selling point is that mixed module formats, .mts/.cts files, and tsconfig paths work without loader configuration
  • You write one-off TypeScript scripts or scratch files and want them runnable with a shebang or npx tsx, no build step
  • You need to load user-provided TS files at runtime from a JS tool: tsImport from tsx/esm/api scopes TS support to specific imports without changing the whole runtime
Skip it if

Setup reality

npm install -D tsx and npx tsx file.ts works immediately; there is no config file at all, which is the point. The install pulls esbuild, which lands as a platform-specific binary via optionalDependencies, occasionally annoying in pnpm setups, offline mirrors, or when CI caches a lockfile across OSes. Node 18+ is required, and the node --import tsx flag replaced the deprecated --loader form used on Node 20.5.1 and below, so copy-pasted older instructions mislead. Remember what is missing by design: no type checking (pair it with tsc --noEmit), no decorator metadata, and watch mode ignores node_modules, dist, and hidden directories unless you pass --include.

Patterns

Run a TypeScript file directlyrun-ts-file

npx tsx ./src/script.ts

# or installed globally
tsx ./src/script.ts

Works for ESM and CJS, .ts/.tsx/.mts/.cts, with tsconfig paths resolved. No types are checked; a file with type errors still runs.

Rerun on change with watch modewatch-mode

tsx watch ./src/server.ts

# watch extra non-imported files, keep the screen
tsx watch --include "./config/*" --clear-screen=false ./src/server.ts

Watches all imported files but ignores node_modules, dist, vendor, and hidden directories. Press Return in the terminal to force a rerun.

Wire it into package.jsondev-script

{
  "scripts": {
    "dev": "tsx watch src/server.ts",
    "start": "node dist/server.js",
    "typecheck": "tsc --noEmit"
  }
}

Keep start pointing at built output; tsx is a dev runner. The typecheck script is not optional in spirit, it is the type safety tsx deliberately skips.

Use the node CLI with tsx as a hooknode-import-flag

node --import tsx ./file.ts

# Node 20.5.1 and below used the deprecated loader API
node --loader tsx ./file.ts

Useful when you need node's own flags (--inspect, --max-old-space-size) alongside TS support. The --loader form is deprecated; prefer --import on modern Node.

Add TS support to another CLI via NODE_OPTIONSenhance-other-binaries

NODE_OPTIONS='--import tsx' npx some-binary ./config.ts

This is how you make third-party Node CLIs read TypeScript config or plugin files without the tool supporting TS itself.

Register for only one module systemcjs-or-esm-only

# CommonJS files only
node --require tsx/cjs ./file.ts

# ESM files only
node --import tsx/esm ./file.ts

The split registrations exist for tools that already handle one side; plain --import tsx covers both and is what you want in most cases.

Load one TS file from JavaScript at runtimets-import-scoped

import { tsImport } from 'tsx/esm/api';

const loaded = await tsImport('./user-config.ts', import.meta.url);

// with options
await tsImport('./plugin.ts', {
  parentURL: import.meta.url,
  tsconfig: './custom-tsconfig.json'
});

The second argument (parent URL) is required to resolve relative paths. tsImport does not cache: importing the same file twice loads it twice, by design.

Enable TS loading from inside your entry fileentry-point-registration

import 'tsx';

// dynamic imports after this line can load TS
const mod = await import('./tasks.ts');

Only dynamic imports after the registration work; static imports were already resolved. The docs themselves warn this hides the magic from collaborators, so prefer the CLI flag.

Make a TypeScript file executableshebang-script

#!/usr/bin/env tsx

console.log('argv:', process.argv.slice(2));

// chmod +x ./scripts/deploy.ts && ./scripts/deploy.ts staging

Requires tsx available on PATH (global install or running inside npm scripts where node_modules/.bin is added).

Point tsx at a different tsconfigcustom-tsconfig-path

TSX_TSCONFIG_PATH=./tsconfig.scripts.json tsx ./scripts/migrate.ts

By default tsx looks up the nearest tsconfig.json; the env var is the only override, there is no CLI flag for it.

Pair tsx with real type checkingtypecheck-in-ci

# CI pipeline
npx tsc --noEmit
npx tsx ./scripts/integration-test.ts

tsx strips types with esbuild and never diagnoses them. Without a tsc --noEmit gate, type errors reach main and only surface as runtime behavior.

Alternatives

PackageRegistryPick it when
ts-nodenpmYou need real TypeScript compiler semantics at runtime: emitDecoratorMetadata, optional type checking, or compiler plugins.
jitinpmYou are a library author needing to require a user's TS config file synchronously inside your tool, rather than running whole apps.
esbuild-registernpmYou only need a CJS require hook with esbuild transforms and want the smallest possible layer over esbuild itself.