Skip to content
Ori Pekelman edited this page May 24, 2026 · 8 revisions

Tep documentation

Detailed reference for the framework. The repo's README.md covers the quick start; everything deeper lives here.

Why Tep exists

Two complementary goals:

  1. Exercise Spinel against real-world Ruby code. Tep is the largest pure-Ruby app Spinel compiles end-to-end. Every Sinatra idiom, every battery, every demo doubles as a torture test for the AOT compiler's codegen + analyzer. Bugs surface here, get reduced to minimal repros, and land upstream as PRs or issues.

  2. Be the harness for toy. Toy is Tep's sibling project: a machine-learning framework written in pure Ruby and compiled by Spinel. Toy needs an HTTP / MCP / streaming layer for serving models, exposing training tools to agents (Claude Code et al.), streaming inference results, and wiring presence into collaborative training sessions. Tep is that layer. Every battery here is shaped by what Toy actually needs to ship.

Tep happens to be useful as a general web framework too — fast, single-binary, Sinatra-shaped — but the design choices flow from those two lenses.

Getting started

  • Getting Started — install, build, serve, and deploy your first Tep app, all the way through auth, persistence, and a systemd unit.

Batteries

Pure-Tep modules covering the gem ecosystem's most common needs in a way that lowers cleanly through Spinel.

  • Tep::SQLite — libsqlite3 wrapper: prepare / bind / step / col, plus first_str / first_int conveniences.
  • Tep::Json — primitive encoders, flat-key decoder, hash/array helpers for JSON-over-HTTP.
  • Tep::Logger — levelled logger; stderr or file.
  • Tep::Jwt — HS256 JWT encode / verify / decode; interop- tested against the canonical jwt gem.
  • Tep::Password — PBKDF2-SHA256 hashing with self- describing storage; 200k iters.
  • Tep::SecurityCors (before-filter) + Headers (HSTS, nosniff, frame-options, ...).
  • Tep::Assets — compile-time bundling for <app>/assets/* (CSS, SVG, JS, ...).
  • Tep::Scheduler — cooperative fiber scheduler with timer + I/O parking.
  • Tep::Shell — popen-based shell-out + small-file reader for /proc, /sys, /etc.
  • Tep::Http — outbound HTTP/1.0 client, Faraday-shaped.
  • Tep::Llm — ruby-openai-shaped chat-completions client; sync chat + SSE chat_stream. Backends interchangeable via base_url (Ollama / OpenAI / toy).
  • Tep::WebSocket — RFC 6455 server-side WebSocket. Sinatra-style websocket '/p' do |ws| ... end DSL with on_open / on_message / on_close event blocks.
  • Tep::Parallel — grosser/parallel-shaped fork fan-out.
  • Tep::Job — sidekiq-shaped queue over SQLite.

The agentic batteries

These four ship a small framework for "web apps in a live agentic age" — req.identity is always a principal+delegate pair so agents acting on behalf of humans are first-class through every battery. End-to-end design + a realistic chat-room scenario walked through every seam lives in docs/BATTERIES-DESIGN.md.

  • Tep::Auth — principal+delegate identity (humans + agents) + provider chain: BearerToken (JWT), SessionCookie, OAuth2-grant issuance. Same req.identity surface regardless of provider.
  • Tep::Broadcast — in-process pub/sub + cross- worker via PG LISTEN/NOTIFY. WS-framed subscribe_ws is the seam Presence + LiveView use.
  • Tep::Presence — topic-keyed who's-here registry, agent-aware. Structured 3-state status (:available | :busy | :blocked) with notes + expiry. Diffs broadcast on join/leave/status; PG mirror for cross-worker list_global snapshots.
  • Tep::LiveView — Phoenix.LiveView-shape server-rendered stateful UI over WebSocket. Subclass + override render / handle_event; bootstrap client ships inline (~10 lines of JS).
  • Tep::MCP — Tools + resources exposed via Model Context Protocol so Claude Code / OpenCode / Gravity CLI drive the app natively. One DSL (mcp_tool / mcp_resource) → JSON-RPC dispatcher at /mcp + HTTP-direct routes + auto-published /llms.txt + /openapi.json. AGENTS.md convention for the prose-level invariants.

Demos

  • examples/counter/ — the smallest Tep.live demo. Shared integer counter; click in one tab, every other tab updates in <100ms. ~80 lines.
  • examples/experiments/ — the Tep::MCP battery demo. Mock training-run manager driven by an MCP client: 4 tools, 2 resources, capability gating, auto-published catalog. ~200 lines + a worked AGENTS.md.
  • examples/agentic_chat/ — the four-battery agentic demo (~270 lines). Sub-second WS push, multi-user chat, agent-spawn with OAuth2-style delegation. Walks through Auth + Broadcast + Presence + LiveView end-to-end.
  • examples/chatbot/ — OpenWebUI-style client (~1500 lines) against any OpenAI- compatible endpoint, exercising the full pre-agentic battery surface.
  • examples/websocket_echo.rbTep::WebSocket in isolation; the smallest possible WS app.

Reference

Reporting issues

Tep deliberately tracks Spinel's edges. If you hit something that "should work" — a Sinatra idiom that doesn't translate, a Spinel- emitted miscompile, a runtime hang — file an issue with a minimal reproduction at OriPekelman/tep/issues.

Clone this wiki locally