Skip to content
LogoLogo

Welcome to VibeLang

VibeLang is a language for writing Effect programs with TypeScript syntax. Its compiler checks .vibe and .ts files together and emits JavaScript and TypeScript declarations.

// run: Console.log(Effect.provide(greet("ada"), Layer.succeed(Users, { find: (id) => ({ id, name: "Ada" }) })))
interface User { id: string; name: string }
 
error UserNotFound { id: string }
 
service Users {
  find(id: string): User!UserNotFound
}
 
function greet(id: string) {
  const name = Users.find(id).name catch "guest"
  return `Hello, ${name}`
}
// string!!Users
// Output: Hello, Ada

A user service, a typed error, and a fallback, in Effect and in VibeLang. The comment under greet is the type your editor shows: string!!Users is VibeLang's spelling of Effect<string, never, Users>. It returns a string, has no expected failures, and needs the Users service. Defects and interruption remain possible. The compiler infers all three from the body, and TypeScript code that imports greet sees the Effect type. The TypeScript example adds a tracing span with Effect.fn("greet"); the VibeLang function is untraced by default.

VibeLang is v0. The language will change in major, breaking ways, and it is not ready for production use.

Why a language

Effect tracks failures and services. A TypeScript signature says what a function returns, but not what can fail or what it depends on. Effect puts all three in one type, Effect<Success, Error, Requirements>, and the compiler checks it. Retries, timeouts, concurrency, resource cleanup, and tracing come with it.

Effect expresses sequencing through library calls. Effect is a library, so it builds every feature out of what TypeScript already has: generators and yield* to run steps in order, pipe to compose them, and classes to declare errors and services. The code reads like a separate language written in library calls.

VibeLang adds language syntax. Each Effect idea gets its own syntax. Calls run in order, throw fails with a typed error, catch handles it, service declares a dependency, and fork starts a fiber. The compiler builds the same Effect program you would have written by hand.

TypeScript stays one step away

VibeLang shares TypeScript's ecosystem in two ways:

  1. It shares TypeScript's compiler and types. VibeLang's compiler is TypeScript's compiler, extended. It checks .vibe and .ts files together and emits JavaScript and .d.ts files, so you can use existing Effect code and npm packages through TypeScript interop. TypeScript code calls exported VibeLang functions as ordinary Effect functions.
  2. You can opt out to plain TypeScript. sync, try, and callback take a plain TypeScript function, and a .ts file can sit beside any .vibe file.
// run: Console.log(slug("Hello VibeLang"))
function slug(title: string) {
  return sync((title) => {
    // Plain TypeScript: nothing in here is an Effect.
    let s = title.trim().toLowerCase()
    s = s.replaceAll(/[^a-z0-9]+/g, "-")
    return s
  }, title)
}
// string!!
// Output: hello-vibelang

A hatch's function is self-contained: it reads the .vibe file's values only as the arguments passed after it, here title.

Effect's features, in VibeLang syntax

VibeLang runs on Effect and uses its library modules. Common operations have language syntax:

Effect featureVibeLang
Effect typesUser!NotFound!Users: returns User, fails with NotFound, needs Users
Typed errorserror NotFound { id: string }, throw new NotFound({ id }), x catch fallback
Dependency injectionservice Users { ... }, provide UsersLive { ... }
Structured concurrencyfork, join, await.all [a(), b()], for concurrent(8) (const id of ids)
Retries and timeoutswork() |> retry(%, policy) |> timeout(%, "1 second")
Resource safetyusing conn = connect(), finally
TracingwithSpan("checkout") { ... }
Schema validationschema User { id: string; role: "admin" | "member" }
Pattern matchingmatch (e) { when NotFound: ...; }

Streams, configuration, and Effect's HTTP, SQL, CLI, and AI packages need no syntax of their own: call them as you would in TypeScript. The cheat sheet puts every VibeLang form beside the Effect code it replaces.

Check application code

The compiler tracks expected failures and required services for each function. A declared contract lets it reject code that adds an unhandled failure or dependency. Run focused tests to check behavior, including recovery, cancellation, and cleanup; successful type checking does not establish those results.

Try it

bun create vibelang@latest my-app
cd my-app
bun run dev

Then open the folder in VS Code or Cursor and install the editor extension that comes with the compiler: code --install-extension node_modules/vibelang/editor/vibelang.vsix. Installation covers existing projects.

Where to go next


The matching Effect page: effect.website/docs/v4/onboarding