@! VIBE
Developer tools

A language made
of sigils.

No keywords in any human language. Compiled straight to machine code.

vibec writes the ELF bytes itself. No assembler, no linker, no C library, and nothing at all inside the executable it produces. A hello-world binary is under 1 KB and depends on nothing. For release builds, --backend=c sends the same program through gcc or clang and runs level with C at -O3.

sum3.vibe
@ sum3 (a s64, b s64, c s64) s64 {
  ^ (a + b) + c
}
→
what the compiler emits
4c 8b c2   mov  r8, rdx
48 01 f7   add  rdi, rsi
4c 01 c7   add  rdi, r8
48 8b c7   mov  rax, rdi
c3         ret
Five instructions, seventeen bytes. Nothing sits between the two panes — no LLVM, no as, no ld. The compiler is 6,000 lines of Python that knows x86-64 encoding and the ELF format.
Why it looks like this

Three rules that remove three ambiguities.

VIBE is meant to be written correctly the first time, by a person or a model. Each rule below deletes a class of bug rather than warning about it.

RULE 1

No operator precedence

Mixed operators without parentheses are a compile error. An expression means exactly what its shape says.

1 + 2 * 3
1 + (2 * 3)
RULE 2

No implicit conversions

Widths never change behind your back. If you want a conversion, you write one.

a + b        ; s64 + s32
a + s64(b)
RULE 3

One statement per line

A newline ends a statement. No semicolons, no line joining, no ambiguity about where anything stops.

$~ t = 0
* i 0 n {
  t += i
}
Install

One line, on any system.

The compiler is Python 3 with no dependencies, so it installs anywhere. What it emits is a static Linux x86-64 executable — on Windows run those under WSL, on macOS in a container or VM.

curl -fsSL https://benjiapps.com/vibe/apt/vibe.gpg | sudo tee /usr/share/keyrings/vibe.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/vibe.gpg] https://benjiapps.com/vibe/apt stable main" | sudo tee /etc/apt/sources.list.d/vibe.list
sudo apt update && sudo apt install vibe
A signed APT repository. Installs the vibe package with a man page and examples; the .deb is also under Downloads below.
Direct downloads

Checksums: SHA256SUMS. Every artifact is reproducible with packaging/release.sh from the repository. All releases are listed on GitHub.

The language

Every construct is one sigil.

This is the whole vocabulary. Identifiers are yours and may be written in any script — nothing in VIBE requires knowing English.

@
function
@!
entry point
%
struct
%|
tagged union
$
binding
$~
mutable binding
$$
compile-time constant
^
return
? :
if / else
??
match
|
match arm
*
loop while
* i a b
counted loop
*<
break
*>
continue
~
defer to scope exit
<T>
generics
@<
C function
x.f( )
method call
e!
unwrap or return the error
f32x4
SIMD vector
\name
intrinsic
\N
syscall N
\\[ ]
inline machine code
&
address of
'
dereference
#
size of a type
<<
include
@( )
function pointer
;
comment
a whole program — matching is checked for exhaustiveness
<<"heap.vibe"

@ divide (a s64, b s64) %Res<s64, %Str> {
  ? b == 0 {
    ^ %Res|Err("divide by zero")
  }
  ^ %Res|Ok(a / b)
}

@ halve_all (v *%Vec<s64>) %Res<s64, %Str> {
  $~ t = 0
  * i 0 v.n {
    t += divide(v.p[i], 2)!        ; ! returns the Err for us
  }
  ^ %Res|Ok(t)
}

@! () s64 {
  $~ v %Vec<s64> = vnew()
  v.vpush(84)
  v.vpush(10)
  ?? halve_all(&v) {
    |Ok(t)  { \print("total {}\n", t) }   ; total 47
    |Err(m) { \eprint("{}\n", m) }
  }
  ^ 0
}
What you can build

Every category ships as a program that runs.

These are in the repository under examples/ and tests/. Unless they ask for a C library, none of them link against anything — they talk to the kernel directly.

A playable game

examples/snake.vibe

Snake in the terminal: raw mode through ioctl, non-blocking input, frame timing through nanosleep. No curses, no libc.

Command line tools

examples/wc.vibe

A wc clone reading files named in argv. Its output is byte-identical to GNU wc on every file tested.

Network services

examples/httpd.vibe

An HTTP server: socket, bind, listen, accept, all straight through the syscall form. It serves real requests to curl.

Parallel compute

examples/par.vibe

Counting primes across forked processes, results returned through a pipe. 400,000 numbers: 44 ms on one process, 6 ms on sixteen.

Threads and atomics

tests/t22_threads.vibe

Real kernel threads from spawn and join, atomic counters through \xadd and \cas, spin locks, and a thread-safe heap — still with no libc.

Generic data structures

tests/t23_generics.vibe

%Vec<T>, %Opt<T> and generic functions, compiled once per type actually used, with the type arguments inferred.

Any C library

tests/t20_ffi.vibe

One line — @< "m" pow (f64, f64) f64 — declares a C function. GUI toolkits, databases and GPU runtimes are all reachable the same way.

Speed and size

Measured against gcc, on identical programs.

Least CPU time of seven runs, with every build's output verified equal before the timings are reported. Reproduce them with python3 bench/run.py.

BenchmarkVIBE nativeVIBE --backend=cgcc -O0gcc -O2gcc -O3
fib(35)0.033s0.018s0.062s0.029s0.017s
sieve, 10M0.022s0.025s0.071s0.025s0.026s
matmul, 400²0.074s0.051s0.160s0.037s0.035s
mandelbrot, 900²0.052s0.047s0.146s0.042s0.040s
= -O3
through --backend=c: level with gcc -O3 on all four benchmarks
319 B
stripped hello world, where the same static C program is 785 KB
0
external tools: no assembler, no linker, no libc, no runtime

Two backends, one language. The native backend needs nothing but Python, builds instantly, and runs 2–3× faster than gcc -O0 and between parity and about 1.7× of gcc -O2. The C backend prints the same program as freestanding C and lets gcc or clang optimise it: still a static binary with no libc, now level with C. Develop with the first, ship with the second.