Jennifer is an interpreted programming language.
Jennifer is batteries-included, and not just in name:
41 built-in libraries and
74 distributable modules - over 1,800 functions,
constants, and types cover what real programs actually need, so you build genuine tools,
not toys. Talk to a
real database with the SQL library
(MySQL/MariaDB/Galera and PostgreSQL, parameterized and injection-safe) or map rows
to structs with the ORM. Read and write
JSON, YAML,
TOML, and XML; match text
with full regular expressions. The web works both
ways: an HTTP/S client and ergonomic
REST layer to call out, a built-in
HTTP server and web framework
to serve. Email is a complete stack - SMTP to send,
POP3 / IMAP to receive; caches
and stores come through Redis and
memcached clients. Security is the real thing, not a
stub: AES-256-GCM, Ed25519, HKDF / PBKDF2, and JWT.
Wire your program into AI agents with the
Model Context Protocol: expose your own functions as tools
/ resources / prompts to a host (Claude, an IDE, ...), or call another MCP server
as a client - validated end to end against the official MCP SDK.
And lightweight concurrency is built into the
language via spawn and the task library. Something
more niche - Gotify push, strict
SemVer, S3 object storage,
vCard / iCalendar,
MQTT and AMQP messaging,
ACME certificate issuance,
TOTP two-factor codes - and lots of others? No need to
ask: it is all there already. The interpreter and its built-in libraries ship
as one self-contained static binary - about 23 MB with everything, ~10 MB for
the embeddable build - with nothing else to install to run everything built in:
no separate runtime, and no dependency tree to resolve first. The modules ride
along as plain .j source files (installed beside the binary and resolved
through the module path), readable and hackable with no compile step. Reaching
past the built-ins is opt-in: third-party decks (Jennifer's packages) are
vendored into your project's own tree - no global install, no daemon - with the
jvc package manager to resolve and pin them.
It is also a natural fit for teaching and learning: an interactive
REPL, an
easy-to-read grammar, and
token and AST dumps that make it ideal for
mastering language design, plus a built-in
linter and
profiler and full
test support. Its
strict, explicit design - conditions must be
bool, conversions are spelled out, names never shadow, and errors are
positioned - surfaces a mistake as a clear message instead of a silent
surprise, so a learner sees exactly what went wrong.
The interpreter is written in Go and ships as two binaries:
jennifer (built with the standard Go toolchain, full
host-feature surface - the default you install and reach for) and
jennifer-tiny (built with TinyGo, smaller
and embeddable; missing os/exec and the network stack). make build produces both side by side. Source files use the .j
extension.
Jennifer's supported platform is Linux. Best-effort, unsupported macOS and Windows binaries (64- and 32-bit) are published alongside each release - see Install for the caveats.
Same source, same language; pick by use case:
jennifer(standard Go toolchain, the default): full host-feature surface, competitive on single-thread compute and the reliable choice for multi-core parallelspawn(it wins the end-to-end wall clock whenever parallelism is in play), supportsos.run/os.spawn/ the wholenetlibrary. This is what you want unless you have a specific reason to use the constrained variant.jennifer-tiny(TinyGo): smaller binary, embeddable in minimal-footprint deployments (embedded systems, minimal containers, small-footprint scripting hosts). Trade-off: noos/exec(TinyGo runtime gap) and no network stack (no netdev driver registered). Calls into those surfaces return a friendly runtime error pointing back atjennifer.
Both binaries install side by side. Benchmarks comparing the two on the same workload set live in docs/technical/benchmark.md.
Linux is the supported platform. Best-effort unsupported macOS
and Windows binaries (the standard jennifer build only, no TinyGo) are
attached to each release;
read the caveats in
docs/user-guide/installing.md
before relying on them.
# Debian / Ubuntu - pick the .deb for your arch from the Releases
# page (https://github.com/jennifer-language/jennifer/releases) and:
sudo dpkg -i jennifer_X.Y.Z_amd64.deb
# Arch (AUR) - prebuilt binary, fast install:
yay -S jennifer-bin
# Or build-from-source, tracks main:
yay -S jennifer-git
# Any Linux - tarball download + extract:
tar -xzf jennifer-X.Y.Z-linux-amd64.tar.gz
cd jennifer-X.Y.Z-linux-amd64
./jennifer version
# Build from source (developer path, any platform with Go + TinyGo):
make buildSee docs/user-guide/installing.md for verified checksums, the full FHS layout, system-wide install commands from a tarball, and platform-specific notes.
Syntax highlighting for your editor lives in editors/: a true drop-in for Vim / Neovim, a TextMate grammar for VS Code / Sublime / Zed, and a highlight.js definition for static sites.
And because Jennifer is new enough that an AI assistant has no built-in
knowledge of it, we ship JENNIFER.md - a single,
self-contained language reference. Drop it into your project and point
your assistant at it ("we code in Jennifer, see JENNIFER.md, let's go")
and it writes correct .j from the start instead of guessing
Python-with-dollar-signs. Details in
docs/user-guide/tooling.md.
Jennifer is pre-1.0. While the major version stays at 0.x.y,
anything can change at any time - syntax, semantics, library names,
function signatures, file formats. We aim for best-effort stability
between minor versions but make no guarantees: a milestone may rename a
keyword, retype a builtin, or restructure the standard library when a
better design is found. Pin to a specific version if you need
reproducibility; expect to migrate when you upgrade.
Starting with 1.0.0, Jennifer will follow Semantic
Versioning: breaking changes only on a major
version bump, additive features on minor, fixes on patch.
Seven design stances shape every feature in Jennifer. They are deliberately uncompromising - "convenience" is rejected when it creates parallel ways to do the same thing or hides what the code does. See docs/design-stances.md for the full table and rationale.
If you cloned the repo and want to build + iterate locally:
# Build both binaries side by side
make build
./jennifer run examples/hello.j # prints "42" (standard Go, default)
./jennifer-tiny run examples/hello.j # prints "42" (TinyGo, constrained)
# Quick iteration without rebuilding
go run ./cmd/jennifer run examples/hello.jA first program:
use io;
def x as int init 21;
io.printf("%d\n", $x + $x);
The full docs are built with Grimoire
and served at jennifer-lang.dev
(published from main on every push). The same content also reads
fine inside the GitHub file tree:
- docs/user-guide/ - language tutorial and reference split by topic: installing, first program, syntax, types and values, methods, control flow, imports, examples.
- docs/libraries/ - per-library reference
- alphabetical cheatsheet of every builtin.
- docs/technical/ - interpreter internals: lexer, grammar / parser, preprocessor, interpreter, CLI, testing, TinyGo notes.
- docs/milestones.md - what's implemented, what's coming, and the rationale behind the order.
- RELEASE.md - the maintainer-facing release checklist.
go test ./...Tests run under the standard Go toolchain because TinyGo's testing
support is partial. After non-trivial changes, smoke-test both
binaries (make build produces them) since a few standard-library
features behave differently under the TinyGo runtime - see
docs/technical/tinygo.md for the
current restriction list.
LGPL-3.0-only. The full license text and copyright information
ship inside the packaged distributions
(packaging/debian/copyright for the
.deb, the AUR packages reference the upstream license);
gnu.org/licenses/lgpl-3.0.html
is the canonical text.