Skip to content
LogoLogo

Language Syntax

Quick reference for VibeLang source forms

VibeLang keeps additions TypeScript-shaped where possible. Compiler-recognized behavior is exposed through imported functions and ordinary generic types instead of new keywords.

Source Files

FormStatusMeaning
.vibeLockedVibeLang source file
.tsLockedimported TypeScript with TypeScript behavior
.vibexOpencandidate JSX-capable VibeLang extension

Results and Errors

class Name extends Error {
  constructor(readonly field: Type) {
    super("failure message")
  }
}
 
function operation(): Result<Value, Name> {
  if (failed) throw new Name(value)
  return value
}

Plain returns and throws are compiler-lifted in a Result-returning function. Propagate a Result with .unwrap() and recover with match, recover, or error.match:

const value = operation().unwrap()
 
const label = operation().match({
  ok: value => render(value),
  error: error => error.match({ Name: describe }),
})

An async fallible function returns Promise<Result<A, E>>. await unwraps only the Promise. Promise .then, .catch, and .finally are banned in authored VibeLang.

Optionals

function lookup(): Optional<Value> {
  if (missing) return undefined
  return value
}
 
const label = lookup().match({
  some: value => render(value),
  none: () => "missing",
})

Use methods such as map, andThen, filter, unwrap, unwrapOr, and toResult. The compiler lifts plain values and nullish returns in Optional-returning functions.

Requirements

import { Context } from "vibelang/context"
 
const store = Store.context()
const log = Logger.context()

context() returns a capability instance and adds its nominal identity to the enclosing function's inferred requirement channel. There is no requirement keyword.

Expression Control Flow

const value = if (condition) whenTrue else whenFalse
 
const result = switch (input.kind) {
  case "a":
    resultA
  case "b":
    resultB(input.value)
}

Blocks, if, switch, for, and while may produce values. Switches use TypeScript case clauses, and known finite domains are exhaustiveness-checked.

Labeled Values and Loop Else

const value = label: {
  break :label result
}
 
const found = search: for (const item of items) {
  if (matches(item)) break :search item
} else fallback

Cleanup

defer cleanup()
errdefer rollback()

defer runs on scope exit. errdefer runs when the scope exits with a Result error.

Comptime

import { comptime } from "vibelang:comptime"
 
const value = comptime(expression)
const generatedFunction = comptime(functionValue)
comptime.target

Passing a value requests deterministic compile-time evaluation. Passing a function marks and returns a compile-time function without invoking it. comptime is an imported intrinsic, not a keyword.

Durable Functions

import { durable } from "vibelang:flows"
 
const workflow = durable(function workflow(
  input: Input,
): Result<Output, BuildError> {
  return Build.run(input)
})

The compiler lowers a statically resolvable durable function to Plan IR without invoking the Flow in plan mode. durable is an imported intrinsic, not a keyword.

Import Attributes

All non-code and foreign-source imports use standard import attributes:

import config from "./config.json" with { type: "json" }
import frozen from "./config.json" with { type: "json", mode: "const" }
import prompt from "./prompt.md" with { type: "text" }
import kernel from "./kernel.zig" with { type: "zig" }

Attribute values are strings. Ordinary .vibe, .ts, and .js code imports do not need a type attribute.

Deliberately Absent Syntax

The initial language has no failure clause, prefix propagation syntax, postfix catch expression, special Error declaration, optional type sigil, optional fallback operator, comptime keyword, durable keyword, or separate const-import grammar.