Use when running TypeScript directly on Node.js without a build step — native type stripping, its limits, or when to reach for tsx. Not for Bun (ts-runtime-bun).
Scanned 9/6/2026
Install to Claude Code
npx -y skills add fusengine/agents --skill ts-runtime-node --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Ts Runtime Node?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/fusengine-ts-runtime-node)More formats (shields.io, HTML) on the badges page.
---
name: ts-runtime-node
description: Use when running TypeScript directly on Node.js without a build step — native type stripping, its limits, or when to reach for tsx. Not for Bun (ts-runtime-bun).
versions:
node: "24 LTS"
typescript: "5.8+ (latest stable 6.0)"
tsx: "4.x"
references: references/type-stripping.md, references/tsx-when-needed.md, references/node24-features.md, references/templates/node-esm-setup.md
related-skills: ts-runtime-bun, ts-lint-format, solid-generic
---
<objective>
This skill covers running .ts/.mts/.cts files directly on Node 24 LTS via native type
stripping: what erases cleanly versus what throws ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX (enum,
namespace with runtime code, parameter properties, import aliases), why tsconfig.json
paths/downleveling are ignored at runtime, and mandatory explicit file extensions and import
type usage.
It also covers when native stripping is insufficient and a full loader (tsx) is needed —
paths, decorators, enum, or .tsx — plus setting up an ESM-only Node project, --watch mode,
and node:test, and migrating a script/CLI off ts-node.
Out of scope: Bun runtime specifics belong to ts-runtime-bun; tsconfig configuration details
belong to ts-config.
</objective>
# TypeScript on Node.js
## Agent Workflow (MANDATORY)
Before ANY implementation, spawn 3 agents in parallel, one `Agent` call each with a `name`:
1. **fuse-ai-pilot:explore-codebase** - Inspect existing `package.json`, `tsconfig.json`, entry scripts
2. **fuse-ai-pilot:research-expert** - Verify latest Node LTS + type-stripping behavior via Context7/Exa
3. **mcp__context7__query-docs** - Check Node `Modules: TypeScript` and CLI flag docs
After implementation, run **fuse-ai-pilot:sniper** for validation.
## Use when
- Running `.ts`/`.mts`/`.cts` files directly with `node file.ts` (no bundler)
- Deciding between native **type stripping** and a full loader (`tsx`)
- Setting up an ESM-only Node project, `--watch` mode, or `node:test`
- Migrating a script/CLI/hook off `ts-node` to Node's built-in support
## Do NOT use for
- Bun runtime or `bun test` → use [ts-runtime-bun](../ts-runtime-bun/SKILL.md)
- Linting / formatting choices → use [ts-lint-format](../ts-lint-format/SKILL.md)
- Framework runtimes (Next.js, Astro) that own their own transpile pipeline
- Browser/bundled output → use a bundler skill
## Critical Rules
1. **Type stripping is erase-only** - Node replaces types with whitespace and does NO type checking. Run `tsc --noEmit` separately for safety.
2. **`tsconfig.json` is ignored at runtime** - `paths`, downleveling, and JS target lowering do not apply. Native stripping only erases inline types.
3. **Non-erasable syntax errors out** - `enum`, `namespace` with runtime code, parameter properties, and import aliases throw `ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX`.
4. **Use `import type` / `verbatimModuleSyntax`** - Value imports of types crash at runtime; the `type` keyword is mandatory for type-only imports.
5. **File extensions are mandatory** - `import './file.ts'`, not `./file`. `.tsx` is unsupported by native stripping.
## Architecture
```
project/
├── package.json # "type": "module"
├── tsconfig.json # noEmit, erasableSyntaxOnly, verbatimModuleSyntax
├── src/
│ ├── index.ts # node src/index.ts
│ └── interfaces/ # type-only modules (import type)
└── test/
└── unit.test.ts # node --test (node:test)
```
→ See [node-esm-setup.md](references/templates/node-esm-setup.md) for a complete setup
## Reference Guide
### Concepts
| Topic | Reference | When to Consult |
|-------|-----------|-----------------|
| **Type Stripping** | [type-stripping.md](references/type-stripping.md) | Running `.ts` natively, understanding what erases and what errors |
| **When tsx** | [tsx-when-needed.md](references/tsx-when-needed.md) | Native stripping is insufficient (paths, enums, decorators, `.tsx`) |
| **Node 24 features** | [references/node24-features.md](references/node24-features.md) | Watch mode, `node:test`, ESM resolution, relevant built-ins |
### Templates
| Template | When to Use |
|----------|-------------|
| [node-esm-setup.md](references/templates/node-esm-setup.md) | Starting an ESM Node + native TS project |
## Best Practices
### DO
- Set `"type": "module"` and use `.ts`/`.mts` with explicit import extensions
- Keep `tsc --noEmit` in CI for real type safety alongside runtime stripping
- Reach for `tsx` the moment you need `paths`, decorators, `enum`, or `.tsx`
### DON'T
- Assume `tsconfig` `paths` or `target` downleveling work at runtime — they don't
- Publish `.ts` files inside `node_modules` — Node refuses to strip them
- Rely on native stripping for decorators (TC39 Stage 3, not transformed)
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!