Open source · MIT licensed

A Ruby-like language to extend your app.

Let users and AI agents add features with scripts. You choose which data and functions they can use, and how much work each script can do.

Hundreds of examples to run in your browser

trial_reminder.vibe v0.80.0
enum Plan
  Free
  Pro
end

def reminder(plan: Plan, left: duration) -> string?
  return nil if plan == Plan::Pro || left > 3.days
  "Your trial ends in #{left.days} days."
end

def run -> string?
  reminder(:free, 2.days)
end

Why Vibescript

Software people can shape.

Vibecoding will have a profound impact on personal computing. But it still requires expertise. Generated code needs to be maintained, or it will rot and become vulnerable to attack.

I think the future is malleable software, where people vibecode their own customizations on top of a base package.

I built Vibescript to help power that future. It's a small, statically typed scripting language for customizing an existing app. The host app decides which capabilities scripts can use and how much work they can do.

The syntax is inspired by Ruby, so it's easy to read. The type checker catches mistakes before a script runs and suggests fixes in its diagnostics. People and AI can write custom behavior, and the host app stays in control.

Signature of Mauricio Gomes
Mauricio Gomes Creator of Vibescript

Language

If you know Ruby, much of this will look familiar.

Write functions, work with collections, and check types before running. Vibescript also has money, durations, and enums built in.

Small on purpose.

Functions have names, and blocks run during the call that receives them. Changing an array or hash leaves other copies alone. Hash keys are strings, and records declare the keys they contain.

small_surface.vibe
module Scoring
  BONUS = 10

  def self.with_bonus(score: int) -> int
    score + BONUS
  end
end

type Order = { status: string, score: int }

def approve(order: Order) -> Order
  order["status"] = "approved"
  order["score"] = Scoring.with_bonus(order["score"])
  order
end

pending = { status: "pending", score: 80 }
approved = approve(pending)

pending["status"] # "pending"
approved["score"] # 90

Add your own services.

Give a script an SMS service, an email client, or your own API through a host capability. You write the adapter. The script calls it like any other method. Here's how to connect one.

notifications.vibe host side
type SmsReceipt = { to: string, body: string, status: string }

def run -> SmsReceipt
  sms.send("+15555550123", "Your order is ready.")
end

Set hard limits for each script.

Set a budget for execution steps, memory, and call depth. If a script reaches a limit, the engine stops it and returns an error.

untrusted.vibe · sandboxed
$ cat untrusted.vibe
def run
  balance = 0
  while true
    balance = balance + 1
  end
end

$ vibes run --function run untrusted.vibe
RuntimeError: step quota exceeded
✓ stopped at 10,000,000, page stays responsive

Built-in money, duration, and enum types.

Write 3.days for a duration. Use money values for exact decimal arithmetic. Define enums for choices such as shipping speeds or order states.

primitives.vibe
enum ShippingSpeed
  Economy
  Priority
  Overnight
end

def transit_time(speed: ShippingSpeed) -> duration
  if speed == ShippingSpeed::Overnight
    6.hours
  else
    5.days
  end
end

def net_after_fee(cents: int) -> money
  gross = money_cents(cents, "USD")
  gross - money("1.75 USD")
end

In your app

Give scripts access to your app's services.

Put pricing rules, approval steps, or notification schedules in scripts that users can change without rebuilding your app.

Your app handles I/O and scheduling. Scripts use the functions and data you provide to calculate a price, choose the next reviewer, or plan a reminder.

Add services through host capabilities. A script can then call sms.send(...) or email.send(...). Try the message previews and edit the scripts behind them.

Sandbox limits

These limits apply to this site's examples. Choose the values that fit your app.

Step quota
10,000,000
Stops execution when the script uses its step budget.
Recursion limit
128
Limits how deeply function calls can nest.
Memory quota
16 MiB
Limits the memory a script can use.
Effects control
strict
Operations such as database writes need permission from your app.
Module paths
allowlist
Loads modules from directories you approve.
App access
host adapters
You choose which services scripts can call.

Try it

Run a few examples.

Pick an example, read the code, and run it. You don't need to install anything.