Generate TypeScript bindings from annotated Python source and call numpy, pandas, torch, and scipy from Node, Bun, Deno, or the browser. The types come from the Python code itself.
Copy this into your coding agent to get started in one shot:
View full documentationCall the scientific stack from TypeScript
numpy, pandas, scipy, torch, and sklearn results arrive typed, over Apache Arrow with JSON fallback.
Generate, don’t hand-write
npx tywrap generate reads annotated Python source and emits TypeScript wrappers with real signatures.
Same wrapper, four runtimes
Node, Bun, and Deno subprocess bridges, Pyodide in the browser, or a remote HTTP server.
A boundary that won’t lie
Values that can’t be preserved fail loudly with a named error and a recipe, never a silently wrong result.
npm install tywrap
pip install tywrap-ir # Python component for code generation
npx tywrap init
npx tywrap generatetywrap and tywrap-ir are versioned independently. Install the latest published release of each package unless you need to pin them explicitly.
import { NodeBridge } from 'tywrap/node';
import { setRuntimeBridge } from 'tywrap/runtime';
import * as math from './generated/math.generated.js';
setRuntimeBridge(new NodeBridge({ pythonPath: 'python3' }));
const result = await math.sqrt(16); // 4, typed from the Python annotationimport { startNodeWatchSession } from 'tywrap/dev';
import { NodeBridge } from 'tywrap/node';
const session = await startNodeWatchSession({
configFile: './tywrap.config.ts',
createBridge: async config =>
new NodeBridge({
pythonPath: config.runtime.node?.pythonPath ?? 'python3',
timeoutMs: config.runtime.node?.timeout ?? 30000,
}),
});Use reloadNow() for an explicit rebuild or close() to stop watching. Node gets full hot reload, Pyodide gets manual bridge replacement through createBridgeReloader(...), and HTTP reload remains external to tywrap.
Experimental: APIs may change before v1.0.0. See Releases for breaking changes.
If tywrap saves you time, a ⭐ on GitHub helps others find it.