Skip to content

PyStack

The Full Stack, From Scratch

What's a "Full Stack"?

A full stack is all the layers of software that make a computer useful. Think of it like a school. A school isn't just one thing -- it's a building, a language, filing cabinets, locks, a phone system, a library, an intercom, and hallways that connect them all.

PyStack connects ten educational projects, and each one teaches you how a real piece of technology works:

Project What It Is School Analogy
PyOS Operating system The school building -- manages everything
Pebble Programming language The language students speak
PyDB Database engine The filing cabinet -- stores and retrieves data
PyCrypt Cryptography toolkit The combination lock -- keeps secrets safe
PyWeb HTTP web server The front office -- talks to visitors
PyNet Networking library (DNS, event loop, messaging, WebSockets) The phone system -- connects to the outside world
PyGit Version control The yearbook archive -- tracks every change
PySearch Full-text search engine The library index -- finds things fast
PyMQ Message queue The intercom -- sends messages between rooms
PyStack Integration layer The hallways connecting everything

You built all ten from scratch. PyStack is the hallways -- it lets a single Pebble program use any of these systems together.

Seven Pebble Modules

When PyStack boots, it registers 7 stdlib modules in the Pebble language. Each module comes from a different project. Just write import "modulename" at the top of your Pebble program.

Module Project Functions
db PyDB db_query(sql), db_execute(sql), db_tables()
crypto PyCrypt hash(text), caesar_encrypt(text, shift), caesar_decrypt(text, shift), hmac_sign(msg, key), hmac_verify(msg, tag, key)
web PyWeb + PyNet http_get(url), url_parse(url)
git PyGit git_hash(text), git_diff(old, new)
net PyNet dns_lookup(hostname), url_parse(url), base64_encode(text), base64_decode(text)
search PySearch search_create(), search_add(engine, id, text), search_query(engine, query)
mq PyMQ mq_create(name), mq_put(name, msg), mq_get(name), mq_publish(topic, msg), mq_subscribe(topic), mq_receive(topic)

That's 25 functions across 7 modules. Every one of them calls real code from a real project you built yourself.

Four Ways to Use PyStack

1. Run a Pebble program with all modules available

Write a program that creates a table, adds data, and queries it:

import "db"

db_execute("CREATE TABLE friends (name TEXT, age INTEGER)")
db_execute("INSERT INTO friends VALUES ('Alice', 12)")
db_execute("INSERT INTO friends VALUES ('Bob', 13)")

let friends = db_query("SELECT * FROM friends")
for f in friends {
    print(f["name"] + " is " + str(f["age"]))
}
pystack pebble hello_db.pbl

2. Use the integrated OS shell

The OS shell has pebble, sql, and all plugin commands built in:

pystack os
pystack-os> pebble eval 'print(1 + 2)'
3
pystack-os> sql CREATE TABLE scores (player TEXT, score INTEGER)
Table 'scores' created
pystack-os> hash hello
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
pystack-os> dns example.com
93.184.216.34
pystack-os> mq-put orders "one coffee"
Queued on 'orders': one coffee
pystack-os> mq-get orders
one coffee
pystack-os> mqnet
broker: listening on a free local port
boss: declared queue 'jobs' (2 attempts per job)
worker A: took job-1 (attempt 1) and crashed - connection lost
broker: took job-1 back from worker A (lease returned, attempt 1 used up)
worker B: job-1 done (attempt 2)
worker B: job-2 done (attempt 1)
worker B: job-boom failed (attempt 1)
worker B: job-boom failed (attempt 2)
dead: job-boom (max_attempts) - poison job
announced: $sys.dead.jobs
broker: closed
pystack-os> ls /data
scores.json

3. Open the web UI

A browser-based interface with three panels side by side:

pystack web
# Opens http://localhost:8080
  • OS Terminal -- type shell commands
  • Pebble Editor -- write and run code
  • SQL Console -- query the database

4. Interactive SQL REPL

pystack sql
pydb> CREATE TABLE cards (name TEXT, power INTEGER)
pydb> INSERT INTO cards VALUES ('Pikachu', 55)
pydb> SELECT * FROM cards

Shell Commands in PyStack OS

When you run pystack os, these commands are available at the prompt. The first two come from the core adapters. The rest come from plugins.

Command What It Does Provided By
pebble run <file> Run a Pebble program Core (OS-Pebble adapter)
pebble eval '<code>' Evaluate Pebble code inline Core (OS-Pebble adapter)
sql <statement> Run a SQL statement Core (OS-DB adapter)
hash <text> Print the SHA-256 hash of text CryptoPlugin
curl <url> Fetch a URL and print the body WebPlugin
webdemo Visit PyWeb's async restaurant: read the public menu, get turned away by the doorman, log in for a wristband (session cookie), then listen to a live stream of three events WebPlugin
dns <hostname> Resolve a hostname to an IP address NetPlugin
git-hash <text> Print the SHA-1 hash (Git-style) GitPlugin
git-diff <old> <new> Show a unified diff GitPlugin
mq-put <queue> <msg> Put a message on a named queue MQPlugin
mq-get <queue> Get the next message from a queue MQPlugin
mqnet Visit PyMQ's networked post office: one worker crashes, its lease comes back to another, a poison job lands in the dead-letter box MQPlugin
dbcrash Pull the plug on PyDB's diary-keeping (journalled) database: three finished job runs survive a crash, the unfinished fourth is gone PyDBPlugin
sched Run a tiny job chain on PyScheduler: a flaky job passes on its retry, a cleanup job is skipped because nothing failed, and the history survives a restart PySchedulerPlugin
schedagents Hand PyScheduler jobs to two helper agents on other desks: one job is pinned to build-01, one asks for a helper tagged gpu, and the output says who ran each PySchedulerPlugin
schedalerts Make a PyScheduler job fail and follow its alert: stored first, routed to a log notifier, delivered once PySchedulerPlugin
schedweb [--seconds N] Open PyScheduler's web UI over a dozen demo jobs and three days of runs (log in as admin / demo); stops on Ctrl-C or after N seconds PySchedulerPlugin

Plus all the standard PyOS commands like ls, cat, mkdir, help, and more.

How It Works

PyStack uses adapters and plugins to connect projects together. Think of them like translators between people who speak different languages.

Your Pebble program calls db_query("SELECT * FROM pets")
    |
    +-- The adapter translates this for PyDB
    |       |
    |       +-- PyDB parses the SQL and runs it
    |               |
    |               +-- Results come back as a Pebble list
    |
    +-- print(results)  -- your program gets the data!

Adapters connect core systems (Pebble to PyDB, PyOS to Pebble). They are small -- about 90 lines each.

Plugins connect additional projects (PyCrypt, PyWeb, PyGit, PyNet, PySearch, PyMQ). Each plugin registers a Pebble module and optionally adds shell commands.

Plugin System

PyStack has 6 active plugins that integrate projects beyond the core three (PyOS, Pebble, PyDB):

Plugin Pebble Module Shell Commands Project
CryptoPlugin import "crypto" hash PyCrypt
WebPlugin import "web" curl, webdemo PyWeb
GitPlugin import "git" git-hash, git-diff PyGit
NetPlugin import "net" dns, overlap, netecho, wsecho PyNet
SearchPlugin import "search" (none) PySearch
MQPlugin import "mq" mq-put, mq-get, mqnet PyMQ
PyDBPlugin (none) dbcrash PyDB
PySchedulerPlugin (none) sched, schedagents, schedalerts, schedweb PyScheduler

The db module is handled separately by the Pebble-DB adapter because it needs a live database instance.

Each plugin is a Python class that extends the Plugin base class. A plugin can do three things:

  1. Register a Pebble module -- so programs can import it
  2. Add shell commands -- available in pystack os
  3. Run boot logic -- custom setup when PyStack starts

Plugins can also be discovered automatically via Python entry points (the pystack.plugins group), so other packages can extend PyStack without modifying its code.

Install

pip install fromscratch-pystack

That pulls in all 17 other projects too. To read the code or run the tests, clone it from GitHub.

Develop from source

# Clone the repository
git clone https://github.com/robcox2910/pystack.git
cd pystack

# Install all dependencies (all 18 projects wired together)
uv sync --all-extras

# Run an example
pystack pebble examples/hello.pbl

# Run the tests
uv run pytest