Python-native local sandbox runtime with HTTP inspection and Cloudflare tunnel exposure
Project description
porthole-sandbox
Local sandbox runtime for Python with built-in HTTP inspection, Cloudflare tunnel exposure, and Cloudflare Workers deployment. Zero Docker, zero VMs, zero config.
Install
pip install porthole-sandbox
Quick Start
import asyncio
from porthole import Sandbox, SandboxOptions
async def main():
sandbox = await Sandbox.create(SandboxOptions(
entry="./app.py",
))
print(f"Proxy: {sandbox.url}") # http://localhost:9090
print(f"Inspector: {sandbox.inspector_url}") # http://localhost:9099
print(f"Tunnel: {sandbox.tunnel_url}") # https://random-words.trycloudflare.com
# ... do work ...
await sandbox.close()
asyncio.run(main())
Features
- Runs any HTTP app in a subprocess sandbox
- Reverse proxy with full request/response logging
- Live inspector dashboard (WebSocket-powered)
- Auto-exposes your app publicly via Cloudflare Quick Tunnels — no install needed
- One-call deploy to Cloudflare Workers
Configuration
Sandbox.create() accepts a SandboxOptions dataclass:
| Option | Type | Default | Description |
|---|---|---|---|
entry |
str |
(required) | Path to the script to run |
port |
int |
9090 |
Port for the reverse proxy |
inspector_port |
int |
9099 |
Port for the inspector dashboard |
env |
dict[str, str] |
{} |
Environment variables passed to the subprocess |
args |
list[str] |
[] |
Arguments passed to the subprocess |
inspector |
bool |
True |
Enable/disable the inspector dashboard |
expose |
bool |
True |
Expose app via Cloudflare Quick Tunnel on create |
command |
str |
"python" |
Command to run the entry script |
command_args |
list[str] |
[] |
Arguments passed before the entry path |
Cloudflare Quick Tunnels
By default, Sandbox.create() automatically exposes your app to the internet using Cloudflare Quick Tunnels — no Cloudflare account needed.
Porthole manages the cloudflared binary for you:
- If
cloudflaredis already installed on your system, Porthole uses it - If not, Porthole automatically downloads the correct binary for your platform and caches it at
~/.porthole/bin/cloudflared - A tunnel is opened from your proxy port to a public
*.trycloudflare.comURL - The tunnel is automatically closed when you call
sandbox.close()
Disable the tunnel
sandbox = await Sandbox.create(SandboxOptions(
entry="./app.py",
expose=False,
))
Manually expose later
sandbox = await Sandbox.create(SandboxOptions(entry="./app.py", expose=False))
public_url = await sandbox.expose()
Deploying to Cloudflare Workers
from porthole import DeployOptions
worker_url = await sandbox.deploy(DeployOptions(
account_id=os.environ["CF_ACCOUNT_ID"],
api_token=os.environ["CF_API_TOKEN"],
name="my-app",
))
API Reference
Sandbox
| Property / Method | Returns | Description |
|---|---|---|
Sandbox.create(options) |
Sandbox |
Create and start a sandbox |
Sandbox.MAX_LOGS |
int |
Maximum log entries retained (10,000) |
Sandbox.MAX_REQUESTS |
int |
Maximum request entries retained (5,000) |
sandbox.url |
str |
Proxy URL (http://localhost:<port>) |
sandbox.inspector_url |
str | None |
Inspector URL (None if disabled) |
sandbox.tunnel_url |
str | None |
Public tunnel URL (None if not exposed) |
sandbox.logs |
list[LogEntry] |
All captured log entries |
sandbox.requests |
list[RequestLog] |
All captured HTTP requests |
sandbox.stats |
ProcessStats |
Process stats (pid, uptime, request count, ports) |
sandbox.expose() |
str |
Open a Cloudflare Quick Tunnel |
sandbox.deploy(options) |
str |
Deploy to Cloudflare Workers |
sandbox.close() |
None |
Gracefully shut down everything |
Also available for Node.js and Deno
npm install porthole-sandbox
import { Sandbox } from "jsr:@porthole/core"; // Deno
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file porthole_sandbox-0.1.0.tar.gz.
File metadata
- Download URL: porthole_sandbox-0.1.0.tar.gz
- Upload date:
- Size: 14.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
65155a318e71444b752604366fc038128b1bcf92932821de8a01e28c57e2c234
|
|
| MD5 |
f76c1f0a21634f56d690f71f19994c8b
|
|
| BLAKE2b-256 |
6d715b49b0e32550d89691a40c584d126b3114bbec021b1f39eaaac95f9d8c6c
|
File details
Details for the file porthole_sandbox-0.1.0-py3-none-any.whl.
File metadata
- Download URL: porthole_sandbox-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ba9562c8df3274595afc55508e7ce8338702b7eaa440615ed56b0b103dd9c5ae
|
|
| MD5 |
97a00aeea412337ca29e59f10eb3c967
|
|
| BLAKE2b-256 |
6d6ca15652b10adcca4f64cdda068724705b10be1f5a77aefb10956746cb1670
|