Quickstart
curl -fsSL https://tamnd.github.io/bunpy/install.sh | bash
export PATH="$HOME/.bunpy/bin:$PATH"
bunpy --version
# bunpy 0.10.29 (linux/amd64)Run a script
Create a file and run it directly:
# hello.py
print("Hello from bunpy!")bunpy hello.py
# Hello from bunpy!No compile step, no virtualenv, no interpreter to configure. bunpy embeds Python 3.14 (via goipy) and runs the file immediately.
Use the standard library
All 214 goipy-provided stdlib modules are available out of the box:
# stdlib.py
import json
import math
import datetime
data = {
"pi": math.pi,
"e": math.e,
"now": datetime.datetime.utcnow().isoformat(),
}
print(json.dumps(data, indent=2))bunpy stdlib.py
# {
# "pi": 3.141592653589793,
# "e": 2.718281828459045,
# "now": "2026-04-28T10:00:00.000000"
# }Use the fetch global
fetch is injected into every script’s global scope. No import needed:
# fetch_example.py
resp = fetch("https://httpbin.org/get")
data = resp.json()
print(data["url"])
print(data["headers"]["User-Agent"])bunpy fetch_example.py
# https://httpbin.org/get
# bunpy/0.10.29For POST requests:
resp = fetch("https://httpbin.org/post", {
"method": "POST",
"headers": {"Content-Type": "application/json"},
"body": '{"name": "bunpy"}',
})
print(resp.status) # 200Start a project
Use bunpy init to scaffold a new project with pyproject.toml:
bunpy init myapp
cd myappThe generated pyproject.toml:
[project]
name = "myapp"
version = "0.1.0"
requires-python = ">=3.14"
dependencies = []Install packages
Add a package from PyPI:
bunpy add requests httpxThis updates pyproject.toml, resolves the full dependency graph, downloads the wheels, and writes uv.lock:
# pyproject.toml after bunpy add requests httpx
[project]
dependencies = [
"requests>=2.31.0",
"httpx>=0.27.0",
]Then use the packages in your script:
# main.py
import requests
r = requests.get("https://httpbin.org/get")
print(r.status_code) # 200
print(r.json()["url"]) # https://httpbin.org/getbunpy run main.py
# 200
# https://httpbin.org/getStart an HTTP server
# server.py
from bunpy.serve import serve
def handler(req):
if req.path == "/health":
return {"status": 200, "body": "ok"}
name = req.query.get("name", "world")
return {"status": 200, "body": f"Hello, {name}!"}
print("Listening on http://localhost:3000")
serve(handler, port=3000)bunpy server.py
# Listening on http://localhost:3000In another terminal:
curl http://localhost:3000?name=bunpy
# Hello, bunpy!
curl http://localhost:3000/health
# okWrite and run tests
# tests/test_math.py
from bunpy.test import test, expect
@test("addition is commutative")
def _():
expect(1 + 2).to_be(3)
expect(2 + 1).to_be(3)
@test("division by zero raises")
def _():
def bad():
return 1 / 0
expect(bad).to_raise(ZeroDivisionError)bunpy test
# bunpy test v0.10.29 (myapp)
#
# tests/test_math.py:
# ✓ addition is commutative [0.12ms]
# ✓ division by zero raises [0.08ms]
#
# 2 tests passed (2)Bundle to a .pyz
Package your project as a standalone .pyz archive that runs with python3 or with bunpy:
bunpy build
# Built myapp.pyz (1.2 MB)bunpy run myapp.pyz
# or
python3 myapp.pyzThe .pyz contains your source, all dependencies, and a __main__.py entry point. It does not embed the goipy runtime, so the target machine needs either bunpy or a CPython 3.14 install.
The lockfile
Every bunpy add and bunpy install updates uv.lock. Commit this file to version control. It guarantees that bunpy install produces byte-for-byte identical installs on every machine:
git add pyproject.toml uv.lock
git commit -m "add requests and httpx"Next steps
- Installation – platform-specific install options
- CLI reference – all bunpy commands
- Runtime docs – Python compatibility, globals, import resolution
- API reference – all
bunpy.*modules - Package manager – lockfile, workspaces, patches