npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

r2pipe-ts

v0.4.0

Published

TypeScript r2pipe API

Readme

r2pipe API for radare2

r2pipe logo

This is a reimplementation in TypeScript of the original r2pipe and r2pipe-promise modules for NodeJS.

Usage

If you are using r2skel (r2pm -ci r2skel) you can get a hello world to use this module with the following line:

r2pm -r r2skel r2-script-r2pipe-ts hello-ts
make -C hello-ts

Basics

The basic fundamentals of r2pipe is that you the API provides the most basic communication channel with r2, this is a single function called cmd that takes the command to be executed and returns the output of the command as a string.

Many commands in r2 return JSON. cmdj<T>() parses that output, with an optional result type. Its default result type is unknown; specifying T describes the expected result without validating it.

import { open } from "r2pipe-ts";

const r2 = open("/bin/ls");
const flags = await r2.cmdj<Array<{ name: string; addr: number | bigint }>>("fj");
await r2.quit();

Integer JSON literals outside JavaScript's safe integer range are returned as bigint, preserving 64-bit addresses exactly. Safe integers, fractions, and numbers written with an exponent remain JavaScript numbers. JSON strings, booleans, arrays, and null keep their usual meanings. Use String(value) to display a bigint; native JSON.stringify requires a replacer for bigint values.

To retain native JSON.parse behavior, or use another parser, pass jsonParser when opening any backend:

const r2 = open("http://localhost:9090", { jsonParser: JSON.parse });

The package also exports R2PipeCmdInterface, R2PipeOptions, R2PipeWasmOptions, and JsonParser types and the default parseJson function.

In order to provide compatibility with all kind of backends, the whole api has been made asynchronous, this allows the developer to change the backend by only changing one line.

The spawn backend consumes radare2's stderr so diagnostics cannot block command processing. Its quit(timeoutMs = 5000) rejects pending commands, sends SIGINT and waits for the child process and its stdio to close before resolving true. If the child is still running after that grace period, it sends SIGKILL and waits up to five more seconds for closure. A signaling failure or failure to confirm closure rejects the promise; the same instance retains the child so quit() can be retried. Commands remain closed after shutdown starts. Concurrent calls share the first pending shutdown attempt and its grace period. A later call after closure resolves immediately. The optional timeout is a nonnegative integer in milliseconds, at most 2147483647; other backends do not use it. This shuts down the directly spawned child, without claiming to terminate detached descendants.

Supported r2pipe methods

  • http (command text is URL-encoded; radare2 versions that emit LF-only HTTP response headers require Node's --insecure-http-parser flag)
  • spawn (launch a new radare2 process and communicate with it sending async commands to collect the response)
  • local (the local pipe is used when launching scripts from r2 -i too.ts or > . too.ts
  • wasm (opt-in WASI API backend, running an isolated radare2 instance without a native process)

Optional WASM backend

Set wasm.path to a local radare2.wasm from a wasi-api archive on the radare2 releases page. These are reactor builds exporting the C API; the CLI and browser archives are different builds. The r2wasm project provides browser components.

import { open } from "r2pipe-ts";

const r2 = open("malloc://64", { wasm: { path: "./radare2.wasm" } });
try {
  await r2.cmd("wx 9090c3");
  console.log(await r2.cmd("p8 3"));
} finally {
  await r2.quit();
}

open() keeps its synchronous interface. The first command reads and instantiates the selected module, initializes WASI, and creates a core with r_core_new(). Commands call r_core_cmd_str() to capture their output; command buffers and returned strings are freed after each call. Commands are serialized, and quit() waits for accepted commands before freeing the core. An empty target creates a core without opening a file. cmdj() and jsonParser work as with the other backends.

The feature is disabled unless wasm is supplied. Loading the package and using other backends requires neither WebAssembly nor WASI. The WASM backend loads node:wasi only on its first command and requires a runtime providing WebAssembly and Node's WASI preview1 API. It downloads nothing automatically and adds no runtime dependencies.

No host directories or environment variables are exposed by default. For host files, explicitly map a directory and use the guest path as the target:

const r2 = open("/data/program", {
  wasm: { path: "./radare2.wasm", preopens: { "/data": "/absolute/host/directory" } },
});
console.log(await r2.cmdj("ij"));
await r2.quit();

Preopened directories permit file access, including writes through radare2 commands. Node's WASI implementation is not a security boundary for untrusted modules.

Downloading API builds

The separate helper requires Node.js 20+ and unzip. It lists all published releases, marking those without API builds, and downloads only the API archive's radare2.wasm:

cd typescript
node wasm-download.cjs --list
node wasm-download.cjs                       # newest stable release with an API build
node wasm-download.cjs 6.2.0                 # explicit release
node wasm-download.cjs 6.2.0 ./r2-6.2.0.wasm  # explicit output path

npm run wasm -- ... also invokes the helper. Downloads replace the output file only after successful extraction and WASM header validation. Releases without API assets are skipped for latest; explicitly selecting one reports an error.

The 6.2.0 API build has been verified with this backend. The 6.2.2 API build traps inside r_core_new() during initialization in Node.js 24; select 6.2.0 if you encounter that upstream build issue.

r2Frida-Compile

radare2 also supports the esm modules generated by frida-compile. But it is worth to mention that r2frida comes with a C reimplementation of frida-compile (python). Which ships a typescript compiler and is able to pack multiple ts/js files into a single file.

Runtime

This module is suposed to run with NodeJS, under some circunstancies, it may also with with r2js, bun or deno.

Development tools require Node.js 20.19+, 22.13+, or 24+. Use npm ci to install dependencies, npm test to build and test, and npm run lint to lint the TypeScript sources.

WASM tests include a small offline API fixture. To also exercise a released radare2 module, run R2PIPE_WASM=/absolute/path/radare2.wasm npm test.

Author

--pancake <@nopcode.org>

IO address values

IO requests encode unsigned 64-bit addresses as hexadecimal strings. Use parseAddress for those strings or legacy numbers/bigints; it returns an exact bigint and rejects invalid syntax, out-of-range values and already-rounded JavaScript numbers. parseJson continues to preserve JSON strings as strings.

import { parseAddress, parseJson } from "r2pipe-ts";
const offset = parseAddress("0xffffffffffffffff"); // 18446744073709551615n
const legacy = parseAddress(parseJson("9007199254740993") as bigint);