One self-contained binary. One Python-like language. AI, graphs, persistence, APIs, UIs, and cloud deployment as language features, compiled to Python bytecode, JavaScript, and native machine code.
Docs · Playground · Tutorial · Discord
Jac is a programming language designed for humans and AI to build together. It compiles one clean, Python-like syntax to Python bytecode, JavaScript, and native machine code, with the entire PyPI, npm, and C ecosystems available without wrappers or interop layers. The things every real application needs (an LLM call, a data model that persists, a REST API, a frontend, a deployment story) are language features, not frameworks you assemble around it. The design rests on two properties, synechic and topokinetic, defined below.
Install the self-contained jac binary. No Python, pip, Node, or C toolchain required:
curl -fsSL https://raw.githubusercontent.com/jaseci-labs/jaseci/main/scripts/install.sh | bashThen clone and run this_is_jac, a showcase site built entirely in Jac:
git clone https://github.com/jaseci-labs/this_is_jac
cd this_is_jac
jac install # first run: pulls python + npm deps
jac start # builds the frontend + wasm, serves on http://localhost:8000Open http://localhost:8000 and scroll. Sign the guestbook -- it's backed by walkers writing to a real graph that persists automatically, no database to set up. Spawn a walker that traverses that graph live, play a native-compiled shooter running in the browser as WebAssembly, and poke at a full social app embedded as a single component. One language, one codebase, all the way down.
Don't want to install anything? Open the Jac Playground in your browser.
Prebuilt binaries ship for macOS and Linux; on Windows, use WSL (a native PowerShell installer is coming soon). See the installation guide for versions, upgrading, and IDE setup.
Open the repository of any well-built product and count what a maintainer must read: TypeScript, Python, SQL, and shell where the logic lives; JSX and CSS for presentation; JSON, TOML, YAML, Dockerfile, HCL, and dotenv for configuration. Twelve notations, five package ecosystems, two lockfiles. Nobody chose that. It is what precipitates when every architectural seam is also a change of language, type system, package manager, and serialization format.
The deeper cost isn't the reading; it's that no compiler can see across any of those seams. Rename one field and TypeScript checks the frontend, Python checks the backend, and nothing checks the wire format, the ORM mapping, the OpenAPI document, or the prompt template between them. The whole-program type checker of the modern stack is grep. That is where bugs pool, and it's why teams staff a specialist per boundary: the org chart is a picture of the glue.
The four-copy record (what one field costs in a conventional stack)
One record, maintained in four notations, in one repository:
CREATE TABLE users ( -- migrations/0004_users.sql
id UUID PRIMARY KEY,
email TEXT NOT NULL UNIQUE,
display_name TEXT NOT NULL );class User(Base): # app/models.py (ORM)
id: Mapped[UUID] = mapped_column(primary_key=True)
email: Mapped[str] = mapped_column(unique=True)
display_name: Mapped[str]
class UserOut(BaseModel): # app/schemas.py (API)
id: UUID
email: str
display_name: strexport interface User { // web/src/types/user.ts
id: string;
email: string;
displayName: string;
}Four copies, three type systems, and one landmine: the fourth copy renames display_name to displayName in a serializer config nobody has reviewed since it was pasted in. Adding one field is a four-file, three-language change plus a migration, a regenerated client, and a cache-key bump -- and not one line of that diff implements behavior. In Jac the record is one node declaration; the compiler owns its representation in the store, on the wire, and in the browser.
None of this is required by computation. The pattern traces to two silent assumptions in the 1945 report that defined the stored-program computer: that computation is stationary (the site of processing is fixed, and data travels to it), and that the machine is the program's world (a program's semantics end at the edge of its process, so frontend and backend, managed and native, script and service are separate programs, joined by hand). Both were engineering defaults for a machine with one memory. Seventy years of habit made them look like laws. Jac is one bet against each.
Against the second assumption, Jac is synechic (from the Greek synecheia, continuity): one continuous, checked medium across ecosystems, tiers, and toolchains. One language spans frontend, backend, and native code, and inherits each one's ecosystem (PyPI, npm, the C world) through a plain import, so one compiler sees both sides of every call: rename a field and every stale use (server, client, or native) is a compile error, not a production incident. Building the first production synechic language is the whole point of Jac.
Against the first assumption, Jac is topokinetic (from the Greek topos, place, and kinesis, motion): the moving locus of computation is a language construct. In Jac's Object-Spatial Programming, data lives as a persistent topology of nodes and edges, and walkers carry computation through it, dispatched by arrival. Whatever is reachable from root persists: persistence is a predicate, not an event, and the database dissolves into the language.
The two properties compound, and the dissolved database is the proof: continuity without motion still calls a store outside the language's semantics, and motion without continuity is a graph paradigm marooned in one process. Jac is the first language that is both. And the boundaries that are physics stay visible on purpose: a cross-tier call is async because the network is real, write conflicts surface as typed errors, and sharing data across users takes an explicit grant. Jac deletes the paperwork, not the physics.
The full argument: Why Jac Exists and The Two Ideas, or the side-by-side count in One App, Two Stacks.
Jac is designed for humans and AI to build together, and that includes your coding agent. The lowest-effort setup is no setup: point your agent at the jac CLI and tell it to figure it out. The binary is self-documenting -- jac guide prints curated reference guides on every corner of the language, and one command extracts them as Agent Skills your agent can load directly:
jac guide --export ~/.claude/skillsFor a deeper integration, the jac binary also ships an MCP server with Jac validation, formatting, docs, and examples built in. Wire it into Claude Code with one command:
claude mcp add jac -- jac mcpFor Cursor, Windsurf, or any other MCP client, add this to your MCP config (use jac mcp --mode lite for smaller models):
{ "mcpServers": { "jac": { "command": "jac", "args": ["mcp"] } } }Or skip the setup entirely and paste this into your agent's chat; it will install Jac and configure itself:
Fetch https://raw.githubusercontent.com/jaseci-labs/jaseci/main/SKILL.md and follow its instructions.
LLM-friendly docs pointers live at docs.jaseci.org/llms.txt, and jac ai gives you a Jac-fluent coding agent in your terminal with no setup at all.
There's a structural reason agents do better in Jac than in a conventional stack. Glue code is most of what coding models emit (it dominates their training corpora), and glue is exactly the code no tool can verify -- cheap to generate, expensive to trust. In Jac there is less glue to write and one compiler that checks all of it: a whole full-stack app fits in one file that fits in a context window, and a cross-tier mistake an agent makes is a compile error instead of a production surprise. When authorship is abundant, the scarce resource is jurisdiction: the reach of the verifiers that can examine a change and say no, and Jac is built to leave no program point outside it. Even sem annotations do triple duty: prompt material for by llm(), documentation for humans, context for your agent.
One download replaces the interpreter, the JS runtime, the compilers and linker, the package managers, the server, and the deployer. At its center is a polypiler: a compiler whose unit of compilation is the whole polyglot application and whose targets are ecosystems rather than instruction sets:
What's inside the binary (and what you can uninstall)
Here is the actual anatomy. The jac you download is a small native launcher stub with the entire runtime payload appended to the same file. The first run unpacks the payload into a per-version cache; every run after that is instant.
| Component | How it's in the binary | What you can uninstall |
|---|---|---|
| Launcher stub | The jac file itself: native machine code linked against libc only; everything below rides in the appended payload |
-- |
| CPython 3.14 | A private python-build-standalone build (PGO+LTO, stripped), dlopened by the launcher at startup -- your system Python is never consulted |
Python, pyenv, conda |
| Jac compiler + runtime | Precompiled to JIR in the payload's private site -- includes the REST server (jac start), client framework, K8s deployer (--scale), and byLLM (by llm()); their optional third-party deps (litellm, pymongo, ...) resolve per-project via jac install |
Flask, FastAPI, Express · Docker, kubectl, Helm · LangChain |
| Bun | The real Bun executable, carried inside the payload and invoked by absolute path -- never on your PATH |
Node.js, npm, npx, yarn |
| LLVM 22 | Statically linked into a single jacllvm shared library behind the llvmlite ABI |
gcc, clang |
| Linker + C floor | Jac's own linker emits ELF / Mach-O / PE / wasm directly; static libc + crt archives, a musl runtime (Linux), and wasm32 libc bitcode are vendored in the payload | ld, lld, make, cmake, emscripten |
| Package manager | pip runs inside the private interpreter, npm resolution goes through the carried Bun -- one jac.toml, an automatic .jac/venv, and jac x to run any installed CLI tool |
pip, pipx, uv, poetry, venv/virtualenv |
| Type checker | Built into the compiler (jac check), with the typeshed stdlib stubs vendored at a pinned commit |
mypy, pyright, tsc |
| Dev tooling | Formatter, test runner, language server, and MCP server are modules of the same site (jac fmt / jac test / jac lsp / jac mcp) |
black, ruff, pytest, jest |
jac ninja editor |
A pinned Neovim fork statically linked into the launcher itself -- boots in milliseconds, with jac lsp pre-wired |
a separate editor + LSP setup |
Full story: One Binary, Build Anything.
The commands you'll use every day:
| Command | What it does |
|---|---|
jac run main.jac |
Run a program (like python3, but for anything) |
jac dev |
Live dev loop with hot reload |
jac start |
Serve your program: REST API, auth, Swagger docs, frontend |
jac build |
Type-check the whole project and emit a sealed app bundle |
jac build --as native |
Compile to a standalone, zero-dependency executable |
jac install / jac x |
Manage PyPI + npm deps / run any installed CLI tool |
jac check / jac fmt / jac test |
Type-check, format, test |
jac ai / jac mcp / jac guide |
Built-in coding agent, MCP server, curated docs |
One language and one skill set produce every kind of software. Each row is one command away:
| What you're building | The command | Guide |
|---|---|---|
| Script / CLI tool | jac run app.jac |
CLI & native |
| Zero-dependency native executable | jac build --as native |
CLI & native |
Single-file app bundle (.jab) |
jac build |
CLI reference |
| Self-contained app executable | jac build --as binary |
CLI reference |
| REST API (+ Swagger, auth, persistence) | jac start api.jac |
Backend APIs |
| Microservices | sv import + jac start |
Backend APIs |
| Full-stack web app | jac start |
Full-stack web |
| Desktop app (native webview) | jac build --client desktop |
Desktop & mobile |
| Mobile app (Android / iOS) | jac build --client mobile |
Desktop & mobile |
| AI agents & LLM apps | by llm() |
AI agents |
| Python package (PyPI wheel) | jac build --as wheel |
Libraries |
| npm package | jac build --as npm |
Libraries |
C-ABI shared library (.so/.dylib/.dll) |
jac nacompile lib.na.jac --shared |
Libraries |
| WebAssembly in the browser | jac build in a web-static project |
Native pathway |
| Kubernetes deployment | jac start --scale |
Deploy & scale |
Proof it's real: a playable chess engine compiled to a standalone binary, a raylib game running as WebAssembly in the browser, and littleX, a full Twitter-style social app. littleX's entire backend -- 4 node types, 4 edge types, and 20 walkers that serve as business logic, REST endpoints, persistence, and authorization at once -- is 2 files and 475 lines; the whole app, frontend included, is 37 Jac files with exactly one 65-line config file and zero glue artifacts: no route tables, no ORM models, no migrations, no serializers, no auth middleware. Run wc -l on it and check.
Each of those deliverables is a project kind: jac create myapp --kind <kind> scaffolds it, stamps the kind into jac.toml, and a bare jac run already knows whether to execute, serve, or build it. The scaffolding is the small part -- the point is what the language does for each kind that a traditional stack makes you assemble by hand:
--kind |
What you ship | What Jac adds beyond a traditional language |
|---|---|---|
cli |
Terminal script / tool | Graph-native data modeling in a one-off script, a root graph that persists between runs (no database, no files), and by llm() AI with zero glue -- where a script normally means Python + SQLite + an LLM SDK |
cli-native |
Compiled program, run in place | The same source compiled through statically linked LLVM -- C-level speed with no gcc, clang, or rustc installed |
native-binary |
Zero-dependency executable | Jac's own linker emits the ELF/Mach-O/PE file (no ld in the loop) -- ship to machines with no Jac and no Python, territory that normally means learning C, Rust, or Go |
native-lib |
C-ABI shared library (.so/.dylib/.dll) |
Expose Jac to any language with a C FFI (C, Rust, Go, Python ctypes) by marking functions :pub -- refcounted handles included, and --target cross-builds for Linux/macOS/Windows with no extra toolchain |
service |
Headless REST API | walker:pub is the endpoint: request bodies map to its fields, report is the JSON response, Swagger at /docs, and per-user isolated persistence -- no FastAPI + SQLAlchemy + Pydantic + auth middleware to wire up |
service-mesh |
Microservice cluster | sv import is the architecture: the compiler turns imports into HTTP stubs, the consumer auto-starts its providers, and env vars re-point services across hosts -- no OpenAPI codegen, no client SDKs |
py-package |
pip-installable wheel | jac build --as wheel with nothing beyond jac.toml; the wheel runs under the jac binary with no jaclang runtime dependency |
js-package |
npm tarball | Compiles to ES modules with auto-generated package.json and .d.ts declarations, consumable from any JS/TS project -- built with no Node.js installed |
web-app |
Full-stack web app | Backend, frontend, and data model in one file: cl code compiles to React, and the compiler writes every RPC and shares types across the boundary -- instead of two projects and five frameworks |
web-static |
Client-only page | na {} blocks compile to WebAssembly with Jac's own wasm linker (no emscripten); jac build emits a portable index.html that opens straight from disk |
desktop 🧪 |
Native desktop binary | The same app wrapped in the OS webview as one compiled binary -- no Electron, no Rust, no PyInstaller |
mobile 🧪 |
Android / iOS app | The same cl bundle wrapped by Capacitor, or true-native React Native via mobUI -- JS tooling runs on the bundled Bun, no Node.js |
The full matrix, with a working recipe and guided track for each: What You Can Build.
enum Priority { LOW, MEDIUM, HIGH, URGENT }
def assess(ticket: str) -> Priority by llm();
with entry {
print(assess("Checkout is down and customers are leaving!"));
# Priority.URGENT
}No prompt, no parsing, no API glue. The compiler constructs the prompt from your function's name, argument names, and types (plus optional sem annotations), and the return type is an enforced output schema. These are meaning types, the constructs of Meaning-Typed Programming. Declare your model once in jac.toml, run jac install byllm, and use any LiteLLM-compatible provider, or go fully local with jac install 'byllm[local]'. Learn more →
node Task {
has title: str;
has done: bool = False;
}
walker:pub add_task {
has title: str;
can create with Root entry {
task = Task(title=self.title);
root ++> task;
report {"id": jid(task), "title": task.title};
}
}
walker:pub list_tasks {
can fetch with Root entry {
report [{"id": jid(t), "title": t.title, "done": t.done}
for t in [-->][?:Task]];
}
}jac start api.jac --no-client # POST /walker/add_task · /walker/list_tasksModel your domain as nodes and edges, and send walkers (mobile computation, dispatched by arrival) to traverse it: this is Object-Spatial Programming. Mark a walker :pub and jac start turns it into a REST endpoint: request bodies map onto its fields, report becomes the JSON response, Swagger docs appear at /docs, and every user gets their own isolated, persistent graph. Whatever is reachable from root persists. No ORM, no schema migrations, no session plumbing. Object-Spatial Programming →
node Todo {
has title: str, done: bool = False;
}
def:pub add_todo(title: str) -> Todo {
todo = Todo(title=title);
root ++> todo;
return todo;
}
def:pub get_todos -> list[Todo] {
return [root-->][?:Todo];
}
cl def:pub app -> JsxElement {
has todos: list[Todo] = [], text: str = "";
async can with entry { todos = await get_todos(); }
async def add {
if text.strip() {
todos = todos + [await add_todo(text.strip())];
text = "";
}
}
return <div>
<input value={text}
onChange={lambda e: ChangeEvent { text = e.target.value; }}
placeholder="Add a todo..." />
<button onClick={add}>Add</button>
{[<p key={jid(t)}>{t.title}</p> for t in todos]}
</div>;
}Code in cl (the client codespace) compiles to a React/JSX bundle for the browser; everything else compiles to Python for the server. That await add_todo(...) in the click handler is a real RPC: the compiler generates the HTTP call, serialization, and shared types across the boundary. jac start serves it; jac start --dev gives you hot reload. Full-stack tutorial →
For all three ideas in one file (an AI categorizer, a native-compiled scoring function, a persistent graph, and a React UI), see jac/examples/mini_todo.
jac start main.jac # local: REST API + auth + Swagger + persistence
jac start main.jac --scale # cloud: Kubernetes with Redis, MongoDB, load balancingYour program text does not change with the shape of its deployment: this is scale invariance, and the scale subsystem that delivers it ships inside the binary. --scale builds the images, provisions Redis and MongoDB, and deploys to Kubernetes with health checks. You write no Dockerfile and no YAML, and what stays in your code is only the physics: latency, failure, and cost surface as typed semantics. Deploy & scale →
- Build an AI Day Planner -- the flagship tutorial: every core concept in one guided full-stack project
- Jac Fundamentals -- the language itself, for Python developers
- Build a Chess Engine -- the native pathway, from source to standalone binary
- WebAssembly in the Browser -- native-speed compute, client-side
- Jac Playground -- run Jac in your browser, and Ask Jac GPT -- a docs-trained assistant
- In your terminal:
jac guide(curated references),jac ai(interactive coding agent),jac mcp(wire Jac expertise into Claude Code, Cursor, and friends)
This is the Jaseci monorepo, home to everything that makes Jac work:
| Directory | What it is |
|---|---|
jac/ |
jaclang -- the compiler, runtime, and everything inside the jac binary: the language, the full-stack client framework, the scale deployment subsystem, the MCP server, and the LLVM native pathway |
jac-byllm/ |
byllm -- AI/LLM integration via Meaning-Typed Programming (jac install byllm) |
docs/ |
The documentation site at docs.jaseci.org |
scripts/ |
The installer and release tooling |
The official VS Code extension lives at jaseci-labs/jac-vscode.
Jac's core ideas are peer-reviewed research, not just design taste:
- Object-Spatial Programming -- the formal model behind nodes, edges, and walkers: mobile computation over a persistent typed topology (arXiv:2503.15812)
- MTP: A Meaning-Typed Language Abstraction for AI-Integrated Programming --
by llm()andsem, evaluated against hand-built prompt pipelines: comparable-or-better accuracy with substantially less code and lower token cost (OOPSLA 2025, arXiv:2405.08965) - The Jaseci Programming Paradigm and Runtime Stack -- the production lineage: walkers served as scale-out endpoints in commercial products (IEEE Computer Architecture Letters, 2023)
A book-length treatment, developing the synechic and topokinetic language classes and the theory beneath Jac's design, is in preparation. The project grew out of research at the University of Michigan and is now developed in the open by a global community. Citing Jac in your own work? GitHub's "Cite this repository" button (powered by CITATION.cff) gives a ready-made reference. More on docs.jaseci.org: Research & Papers.
| Project | Description |
|---|---|
| Tobu | AI-powered memory keeper for the stories behind your photos and videos |
| TrueSelph | Production-grade scalable agentic conversational AI platform |
| Myca | AI-powered productivity tool for high-performing individuals |
| Pocketnest Birdy AI | Commercial financial AI powered by your own financial journey |
Building something with Jac? Tell us on Discord and we'll add it here.
Jaseci is a member of the NVIDIA Inception Program for cutting-edge AI startups.
We welcome contributions of every size, from typo fixes to compiler passes.
- Ask questions & share ideas on our Discord server
- Report bugs via GitHub issues
- Send PRs: start with the contributing guide and CONTRIBUTING.md;
bash scripts/fresh_env.shsets up a dev environment
If Jac looks useful to you, star the repo. It helps other developers discover the project.
Jac and the Jaseci stack are MIT licensed. Vendored third-party components retain their own permissive licenses.