The post-game terminal of Definitely not an Impostor, a puzzle/ARG game: players who finish the game get a personal code, bring it here with their name, and find out what comes next.
Live at
teletypegames.org:2324, in the browser on bbsweb, and through TTG Gate BBS
A Ruby app on the rubbs gem, like the Teletype BBS. rubbs itself was extracted from this board (rubbs 0.1.0). It has two faces on one port:
A call starts with rubbs' BBS::Terminal question: RETURN takes the guess from the telnet answers, 1 picks the modern face, 2 the C64.
NORMAN and NORBERT share a code).Every session, successful or not, is a row in data/sessions.csv:
session_id,timestamp,player_name,code,feedback,email
The row is written when the name and code arrive, then updated in place as the feedback and the email come in. IMPOSTOR_BBS_SESSIONS moves the file; the compose file mounts data/, so the records survive restarts.
The personal code of a player name comes from the CLI tool, which reads the name from IMPOSTOR_BBS_PLAYER_NAME:
IMPOSTOR_BBS_PLAYER_NAME=norman bin/generate_code
# => 2J5GFN
The repository is two things: the impostor gem (lib/impostor*, screens/), the debrief terminal with its rules, and the standalone board around it. Another rubbs board can pull the gem and run the same terminal as a door, with a sessions store of its own (the Teletype BBS did until 2026-11-01; since then this board on 2324 is the one place of the terminal):
gem 'impostor', git: 'https://git.teletypegames.org/bbs/impostor-bbs.git'
require 'impostor'
sessions = Impostor.sessions_store('data/impostor_sessions.csv')
door :impostor, Impostor::Modern.flow(sessions: sessions), label: '&Impostor'
A C64 caller gets Impostor::Petscii.flow(sessions: sessions). When the flow ends, the door asks for ENTER and hands the caller back to the host BBS. The host's Gemfile.lock pins the revision, so a change here reaches the door only with a lock bump there.
| Path | What it is |
|---|---|
bbs.rb |
Entry point: one ImpostorBBS, BBS::Terminal with the two faces |
lib/domain/impostor_bbs.rb |
The composition root: reads the environment, builds the sessions store |
lib/ui/modern.rb, lib/ui/petscii.rb |
The board's faces: the gem's flows, then goodbye and NO CARRIER |
lib/impostor.rb, lib/impostor/ |
The gem: the debrief flow, Impostor::Modern, Impostor::Petscii, the code generator (a Ruby port of the Lua original) |
screens/modern/, screens/petscii/ |
The welcome and congratulations screens of the two faces |
bin/generate_code |
The code generator CLI |
Environment: BBS_PORT, BBS_MAX_SESSIONS (rubbs) and IMPOSTOR_BBS_SESSIONS; env-example lists them with their defaults.
A push to master deploys it from Woodpecker (RuboCop, compose check, ci-deploy impostor-bbs); the container is impostor-bbs, in /srv/stacks/impostor-bbs, public port 2324, and data/ stays between deploys. The entrypoint updates rubbs on start. See the BBS Network for the other boards.