v0.2 · MIT · zero-install CLI

The token-efficient language for AI-authored code.

Tel gives coding agents one compact surface for CLIs, HTTP APIs and browser UIs — Python-style layout, real JavaScript interop, and a 2,193-token guide that fits in context.

$npx @codebam/tel init

  • Interpreter + TS/JS/browser compilers
  • Installed npm packages stay available
  • Machine-checked agent guide
api.tel121 cl100k tokens
import std.http as http

type User = {id: Num, name: Str}

fn route(req):
  match req.path:
    "/api/users": [User(id=1, name="ada")]
    "/api/sum":
      n = int(req.query.n ?? "0")
      {sum: (1..=n).sum()}
    _: http.res(404, {error: "not found"})

async fn main():
  server = await http.serve(int(env.get("PORT", "0")), route)
  print("listening on :{server.port}")
  server
2,193
tokens in the agent guide
budgeted at 2,200 · contract-tested
-28.9%
cl100k tokens vs TypeScript
540 vs 759 across six equivalent programs
3
ways to run Tel
tree-walk interpreter · typed ESM · browser bundle
0
npm dependencies
one command: npx @codebam/tel

Why Tel

Less ceremony. More context.

Tel is designed for the way agents actually write code: a tiny guide, dense but explicit syntax, and a standard library that removes boilerplate.

01

Small enough to stay in context

The whole onboarding surface is one 2,193-token AGENTS.md. Every fenced snippet in it executes in CI, so stale examples cannot survive.

02

Token-lean syntax

Python-style layout, ambient bindings, underscore placeholders, pipelines and pattern matching remove ceremony without hiding the shape of the program.

03

JavaScript and npm interop

Import npm packages and Node builtins, use native prototypes, pass Tel lambdas as JS arrows and await promises — under run, --target js and --target ts.

04

One language, three targets

Run it with the tree-walk interpreter, compile typed ESM for Node, or build a reactive browser bundle with the call-style view DSL.

05

Patterns, sums, results

match with destructuring and guards, variant types, Result with ? and ??, plus a stdlib that ships http, json, fs, env and time.

06

A feedback loop for agents

npx @codebam/tel check reports file:line:col for undefined names, arity and scope mistakes. The same CLI reformats code and counts exact cl100k tokens.

Syntax

A whole language, one guide

Five representative programs. The exact snippets below are counted with the same cl100k_base tokenizer used in the benchmark.

CLI toolOne-line entry point23 cl100k tokens

The interpreter calls fn main(args). Strings interpolate; nil falls back with ??.

fn main(args):
  name = args[0] ?? "world"
  print("hello, {name}")

npx @codebam/tel run app.tel -- ada

HTTP JSON APIThe stdlib is the framework98 cl100k tokens

std.http serves async handlers. Returning an object sends JSON; http.res overrides.

import std.http as http

async fn handle(req):
  match req.path:
    "/health": {ok: true}
    "/sum": {sum: (0..=int(req.query.n ?? "0")).sum()}
    _: http.res(404, "not found")

async fn main():
  server = await http.serve(int(env.get("PORT", args[0] ?? "0")), req => handle(req))
  print("bound {server.port}")
  server

PORT=8080 npx @codebam/tel run app.tel

Browser componentSignals in the view DSL38 cl100k tokens

Top-level bindings inside web fn become signals. Reads re-render; writes in handlers update the DOM.

web fn App():
  n = 0
  div(class="app",
    h1("Counter ", n),
    button(onclick=() => n += 1, "+"))

npx @codebam/tel build app.tel --target web -o app.mjs

Types & patternsSums and destructuring70 cl100k tokens

Variant types, match arms and guards. No exhaustiveness bugs hiding in a switch fallthrough.

type Shape = Circle(r: Num) | Rect(w: Num, h: Num)

fn area(s: Shape) -> Num:
  match s:
    Circle(r): 3.14159 * r * r
    Rect(w, h): w * h

print(area(Circle(2)), area(Rect(3, 4)))

npx @codebam/tel run app.tel

Data pipelineCollections, composed61 cl100k tokens

Comprehensions, UFCS methods and placeholder lambdas keep data code dense and readable.

import std.{json}

xs = [3, 1, 4, 1, 5]
evens = xs.filter(_ % 2 == 0).map(_ * 10)
print(json.stringify({count: len(xs), max: xs.max(), evens: evens}))

npx @codebam/tel run app.tel

Token efficiency

Fewer tokens per program

Exact cl100k_base BPE counts over equivalent programs that were all executed and compared. Lower is cheaper, and cheaper means more room for the actual task.

540
Tel tokens
vs
759
TypeScript tokens
-28.9%
ProgramTelPythonTypeScriptTel share of TS
FizzBuzz58597478%
List pipeline789810078%
HTTP JSON handler10426421050%
Base three24042138463%
v0.2 programTelTypeScriptTel share of TS
Typed record pipeline8912472%
Async load475290%
Route dispatcher16419982%
v0.2 three30037580%

Six equivalent programs, counted with the exact cl100k_base tokenizer in tools/tokcount.mjs. Methodology and per-file counts live in docs/TOKENS.md. The 2,193-token agent guide is budgeted at 2,200 and contract-tested.

Quickstart

From clone to running in a minute

Tel is published as @codebam/tel, so npx runs it with zero project dependencies. tel init also installs AGENTS.md, so your agent picks up the language contract automatically.

1

Start a project

Nothing to install globally: npx fetches the published @codebam/tel package. tel init writes main.tel and the 2,193-token AGENTS.md contract.

mkdir app && cd app
npx @codebam/tel init
2

Run it

The interpreter calls fn main(args). No build step and no dependencies to wire up.

npx @codebam/tel run main.tel -- world
3

Check and build

Static diagnostics in file:line:col, then typed ESM for Node or a browser bundle with --target web.

npx @codebam/tel check main.tel
npx @codebam/tel build main.tel --target ts --outdir out

For agents

The one prompt that works everywhere

Paste this into your coding agent before it writes any Tel. The guide is small enough to stay in context and every fenced snippet in it executes in CI.

agent-instructions.txtthe contract
Read AGENTS.md first and follow it. Write new application code in Tel (.tel),
not TypeScript. Use `npx @codebam/tel run FILE` to execute and
`npx @codebam/tel check FILE` before you finish. If you need details
beyond AGENTS.md, read docs/SPEC.md.
  • Zero-install — npx @codebam/tel runs the published package; there is no global toolchain to maintain.
  • 2,193 tokens — measured with cl100k_base and budgeted to fit alongside real work.
  • Executable — 10/10 guide snippets and 26/26 SPEC snippets run in the test suite.
  • Machine-checked — tel check gives file:line:col diagnostics; tel fmt keeps code canonical.
  • Conventional — AGENTS.md is auto-ingested by Codex, opencode and other agent harnesses; symlink it for Claude Code, Cursor, Windsurf and Aider.

Dogfooding

This site is Tel too

Every dynamic byte here — HTML, JSON and the browser island — is compiled from .tel source and runs at the edge.

SSR

Pages rendered in Tel

The Worker matches routes in Tel, builds vnodes with the call-style DSL, runs them through html(), and returns a Response.

API

JSON APIs in Tel

Health, benchmarks and the token estimator are Tel functions. The estimator is the exact same module the browser island imports.

Client

The browser runs Tel

The interactive tour is a web fn component compiled with --target web. Signal writes re-render the DOM; there is no framework underneath.

FAQ

Questions, answered

Everything below is verifiable from the repository and the measured results on this page.

How do I run it?

Install Node >= 20 and run npx @codebam/tel. The published package is @codebam/tel, so there is no global install: npx @codebam/tel init writes main.tel plus the AGENTS.md guide, and npx @codebam/tel run main.tel executes it.

Is Tel production-ready?

Tel is v0.2. The runtime, compiler, checker and formatter are covered by a 94-test verification suite, and known limitations are documented. It is young, but already pleasant for small tools, APIs and prototypes.

How is this different from just writing TypeScript?

TypeScript is one of Tel's compile targets. Tel adds a Python-style surface, a higher-level stdlib, built-in checking and token-lean idioms for AI-authored code, then emits typed ESM you can read, review and deploy.

Can I use npm packages?

Yes. Default, named and namespace imports work, Tel lambdas are JavaScript arrows, and await works on promises. Packages must be installed exactly as in Node; the Tel toolchain itself needs none.

Does it run on Cloudflare Workers?

This site does. Tel compiles to a standalone ESM module; a small generated wrapper turns its exported fetch handler into a Worker default export. The HTML you are reading, the JSON APIs and the browser island are all compiled from Tel.

How big is a compiled program?

Each compiled file inlines the shared runtime, so a hello-world bundle is roughly 28 KB before gzip. There are no runtime npm dependencies, and the Worker here needs no Node compatibility flags.

Is there tooling for agents?

Yes: npx @codebam/tel check gives file:line:col diagnostics, fmt canonicalizes layout, tokens reports exact cl100k_base counts, and init installs the AGENTS.md contract into a project.

What is the license?

MIT.