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

@unkindnesses/raven

v0.4.1

Published

<p align="center"> <img width="400px" src=".github/logo.png"/> </p>

Downloads

219

Readme

Raven is the next web-native language. It combines the flexibility of a scripting tool with the ambition of a systems one. It plays well with JavaScript (or TypeScript) and mitigates its weaknesses with proper data types, modern syntax and a helpful compiler. And it inherits the great strengths of the web platform, running everywhere with painless sandboxing – whether you want to build interactive browser experiences, deploy serverless cloud functions, or safely execute code written by LLMs.

Start with the language tour for a feel, then visit the docs to get running on your machine. I recommend a browse of the standard library to see how Raven looks in practice. For example, our complex numbers or malloc.

Some features. Raven is concise, high-level and easy to read. It supports gradual type annotations, but without them code is fully type-inferred for both performance and correctness. We have real data types and good control over layout and allocations (ints, bytes etc – defined in the standard library!). Compound types are values first, with multi-dispatch and pattern matching. What we don't have is function colouring: any code can suspend without complications. JS objects and interop are first class, so Raven can interact with the DOM or other JS interfaces without glue. The compiler is fully incremental, for fast builds, editor tooling and live REPL/notebook experiences. Errors come with reasonable stack traces and debugger support.

Some flaws. It's early days and if you try Raven out you're beta testing. Expect bugs! There are lots of things we're ambitious about but still working on. Currently we only compile one file at a time, for example. Modules, packages and seperate compilation are on the roadmap. Editor tooling is basic for now (mostly syntax highlighting). The standard library is sparse and missing core data structures, like hash maps. Interfaces will change and break.

But we think it's fun all the same.

You can get going quickly with npm i -g @unkindnesses/raven. Then you can launch a repl:

$ raven
> 2+2
4

Or run a hello world program:

$ cat hello.rv
println("Cacaw, World!")
$ raven hello.rv
Cacaw, World!

You can explicitly compile and run a wasm binary. fib.rv:

fn fib(n) { fib(n-1) + fib(n-2) }
fn fib(1) { 1 }
fn fib(0) { 0 }

fn fibSequence(n) {
  xs = []
  for i = range(1, n) {
    append(&xs, fib(i))
  }
  return xs
}

show fibSequence(10)
$ raven build fib.rv
$ raven fib.wasm
fibSequence(10) = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

It may entertain you to create a self-contained JS file (with the shebang and permissions needed to run like a binary).

$ raven build --js --embed hello.rv -o hello
$ ./hello
Cacaw, World!

Here's a brainfuck interpreter:

bundle Instr {
  Left(), Right()
  Inc(), Dec()
  Read(), Write()
  Loop(body: List)
}

fn parse(code) {
  stack = []
  body = []
  for ch = code {
    if ch == "<" {
      append(&body, Left())
    } else if ch == ">" {
      append(&body, Right())
    } else if ch == "+" {
      append(&body, Inc())
    } else if ch == "-" {
      append(&body, Dec())
    } else if ch == "," {
      append(&body, Read())
    } else if ch == "." {
      append(&body, Write())
    } else if ch == "[" {
      append(&stack, body)
      body = []
    } else if ch == "]" {
      loop = Loop(body)
      body = pop(&stack)
      append(&body, loop)
    }
  }
  return body
}

bundle Tape(data: List, i: Int64)

fn Tape() { Tape([0], 1) }

fn Tape(xs, i)[] { xs[i] }

fn left(&tape: Tape(xs, i)) {
  i = i - 1
  if i < 1 { abort("Tape error") }
  tape = Tape(xs, i)
}

fn right(&tape: Tape(xs, i)) {
  i = i + 1
  if i > length(xs) { append(&xs, 0) }
  tape = Tape(xs, i)
}

fn inc(&tape: Tape(xs, i)) {
  xs[i] = xs[i]+1
  tape = Tape(xs, i)
}

fn dec(&tape: Tape(xs, i)) {
  xs[i] = xs[i]-1
  tape = Tape(xs, i)
}

fn eval(&tape: Tape, instr: Instr) {
  match instr {
    let Left()  { left(&tape) }
    let Right() { right(&tape) }
    let Inc()   { inc(&tape) }
    let Dec()   { dec(&tape) }
    let Write() { print(js().String.fromCharCode(tape[])) }
    let Loop(body) {
      while tape[] != 0 {
        interpret(&tape, body)
      }
    }
  }
  return
}

fn interpret(&tape: Tape, code) {
  for instr = code {
    eval(&tape, instr)
  }
  return tape
}

fn interpret(code) {
  interpret(Tape(), code)
}

{
  code = parse(readFile(args()[3]))
  interpret(code)
}
$ raven build --js --embed brainfuck.rv -o bf
$ cat hello.bf
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
$ ./bf hello.bf
Hello World!

Architecture

flowchart TD
  CLI["CLI (`raven build`)"] --> PARSE["Parsing (frontend/parse.ts, middle/load.ts)"]
  SRC["Raven source (.rv)"] --> PARSE

  PARSE --> LOWER["AST -> MIR lowering (frontend/lower.ts)"]

  LOWER --> INTERP["Interpret + method matching (middle/tracer.ts, middle/patterns.ts)"]
  INTERP --> INFER["Type inference (middle/abstract.ts)"]
  INFER --> EXPAND["Expansion (middle/expand.ts)"]
  EXPAND --> INLINE["Inlining (middle/inline.ts)"]
  INLINE --> RC["Refcounting (middle/refcount.ts)"]
  RC --> WASMIR["WASM lowering (backend/wasm.ts)"]
  WASMIR --> EMIT["Emitter (backend/compiler.ts)"]

  EMIT --> BIN["WASM binary (.wasm)"]
  EMIT --> JS["Optional JS wrapper (compileJS)"]