mrkeyoor.com_
Sun 20 Sept 07:01 UTC
npmCLI & Toolingupdated 20 Sept 2026

tsx review

tsx 4.23.12 runs TypeScript and current JavaScript directly in Node by transforming syntax with esbuild and handing execution back to Node's module system. Its CLI supports CommonJS and ESM projects, tsconfig path aliases, watch restarts, Node flags, the Node test runner, shell evaluation, and scoped registration APIs. It removes types but does not check whether they are correct, emit declaration files, or create a deployable build directory. The current patch fixes import.meta shimming when comments or newlines split those tokens; nearby 4.23 patches repair async ESM require fallback and nyc coverage discovery.

63.8Mdownloads / wk
Verdict

tsx 4.23.12 installed in 1.8 seconds and used 12 MB across 3 packages in our sandbox, with working require and import and 0 audit findings; its browser bundle failed. Use it for Node development execution when tsc checks types elsewhere, and keep a separate build when production needs emitted artifacts.

We installed it

Lab card: what happened when we installed tsxScreenshot of tsx documentation
Install✓ · 1.8s3 packages on disk · 12 MB
ImportESM import works · require() works · ESM package with exports map
Browsern/acould not be bundled for the browser (Node-only code, most likely)
Typesno TypeScript types found
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does tsx install cleanly?

Yes. In a fresh container with an empty cache, npm install tsx finished in 2 seconds, leaving 3 packages and 12 MB on disk. npm audit reported no known vulnerabilities.

Can tsx run in a browser?

Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.

Does tsx work with both ESM and CommonJS?

Yes. Both import 'tsx' and require('tsx') worked in Node 22 in our run. The package is published as ESM with an exports map.

Does tsx include TypeScript types?

No type declarations were found in our install, so TypeScript users need their own declarations.

tsx or ts-node: which should you use?

ts-node: Choose it when TypeScript compiler integration and optional type checking matter more than esbuild transformation speed. tsx 4.23.12 installed in 1.8 seconds and used 12 MB across 3 packages in our sandbox, with working require and import and 0 audit findings; its browser bundle failed.

When should you not use tsx?

Execution must fail on a type error; tsx strips TypeScript syntax and leaves semantic checking to tsc or an editor

API stability4/5The version 4 CLI keeps a compact contract: tsx file.ts, watch, Node option forwarding, evaluation, and test-runner use. Public ESM and CommonJS APIs also expose scoped import and registration. Loader behavior must follow changing Node module semantics, and the 4.23.8 through 4.23.12 fixes cover package subpaths, typeless ESM exports, require fallback, test locations, and import.meta. Ordinary CLI calls are steady, while mixed-module integrations need regression tests.
Docs4/5tsx.hirok.io separates getting started, TypeScript limits, compilation, watch behavior, shell scripts, Node enhancements, VS Code, and development APIs. It plainly says tsx does not type-check and shows where Node flags belong. The registration pages document CommonJS top-level-await and dynamic-import limits. Diagnosing a module failure can still require consulting Node resolution, tsconfig, package exports, and esbuild behavior alongside tsx, which limits the score to 4.
Maintenance5/5Version 4.23.12 and the repository's latest push both landed on 2026-08-10. GitHub reports 107 open issues and pull requests in an unarchived project. Three releases between 2026-08-07 and 2026-08-10 fixed nyc discovery, an async ESM require fallback, and split-token import.meta shimming. That response rate matters for a loader attached directly to Node internals and supports a maintenance score of 5.
Ecosystem5/5npm counted 84,056,131 downloads for the week ending 2026-08-24, and GitHub reports 12,119 stars. tsx slots into npm scripts, Node's test runner, watch workflows, shell scripts, Docker development commands, and programmatic loaders. One direct dependency keeps the graph small by count, though esbuild's platform executable contributes to the measured 12 MB installation. Adoption and Node integration breadth support a score of 5.

Use it if

  • Development scripts, migrations, generators, or local servers should execute TypeScript without a separate output directory
  • A repository crosses CommonJS and ESM boundaries and needs Node-aware transformation during development
  • Watch mode should restart an entry point when its imported TypeScript files or selected extra files change
  • TypeScript tests should run through Node's built-in test runner while type checking remains a separate CI command
Skip it if

Setup reality

We installed tsx 4.23.12 without a cache in a fresh Node 22 Bookworm sandbox. npm took 1.8 seconds and left 3 packages occupying 12 MB. The tsx package is 692 KB unpacked, declares 1 direct dependency and no peers, uses the MIT license, and requires Node 18 or newer. npm audit found 0 known vulnerabilities. It is ESM with an exports map; require and ESM import both worked. Our package scan found no TypeScript types.

No credential or tsx-specific config file is required. tsx reads the project's tsconfig for path aliases and relevant compiler settings, while package.json type and file extensions still tell Node whether a module is ESM or CommonJS. Put Node flags before the entry file and application arguments after it. Keep tsc --noEmit in CI because a successful tsx run proves only that the executed path could be transformed.

Version 4 watch mode follows imported files and skips node_modules, vendor, dist, and hidden directories by default. Use --include for non-imported config or data and --exclude for generated files that would create restart loops. Each restart replaces the child process, so servers and workers need signal handlers that close sockets, database pools, and temporary resources promptly.

Our browser bundle attempt failed in esbuild, as expected for a Node execution hook. Programmatic registration can affect every later import or require in the process; call its unregister function or use a namespaced tsImport and require helper for narrow scope. CommonJS transformation cannot support top-level await, and dynamic import from a CommonJS-loaded file needs the ESM hook instead.

Patterns

Execute a TypeScript command directly run-typescript-file

npx tsx src/index.ts --port 3000

Flags after src/index.ts belong to the application. Put Node runtime flags before that entry path.

Run development and type checks separately add-package-script

{"scripts":{"dev":"tsx watch src/server.ts","check":"tsc --noEmit"}}

The dev command transforms and executes. The check command is what reports invalid TypeScript types.

Restart when an imported module changes watch-import-graph

npx tsx watch --clear-screen=false src/worker.ts

tsx restarts the child process. Close open connections on signals and exclude generated files that would trigger a loop.

Execute TypeScript with Node's test runner run-node-tests

npx tsx --test "test/**/*.test.ts"

The quoted glob reaches the Node test runner instead of being expanded differently by each user's shell.

Apply Node options before the entry point pass-node-flags

npx tsx --env-file=.env --trace-warnings src/index.ts

Node options must precede src/index.ts. A flag after it is passed to the script instead.

Evaluate a typed expression from the shell evaluate-expression

npx tsx -e "const n: number = 4; console.log(n ** 2)"

Evaluation removes the annotation and runs the JavaScript. It does not reject a wrong annotation.

Attach tsx through Node's import hook import-tsx-loader

node --import tsx ./src/index.ts

Current Node uses --import for this hook. Avoid copying older --loader examples into a new setup.

Load one TypeScript module with local scope register-scoped-import

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

const module = await tsImport('./tool.ts', import.meta.url)

tsImport transforms this request without registering TypeScript handling for every later ESM import in the process.

Include config changes and ignore generated data watch-extra-files

npx tsx watch \
  --include "config/*.json" \
  --exclude "data/generated/**/*" \
  src/server.ts

Imported source files are watched automatically. --include adds outside dependencies, while --exclude prevents unwanted restarts.

Run an executable TypeScript script typescript-shell-script

#!/usr/bin/env -S npx tsx

const name: string = process.argv[2] ?? 'world'
console.log(`hello ${name}`)

Make the file executable on POSIX systems. env -S is needed because the shebang passes npx and tsx as separate arguments.

Enable and then remove the ESM hook register-esm-temporarily

import { register } from 'tsx/esm/api'

const unregister = register()
try {
  await import('./task.ts')
} finally {
  unregister()
}

This registration changes later ESM loads process-wide until unregister runs. A namespace is safer when only one importer needs it.

Load one TypeScript file from CommonJS require-typescript-from-cjs

const tsx = require('tsx/cjs/api')

const loaded = tsx.require('./file.ts', __filename)
const resolved = tsx.require.resolve('./file.ts', __filename)

Pass the current filename so relative resolution has context. CommonJS transformation does not support top-level await or enhance dynamic import calls.

Alternatives

PackageRegistryPick it when
ts-nodenpmChoose it when TypeScript compiler integration and optional type checking matter more than esbuild transformation speed.
jitinpmChoose it for loading configuration files with mixed module syntax and runtime interop.
vite-nodenpmChoose it inside Vite-based tools that need Vite plugins, transforms, and module graph behavior.

More cli & tooling guides

commander · chalk · typescript · esbuild · yargs · click · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.