This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
GitHub Repository: coder/balatrollm
BalatroLLM is an LLM-powered bot that autonomously plays Balatro using strategic decision-making. It uses the BalatroBot API (a Lua mod exposing JSON-RPC 2.0 endpoints) to control the game while leveraging large language models for gameplay decisions.
Key capabilities:
- Autonomous gameplay from start to completion
- LLM-driven strategic decision-making using OpenAI function calling
- Configurable strategies via Jinja2 templates
- Parallel execution of multiple game instances
- Comprehensive data collection for analysis and benchmarking
Available make targets:
| Target | Description |
|---|---|
make help |
Show all available targets |
make lint |
Run ruff linter (check only) |
make format |
Run ruff and mdformat formatters |
make typecheck |
Run type checker |
make quality |
Run all code quality checks (lint + typecheck + format) |
make all |
Run all quality checks |
make install |
Install dependencies |
Important rules:
- Only run make commands when explicitly asked. Do not proactively run
make quality,make lint, etc. - Never run bare linting/formatting/typechecking tools. Always use make targets instead:
- Use
make lintinstead ofruff check - Use
make formatinstead ofruff format - Use
make typecheckinstead ofty check - Use
make qualityfor all checks combined
- Use
The bot is structured as a pipeline: CLI → Executor → Bot → (LLMClient + BalatroClient) → Game.
Entry point for the balatrollm command. Parses CLI arguments and YAML config files, generates task combinations from game parameters (seed, deck, stake, strategy, model). Config precedence: environment variables < YAML < CLI args.
Core game loop with LLM-powered decision-making. Handles game states (SELECTING_HAND, SHOP, ROUND_EVAL, BLIND_SELECT, GAME_OVER). Each decision: sends game state + strategy + memory to LLM → receives tool call → executes via BalatroClient. Tracks consecutive failures (max 3) and logs all data via Collector.
JSON-RPC 2.0 HTTP client for BalatroBot mod. Async client to http://127.0.0.1:12346 (default 30s timeout). Methods: gamestate, start, select, cash_out, play, buy, sell, use, screenshot, etc.
Async OpenAI client wrapper with retry logic. Provider-agnostic (works with OpenAI, OpenRouter, any compatible API). Default: OpenRouter. Exponential backoff (max 3 retries), aborts after 3 consecutive timeouts. Default timeout: 240s.
Manages Jinja2 strategy templates. Each strategy folder contains: STRATEGY.md.jinja (game rules/tactics), GAMESTATE.md.jinja (current state), MEMORY.md.jinja (action history), TOOLS.json (function calling tools), manifest.json (metadata). Current: default (conservative, financially-focused).
Multi-source configuration. Precedence: environment variables < YAML < CLI args. Key env vars: BALATROLLM_API_KEY, BALATROLLM_BASE_URL, BALATROLLM_MODEL, BALATROLLM_SEED/DECK/STAKE, BALATROLLM_STRATEGY, BALATROLLM_PARALLEL, BALATROLLM_HOST/PORT.
Orchestrates parallel execution. Manages pool of Balatro instances via balatrobot package, assigns consecutive ports (12346, 12347, ...), uses task queue with worker pool pattern.
Data collection and statistics. Output: runs/v1.0.0/{strategy}/{vendor}/{model}/{timestamp}_{deck}_{stake}_{seed}/. JSONL format, OpenAI Batch API compatible.
Template-based system using Jinja2. Templates render strategy guidance, game state, and action history into LLM prompts. At each decision point: render templates → send to LLM with tools → execute tool call. Custom strategies: create folder in src/balatrollm/strategies/ with required template files.
BalatroBot is a Lua mod that runs inside the Balatro game and exposes a JSON-RPC 2.0 HTTP API for programmatic control.
How BalatroLLM uses BalatroBot:
┌─────────────────────────────────────────┐
│ BalatroLLM (Python) │
│ │
│ ┌────────┐ ┌──────────────────┐ │
│ │ Bot │──────│ LLMClient │ │◄──── OpenAI API
│ └───┬────┘ └──────────────────┘ │ (OpenRouter, etc.)
│ │ │
│ ┌───▼────────────────────────────┐ │
│ │ BalatroClient │ │
│ │ (JSON-RPC 2.0 HTTP Client) │ │
│ └───┬────────────────────────────┘ │
└──────┼──────────────────────────────────┘
│ HTTP POST
│ JSON-RPC 2.0
┌──────▼──────────────────────────────────┐
│ BalatroBot (Lua Mod) │
│ JSON-RPC 2.0 HTTP API Server │
└──────┬──────────────────────────────────┘
│
┌──────▼──────────────────────────────────┐
│ Balatro Game │
│ (Love2D) │
└─────────────────────────────────────────┘
Integration: BalatroLLM imports BalatroInstance from balatrobot to manage game instances. BalatroClient sends JSON-RPC requests to BalatroBot's HTTP server (default port 12346).
Output directory: runs/v1.0.0/{strategy}/{vendor}/{model}/{timestamp}_{deck}_{stake}_{seed}/
Files generated:
requests.jsonl- LLM requests (OpenAI Batch API format)responses.jsonl- LLM responses with timing/token datagamestates.jsonl- Game state snapshots after each actionscreenshots/- PNG screenshots at each decision pointtask.json- Run configurationstrategy.json- Strategy metadatastats.json- Aggregated statistics (outcome, tokens, timing, cost, provider distribution)
| File | Purpose |
|---|---|
src/balatrollm/cli.py |
CLI entry point and argument parsing |
src/balatrollm/bot.py |
Core game loop and LLM integration |
src/balatrollm/client.py |
BalatroBot JSON-RPC client |
src/balatrollm/llm.py |
OpenAI client wrapper with retry logic |
src/balatrollm/strategy.py |
Strategy template management |
src/balatrollm/config.py |
Multi-source configuration management |
src/balatrollm/executor.py |
Parallel execution orchestration |
src/balatrollm/collector.py |
Data collection and statistics |
src/balatrollm/views.py |
HTTP server for views overlay |
| File | Purpose |
|---|---|
pyproject.toml |
Python dependencies and tool configuration |
config/example.yaml |
Example YAML configuration file |
Makefile |
Development commands (lint, format, typecheck) |
| File | Purpose |
|---|---|
src/balatrollm/strategies/default/ |
Default strategy templates |
Tracks consecutive failures (max 3 before aborting). Two failure types: error calls (invalid LLM response) and failed calls (valid tool call but execution failed). LLM retry with exponential backoff (max 3 retries), aborts after 3 consecutive timeouts. Error context included in next prompt's memory for recovery.
Config precedence: environment variables < YAML config file < CLI arguments (highest priority).
Environment variables (prefix: BALATROLLM_):
API_KEY,BASE_URL,MODEL- LLM configurationSEED,DECK,STAKE,STRATEGY- Game parametersPARALLEL,HOST,PORT- Execution settingsVIEWS- Enable HTTP server for views overlay (set to1)
Usage: balatrollm config/example.yaml --model openai/gpt-4o --seed AAAAAAA --deck RED --stake WHITE
Views overlay: Use --views to start an HTTP server on port 12345 that serves the HTML views (views/task.html, views/responses.html).