https://github.com/tamnd/zag
A Zig interpreter for CPython 3.14 bytecode. One static binary, no libpython.
https://github.com/tamnd/zag
bytecode cpython interpreter pyc python python-interpreter python3 vm zig ziglang
Last synced: about 9 hours ago
JSON representation
A Zig interpreter for CPython 3.14 bytecode. One static binary, no libpython.
- Host: GitHub
- URL: https://github.com/tamnd/zag
- Owner: tamnd
- License: mit
- Created: 2026-04-25T02:21:45.000Z (3 days ago)
- Default Branch: main
- Last Pushed: 2026-04-25T06:56:54.000Z (3 days ago)
- Last Synced: 2026-04-25T07:33:22.868Z (3 days ago)
- Topics: bytecode, cpython, interpreter, pyc, python, python-interpreter, python3, vm, zig, ziglang
- Language: Zig
- Homepage:
- Size: 114 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
zag
A Zig interpreter for CPython 3.14 bytecode.
One static binary. No libpython. No cgo.
```sh
# One-off: generate .pyc + expected-stdout pairs for the fixtures.
bash tests/fixtures/gen.sh
zig build test
zig build run -- tests/fixtures/00_hello.cpython-314.pyc
```
zag reads a `.pyc` file and runs it. CPython compiles; zag executes. Execution happens inside a Zig `switch` with labeled-continue dispatch (the equivalent of GCC's computed goto), with Python values held in a tagged union and memory owned explicitly by the interpreter.
## Why
Embedding Python inside a Zig program usually means linking `libpython` and bridging two runtimes. That works; it also drags in the whole CPython build. zag is the alternative: accept compiled `.pyc` on input, execute it inside a single Zig binary, exit cleanly.
Good fits: a Zig service that wants user-pluggable logic, a CLI that accepts small Python scripts as config, a sandbox that runs auditable `.pyc` payloads.
Trade you lose: peak speed and the C extension ecosystem. Trade you keep: one binary, one toolchain, one kind of crash dump.
zag is the Zig sibling of [goipy](https://github.com/tamnd/goipy), which does the same thing in Go. The two projects share test fixtures and disagree only on host language.
Per-release notes live in [CHANGELOG.md](CHANGELOG.md). Prebuilt
binaries for Linux (x86_64/aarch64 musl), macOS (x86_64/aarch64), and
Windows (x86_64) are attached to each GitHub release.
## Requirements
- Zig 0.16 (tested against `0.16.0-dev.2984+cb7d2b056`).
- CPython 3.14 on `PATH` to produce `.pyc` inputs.
## Layout (planned)
```
src/
main.zig CLI entry point
root.zig library root
marshal/ .pyc header + marshal decoder
op/ 3.14 opcode enum + cache widths
object/ Value tagged union and per-type structs
vm/ interp, frame, dispatch, call, builtins
tests/
fixtures/ .py + .pyc + expected stdout
```
## License
MIT. `.pyc` input files remain under the PSF license that covers CPython bytecode output.