GENO

Preview 0.5.0 release notes /Apache-2.0/Python 3.10–3.13

A programming language for code you didn’t write.

Geno is a statically typed, functional-first language for programs written with LLMs. Functions carry examples that run as tests, every block closes by name, and files, the network and other processes stay off until you grant them. It runs directly and compiles to Python and JavaScript.

$ pip install geno-lang
Open the playground

Needs Python 3.10–3.13. Geno is pre-1.0, so the language may still change.
Read the datasheet

The replay in five steps:

  1. A model writes score_label, a function that labels exam scores. It has four examples: 90 is excellent, 89 and 60 are passing, 59 needs work. The model sets the passing threshold at 75.
  2. geno test -v score.geno prints: FAIL score.geno (3/4). x score_label: expected "passing", got "needs work".
  3. The model reads the examples: 60 passes and 59 does not, so it changes the threshold from 75 to 60.
  4. geno test -v score.geno prints: PASS score.geno (4/4). 4 passed, 0 failed.
  5. geno compile writes score.py and, with --target js, score.js.
Figure 1. Typical repair sequence. TV1–TV4 are its four examples, run as test vectors. Every line Geno prints here is real output from the 0.5.0 CLI. Passing examples are evidence, not proof.

1Features

  • Executable example clauses, required on ordinary functions
  • requires and ensures contracts, compiled into every backend
  • Named block endings: end func, end if, end match
  • Exhaustive pattern matching over algebraic data types
  • Capability-gated effects: files, network, processes, environment, clock
  • Static types with local inference, generics and traits
  • Runs directly; compiles to Python and JavaScript
  • Next-token constraints for guided generation (research)

2Applications

  • Command-line tools and automation on Python or Node.js
  • Browser dashboards, internal tools and small games
  • Hosted request handlers behind geno serve
  • Code paths written or repaired by coding agents
Device information(1)
TargetRuntimeStatus
python-cliCPython 3.10–3.13Beta
node-cliNode.jsBeta
browserStatic HTML + JSBeta
python-hostedgeno serveBeta

(1) For what each target needs, see 10.2 Targets.

3Description

Models are good at writing code that looks right. Geno is designed so that looking right is not enough. A function states its types, carries examples that run, and closes every block by name. A program cannot grant itself access to files, the network or other processes; the person running it grants each capability by name.

The result reads like a small, strict functional language: immutable by default, with algebraic data types, Result and Option for errors, pipelines and traits. The checker makes sure every case is handled, and geno test makes sure every example still holds.

Geno is in public preview. The parser and type checker are stable; the language surface may change before 1.0.

Contents4 Anatomy of a function
  1. 4Anatomy of a function
  2. 5Break it yourself
  3. 6Playground
  4. 7Install
  5. 8Capabilities and limits
  6. 9The language
  7. 10How Geno runs
  8. 11Performance
  9. 12Applications
  10. 13Tools and community
  11. 14Releases

4Anatomy of a function

A Geno function is a component with a published interface. Its signature is the pinout, its examples are the test conditions, and its last line says exactly what it closes.

score_label drawn as an integrated circuit A Geno function shown as a chip: input pin score of type Int, output pin String, a requires pin for the precondition, an example pin carrying four test vectors, a caps pin showing no effects, and an end func pin. U1 score_label GENO 0.5 · FUNC 12 34 56 score: Int caps: none → String example ×4 requires score >= 0 end func 90 pure "excellent" 4/4 pass
Test vectors from the example clauses of score_label
VectorscoreExpectedResult
TV190"excellent"PASS
TV289"passing"PASS
TV360"passing"PASS
TV459"needs work"PASS
Figure 4-1. Functional diagram of score_label. Each example clause is a test vector, run by geno test. Point at a pin to read its function.
score.geno15 lines · 4 examples
1func score_label(score: Int) -> String3
5    requires score >= 0
4    example 90 -> "excellent"
    example 89 -> "passing"
    example 60 -> "passing"
    example 59 -> "needs work"
 
    if score >= 90 then
        return "excellent"
    else if score >= 60 then
        return "passing"
    else
        return "needs work"
    end if
6end func
Figure 4-2. score.geno after the repair in Figure 1, with its pins marked.
Table 4-1. Pin functions of score_label
PinNameTypeDescription
1score: IntIParameters always carry types. Local let bindings may be inferred.
2caps: nonePEffects. The body uses no capability, so it runs anywhere. A function that read files would run only where --cap fs is granted.
3-> StringOReturn type, required. Errors are values, Result[T, E] and Option[T], never null.
4exampleTExecutable specification, run by geno test. Required on ordinary functions; main, async functions, app lifecycle hooks and @untested functions are exempt.
5requiresCPrecondition, checked on every call in the interpreter, Python and JavaScript. ensures checks result.
6end funcTNamed terminator. A mismatched end fails on its own line, so generated structure cannot drift silently.

I = input, O = output, P = permission, C = contract, T = checked by the toolchain. Pin numbers match Figure 4-1.

5Break it yourself

Every number in this listing is live. Drag one sideways, or focus it and use the arrow keys. Move a threshold and watch which example catches it; the output is what geno test -v prints for the same program.

Figure 5-1. Example clauses under test. All 4 examples hold


        

      

6Playground

The real Geno 0.5.0 toolchain, running in this tab on CPython compiled to WebAssembly (Pyodide). The first run downloads Python, about 13 MB, and your browser caches it. Your code never leaves the page.

Output

        
Esc, then Tab, leaves the editorOpen the full-size playground

7Install

Geno needs Python 3.10 to 3.13. Install the CLI, create a project, and run its examples.

  1. 01
    Install
    $ pip install geno-lang
  2. 02
    Create a project
    $ geno init hello --template cli
  3. 03
    Test and run
    $ cd hello && geno test Main.geno
      PASS  Main.geno (3/3) (1 untested)
    
    3 passed, 0 failed, 1 untested, in 0.11s
    $ geno run Main.geno
    >>> Hello, World! <<<
Table 7-1. Project templates
TemplateCommandCreates
GENO-CLIgeno init app --template cliCommand-line program
GENO-WEBgeno init app --template webBrowser app with canvas
GENO-APIgeno init app --template apiMulti-module API
GENO-LIBgeno init app --template libReusable library

From source: git clone https://github.com/davidiach/geno-lang && cd geno-lang && pip install -e ".[dev]"

8Capabilities and limits

Generated code runs with what the person running it allows, and within limits they can see.

8.1Capabilities

Most computation is always available. Regular expressions and anything that reaches outside the program need a capability. Plain geno run grants print, clock and random; every other capability is granted by name by the person who runs the program, and a program cannot grant itself anything.

Table 8-1. Capabilities
CapabilityUnlocksPlain geno run(1)
printConsole outputGranted
clockTimestamps, timing, sleep_msGranted
randomRandom numbersGranted
fsRead, write and list filesDenied
httpOutbound HTTP and HTTPSDenied
envEnvironment variables, CLI argumentsDenied
processRun other programsDenied
regexRegular expressionsDenied
stdinStandard inputDenied
serveListen for HTTP requestsDenied

(1) geno run app.geno compiles to Python and runs it in an isolated process with print, clock and random. Every other call is refused where it happens, naming the capability it needs (reported as E412 by --json and the embedding API).

Granting a capability

$ geno run --unsafe --cap print,fs app.geno   # direct interpreter
$ geno run --json --cap print,env app.geno    # embedding API, JSON result
$ python app.py --cap print,fs                # compiled Python

--cap grants exactly the capabilities it lists, so name print too if the program prints. The default lane refuses --cap, so a grant can never quietly switch off process isolation. --unsafe means no process isolation; capability checks and step limits still apply.

Granted is not unlimited. With fs, paths resolve inside the project’s filesystem roots and absolute paths are rejected; with http, loopback and private-network addresses are refused and responses are read through size limits. Generated JavaScript is trusted code, not a sandbox. See the security policy.

Figure 8-1. Capability gating. Grant capabilities and watch where the program stops.

--cap

          

        

8.2Resource limits

Every geno run is bounded: a program that exceeds a limit stops with an error instead of exhausting the machine. Standalone compiled Python and JavaScript keep the integer and collection guards, but have no timeout or step limit of their own.

Table 8-2. Default limits
ParameterDefaultUnitSet with
Python, toolchain and compiled output3.10 – 3.13version—
Interpreter steps per run(2)1,000,000steps--max-steps
Call depth500frames--max-recursion-depth
Integer size33,219bits--max-integer-bits
String and collection size10,000,000elements--max-collection-size
Captured output100,000characters--max-output-length
Sandboxed memory, geno run268,435,456bytes (256 MiB)--max-memory-bytes
Wall-clock timeout, geno run30seconds--timeout

(2) Applies to geno run --unsafe and --json. Every limit except memory is also a field of RunConfig in the embedding API, where the host sets it.

9The language

A small, strict functional language: immutable by default, with algebraic data types, Result and Option for errors, pipelines and traits. Each feature below is there because it turns a plausible mistake into a reported one.

9.1Named block endings

A model writes one token at a time. With braces, the end of a loop and the end of a function are the same character, and losing count produces code that parses and means something else. In Geno every block closes by name, so a mistake fails at the exact line.

Because openers and closers always pair, Geno can say at any point in a partial program what is still open. That is what geno constrain reports, and what a constrained decoder can use to keep a model’s block structure intact.

Stack values in Figure 9-1 come from geno.constraints.get_unclosed_blocks on each prefix.

Figure 9-1. A model streaming Geno. Open blocks, innermost first.


        

9.2Exhaustive matching

Algebraic data types describe every shape a value can take, and the checker holds every match to all of them. Add a variant later and each match that ignores it stops compiling, naming the case it missed.

Click an arm to remove it or put it back. The output is geno check.

A wildcard _ also satisfies the checker. It covers every case, including variants added later, without naming them, so use explicit arms where a new case should force a decision.

Figure 9-2. Click a match arm to toggle it.


        

      

9.3Errors are values

func parse_port(arg: String) -> Result[Int, String]
  example "8080" -> Ok(8080)
  example "http" -> Err("not a number: http")
  match parse_int(arg) with
      | Some(n) -> return Ok(n)
      | None -> return Err("not a number: " + arg)
  end match
end func

Result and Option replace null and unchecked exceptions. The ? operator returns an error early.

9.4Pipelines

func squares_of_evens(xs: List[Int]) -> List[Int]
  example [1, 2, 3, 4, 5] -> [4, 16]
  return xs
      |> filter(_, fn(x: Int) -> x % 2 == 0)
      |> map(_, fn(x: Int) -> x * x)
end func

Data flows left to right; _ marks where the value goes. List comprehensions cover the rest.

9.5Traits

type Planet = Planet(name: String, moons: Int)

trait Describable
  func describe(self: Self) -> String
end trait

impl Describable for Planet
  func describe(self: Planet) -> String
      example Planet("Mars", 2) -> "Mars has 2 moons"
      return f"{self.name} has {self.moons} moons"
  end func
end impl

Shared behaviour without inheritance. Methods carry examples like every other function.

9.6Async, data, modules

async func page_size(url: String) -> Int
  return length(http_fetch(url))
end func

func main() -> Int
  let size = await page_size("https://example.com")
  let rows = csv_parse_with_headers("name,age\nAda,36")
  return size + length(rows)
end func

async and await, built-in JSON, CSV and TOML, and modules with explicit export.

10How Geno runs

10.1Toolchain

One front end, three ways to execute. Before any backend sees the program, the checker holds every match to all of its cases and works out which effects each function has. geno test runs the examples; geno compile does not, so keep geno test in CI.

IN.geno sourcewritten by you or a model
GENO 0.5 TOOLCHAIN
Lexertokens
ParserAST, block stack
Type checkergenerics, effects, exhaustiveness
Example harnessgeno test
Interpretergeno test, --unsafe, REPL
Python backendgeno compile, geno run
JavaScript backendESM, source maps, .d.ts
Constrainallowed next tokens, open blocks
OUTpython-cli
node-cli
browser
python-hosted
Figure 10-1. Functional block diagram. Highlighted blocks are where generated code gets checked.

10.2Targets

One program, four places to run. A project declares its targets in geno.toml, and geno check --target rejects builtins a target does not provide before anything runs.

MODE A

python-cli

Beta

Command-line tools and automation. Multi-module projects compile to one Python file that runs without Geno installed.

$ geno compile app.geno -o app.py
$ python app.py --cap print,fs
MODE B

node-cli

Beta

The same program on Node.js, as a script or ES module with source maps and type declarations. Trusted execution only.

$ geno compile app.geno --target js -o app.js
$ node app.js --cap print
MODE C

browser

Beta

App-mode programs with init, update and render build to static files with canvas, keyboard and mouse.

$ geno build Main.geno -o dist/
$ geno dev   # live reload
MODE D

python-hosted

Beta

An HTTP runtime with isolated execution, authentication, rate limits and Prometheus metrics.

$ geno serve
# POST /run · GET /healthz · GET /metrics

11Performance

Compiled Geno against hand-written Python on the same 53 problems. Geno keeps its safety checks in the compiled output, guarding integer growth and collection sizes, and pays for them here.

1.60×median time vs Python
84.9%of problems at or under 2×
0.92×best case, mutual recursion
2.84×worst case, list building
Figure 11-1. Runtime ratio, Geno compiled ÷ Python, one dot per problem. Teal dots meet the ≤ 2× target. Measured 2026-06-10, Python 3.11, Linux; problems under 5 ms on both sides excluded.
Show the data

12Applications

12.1Reference apps

Each reference app must check, test and build before a release is tagged. Together they cover all four modes.

12.2Prompting a model

Models arrive knowing Python and JavaScript. These rules cover the mistakes they make most often in Geno. Paste them into a system prompt, then let geno test report anything they miss.

  • let mut var
  • True true
  • "a" ++ "b" "a" + "b"
  • end: Int stop: Int
  • clamp(5, 0, 10) clamp(value: 5, lo: 0, hi: 10)
system-prompt.txt
You are writing code in Geno, a statically typed, functional-first language.
- Immutable: let x = 5. Mutable: var count = 0.
- Parameters and return values need type annotations.
- Booleans are lowercase: true, false.
- Concatenate strings with +. Integer division truncates: 7 / 2 = 3.
- Close blocks by name: end func, end if, end for, end while, end match.
- Write then after if conditions and do after for and while.
- Every function except main needs at least one example clause.
- Functions with 3 or more parameters take named arguments.
- Use Option[T] instead of null and Result[T, E] for errors.
- Do not name anything end, in, with, type, or a Python builtin.

13Tools and community

13.1Tools

geno run
Run a file, sandboxed by default
geno test
Run every example and test block
geno check
Types, exhaustiveness, target fit
geno compile
Emit Python or JavaScript
geno build
Static browser app in dist/
geno dev
Dev server with live reload
geno constrain
Allowed next tokens for a prefix
geno fmt
Format source files
geno init
New project from a template
geno add
Add a dependency
geno doc
Generate HTML documentation
geno serve
Hosted HTTP runtime
geno repl
Interactive session
geno watch
Re-run on file changes
geno lsp
Language server

13.2Docs and community

Take part

Geno is created and led by David Iach, the project lead and code owner. Governance explains how decisions are made and how contributors become maintainers.

13.3Status

Geno is in public preview. This is what you can rely on today, from the maturity matrix.

Stable

  • ParserFull language coverage, structured diagnostics
  • Type checkerGenerics, ADTs, traits, exhaustiveness

Beta

  • Language coreThe pre-1.0 surface may still change
  • Python and JavaScript backendsProjects, source maps, ESM, .d.ts
  • InterpreterEvery feature, including capability gating
  • Browser appsgeno build to dist/ or one HTML file
  • Capability systemEnforced across interpreter and hosted entry points
  • Hosted runtimeAuth, rate limits, metrics; not yet proven under production load

Experimental

  • Package managerGit dependencies, pins, lockfile hashes
  • LSP, formatter, VS CodeWork for common cases
  • Self-hosted front endLexer to interpreter in Geno; no code generation yet

Research

  • Constrained decodingBlock-structure checks on a prefix work; not yet benchmarked with models

14Releases

RevisionDateChanges
0.5.02026-10-140.5.0-rc.1 promoted unchanged; still pre-1.0
0.5.0-rc.12026-10-14main() -> Int becomes the exit status; named constructor arguments; an Async value runs once; module constants; normative 0.5 specification
0.4.42026-09-20geno check validates lowering through the Python backend
0.4.22026-07-22Versioned specification, frozen conformance corpus, weekly 2,000-case differential fuzzing
0.4.02026-07-13Single builtin manifest; recursive exhaustiveness for nested patterns
0.3.02026-04-06CSV and TOML builtins; process capability
0.2.12026-03-31JavaScript backend
0.2.02026-02-06Embedding API; capability-based security
0.1.02024-12-01Initial release: lexer, parser, type checker, interpreter, Python compiler

Complete history in the changelog.