v0.2.5 - active development

fluid syntax,
disciplined state

Rye is a high-level, function-centric language with no keywords, strict state handling, and rich failure values - designed for predictable, composable programs and interactive use.

no keywords code-as-data 41 datatypes strict state no null multiple DSLs table datatype console / REPL++ embeds in Go
rye
; all control flow is just functions with 2 arguments
probe ?if ; [Builtin(2): if condition block]

blk: { print } .concat "Hello Rye"
if 2 > 1 blk ; Hello Rye

; expressions compose linearly
range 1 10
|filter { .math/is-prime }
|map fn { n } { 1 / n }
|sum |probe ; [Decimal: 1.176190]

; no null - rich failures, in-flow handling
person -> "user"
|fix { "Anonymous" } |print

; constants by default
name: "Tango" ; set-word - constant
age:: 42 ; mod-word - variable

A few clear ideas, taken seriously

Rye is shaped by a small number of strong principles rather than a large bag of features. These ideas determine how the language behaves and why it feels different.

01 - Flexibility

Everything is an expression

All constructs - control flow, assignment, I/O - return a value. Code composes linearly with the pipe operator, reducing intermediate state and variable noise.

; assign and print inline apples: print 12 ; prints 12, assigns 12 ; compose without temporaries range 1 10 |filter { .math/is-prime } |map fn { n } { 1 / n } |sum
02 - Flexibility

Functions are all you need

Rye has no keywords and no special forms. if, loop, fn, try, return are all built-in functions - meaning you can inspect, replace, or build your own.

probe ?fn ; prints the builtin's docs ; your own control structure if-joe: fn { n code } { if n = "Joe" { do code } } if-joe "Joe" { print "Hey" }
03 - State

Constants by default

Words defined with : are constants and cannot be redefined. Mutation requires a mod-word ::, which is visually explicit and intentionally costly.

name: "Tango" name: "Cash" ; Error: can only set once name:: "Cash" ; Error: can't mod constant ; declare word as variable in current context var 'month "January" month:: "February" ; Creates of modifies var.
04 - State

No Null - rich Failures

Functions return a value or a Failure. Failures carry a message, type, and status code. Unhandled failures escalate to errors, forcing resolution before they cause invisible bugs.

; missing key = Failure, not nil person -> "surname" |fix { "Doe" } |print ; prints Doe ; failures nest and carry context Read %user.txt |^check "Couldn't read user file"
05 - Flexibility

Code is data

Rye code is made of Rye values. Blocks of code can be passed, stored, combined, and introspected - without a macro system or eval quirks.

thats-true: { capitalize "that's true" } do thats-true ; "That's true" ; combine blocks as data print-it: { print } ++ thats-true if 1 > 0 print-it ; prints That's true
06 - State

Strict scope isolation

You cannot modify variables in outer or nested scopes directly. Mutation across scopes requires explicit functions ending in !, making side effects visible and intentional.

var 'name "EU" country: context { change-name!: fn { n } { .change! 'name } } ; country/name:: "X" - doesn't exist country/change-name! "France" ; OK

What Rye looks like in practice

String manipulation
"Hello World" .replace "World" "Mars" |print ; Hello Mars
Sum of unique numbers in a string
"12 8 12 16 8 6" .load .unique .sum ; returns 42
Switch / pattern matching
switch 'cow { dog { "woof" } cow { "mooo" } cat { "meow" } } ; returns mooo
Filter a collection
{ "Anne" "Joan" "Adam" } |filter { .first = "A" } |for { .print }
Regexp extraction
regexp "([0-9][a-z])" |Submatch? "-7--x3--0k-r--" ; returns 0k
Primes - functional pipeline
range 1 10 |filter { .math/is-prime } |map fn { n } { 1 / n } |sum |probe ; [Decimal: 1.176190]
Read file - count lines, show tail
Read\lines %data.txt |with { .length? .print .tail 5 |print }
Load CSV, query average
Load\csv %ryebots.csv |where-equal 'level 7 |column? 'score |avg
Fetch page, save, extract links
Get https://ryelang.org |Write* %page.html |reader |Parse-html { <a> [ .Attr? 'href |print ] }
HTTP JSON fetch in a goroutine
go does { Get https://httpbin.org/get |parse-json -> "headers" -> "User-Agent" |print } print "Loading ..."
Serve a static folder
http-server ":8082" |Handle "/" new-static-handler %public_html |Serve
Respond with current time
http-server ":8081" |Handle "/time" fn { w r } { .Write to-string now } |Serve
SMTP server - print on new mail
handler: fn { mail from to origin } { printv from "new mail from {}" } smtp-server ":25" |Serve ?handler "demo"
SQL query with dialect
rye .Args? .first :id Open sqlite://data.db |Query { select * from operator where id = ?id }
Validation dialect
dict { name: "anakin" } |validate { name: required calc { .capitalize } score: optional 0 integer } ; { name: "Anakin" score: 0 }
Math dialect (with operator precedence)
; Rye normally has no precedence ; math dialect adds it math/calc { 2 + 2 * ( 12 + ( 24 / 3 ) ) } ; returns 42
GUI with Fyne (Go binding)
fyne: import\go "fyne" widget: import\go "fyne/widget" lab: widget/label "Waiting ..." btn: widget/button "Click" does { lab .set-text "Done!" } app/new .window "Demo" |.set-content container/vbox [lab btn] |.show-and-run
A simple rule engine
rules: [ context { condition: { temp > 0 |and level < 70 } action: { print "OPEN" } } ] temp: 23 , level: 45 for rules { ::rule if do rule/condition rule/action }
Load XLSX, filter and display
spr: Load\xlsx %adversaries.xlsx spr .where-contains 'Species "AI" |order-by 'Year 'asc |head 3 |columns? { 'Name 'Keywords } |display
Group-by aggregation
Load\csv %sightings.csv |add-col! 'Area 'Location [ regexp ".*?,(.*?) \d+" "$1" ] |group-by 'Area { 'Sightings sum } |display

What's included out of the box

Written in Go

Rye compiles to a single binary. Go libraries integrate seamlessly - Rye can embed or extend any Go program as a scripting or config language.

Interactive console

Syntax highlighting, history, tab completion, and environment exploration tools are built into the REPL. Designed for iterative development.

Multiple DSLs

Validation, Math, SQL, and HTML dialects are built-in. The same code-as-data foundation lets you build your own domain-specific languages.

HTTP servers SMTP server SQLite MySQL PostgreSQL JSON BSON HTML parser Regexp Goroutines Crypto Bcrypt AWS Postmark FT search SXML
Fyne GUI Gio UI Ebitengine (games) Ryegen (bindings generator)

Download & install

Rye runs on Linux, macOS, and Windows. Also available for WASM (browser), Docker, Android, and iOS.

Platform x86 64-bit ARM 64-bit WASM
Linux v0.2.5 ↓ download ↓ download ↓ wasm
macOS v0.2.5 ↓ download ↓ download =/=
Windows v0.2.5 ↓ download / =/=
Homebrew
brew install ryelang
Arch Linux (AUR)
yay -S ryelang
Docker
docker pull ghcr.io/refaktor/rye:latest

Building from source is straightforward with Go. See the README on GitHub for instructions.

Documentation & community

Meet Rye

Language basics, concepts, and core components. The best starting point after these examples.

Read →

Rye Cookbook

Practical guides for specific tasks - tables, HTTP, GUI, databases, and more.

Browse →

Function reference

Documentation and short examples for core built-in functions.

Explore →