Skip to content
pleme-ioPublic

About

The pleme-io language: a Ruby/Elixir surface on a tatara-lisp AST, macros as term rewriting, and a Rust runtime. Sliding-scale optional typing, bounded macro expansion, OTP-style supervision, and a WASM target with zero host imports.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

1,149 Commits

Folders and files

Repository files navigation

blue

████  blue          nord7 → nord8 → nord9 → nord10
────────────────────    teal   cyan   light  deep blue
a Ruby/Elixir surface on tatara-lisp and Rust

blue is the pleme-io language. You write it like Ruby or Elixir. It parses to a tatara-lisp tree, macros rewrite that tree, and a Rust runtime runs it, not the BEAM. Each thing has one spelling, and the formatter writes it. Rigor is your choice: declare nothing and a program is dynamic and fast; annotate one function and that function is checked. Safety is not a choice: a program reaches the host only through the capabilities it is given. The standard library is a set of packages called bidamas, and one Bluefile says how a project is built, tested, documented and shipped.

The philosophy is two axes (theory/BLUE.md §0). Form has no choices: there is one short, distinct way to write each thing, every larger form is built from smaller ones, and every tool and gate enforces it. Rigor has every choice: a program is as strict as you write it, where you write it, and pays for nothing else. Every blue word (bidama, waku, mondou, the blueshift) maps to the concept you already know in the glossary.

A file is a program, a library and its tests at once:

@doc """
shout: The text in capitals, with an exclamation mark.

    shout("olá") #=> "OLÁ!"
"""
def shout(text: String) -> String
  "#{upcase(text)}!"
end

def main()
  write_stdout(unlines([join(map(shout, argv), " ")]))
end

test "shout raises its voice and keeps the text"
  assert shout("oi") == "OI!"
  assert shout("") == "!"
end
$ blue words.b olá mundo
OLÁ! MUNDO!
$ blue test words.b
2 test(s): 2 passed, 0 failed

The example in the @doc is the second test: blue test runs it beside the test block, so a documented example cannot drift from the code.

Quickstart

You need Nix with flakes turned on. Install blue into your profile:

$ nix profile install github:pleme-io/blue

To try blue without installing it, put nix run github:pleme-io/blue -- in front of each command below.

Ask blue for a value:

$ blue eval '1 + 2'
3

Write a file called hello.b:

write_stdout(unlines(["Olá, mundo!"]))

Run it:

$ blue hello.b
Olá, mundo!

That is a whole blue program. The next tutorial, a first script, gives it arguments.

The blueshift

The blueshift is how far a program has moved from dynamic toward checked. You move it one definition at a time. Here add has no annotation, so nothing analyses it. fact is annotated, so the checker proves it:

def add(a, b)
  a + b
end

def fact(n: Int) -> Int
  if n < 2
    1
  else
    n * fact(n - 1)
  end
end

blue check prints what the check cost, so the claim is a measurement:

$ blue check shift.b
typed declarations: 1
nodes analysed:     11
seams:              0
names resolved:     11
waived:             0

blue shift names the rung the file stands on and what holds it back:

$ blue shift shift.b
██░░ annotated  (1/2 typed, 11 nodes analysed)
some declarations are typed; untyped ones are unchecked

  · untyped declaration      `add` has no annotation — annotate it to shift further
  → type annotation          `fact` is annotated, so it is checked

The language server closes the gap for you: on a loose definition it offers a code action that writes the types its calls showed.

Safety first

Every effect outside the program is a capability: process, filesystem, environment, clock, network or entropy. --allow holds a run to the ones you name, and the check stage refuses the program before it runs when it writes a host name outside them:

def main()
  write_stdout(read_file("words.b"))
end
$ blue --allow none peek.b
refused: `read_file` reaches the host (filesystem), which this run does not allow; pass --allow filesystem to grant it

A script states its capabilities in its shebang, #!/usr/bin/env -S blue --allow filesystem. A project states them once in its Bluefile: allow is the ceiling of the whole program, reach is the floor each package needs, and blue lock refuses a package whose floor does not fit under the ceiling. virtualize binds a capability to a pure provider, such as a stepped clock, a seeded random source or an in-memory file tree, for the whole program or only for the packages you name. An evaluation session (eval, repl, serve) is pure unless you start it with --allow. Every Rust guarantee, the blue gate that matches it and its off switch are in Safety first.

What ships

Battery What you get Read
The language macros as term rewriting, with bounded expansion; errors raised and rescued by kind, or returned as refusals; OTP-style processes with private environments, copy-on-send and supervised restarts the reference, the agent guide
Tests test blocks beside the code, a doctest in every @doc, coverage, mutation testing, and a conformance suite every evaluator must pass Testing, the spec
Tools one formatter; a check stage whose rules carry their own fixes; a language server with hover, completion, definitions, references, rename, signature help, semantic tokens, inlay hints and code actions; a REPL; watch, profile, trace and code queries Diagnostics
Packages bidamas, each a namespace; a Bluefile that is itself a blue program, pinned by its lock; registries rendered as publish workflows Authoring, Registry
Shipping a Bluefile app, image (built by nix, distroless by default), workload and service (Kubernetes objects and a Helm chart, committed and gated fresh for GitOps), and blue diff, read-only the build stack
Services configuration (settei), entries each off or refused alone (kousei), postures (shisei), request defence (bougyo), retries (saishikou); HTTP, NATS, PostgreSQL, Valkey and JetStream; HTTP/2 framing and HPACK in pure blue Service architecture, HTTP/2
Documentation this README, AGENTS.md, llms.txt and the book, rendered from one source per fact, every example run Documentation, Markdown
Editors a tree-sitter grammar generated from blue's own grammar spec tree-sitter
WebAssembly the whole pipeline compiled to wasm32-unknown-unknown with no host imports at all blue-lang-wasm

Commands

Every command blue takes, read from its own argument parser when this file was rendered. blue help COMMAND shows each one's flags.

Command What it does
blue FILE [ARGS]... Run a program as a script: quiet, and every argument after the file reaches argv.
blue run FILE [ARGS]... Parse, type-check, erase, and execute a program.
blue fmt FILE... Format a program.
blue ast FILE Print the tatara-lisp form, annotations intact.
blue erase FILE Print the tatara-lisp form after type erasure — what actually runs.
blue check [FILE] Check a program against every rule in the registry — unbound names, unused bindings, types, waivers — and report the typing analysis.
blue query QUERY [PATHS]... Every definition under PATH (files, or directories of .b files; . when none) that satisfies QUERY, one line per hit: file:line:col: definition name = value….
blue migrate FILES... Make every reference each FILE makes to another bidama's definition explicit (use("retsu", [:first]), and the bidama's needs), keeping a file only when its resolved tree is proven unchanged.
blue doc [NAME] What NAME is: its signature, doc line, namespace, tier and an example, for a builtin, pkg::name, or a bare name across the builtins and every bidama on BLUE_PATH; a bidama's name lists the package.
blue verbs ARGS... The verb graph (bidamas/mokuroku/graph): import region or merged TSVs into its row files, export them back to TSV (the only writer of TSV), check its gates against the recorded baseline, findings of a TSV directory.
blue explain-name NAME AT How a bare NAME resolves at FILE:LINE: every tier of the resolution order, what each holds, and which wins.
blue census [ROOT] Count, over every .b file under ROOT, each finding of every rule still being ratcheted in, and fail unless each count equals its registry row's ratchet.
blue explain [CODE] Explain a diagnostic code (blue explain B0001), or list them all.
blue test FILE Check the file (as blue check does), then run its test blocks.
blue profile FILE [ARGS]... Run a program and report every function it called: calls, inclusive and exclusive time, and what it allocated, most exclusive time first.
blue trace DEF FILE [ARGS]... Run a program and print each call of DEF with its arguments, and each exit with its value, to stderr.
blue deps FILE Resolve a Bluefile's dependencies.
blue posture FILE Report the posture a Bluefile's declared floor requires.
blue bluefile FILES... Print a Bluefile's evaluated manifest, or confirm its lock is fresh.
blue lock [DIRS]... Evaluate each directory's Bluefile, pin every source(...) with nix flake prefetch, and write Bluefile.lock beside it.
blue bundle FILE Seal FILE into an appliance payload: the program compiled (every use resolved, checked, erased) with the capability record its project's fresh Bluefile.lock verified, closed with its BLAKE3 digest.
blue lsp Run the language server, speaking LSP over stdin/stdout.
blue serve Serve one evaluation session as JSON lines on stdin/stdout (theory/BLUE-TOOLING.md §4): the door an editor drives.
blue repl An evaluation session at the terminal.
blue eval TARGET Evaluate EXPR, or the top-level form at FILE:LINE:COL in that file's context, and print its value.
blue banner Print blue's wordmark.
blue shift FILE Report the blueshift: how far this program is shifted, and what is shifting it.
blue morph The morphology: what each posture grants, what it forfeits, which pairs are genuinely exclusive, and which language each shape corresponds to.
blue reference Print the language reference as JSON: operators, keywords, surface forms, Bluefile words, every bound name and every command, each read from the table the implementation runs on.
blue replay TRACE Run a crashed process again from the trace its crash wrote, and say whether it crashed the same way.
blue crash dump CRASH What a crash violated and where: its class, the host name and capability a breach demanded, the breaching call's file, line and column, the hold, the exit and the mailbox.
blue crash bisect CRASH The fewest messages the process took that still replay to the same crash, found by delta debugging against deterministic replay; the reduced trace is written beside the original under its own hash.
blue crash immunize CRASH The crash's regression lock: a test that spawns the target, sends it the fewest messages that crashed it and asserts it took them, red until the target is fixed.
blue arika like [FILE[:LINE]] The words a draft already is: each definition of FILE (or the one at FILE:LINE) matched to a blue word by def hash (T0), written shape (T1) and shape through a wrapper (T2), with the word's id and import line.
blue arika word NAME Find a blue word by NAME: its canonical spelling, an old spelling's new home, and catalogue glosses that mention NAME (T5).
blue arika emit [ROOT] Write the header SNAPSHOT.json for the bidamas under ROOT (each package's RFC 9162 unit_root and row count, and the snapshot_root over them) and, with --facts, the facts: every definition the engine sees as one JSON line (readable id, def_hash, shape hashes, gloss, file, line, legacy names).
blue receipt verify FILE Recompute a receipt's name from its bytes and check its form; any edit fails.
blue config [TIER] Show the bounds blue is running with, at any tier.
blue new NAME Start a program (a project with its own bidama), a --bidama, a --script, or a --kernel program, each passing blue test as written.
blue watch [CMD] PATH... [-- ARGS]... Rerun check (the default), test or run over each PATH whenever a watched file changes: blue watch test lib.b.
blue image build [NAME] [-- NIX_ARGS]... Build an image(...) through nix and report the tarball, its size and its layers.
blue workload render [NAME] Print a workload's rendered objects, or with --write rewrite every workload's committed output file.
blue diff [NAME] Compare the committed workload files with a cluster, read-only: exit 0 when they agree, 1 when they differ, 2 when the comparison failed.
blue registry render [BACKEND] Print one backend's workflow, or with --write rewrite every standing backend's committed output.
blue registry status The sui state of every pin: warm on the origin SUI_CACHE_URL names, cold, or absent; never fails.

The language in numbers

Counted from the tables the implementation runs on, when this file was rendered:

Built-in names 389: 362 functions, 14 special forms, 13 macros
Surface forms 36, with 13 operators and 26 reserved words
Check rules 78: 42 fix themselves, 8 suggest a fix
Bluefile words 28
Commands 45

The standard library

Every bidama, with the purpose its @moduledoc states

67 packages, 5876 definitions, 1994 tests.

  • angou (暗号) — number theory and the classical ciphers built on it.
  • baito (バイト) — bytes as data: integers at a declared width and order, and record layouts that say where each field sits.
  • bunsho (文書) — Markdown as a first-class value: .md text parsed into one typed tree whose node kinds are the ones CommonMark, GitHub Flavored Markdown and mdast agree on, the tree rendered back in one canonical formatting, and the tree read by node, by kind and by section.
  • burauza (ブラウザ) — the browser: what a blue page needs from the browser, generated.
  • chokkan (直感) — System One judgment: typed questions in, calibrated answers out.
  • chozou (貯蔵, storage) — what a service keeps and reads back.
  • deeta (データ) — JSON data, read safely.
  • eigyou (営業, open for business) — what a running service answers, guards and reports.
  • fairu (ファイル) — files: paths and the files they name.
  • fuuin (封印) — k-of-n threshold signing: a group whose key no one share holds, signed by any k of its n shares in two rounds, RFC 9591 FROST over Ed25519.
  • gamen (画面) — screen: what a program shows, as values: colors and themes, UI trees rendered to HTML, and styled text, tables and trees on the terminal.
  • gitto (ギット) — git, as verbs: a repository read as commits, refs, branches and files, and written by commit, fetch, merge, push and clone.
  • gurafu (グラフ) — directed graphs as values: build them, ask them, order them.
  • hadome (歯止め) — a baseline ratchet: recorded debt may shrink or hold, never grow.
  • happa (葉っぱ) — a template's leaves: their declaration, split, graph, change, schedule and verdicts, as pure decisions.
  • heni (変異) — mutation testing for a blue package: each mutation changes one literal in a fresh copy of the package, runs its tests, and must make them fail.
  • hikisuu (引数) — command-line arguments: one declared spec is parsed into a record, rendered as help, and answered as shell completion.
  • hizuke (日付) — the proleptic Gregorian calendar, as arithmetic.
  • hon (本) — a project's book: its pages, each of one Diátaxis kind, rendered into the files a reader or an agent opens.
  • ibuki (息吹) — the plane an app docks into, as pure decisions: the five structural classes and a docking check over the reach blue lock measured, the Flash channel's token bucket, the Tide channel's LEDBAT controller, and a Strand, a last-writer-wins map whose every transition is a hash-linked record of its input and output roots.
  • isshou (一生, a lifetime) — what a thing goes through, recorded and read back.
  • jisho (辞書) — dictionaries: maps as values, read and changed by key, each change a new map.
  • junjo (順序) — ordering: sorting, searching, selection.
  • kaaneru (カーネル) — the Linux kernel, spoken from blue: maps, programs, links and ring buffers over bpf(2), with every struct a baito layout and no C library in the path.
  • kakehashi (架け橋, a bridge) — blue speaks Nix, Nix runs blue, and a rebuild does only the work that changed.
  • kansuu (関数) — functions about functions.
  • kazu (数) — numbers.
  • keiyu (経由) — by way of: run one command with a proxy set for it alone.
  • khipu — blue's knowledge graph (docs/KHIPU.md): RDF terms as a closed sum, quads, and N-Triples and N-Quads read and written.
  • kiwari (木割): one grammar spec, every syntax artifact emitted from it.
  • kodou (鼓動) — the dual-pulse wire: a Flash channel paced by ibuki's token bucket and a Tide channel paced by ibuki's LEDBAT controller from the one-way delay each acknowledgement measures, over one UDP socket the host frames (0x02 Flash, 0x01 Tide); and the gossip of crash proofs on it: an alert on Flash, the artifact on Tide when a peer asks for it, verified by its content hash and kept in kensa's kensa-immunity.v1 file.
  • koubou (工房, workshop) — shapes made, measured and cut.
  • kousei (構成) — a system composed entry by entry: each entry checked, configured off, tuned or refused alone, then judged into what stands.
  • koutei (工程) — one step of a pipeline, as GitHub Actions runs it.
  • kueri (クエリ) — queries: analysis is authored in blue, and SQL is only the rendered bridge to DuckDB.
  • kurasuta (クラスタ, a cluster): Kubernetes, spoken from blue.
  • kyohi (拒否) — refusals, as data.
  • maakuappu (マークアップ) — XML as data: a document parsed by the runtime's xml_parse (quick-xml) into element maps {name, attributes, children, text}, the queries a reader of a scanner export asks of it (children and descendants by name, attributes, text, a path of element names), and the element rendered back with every value escaped.
  • mitoshi (見通し, a clear view ahead) — what a running program shows of itself.
  • moji (文字) — strings.
  • mokuroku (目録): the catalogue of what every bidama on a BLUE_PATH provides.
  • okite (掟) — blue's decisions, each enforced by laws written in blue.
  • ongaku (音楽) — twelve-tone music theory, as arithmetic on semitones.
  • ran (乱) — deterministic pseudo-randomness.
  • retsu (列) — lists, made TOTAL.
  • ronri (論理) — predicates, and the algebra over them.
  • sabi (錆): Rust source from blue data.
  • saishikou (再試行) — retrying a step that can fail for a moment.
  • seimei (生命) — cellular automata: elementary rules, and Life.
  • settei (設定) — configuration, blue's shikumi: a record of defaults grouped by concern, resolved by read(app, defaults) from the defaults, then ~/.config//.yaml (or CONFIG), then __ in the environment, each value typed by its default and a wrong type refused.
  • shinchoku (進捗) — progress: operational probes that judge by progress over a window, never by one reading.
  • shinsatsu (診察) — the credential doctor: a provider, the failure classes its credential helper can show, and for each class a diagnosis, the remediation steps and a verify step.
  • shinsuu (進数) — base conversion and checksums.
  • shisutemu (システム) — the system.
  • shomei (署名) — signatures and hash chains: Ed25519 and BLAKE3, for real.
  • shuugou (集合) — sets, over plain lists.
  • shuusei (修正) — amending declared data: put a value at a path, delete it, merge into it, upsert a list element, and amend a keyed set of objects by judged patch entries.
  • suugaku (数学, mathematics) — numbers worked over as a discipline.
  • tesuto (テスト) — testing: errors and snapshots as assertions, and the policy that holds every definition to a test beside it.
  • todokede (届出, filings) — what a person or a company declares as entries.
  • toride (砦) — a fort at the border: split-horizon DNS for a machine that roams between sites.
  • toriyose (取り寄せ, fetching on order) — what a frontend asks for and keeps.
  • touroku (登録) — registry: a project published to and resolved from registry backends, each a rendering of the Bluefile, never its truth.
  • ugoki (動き) — motion: how a value moves over time.
  • ukai (迂回) — a detour: keep an overlay VPN reaching its control plane and relays while a full-tunnel corporate VPN owns the default route.
  • utsushi (写し, a transcription) — a part of a repository's history, shown as a history of its own: a lens picks the part, and each commit is written again over the part's tree, with its author, committer and message unchanged, so the same lens over the same commit gives the same commit id on every machine (docs/UTSUSHI.md).
  • zenbu (全部) — the whole distribution, as ONE dependency.

What is not built

blue states its gaps plainly, because a language's honest gaps matter more than its claims. This list is the one in Implementing blue, rendered here:

Stated so nobody cites it as existing: no per-process GC heap (processes have private environments and messages are deep-copied, but reclamation is Arc refcounting — no independent collection pause), no registry client (resolution is real; nothing fetches), no self-hosting on the implementation axis (spec/*.b is the specification axis only), no comment attachment inside a form, no entropy primitive and no encryption (the crypto layer hashes, signs and verifies; a keypair comes from a seed the caller supplies), no TLS (net speaks NATS and HTTP over plain TCP: an https:// url and a NATS server requiring TLS are refused by name; planned in docs/HTTP2.md P4, rustls with ALPN h2), no import EMISSION into a wasm module (blue_lang_waku::imports_of derives the table from a frame — nothing puts an entry into a .wasm, and no engine border is wired: that is BLUE-EXECUTION.md M2, blocked on tatara-wasm not being on crates.io), no editor answer inside a broken buffer (the LSP answers from the newest revision that parsed until the parser recovers, BLUE-ENGINE.md E6), project rules in the editor or as wasm (blue check runs them in-process under the rule frame; the LSP does not run them, and the ABI is shaped for a wasm module that nothing builds yet), no account of a move the send ring cannot carry (from a held node a moved plain process brings its tape, mailbox journal and host-call count, blue-image version 5, and a moved server its journal, count and the root of the state its incarnation began with, version 6, so each crash trace and receipt covers the whole incarnation; an account past the tape bound or the send ring stays behind, and that process's journal, count and a server's receipt input_root start at the node it moved to), no link across nodes (evict breaks a link and tells a partner that traps exits; it refuses one that does not), no authenticated image (an image's BLAKE3 name proves it arrived whole, not who sent it; it runs under the accepting node's frame, never more), and no case/when pattern matching or ranges — the two remaining surface gaps a Ruby or Elixir author would reach for. theory/BLUE.md §V.26 holds the tier ledger; do not build against a DESIGN-tier row without saying so.

Theming

Colours come from irodori, the fleet's Nord palette. blue carries no hex of its own. nord10 (#5E81AC, deep frost blue) is its identity, and nord8 frost cyan stays the fleet's shared interaction colour: identity and interaction are different roles. The mark is a blueshift too: four solid cells walk Nord's Frost band toward blue. It names each colour by ANSI slot, never by hex, so it renders in your Nord and follows you when you retheme.

Building blue

$ nix build .#blue
$ nix flake check
$ cargo test --workspace

nix build is hermetic. nix flake check runs every gate the root Bluefile declares. This README is rendered by hon from docs/introduction.md, the first tutorial, the implementation's own tables and the catalogue; edit those, then run nix run .#regen. Changing blue itself starts at AGENTS.md.

MIT.

The book

Read it in order as The blue Book, or open one page:

Tutorials

  • Install blue: install blue, evaluate one expression and run a first file, in about a minute
  • A first script: write a script that reads its arguments, and let blue start one for you
  • A first program: start a program with blue new, change its code, and test it
  • A first bidama: write a documented bidama with doctests, read its docs with blue doc, and use it from a program
  • A first service: declare a service in a Bluefile, write its handler and tests, and see what blue renders from it
  • A first kernel program: start a kernel program with blue new --kernel, test it with no kernel, make it drop ICMP, and load it on Linux

How-to guides

  • Write a test and a doctest: write a test block and a doctest, read a failure, and run one test by name
  • Climb the blueshift: move a file from dynamic to checked one annotation at a time, reading blue shift at each step
  • Declare what a program may touch: hold a program to the host capabilities it needs with --allow, in a run or in a script's shebang
  • Write an action: write a GitHub Actions step in blue with koutei, and run it locally before CI does
  • Publish a bidama: make a bidama reachable from other projects, and declare the registries that publish it
  • Run a pure worker: write a pure data transformation, run it under --allow none, and see the check stage refuse a variant that reaches the host
  • Supervise processes: start worker processes under a supervisor, crash one, and see its restart strategy bring it back
  • Virtualize a capability: give a program a stepped clock with the Bluefile word virtualize, so now_ms is the same at every run, and scope it to one package with for:
  • Test a refusal: test that code refuses correctly, for an error raised by kind, a kyohi refusal returned as data, and a run held by --allow that breaches with exit 77
  • Pick a kernel hook: choose the kernel hook for a task, compile for its program kind, and attach with one word
  • Read a kernel field: read a field of a kernel struct at the offset the running kernel states, and test the read on the pure machine
  • Debug a kernel refusal: find which layer refused a kernel program, the compiler, the machine or the verifier, and read why
  • Ship a node agent: declare a service that reaches the kernel, see the DaemonSet and exact capabilities blue renders, and test it with no cluster

Reference

  • Canonical forms: every place the surface accepts two spellings, the one blue writes, and the rule that names it
  • Commands: every blue verb with its flags, one row each; the agents page keeps one line per verb and links here
  • Diagnostics: what the check stage reports, every rule code, and the machine-readable shape of a diagnostic
  • blue examples: one tested program per common task, ready to paste as examples
  • Glossary: blue's terms and the concepts they name: every blue term mapped to the compiler, language or distributed-systems concept it names, in both directions, and how the parts meet in a compile, a test run and a deploy
  • blue language reference: syntax, operators, reserved words, every built-in name and the Bluefile words
  • blue roadmap: the one blue roadmap, one row per track with its tier, next step and done gate, and every conflict ruled once
  • Safety first: blue's posture, row by row: the safety-first posture, one row per Rust guarantee: blue today, the gate, its tier and its off switch
  • blue — the agent guide: rules for people and agents who write blue programs or change blue itself, with the build commands from the Bluefile
  • Implementing blue — the detail behind the agent guide: the implementer detail behind the agent guide's "Changing blue itself": the check registry, crate map, hard-won rules, CI gates, dependencies and what is not built

Explanation

50 pages on why blue is shaped as it is

About

The pleme-io language: a Ruby/Elixir surface on a tatara-lisp AST, macros as term rewriting, and a Rust runtime. Sliding-scale optional typing, bounded macro expansion, OTP-style supervision, and a WASM target with zero host imports.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages