"It is pitch black. You are likely to be eaten by a grue."
A testing framework and automation tool for interactive fiction games. Run smoke tests, execute walkthroughs with assertions, or let an LLM play your game autonomously.
- Features
- Quick Start
- Installation
- Testing Commands
- GitHub Action
- LLM Play Mode
- Development
- Why "Gruebot"?
Testing & CI/CD:
- Smoke tests to verify games load and respond
- Walkthrough tests with scripted commands
- Assertion system for validating game state
- Reusable GitHub Action for IF projects
- No API key required for basic testing
Game Format Support:
- Z-Machine via dfrotz (Infocom, Inform 6/7: .z3, .z5, .z8)
- Glulx via glulxe+remglk (modern Inform 7: .ulx, .gblorb)
- MUD servers via telnet
LLM Integration (Optional):
- Let Claude play your game autonomously
- Generate transcripts for review
- Configurable models (Sonnet, Opus)
- Useful for difficulty testing and regression checks
Test your game (no API key needed):
# Install
pip install -e ".[dev]"
# Smoke test - verify game loads
gruebot test mygame.z8 --smoke
# Walkthrough test - run scripted commands
gruebot test mygame.z8 --walkthrough tests/walkthrough.txtLet Claude play (requires API key):
export ANTHROPIC_API_KEY=your-key-here
gruebot test mygame.z8 --ai --max-turns 100 --transcript playthrough.md- Python 3.11 or higher
- Game interpreter: dfrotz (Z-Machine) or glulxe (Glulx)
ANTHROPIC_API_KEY(only for LLM features)
pip install -e ".[dev]"# Z-Machine (macOS)
brew install frotz
# Z-Machine (Linux)
apt install frotzFor Glulx games, glulxe must be built with remglk:
git clone https://github.com/erkyrath/remglk.git
git clone https://github.com/erkyrath/glulxe.git
cd remglk && make
cd ../glulxe
make GLKINCLUDEDIR=../remglk GLKLIBDIR=../remglk GLKMAKEFILE=Make.remglk
sudo cp glulxe /usr/local/bin/Verify a game loads and responds to basic input:
gruebot test game.z5 --smokeRun a sequence of commands and check assertions:
gruebot test game.z5 --walkthrough walkthrough.txtWalkthrough file format:
# Comments start with #
look
north
take lamp
# Assertions check game state
@expect-location "Kitchen"
@expect-contains "brass lantern"
@expect-not-contains "grue"
@expect-inventory "lamp"
@expect-score-gte 10
@expect-turns-lte 50
south
@expect-location "Living Room"
Add assertions via command line:
gruebot test game.z5 -w walkthrough.txt \
--expect-location "Treasure Room" \
--expect-text "gold"| Code | Meaning |
|---|---|
| 0 | All tests passed |
| 1 | Game failed to start |
| 2 | Assertion failed |
| 3 | Game error during playthrough |
| 4 | Invalid input (bad walkthrough file) |
| 5 | Walkthrough execution error |
Add automated testing to your IF project:
name: Test IF Game
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Smoke test
uses: tibbon/gruebot@v1
with:
game: ./mygame.z8
mode: smoke
- name: Walkthrough test
uses: tibbon/gruebot@v1
with:
game: ./mygame.z8
mode: walkthrough
walkthrough: ./tests/walkthrough.txt
expect-location: "Victory Room"| Input | Required | Default | Description |
|---|---|---|---|
game |
Yes | - | Path to game file (.z5, .z8, .ulx, .gblorb) |
mode |
No | smoke |
Test mode: smoke, walkthrough, or ai |
walkthrough |
For walkthrough | - | Path to walkthrough file |
max-turns |
No | 50 |
Maximum turns for AI mode |
expect-location |
No | - | Assert final location contains text |
expect-text |
No | - | Assert final output contains text |
transcript |
No | - | Save transcript to this path |
model |
No | - | Model for AI mode |
anthropic-api-key |
For AI mode | - | Anthropic API key |
verbose |
No | false |
Show detailed output |
Let Claude play your game to test difficulty or generate transcripts:
ai-test:
runs-on: ubuntu-latest
if: github.event_name == 'push' # Save API costs
steps:
- uses: actions/checkout@v4
- name: Claude playthrough
uses: tibbon/gruebot@v1
with:
game: ./mygame.z8
mode: ai
max-turns: '100'
expect-location: "Treasure Room"
transcript: ./playthrough.md
anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
- name: Upload transcript
uses: actions/upload-artifact@v4
if: always()
with:
name: claude-playthrough
path: ./playthrough.mddocker run --rm \
-v $(pwd):/workspace -w /workspace \
ghcr.io/tibbon/gruebot:latest \
test ./mygame.z8 --walkthrough ./tests/walkthrough.txtBeyond testing, Gruebot can run interactive sessions where Claude plays your game in real-time.
# Watch Claude play
gruebot play game.z5
# Use a specific model
gruebot play game.z5 --model claude-opus-4-20250514
# Connect to a MUD
gruebot mud mud.example.com:4000Config file (config.yaml):
llm:
model: claude-opus-4-20250514
max_tokens: 1024
temperature: 0.7gruebot play game.z5 --config config.yamlEnvironment variable:
export GRUEBOT_LLM__MODEL=claude-opus-4-20250514pip install -e ".[dev]"
# Linting
ruff check src/ tests/
ruff format src/ tests/
# Type checking
mypy src/
# Tests
pytest tests/ -vThe grue is the iconic monster from Zork that lurks in dark places, waiting to devour adventurers who wander without a light source. Gruebot helps you navigate through the darkness of untested code paths - whether through automated walkthroughs or by letting an LLM explore your game and report what it finds.
MIT