rubbs is an in-house Ruby gem for building Telnet BBS servers — from a one-screen line prompt to a full Synchronet-style multi-window application, without leaving Ruby. It powers our own BBS Server.
rubbs (the bbs gem) is a batteries-included framework for writing retro, Telnet-accessible bulletin board systems in pure Ruby. It boots a TCP listener, handles Telnet negotiation (SGA, ECHO, NAWS terminal-size, xterm SGR mouse), hands each connection a Session, and gives you three interaction layers to build the actual experience on top of.
The framework provides everything below the application logic: the Telnet server, full key + mouse parsing, frame-buffer delta rendering, a widget tree, themeable ANSI chrome, a Markdown-to-ANSI renderer, CP437 / ANSI-art loading, and CSV-backed persistence. Your code only declares the screens, windows, and services.
require 'bbs'
BBS.configure do |c|
c.flow = BBS::Flow.define do
big_banner 'My BBS'
ask :name, prompt: 'Your name'
say 'Welcome!', style: :success
end
end
BBS.start
Connect with telnet localhost 2323.
rubbs ships three interaction layers, from simplest to richest. They can be mixed in a single session — typically Flow for login, then Application for the main shell.
| Layer | What it is | When to use |
|---|---|---|
BBS::Flow |
Line-oriented declarative dialogue (ask / say / menu / persist) | Login, registration, simple wizards |
BBS::TUI |
Single-screen page router with frame-buffer delta rendering | Single-purpose full-screen UIs |
BBS::Application |
Widget framework: Menubar, Window, Button, TextInput, ListBox, … | Multi-window Synchronet-style BBSes |
The server boots a Telnet TCP listener, hands each connection a Session, which runs the configured Flow. Inside that flow you can hand off to a TUI or Application, then return to the flow when the user exits.
TCPServer → Session → FlowRunner ─┬→ TUIRunner
├→ Application#run
└→ FlowRunner (sub-flow)
Info, Form, MasterDetail, and Stream (chat / log) modals, openable imperatively or via a declarative window DSL.synchronet, nortoncommander, dosnavigator, neumanntronics, mono), each a frozen role-name → ANSI palette that can be overridden per key.BBS::Markdown.to_lines turns Markdown into width-wrapped ANSI line arrays for ScrollView / Info windows.BBS::Store — a thread-safe, upsert-by-session_id CSV file with an in-memory cache.Point a Gemfile at the repository:
gem 'bbs', git: 'https://git.teletype.hu/tools/rubbs.git'
Our public BBS Server (live at games.teletype.hu:2323) is built directly on top of rubbs. The framework provides the full-screen ANSI interface, the top menubar, the stacked modal windows, the Telnet server, and the xterm mouse support; the bbs-server repository contains only the Teletype-specific configuration — service wiring, window definitions, and formatters.
In other words, rubbs is the reusable framework and the BBS Server is one concrete application of it. If you want to see what rubbs looks like in production, connect to the BBS or read the BBS Server page.
| File | Responsibility |
|---|---|
lib/bbs.rb |
Public surface: BBS.configure, BBS.config, BBS.start. |
bbs/server.rb |
TCP accept loop, one thread per client. |
bbs/session.rb |
Telnet negotiation, mouse enable/disable, idle timer. |
bbs/telnet.rb |
Telnet protocol, key parsing, xterm SGR mouse. |
bbs/flow.rb, bbs/flow_runner.rb |
Flow DSL + interpreter. |
bbs/tui.rb, bbs/tui_runner.rb |
Page router with frame-buffer rendering. |
bbs/frame_buffer.rb |
Double-buffer, delta diff, ANSI string utilities. |
bbs/application.rb |
Widget event loop, window stack, builder DSL. |
bbs/widgets.rb, bbs/widget.rb, bbs/container.rb |
Widget tree + built-in widgets. |
bbs/window.rb, bbs/windows/* |
Window + pre-built window types. |
bbs/theme.rb |
Style palette presets. |
bbs/markdown.rb |
Markdown → ANSI line renderer. |
bbs/store.rb |
Thread-safe cached CSV upsert. |
https://git.teletype.hu/tools/rubbs