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

@evmcrispr/core

v0.11.0

Published

EVML interpreter and workspace runtime: parse, validate, simulate and execute EVML scripts with any viem wallet

Readme

@evmcrispr/core

EVMcrispr is still in active development and its API might change until it reaches 1.0.

EVMcrispr parses and runs EVML scripts — a DSL for encoding batches of on-chain actions (contract calls, DAO operations, token transfers, deployments) that can be simulated on a fork and then executed with any viem wallet.

Quick start

bun add @evmcrispr/core viem
import { evml } from "@evmcrispr/core";

const script = evml`
  exec ${tokenAddress} transfer(address,uint256) ${recipient} 100e18
`;

const actions = await script.interpret();  // dry run: resolve Action[]
await script.execute(walletClient);        // sign & send with a viem WalletClient

Values interpolated with ${...} are serialized into EVML literals safely: addresses and hex strings splice bare, other strings are quoted and escaped (injection-safe), numbers and bigints (including negatives) become numeric literals, arrays become [a b c], and nested evml fragments compose. Use evml.raw("...") to splice text verbatim.

Modules

Language modules ship as separate packages and are registered with use() — registration makes load <name> work inside scripts; std is always available:

import { evml } from "@evmcrispr/core";
import aragonos from "@evmcrispr/module-aragonos";

evml.use(aragonos); // eager

// or lazy, keeping code-splitting in bundled apps:
evml.use({ name: "aragonos", load: () => import("@evmcrispr/module-aragonos") });

const script = evml`
  load aragonos
  connect mydao (
    exec token-manager mint ${recipient} 100e18
  )
`;

Configuration

Environment config lives on the tag; with() returns a derived tag that shares the module registry:

const gnosisEvml = evml.with({
  account: "0x...",                       // sender account
  chainId: 100,                           // initial chain (default mainnet)
  transports: { 100: http("https://rpc.gnosischain.com") },
  onLog: (message) => console.log(message),
});

await gnosisEvml`print @token(WETH)`.interpret();

Per-run options go on the method instead:

await script.execute(walletClient, {
  signal: abortController.signal,
  maximizeGasLimit: true,
  handlers: { batched: mySafeBatchHandler }, // override any action type
});

Simulation

With @evmcrispr/module-sim registered, simulate() runs the script inside a fork (anvil, hardhat, tenderly or the in-process ethereumjs backend) and never throws on script failure:

import sim from "@evmcrispr/module-sim";
evml.use(sim);

const { success, logs, error } = await script.simulate({ blockNumber: 21000000 });

Editor tooling

evml.workspace() returns a long-lived EvmlWorkspace with the LSP-style surface: getCompletions, getHoverInfo, getSignatureHelp, getDiagnostics, getDocumentSymbols and prewarm. Prewarm is incremental: it checkpoints per command and only re-resolves from the first edited command on each keystroke.

const workspace = evml.with({ transports }).workspace();
await workspace.prewarm(source);
const hover = await workspace.getHoverInfo(source, { line: 2, col: 10 });

Low-level access

Interpreter is the underlying runtime (new Interpreter(evml.registry, config)), exposing interpret, interpretNode, bindingsManager and module accessors — useful for tests and advanced embedding. parseScript(source) returns the raw AST.

Other examples

Contributing

We welcome community contributions!

Please check out our open Issues to get started.