---
title: 'Impostor BBS'
url: 'https://wiki.teletypegames.org/services/impostor-bbs'
markdown: 'https://wiki.teletypegames.org/services/impostor-bbs.md'
lang: en
date: '2026-11-01'
description: '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 Overview A Ruby app on the rubb…'
taxonomy:
  tag:
    - howto
---

# Impostor BBS

> 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](https://bbsweb.teletypegames.org), and through [TTG Gate BBS](https://wiki.teletypegames.org/services/ttg-gate-bbs)

# Overview

A Ruby app on the [**rubbs**](https://git.teletypegames.org/engines/rubbs) gem, like the [Teletype BBS](https://wiki.teletypegames.org/services/teletype-bbs). rubbs itself was extracted from this board (rubbs 0.1.0). It has two faces on one port:

- **Modern** — ANSI/xterm, 80 columns (SyncTERM, NetRunner, PuTTY, bbsweb).
- **Commodore 64** — PETSCII on a 40×25 screen, the same terminal with its own screens, for a C64 terminal program behind a WiFi modem.

A call starts with rubbs' `BBS::Terminal` question: RETURN takes the guess from the telnet answers, `1` picks the modern face, `2` the C64.

# How a call goes

1. The board asks for the player's **name** and **personal code**.
2. The code is decrypted with a salt-based algorithm and checked against the name. Only the first three characters of the name count, after trimming and upper-casing (`NORMAN` and `NORBERT` share a code).
3. A correct code unlocks a short identity confirmation, then a congratulations screen and a post-game menu: the player can leave **feedback** and an **email** for updates.
4. When the debrief ends (or the code is refused), the board thanks the caller and hangs up with NO CARRIER.

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.

# Generating a code

The personal code of a player name comes from the CLI tool, which reads the name from `IMPOSTOR_BBS_PLAYER_NAME`:

```bash
IMPOSTOR_BBS_PLAYER_NAME=norman bin/generate_code
# => 2J5GFN
```

# As a door

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](https://wiki.teletypegames.org/services/teletype-bbs) did until 2026-11-01; since then this board on 2324 is the one place of the terminal):

```ruby
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.

# Under the hood

| 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](https://wiki.teletypegames.org/services/bbs-network) for the other boards.

'; var prevLevel = 2; for (var i = 0; i < headings.length; i++) { var h = headings\[i\]; var text = h.textContent.trim(); var slug = text.toLowerCase() .replace(/\[áàâä\]/g,'a').replace(/\[éèêë\]/g,'e').replace(/\[íìîï\]/g,'i') .replace(/\[óòôöő\]/g,'o').replace(/\[úùûüű\]/g,'u') .replace(/\[^a-z0-9\]+/g, '-').replace(/^-|-$/g, ''); if (!slug) slug = 'heading-' + i; if (used\[slug\]) { slug += '-' + i; } used\[slug\] = true; h.id = slug; var level = parseInt(h.tagName.charAt(1)); var cls = level > 2 ? ' class="toc-child"' : ''; html += '- [' + text + '](#'%20+%20slug%20+%20')
'; } html += '
'; toc.innerHTML = html; // Scroll-spy: highlight current heading var links = toc.querySelectorAll('a'); var ids = \[\]; for (var j = 0; j < links.length; j++) ids.push(links\[j\].getAttribute('href').slice(1)); function updateActive() { var current = ''; for (var k = 0; k < ids.length; k++) { var el = document.getElementById(ids\[k\]); if (el && el.getBoundingClientRect().top <= 80) current = ids\[k\]; } for (var m = 0; m < links.length; m++) { links\[m\].parentNode.classList.toggle('active', links\[m\].getAttribute('href') === '#' + current); } } window.addEventListener('scroll', updateActive, { passive: true }); updateActive(); })();

---

## Navigation

- Parent: [Services](https://wiki.teletypegames.org/services.md)
- Previous: [Feedia BBS](https://wiki.teletypegames.org/services/feedia-bbs.md)
- Next: [Pixelia BBS](https://wiki.teletypegames.org/services/pixelia-bbs.md)
