tovv0.0.1 experimental
Sing along to the Tov song

Faster than Rust. Written like TypeScript.

A programming language for coding agents. Your agent already writes TypeScript, so it can already write Tov, and when it gets something wrong the compiler hands back the edit that fixes it. What it ships is a native binary that beats Rust's.

Star on GitHub Follow @runtov
$ curl -fsSL https://tov.run/install.sh | sh

Requests a second, a JSON API on one core

  • Tov242k/sfastest
  • Rust (axum)216k/s12% slower
  • Bun111k/s2.2× slower

fetch(), 64 requests at once

  • Tov177k/sfastest
  • Rust (reqwest)162k/s9% slower
  • Bun129k/s37% slower
  • Node30k/s5.8× slower

binary_trees: millions of small objects made and freed

  • Tov260 msfastest
  • Bun376 ms45% slower
  • Node449 ms1.7× slower
  • C688 ms2.6× slower
  • Rust791 ms3.0× slower

Compiling a program to a native binary

  • Tov42 msfastest
  • C (clang)49 ms17% slower
  • Rust (rustc)98 ms2.3× slower

Memory, serving that JSON API

  • Tov1.6 MBleast
  • Rust (axum)4.4 MB2.8× more
  • Bun17 MB10.4× more

What happens when Tov builds a program

Tov is a compiler. It checks the TypeScript your agent wrote, writes it out as C and hands that to clang, so what you ship is one native binary with nothing to install next to it.

Your agent writes TypeScript

Tov reads TypeScript's syntax and types, with int and f64 for numbers, and Bun's and Node's APIs. It leaves out what makes a program hard to follow: any, null and ==.

type Shape =
  | { kind: "circle", r: f64 }
  | { kind: "rect", w: f64, h: f64 }

function area(s: Shape): f64 {
  switch (s.kind) {
    case "circle":
      return Math.PI * s.r * s.r
    case "rect":
      return s.w * s.h
  }
}

Tov checks every line

The checker, written in Rust, catches what TypeScript lets through: a call that can fail without try, a value shared where it should be copied, a switch that misses a case. Each error has a code and, where the fix is clear, the edit that makes it, which tov check --json hands to your agent.

// without the "rect" case
$ tov check shapes.tov
error[F0301] shapes.tov:6:11: `switch` is not
  exhaustive: missing "rect"
    6 |   switch (s.kind) {
  fix: add case "rect"

It writes the program as C

The whole program becomes one C file. Records become structs and a union becomes a tagged union, so switch (s.kind) is a switch on an integer. Values are reference-counted, with the counting written into the C, so there's no garbage collector to pause the program.

struct Shape {
    uint32_t tag;
    union { Circle m0; Rect m1; } u;
};

static double area(Shape s) {
    switch (s.tag) {
    case 0: return 3.141592653589793 * s.u.m0.r * s.u.m0.r;
    case 1: return s.u.m1.w * s.u.m1.h;
    }
}

clang makes one binary

clang compiles that C with Tov's runtime, a C library with the event loop, the HTTP server and client, and Tov's strings, arrays and maps. The runtime is compiled once and cached, so most of a build is clang's. A program that imports an npm package also carries the package and JavaScriptCore, the engine Bun uses, to run it.

$ tov build shapes.tov --time
check 0.3 ms, generate 0.2 ms, C compile 55 ms
build: shapes
$ ls -lh shapes
34K shapes
$ ./shapes
circle: 3.14
rect: 6.00

How an agent writes Tov

1Your agent writes TypeScript

// hello.tov
Bun.serve({
  port: 3000,
  fetch(req) {
    const url = new URL(req.url)
    return new Response(`Hello from ${url.pathname}`)
  },
})

2Tov hands back the fix

$ tov check --json
{
  "code": "T0831",
  "message": "`new URL` can throw `TypeError`; mark the call `try` to pass the error on, or catch it",
  "fixes": [{
    "applicability": "safe",
    "edits": [{ "line": 4, "col": 17, "text": "try " }]
  }]
}

3You ship a native binary

// the agent applies the fix
const url = try new URL(req.url)

$ tov build hello.tov
build: hello
$ ls -lh hello
152K hello
$ ./hello & curl :3000/agents
Hello from /agents

It's TypeScript

With the APIs your agent knows from Bun and Node. Bun.serve, fetch, node:fs, async/await and npm packages work as it expects.

Less to get wrong

There's no any, null or ==, and a call that can fail is marked try. If code looks like TypeScript it behaves like TypeScript, and if it can't, it doesn't compile.

A 42 ms compile

--watch restarts the program on save, and tov test runs the tests that sit next to the code.

Against Rust, C, Bun and Node

Tov compiles to C and counts references instead of collecting garbage, so there are no collector pauses and the binaries stay small.

3.0× faster than Rustbinary_trees: millions of small objects

  • Tov260 ms
  • Bun376 ms
  • Node449 ms
  • C688 ms
  • Rust791 ms

Shorter is better.

1.6× faster than Rustsort: 3M floats, with a comparator

  • Tov45 ms
  • Rust74 ms
  • C275 ms
  • Bun696 ms
  • Node1175 ms

Shorter is better.

1.7× faster than Rustmap_insert: 2M string keys

  • Tov284 ms
  • C476 ms
  • Rust490 ms
  • Bun823 ms
  • Node1178 ms

Shorter is better.

2.1× faster than Rustdispatch: 50M virtual calls

  • Tov36 ms
  • C76 ms
  • Rust77 ms
  • Bun109 ms
  • Node191 ms

Shorter is better.

1.6× faster than Ruststrings: format, join, split

  • Tov143 ms
  • Bun203 ms
  • Rust224 ms
  • C253 ms
  • Node519 ms

Shorter is better.

7% faster than Rustfib: recursive calls, overflow-checked

  • Tov416 ms
  • Rust444 ms
  • C490 ms
  • Bun942 ms
  • Node1485 ms

Shorter is better.

7% faster than Rustnbody: floating point

  • Tov210 ms
  • Rust224 ms
  • C312 ms
  • Bun512 ms
  • Node554 ms

Shorter is better.

12% faster than Rustweb server: JSON API, one core

  • Tov242k req/s
  • Rust216k req/s
  • Bun111k req/s

Longer is better.

2.8× less than Rustserver memory: serving that API

  • Tov1.6 MB
  • Rust4.4 MB
  • Bun16.6 MB

Shorter is better.

9% faster than Rustfetch(): 64 requests at once

  • Tov177k req/s
  • Rust162k req/s
  • Bun129k req/s
  • Node30k req/s

Longer is better.

2.3× faster than Rustcompile: a program to a binary

  • Tov42 ms
  • C49 ms
  • Rust98 ms

Shorter is better.

10.5× smaller than Rustbinary size: a program, stripped

  • Tov33 KB
  • C33 KB
  • Rust351 KB

Shorter is better.

Measured on an Apple M4 Max, and each program prints the same output in every language. Tov checks integer overflow by default; Rust's release builds don't. Method and every result.

Trying Tov on Cap

Cap is our open-source screen recorder. We've tried two parts of its video pipeline on Tov: a new encoder written in Tov, and the media server Cap already has, compiled by Tov as it is. Neither runs in Cap's production yet.

A screen encoder, written in Tov

Every Cap recording ends up as H.264 video. We wrote an encoder for it in Tov, tuned for what's on a screen, and compared it with x264 at the same picture quality. The encoder is on GitHub.

5.2×faster than x264, on average

  • Idle screen8.1×
  • Code, 4K8.0×
  • Busy UI, 60 fps7.2×
  • Slow typing6.9×
  • Busy UI6.5×
  • Dark mode6.5×
  • Code editor6.5×
  • Slides4.6×
  • Scrolling text4.4×
  • Webcam overlay4.2×
  • Dashboard3.5×
  • Full-motion video1.5×
46 MB
of memory at its peak (x264: 377)
561 KB
the whole encoder (x264: 1.3 MB)

12 screen recordings at 1080p, on one thread, against x264's veryfast preset. Every result.

The media server, unchanged

Cap's media server is a Bun app (Hono, zod and FFmpeg) that probes uploaded videos and pulls out their audio. Tov runs it without changing a line; the file below is the whole port. Cap still serves it with Bun.

// main.tov
import server from "cap-media-server"
import { serve } from "bun"

function main() {
  try serve(server)
}
  • 105 msto start (Bun: 120)
  • 27% lessCPU for each video it reads
  • 129 MBof memory at its peak under load (Bun: 143)

Against Bun 1.4 on an Apple M4 Max. Method and every result.

Start with your agent

Paste this into your agent. It installs Tov, reads llms.txt, and from then on checks its own work with tov check --json.

Use Tov (https://tov.run) for this: a programming language with TypeScript's syntax that compiles to native binaries faster than Rust's.

1. Install it: curl -fsSL https://tov.run/install.sh | sh
2. Read https://tov.run/llms.txt. Tov is TypeScript without a few things (no any, null or ==; int and f64 are separate types; a call that can fail is marked try).
3. Write .tov files. After every edit, run `tov check --json <files>` and apply each fix marked "safe".
4. Run with `tov run main.tov`; ship with `tov build main.tov -o app`, one binary.

What works today

Works

  • Command-line programs and web servers
  • Records, unions, generics, classes, interfaces and checked errors
  • async/await, timers, fetch() over HTTP and HTTPS
  • Bun's server API and a Node-style standard library
  • npm packages, including native addons
  • macOS and Linux

Not yet

  • Windows
  • A package manager of its own (install with npm or Bun)
  • TLS sockets and worker threads for npm packages
  • Tuples, enums and a few other TypeScript features (see the spec)

$TOV · ticker

$TOV pays for the builds

The compiler is free and stays free: install it, read the spec and ship binaries without a card. What costs money is the compute around it — hosted builds, the shared runtime cache and the credit an agent needs while it checks its own work. All of it is priced in $TOV. $TOV launches on Solana, and the contract address lands here on launch day.

What $TOV is for

Hosted builds

Push a .tov file and get a native binary back. Tov checks it, writes the C and runs clang; the second that takes is metered in $TOV.

The runtime cache

Tov's runtime is compiled once and shared. Publish a build and earn $TOV every time somebody else's build reuses the C it already paid for.

Agent credit

An agent that runs tov check --json after every edit spends credit. The pool behind that credit is funded in $TOV, so an agent can work without a card of its own.

The builders' fund

A slice of every fee buys $TOV for the treasury, and the treasury pays for the benchmarks, the spec and the runtime.

No subscription and no seat: every paid thing here is one build or one top-up, bought with $TOV.

What it buys

  • Hosted buildsTov runs the toolchain; you download one binarypaid in $TOV
  • Priority queueYour build goes to the front when the runners are fullpaid in $TOV
  • Agent creditTop up an agent that checks its own workpaid in $TOV
  • The compiler, the spec, llms.txtOpen source — no card, no token neededfree forever
$TOV contract addressLaunching on Solana — soon
Launching on Solana soon — the address lands in this slot

$TOV is a Solana SPL token and it pays for compute on this project — hosted builds, the shared cache, agent credit. That is the whole of it, and it is not a promise of anything else.