Bad Decisions
An absurdly overengineered open-source party game engine.
Bad Decisions serves fill-in-the-blank party games through a REST API, browser client, and terminal client. Its terminal client is called Regret.
$ regret deal --packs coffee
I started by talking about workplace accommodations. Somehow the channel is now discussing one hell of a robustly deployed pastebin.
brew install bytesandcoffee/tap/regret
regret deal
Prefer pipx? pipx install bad-decisions-client gets you the same dependency-free
client on Linux, macOS, or Windows. Regret uses the free BytesAndCoffee-hosted
service by default; no account is required.
On Windows, each GitHub release also includes a self-contained regret.exe
ZIP with the Peer Pressure TUI and no Python prerequisite.
Play in the browser · Explore the API · Get started in 60 seconds
Why this exists
Bad Decisions is production-grade infrastructure for profoundly unserious purposes. The protocol is open, packs are portable and provenance-aware, the service is self-hostable, multiplayer needs no permanent accounts, and the overengineering is part of the joke.
What has gone wrong so far
regret deal— get a terrible idea from any compatible service in one command.- Peer Pressure — ephemeral, authenticated multiplayer with a rotating Responsible Adult.
- Browser client — choose packs, deal rounds, and opt into feedback without installing anything.
- OpenAPI — a versioned contract for building clients that should never have existed.
- CardDeck — portable, validated
.carddeckarchives with licensing and provenance inside. - Remote catalog — discover and safely import public packs without making the runtime mutable.
- Provenance — card content keeps its own attribution, source, and license boundaries.
- Consequences — opt-in feedback and owner analytics backed by SQLite.
- Self-hosting — systemd/nginx deployment with immutable releases and health-checked rollback.
- Rootless updates — deploy and roll back application releases without recurring sudo.
- AWS-native mode — a complete managed-cloud alternative optimized for low cost.
How the bad decisions travel
flowchart TB
subgraph distribution["1 · PACK DISTRIBUTION"]
direction LR
archive[(Garage archive)] -->|scan| catalog[Public CardDeck catalog]
end
subgraph activation["2 · OPERATOR ACTIVATION"]
direction LR
importer[Validate + import] --> registry[(Loaded pack registry)]
end
subgraph runtime["3 · IMMUTABLE RUNTIME"]
direction LR
clients[Regret · Web · Other clients]
server[Bad Decisions API]
rooms[(Peer Pressure rooms)]
consequences[(Consequences)]
clients <-->|rounds + game actions| server
server <--> rooms
server --> consequences
end
archive -->|individual .carddeck| importer
catalog -->|remote index| importer
registry -->|load once at startup| server
classDef core fill:#171511,stroke:#bc552f,color:#fff8ed,stroke-width:3px;
classDef action fill:#bc552f,stroke:#7d321b,color:#ffffff,stroke-width:2px;
classDef store fill:#fff4e5,stroke:#bc552f,color:#171511,stroke-width:2px;
classDef edge fill:#4b2317,stroke:#bc552f,color:#fff8ed,stroke-width:2px;
class server core;
class importer action;
class archive,registry,rooms,consequences store;
class catalog,clients edge;
style distribution fill:transparent,stroke:#bc552f,stroke-width:1px
style activation fill:transparent,stroke:#bc552f,stroke-width:1px
style runtime fill:transparent,stroke:#bc552f,stroke-width:1px
Public .carddeck archives and their generated catalog are distribution
inputs, not a writable runtime API. An operator explicitly imports and
validates packs into the registry; the server loads that registry at startup
and then treats it as immutable. Clients consume rounds and pack metadata—or
participate in Peer Pressure—while room state and opt-in Consequences data stay
in separate SQLite boundaries.
Sixty-second quick start
brew install bytesandcoffee/tap/regret
regret health
regret deal
Cross-platform alternative:
pipx install bad-decisions-client
regret health
regret deal
Both pipx packages install manual pages; regret doctor diagnoses PATH,
manual-page, preference, and service issues without changing anything.
Invite friends into an ephemeral Peer Pressure room:
regret together ohno --name Michael
The default endpoint is https://bytes.coffee/bad-decisions. Override it with
--api-url; local preferences live in protected files under your home
directory. See Getting Started for the complete short
path and privacy controls.
Build something stupid with it
The OpenAPI contract is intended to be enough to build another client. Please make an ESP32 button, e-ink daily draw, IRC bot, Discord bot, smartwatch app, desktop widget, or a frontend with even more regrettable typography.
curl -s https://bytes.coffee/bad-decisions/v2/round \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["result"])'
import json
from urllib.request import urlopen
with urlopen("https://bytes.coffee/bad-decisions/v2/round") as response:
print(json.load(response)["result"])
Start with the live OpenAPI UI and the version-2 API notes. If you build something, the maintainer would very much like to see what happened.
Make your own pack
The minimal-pack example goes from editable JSON to a
validated .carddeck in about five minutes:
cp -R examples/minimal-pack /tmp/my-questionable-pack
cd /tmp/my-questionable-pack
./build.sh
bad-decisions pack validate dist/example-pack.carddeck
CardDeck archives contain exact license and attribution documents alongside the cards. Read the CardDeck specification before sharing a pack, and only distribute content you have the right to distribute.
Run the engine
pipx install bad-decisions
bad-decisions --oneshot
bad-decisions serve --host 127.0.0.1 --port 8000
The API exposes /healthz, /v2/packs, /v2/round, Peer Pressure, and optional
Consequences feedback. Packs are loaded at startup; the HTTP API cannot import,
upload, or edit them. An omitted pack selector means every loaded pack.
For a production install, start with Easy Deploy. The full deployment reference covers systemd/nginx, rootless activation, AWS-native mode, object storage, configuration, and rollback.
Licensing is deliberately less funny
Bad Decisions software is licensed under the MIT License. Card packs are separate works: each pack's own license, attribution, provenance, and modification metadata governs that content. The software's MIT license grants no additional rights to third-party cards, and BytesAndCoffee cannot grant rights it does not own.
The official BytesAndCoffee distribution and hosted service are currently free of charge, with no paid API access, sale of access, or advertising. That is a description of the official service, not a restriction on downstream use of the MIT-licensed software.
In other words: use the engine however MIT permits, but check the license on the cards you put into it. If your Bad Decisions have Consequences, that is between you and the stew.
Go deeper
- Documentation map
- Installing and using Regret
- CardDeck format and remote imports
- Peer Pressure and Consequences
- Attribution and content rights
- Deployment and release process
- Contributing, security, and changelog
- Manual pages: bad-decisions(1) and regret(1)
If this terrible decision amused you, consider starring the repository.
This is an unofficial, unaffiliated fan project. No endorsement by any third-party game publisher is claimed or implied.
Metadata
Release files for bad-decisions 2.1.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| bad_decisions-2.1.5.tar.gz | 402.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bad_decisions-2.1.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 526.6 kB
Release files / bad_decisions-2.1.5.tar.gz
| Download URL | bad_decisions-2.1.5.tar.gz |
|---|---|
| Size | 402.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bd36687c8857c028082c8e90f68f61f25ac40dae15674deaf9af5072aeb0f30e
|
|
BLAKE2b-256 checksum How to use checksums |
92ebe1d8664a9f4670782f21cbe9673970c2f6d3242a20cd71362c27bc8a9988
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency logRelease files / bad_decisions-2.1.5-py3-none-any.whl
| Download URL | bad_decisions-2.1.5-py3-none-any.whl |
|---|---|
| Size | 124.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
77945669213cd5dad57b86769d331caaabd265b8b6b0ef7878b6107a8a454af6
|
|
BLAKE2b-256 checksum How to use checksums |
95c07d061d68df9466162c2c4566bb5c59408edff23c328e3feb8d84d1bcc0a2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency log