jiti
A zero-dependency runtime that transpiles TypeScript and ESM on the fly so Node.js can require() or import them directly.
Repository Health
Technical Analysis
jiti is a runtime for Node.js that gives seamless TypeScript and ESM support without a separate build step. It intercepts require() and import() calls, detects when a file needs transforming (TypeScript, JSX, or mismatched CJS/ESM syntax), transpiles it with a lazily-loaded Babel pipeline, caches the result to disk, and hands back a fully interoperable module — smart syntax detection means untouched JavaScript files pass straight through with no added cost.
It ships as a genuinely zero-dependency package: every dependency it needs at runtime, including Babel itself, is pre-bundled into the published lib/ output, keeping install size small and avoiding version drift in consuming projects. It is used as an internal loader by a large slice of the JavaScript ecosystem — Nuxt, Tailwind CSS, ESLint, Docusaurus, Histoire, Nitro, and dozens of other tools depend on jiti to load user config files and scripts written in TypeScript — and it is also usable standalone via npx jiti ./file.ts or as a global ESM loader through node --import jiti/register.
What You Get
- Async
import()and syncrequire()replacements -jiti.import()and the callablejiti()instance load TypeScript/ESM/CJS files interchangeably, matching Node’s native APIs. - Smart syntax detection - files that don’t need transforming (plain JS) are passed straight through, avoiding unnecessary Babel overhead on hot paths.
- Filesystem transpile cache - transformed output is written to
node_modules/.cache/jiti(or a temp dir) with etag-based invalidation, so repeated runs skip re-transpiling unchanged files. - Global ESM loader registration -
import "jiti/register"ornode --import jiti/registerhooks into Node’s module loader so the whole process gains TS/ESM support. - CLI runner -
npx jiti ./script.tsexecutes a TypeScript file directly with no project setup. - Configurable resolution - custom alias maps,
tsconfig.jsonpathsresolution, and control over whichnode_modulespackages are transformed vs. left native.
Common Use Cases
- Loading TypeScript config files at runtime - tools like Nuxt, Tailwind, and ESLint use jiti internally to
require()a user’snuxt.config.tsortailwind.config.tswithout a pre-build. - Running TypeScript scripts without a build step -
npx jiti ./script.tsfor one-off scripts, codemods, or CI tasks. - Building CLI tools that accept user-authored TS plugins - a CLI can
jiti.import()a user’s.tsplugin file and get back a normal module. - Bridging CJS and ESM in mixed codebases - jiti’s
interopDefaultproxy smooths overdefaultexport mismatches between require() and import() semantics. - Global process-wide TS/ESM support - registering
jiti/registeras a Node loader so an entire process canimport/requireTypeScript without per-call wrapping.
Under The Hood
Architecture
The package is organized as a small set of single-purpose modules under src/ (roughly 1,300 lines total, per the project’s own AGENTS.md): jiti.ts is the createJiti() factory that wires shared context (options, aliases, native-require handles) and returns the callable jiti instance; require.ts implements the synchronous require-replacement path, branching on protocol prefixes (node:, file:, data:), builtin modules, virtual modules, and an experimental Bun “try-native-first” fast path before falling through to resolution and evaluation; resolve.ts handles module resolution with alias and tsconfig-paths support; eval.ts evaluates transformed source for both sync and async contexts; transform.ts and babel.ts orchestrate a lazily-loaded Babel pipeline (only pulled in when a file actually needs transforming); and cache.ts manages the etag-keyed filesystem transpile cache. The design deliberately keeps a shared Context object threaded through every function rather than using global state, which is what lets a single process host multiple independently-configured jiti instances.
Tech Stack
Written in TypeScript, built with rspack (primary) or rolldown as an alternative bundler, and published as dual ESM/CJS output (lib/jiti.mjs / lib/jiti.cjs) plus a CLI entry (lib/jiti-cli.mjs). The published package has zero runtime dependencies — everything it needs, including a full Babel toolchain (@babel/core, @babel/plugin-transform-typescript, @babel/plugin-transform-react-jsx, decorator and explicit-resource-management plugins, etc.), plus small utilities like mlly, pathe, get-tsconfig, and yoctocolors, is bundled into the lib/ output at build time rather than left as installable dependencies. Tests run under Vitest with coverage, plus separate native-mode suites for Bun, Deno, and Node’s own --experimental-strip-types.
Code Quality
The project has an extensive test suite: dozens of fixture directories under test/fixtures (TypeScript, JSX, ESM, CJS interop, tsconfig-paths, import maps, top-level-await, explicit-resource-management, and more) drive snapshot-style fixture tests, alongside dedicated suites for the CLI, the global register hook, virtual modules, and native-runtime parity across Bun/Deno/Node. Error handling favors explicit checks and descriptive thrown errors (e.g. rejecting data: URLs in sync context) over silent fallbacks. CI runs lint (ESLint + Prettier), a type-check pass (tsgo --noEmit), and the full multi-runtime test matrix on every change, and the repo has both AGENTS.md and CLAUDE.md files documenting its own architecture for maintainers.
What Makes It Unique jiti’s niche is being the de facto shared implementation for “let this tool load a TypeScript config/plugin file without a build step” — rather than every framework reinventing its own ad-hoc TS-loading shim, a large share of the JavaScript tooling ecosystem (Nuxt, Tailwind, ESLint, Docusaurus, Nitro, Histoire, and others) depends on jiti directly for this. Its smart syntax detection (skipping transformation for files that are already valid JS) and its filesystem cache give it a performance profile suited to being invoked on every process start, which is a harder constraint than a one-time build-time transpiler faces.
Used by 17 apps in this directory
ChartBrew
Analytics · Databases
Open-source reporting platform to build live dashboards from SQL, NoSQL, APIs, and SaaS tools with an AI assistant that creates charts from natural language.
Cline
AI Code Assistants
An open-source AI coding agent that lives in your editor and terminal — reads and edits your codebase, runs commands, browses the web, and requires human approval for every action by default.
Formbricks
Forms Surveys · Marketing · Analytics
Open-source experience management platform for in-app, website, email, and link surveys — privacy-first and fully self-hostable.
Gitea
Devops · Developer Tools · Project Management
Self-hosted DevOps in a single Go binary — Git hosting, GitHub Actions-compatible CI/CD, and 30+ package registries without any SaaS dependency.
Hanko
Security · Authentication
Open source, self-hostable authentication platform with passkeys, SAML SSO, and OAuth — the privacy-first alternative to Auth0 and Clerk.
Kan
Project Management
An open-source, self-hostable Kanban board built as a modern Trello alternative with team workspaces, board permissions, and Trello import.
Mattermost
Team Chat · Collaboration · Devops
Open core, self-hosted team collaboration with chat, AI agents, voice calling, and deep DevOps integrations — all under your control.
MaxKB
AI Development · Knowledge Management
Build enterprise-grade AI agents with RAG, workflows & multi-modal support
OnetimeSecret
Security
Generate self-destructing single-use links to share passwords and sensitive data without leaving traces in inboxes or chat logs.