A gecko is a tiny reptile. This is a tiny Python.
Gecko is a Python runtime built from scratch, for the cases where CPython spends
most of its time starting up.
It runs the same programs, in a fraction of the startup time and the space.
$ ls -lh target/release/gecko
-rwxr-xr-x 737K gecko*
# a frozen program, size-optimized runner
-rwxr-xr-x 265K fib*- Why Gecko?
- Installation
- Benchmarks
- Compatibility
- Concurrency
- Embedding
- Building Gecko
- Security
- Contributing to Gecko
| Gecko | CPython 3.14 | |
|---|---|---|
| Startup, hello world | 3.0 ms | 19.5 ms |
| Peak memory | 1.8 MB | 13.5 MB |
| Install size | 737 KB | 273 MB |
| Standalone binary | 265 KB | none |
| Concurrency | isolates and actors | threads, GIL by default |
| Arbitrary-precision int | yes | yes |
| C extension modules | no | yes |
Gecko is built for environments where size and startup time decide things: serverless functions, edge workers, embedded scripting, CLI tools, and short scripts that do a bit of work and exit.
Gecko implements standard Python with no language extensions. A Gecko program is a valid Python program and still runs on CPython, so LSPs, formatters, linters, and type checkers go on working. The runtime is hand-built: a Rust frontend for the lexer, parser, and compiler, and Setae, a C VM with a computed-goto interpreter, NaN-boxed values, inline caches, and a precise mark-sweep collector.
There is no prebuilt binary yet. Build from source with Rust 1.85 or newer, plus Meson and Ninja for the C runtime:
pip install meson ninja
git clone https://github.com/punctuations/gecko
cd gecko
cargo build --release
./target/release/gecko examples/fib.pyTo put gecko on your PATH:
cargo install --path crates/geckoSee BUILDING.md for supported platforms, the size-optimized runner, and how to freeze a program into a standalone binary.
Scripts are in benchmarks/. They run unmodified on both runtimes
with byte-identical output, apart from arrays.py, which uses the gecko-only
typed-array API. Measured with hyperfine against CPython 3.14.6.
The case Gecko is built for. Loads a script, prints, and exits.
hyperfine -N --warmup 20 --runs 300 \
'target/release/gecko benchmarks/startup.py' \
'python3.14 benchmarks/startup.py'| Runtime | Mean | Min | Max | Relative |
|---|---|---|---|---|
| Gecko | 3.0 ms | 2.7 ms | 3.5 ms | 1.00 |
| CPython 3.14 | 19.5 ms | 18.7 ms | 21.9 ms | 6.62x slower |
A frozen binary starts in 2.9 ms, since it parses and compiles nothing.
Ahead on all five.
| Benchmark | Gecko | CPython 3.14 | Result |
|---|---|---|---|
arithmetic.py, 3M-iter loop |
143.0 ms | 232.7 ms | 1.63x faster |
calls.py, 600k calls |
77.8 ms | 115.9 ms | 1.49x faster |
fib.py, recursive fib(25) |
20.4 ms | 33.5 ms | 1.64x faster |
sieve.py, primes to 1M |
129.3 ms | 132.9 ms | 1.03x faster |
wordcount.py, dict and str |
122.8 ms | 135.5 ms | 1.10x faster |
Integers above 140737488355327 leave the unboxed range and slow down by about 3x.
Environment
| Detail | Value |
|---|---|
| Hardware | Apple M1, 8 GB RAM, 8 cores |
| OS | macOS 26.4.1 (arm64) |
| Gecko | 0.0.8 |
| CPython | 3.14.6 |
| hyperfine | 20 warmup, 300 timed runs |
Gecko runs a large subset of Python end to end: the full expression and
statement grammar (f-strings with format specs, comprehensions and generator
expressions, slicing, the walrus operator, match, with, decorators, and
try/except/else/finally), the whole call convention (keyword arguments,
defaults, *args, **kwargs, spreads), closures with nonlocal, generators,
async/await, classes with single inheritance, super(), @property,
@staticmethod, @classmethod, and import/from ... import.
Built-in types are int, float, bool, str, list, tuple, dict, set, frozenset, range, and typed arrays. Integers are arbitrary precision. Sets of integers iterate in CPython's order.
Constructs outside the supported grammar are rejected at compile time with a located error. There is no standard library yet, and wheels with compiled C extensions do not run. The test suite is 305 tests, most asserting that output matches CPython's.
For the full runtime surface, the builtins, the types and their methods, and what is missing, see docs/design/06-builtins.md.
No GIL. Concurrency comes from isolates: independent runtimes with their own heap and collector that share no mutable state. An actor is an isolate with a mailbox and a handler, in Gleam's shape, and they run on an M:N work-stealing thread pool.
from gecko import actor
def handle(state, message):
message[1].send(state + message[0])
return state + message[0]
counter = actor.spawn(0, handle)
print(counter.call(lambda reply: [7, reply], 1000))Messages are deep copied between isolates, except subjects and typed arrays, which pass by handle. See docs/design/04-concurrency.md.
A host can run many isolated VMs, cap each one's steps, wall-clock time, and
heap, and register native functions that scripts call like builtins. A program
can run other code under those limits through the builtin sandbox module:
from gecko import sandbox
print(sandbox.run('print(2 ** 64)', 100000, 1000, 50))See docs/design/05-embedding.md.
See BUILDING.md for instructions on building Gecko from source and a list of supported platforms.
For information on reporting security vulnerabilities in Gecko, see SECURITY.md.
Contributions are welcome through pull requests. See
CONTRIBUTING.md for the prerequisites, the layout, and the
style the project follows.
For the design decisions behind the runtime, see
ARCHITECTURE.md and docs/design/, and for what
is planned next, ROADMAP.md.
MIT. See LICENSE.