Skip to main content
ClaudeWave

Run code an AI wrote without handing it everything you can reach. Each function declares what it may touch. You grant the run one folder, one host or a number of calls, and the runtime refuses anything else the moment it's tried.

MCP ServersOfficial Registry3 stars0 forks● PythonMITUpdated today
ClaudeWave Trust Score
95/100
✓ Verified
Passed
  • ✓Open-source license (MIT)
  • ✓Actively maintained (<30d)
  • ✓Clear description
  • ✓Topics declared
  • ✓Documented (README)
Last scanned: 10/2/2026
Install in Claude Code / Claude Desktop
Method: pip / Python · sabline-lang
Claude Code CLI
claude mcp add sabline-lang -- python -m sabline-lang
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "sabline-lang": {
      "command": "python",
      "args": ["-m", "sabline-lang"]
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
💡 Install first: pip install sabline-lang
Use cases

MCP Servers overview

<!-- mcp-name: io.github.gowrishankar-infra/sabline -->
<!-- The line above proves to the MCP registry that this package and the
     server io.github.gowrishankar-infra/sabline have the same owner. It is
     read from this file as published to PyPI; removing it breaks publishing
     to the registry. See integrations/mcp_registry/server.json. -->

<div align="center">

# Sabline

**Run code an AI wrote without handing it everything you can reach.**

Each function declares what it may touch. You grant the run one folder,
one host or a number of calls, and the runtime refuses anything else the
moment it's tried.

Not a security boundary by itself: an interpreter in the program's own
process enforces the budget. From 8.4 the operating system is asked to hold
the same budget under it - fully on Linux, partly on macOS and on Windows -
and each run says which it got ([THREAT_MODEL.md](THREAT_MODEL.md),
[docs/confinement.md](docs/confinement.md)).

[![PyPI](https://img.shields.io/pypi/v/sabline-lang)](https://pypi.org/project/sabline-lang/)
[![tests](https://github.com/gowrishankar-infra/sabline-lang/actions/workflows/test.yml/badge.svg)](https://github.com/gowrishankar-infra/sabline-lang/actions/workflows/test.yml)
[![release](https://img.shields.io/github/v/release/gowrishankar-infra/sabline-lang)](https://github.com/gowrishankar-infra/sabline-lang/releases)
[![license](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)

[**Playground**](https://sabline.dev/playground.html) · [**Documentation**](https://sabline.dev/) · [**Guides**](https://sabline.dev/guide-network-access.html) · [**Reference**](SPEC.md) · [**Paper**](https://sabline.dev/papers/sabline.html)

Formerly **Velaris** - [why the name changed](https://sabline.dev/velaris.html)

</div>

<img src="docs/hero.png" alt="Sabline refusing a network call because the run only allowed io" width="100%">

**Who it is for.** The person about to run a program a model wrote - on a
laptop, in CI, behind an MCP server - who wants what it can touch bounded by
what they said, not by what the program says about itself. It bounds
programs written in Sabline, not a Python or shell script the same model
might write instead.

**See it refuse, in one command** - no arguments, no network, under a
minute. It writes the kind of script an agent writes (read `./.env`, post it
to a webhook), runs it with no budget given, and shows the refusal and the
run's receipt; then the same task inside a budget:

<!-- illustrative lines 1: installs from PyPI -->
```sh
pip install sabline-lang
sabline demo
```

<!-- output of: sabline demo -->
```text
error[E310] 'read_file' needs the 'fs' effect, which this run does not allow (it allows: io)
exit 1. receipt: refused; E310 (fs) at line 6; grants used: none
3 setting(s); the report is in out/report.txt
```

It writes what it runs and reads nothing of yours; `--keep` leaves the files,
and `sabline receipt show` renders either receipt as a page.

---

**This project was called Velaris until 8.6.0.** The name belongs to an
unrelated company in the same market (velaris.io), so it was given up
rather than contested. Everything else is unchanged, and nothing written
against the old name stops working in 8.x: the `velaris` command, `import
velaris`, the `VELARIS_*` environment variables, a committed
`velaris.capabilities`, and a `velaris.audit/1` or `velaris.receipt/1`
document are all still read, each saying once that the name has changed.
[docs/renamed.md](docs/renamed.md) lists every published address and where
it now points; [STABILITY.md](STABILITY.md) says what goes in 9.0.

---

<!-- illustrative lines 1: installs from PyPI -->
```sh
pip install sabline-lang
sabline agent_output.vel
```

That program cannot open a socket, read a file, call Python, or ask the
clock. Not "shouldn't" — the runtime refuses, and a refusal cannot be
caught and carried past. You do not have to read the code, understand
it, or trust the compiler's analysis of it.

Since **5.0** that is what a run with no `--allow` gets: `io`, the
console. It used to be all seven effects, which meant the answer to
"what may this program do?" was "everything" until an operator said
otherwise. Widen it by naming what the program needs
(`--allow io,fs:read:./data`); `--allow all` grants every effect and
writes one line to stderr saying so.

`--allow io,ffi:math,json` grants Python for those modules only; a call
that reaches any other module — named, or reached through an attribute of
a granted one — is refused (E311). A granted module can still do whatever
that module itself can do: `ffi:os` is the operating system. Since 3.0
the same grammar
narrows every coarse effect: `fs:read:./data`, `fs:write:./out`,
`net:api.example.com:443`, `net:*.example.com`, and `@100` for at most
that many operations in a run; `env` is its own effect, so an
`io`-only program cannot read the environment. `timeout` and
`max_memory_mb` are available through the library and every door, and
on a door the operator's limits are ceilings a caller cannot raise.
It is still not a security boundary - but the
caveats every review raised, the ffi cliff, unbounded execution, and
`fs` and `net` with no path or host list, are now precise permissions
rather than holes. It is a real guard for the situation everyone is
now in — running a program someone, or something, else wrote.

## The other half: promises, proven

<!-- expect: E700 -->
```vel
fn discount(price: Int) -> Int
    requires price >= 0
    ensures result >= 0
{
    return price - 10
}
```

<!-- output: codes only; the counterexample is the prover's choice -->
```text
error[E700] promise cannot be kept: 'discount' ensures result >= 0 - proven without running the program: price = 5 gives result = -5
```

That `ensures` is not a comment or a runtime assert. The Z3 theorem
prover verifies it for **every possible input** before execution — and
refutes it with an exact counterexample when it lies.

## A rule the customer wrote

A commerce platform lets each customer write their own discount rule.
This one has the shape most of them have: a percentage off once the
basket passes a threshold, a flat amount off as well, and a cap on the
two together.

```vel
record Rule {
    percent: Int         // this much off, once the basket is
    above: Money of INR  // worth at least this,
    flat: Money of INR   // and this much off as well,
    cap: Money of INR    // but never more than this, all together
}

fn discount_for(total: Money of INR, rule: Rule) -> Money of INR
    requires total >= money(0, "INR")
    requires rule.percent >= 0
    requires rule.percent <= 100
    requires rule.flat >= money(0, "INR")
    requires rule.cap >= money(0, "INR")
    ensures result >= money(0, "INR")
    ensures total - result >= money(0, "INR")
{
    let off = money(0, "INR")
    if total >= rule.above {
        off = percent_of(total, rule.percent, 100, "half_up")
    }
    off = off + rule.flat
    if off > rule.cap {
        off = rule.cap
    }
    if off > total {
        off = total
    }
    return off
}
```

The two `ensures` are what the platform needs to know about a rule it
did not write: a discount is never a surcharge, and what is left after
it is never negative. Both are settled for every basket and every rule
the types allow, before the program runs.
[`examples/discount.vel`](examples/discount.vel) is the whole program —
<!-- count:discount-proven:word -->five<!-- /count --> of the <!-- count:discount-promised:word -->five<!-- /count --> functions that make a promise
proven, and it runs under `--allow io`.

[`examples/discount_bad.vel`](examples/discount_bad.vel) is the same
rule with the last `if` deleted. The cap still holds the discount to a
fixed ceiling; nothing holds it to what the basket is worth:

```console
$ sabline check examples/discount_bad.vel
examples/discount_bad.vel:54: [E700] promise cannot be kept: 'discount_for' ensures total - result >= money(0, "INR") - proven without running the program: rule = Rule(percent: 0, above: 0, flat: 2, cap: 1), total = 0 gives result = 1
```

The amounts are in paise: a basket worth nothing, a flat discount of
two paise held down to a cap of one, and one paisa handed back anyway.
The program does not run.

A sandbox answers a different question. It can stop this rule reading a
file or opening a socket; it cannot tell you whether the arithmetic
holds.

## A key it cannot print

Effects say a program printed something. They do not say whether what
it printed was the secret. `Secret of T` (6.0, 7.0) is the other half: the
compiler tracks the value, and refuses any program that hands it to
anything that emits.

```vel
fn key() -> Secret of Text uses env {
    return env("API_KEY", "")          // env() gives a Secret of Text
}

fn authorization(k: Secret of Text) -> Secret of Text {
    return "Bearer " + k               // still a Secret of Text
}
```

[`examples/secret.vel`](examples/secret.vel) reads an API key, builds
the request that would carry it, and prints a summary of that request.
[`examples/secret_bad.vel`](examples/secret_bad.vel) is the same
program with one more line:

```console
$ sabline examples/secret_bad.vel --allow env,io
error[E560] argument 1 of 'print' is Secret of Text, and 'print' performs io - a Secret cannot be printed, written, sent or passed to Python. It came from env(), line 27, through 'key', which returns Secret of Text (line 58)
  --> examples/secret_bad.vel, line 58
```

Nothing ran, nothing was logged, and no reviewer had to notice the
line. A list of secrets, a map of them, or a record with one secret
field carries it too, so the whole structure is refused at a sink — a
`Request` record holding the key cannot be printed either.

**And a program cannot look at the key either.** `key == ""` is a
`Secret of Bool`, not a `Bool`, and an `if` or `while` on one is
`E563`. That is the rule that makes the rest mean something: with
`length` and `code_at`, a plain `Bool` from `==` is not one
ai-agentscompilereffect-systemformal-verificationleast-privilegellvmmcppermissionsprogramming-languagepythonsandboxsecretssmt-solverstatic-analysissupply-chain-securitytheorem-provingz3

What people ask about sabline-lang

What is gowrishankar-infra/sabline-lang?

+

gowrishankar-infra/sabline-lang is mcp servers for the Claude AI ecosystem. Run code an AI wrote without handing it everything you can reach. Each function declares what it may touch. You grant the run one folder, one host or a number of calls, and the runtime refuses anything else the moment it's tried. It has 3 GitHub stars and its last recorded update is dated 2026-10-01.

How do I install sabline-lang?

+

You can install sabline-lang by cloning the repository (https://github.com/gowrishankar-infra/sabline-lang) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is gowrishankar-infra/sabline-lang safe to use?

+

Our security agent has analyzed gowrishankar-infra/sabline-lang and assigned a Trust Score of 95/100 (tier: Verified). See the full breakdown of passed checks and flags on this page.

Who maintains gowrishankar-infra/sabline-lang?

+

gowrishankar-infra/sabline-lang is maintained by gowrishankar-infra. The last recorded GitHub activity is dated 2026-10-01, with 30 open issues.

Are there alternatives to sabline-lang?

+

Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.

Deploy sabline-lang to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: gowrishankar-infra/sabline-lang
[![Featured on ClaudeWave](https://claudewave.com/api/badge/gowrishankar-infra-sabline-lang)](https://claudewave.com/repo/gowrishankar-infra-sabline-lang)
<a href="https://claudewave.com/repo/gowrishankar-infra-sabline-lang"><img src="https://claudewave.com/api/badge/gowrishankar-infra-sabline-lang" alt="Featured on ClaudeWave: gowrishankar-infra/sabline-lang" width="320" height="64" /></a>

More MCP Servers

sabline-lang alternatives