Skip to content

Latest commit

 

History

37 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TSpire

Play Slay the Spire from a text window — and keep your achievements.

TSpire lets you play the first Slay the Spire by typing simple commands (like play 0 1 or end) instead of clicking. The game still runs and looks completely normal on your PC; TSpire just acts as its eyes and hands:

  • A host runs on your gaming PC. It reads what's on screen and moves the mouse for you.
  • A client is the text window where you see the state (your hand, enemies, HP, energy…) and type your moves. It can run on the same PC or on another device on your network.

You make every decision — TSpire never plays for you.

Is this a cheat / mod? Will I lose achievements? No. The recommended setup uses a tiny read-only helper that only looks at the game and never changes it, so Steam achievements, unlocks, and stats all keep working. It is not ModTheSpire and does not mark your save as modded.

What it looks like

The client is a text dashboard showing the current screen, your choices, and the commands you can type. Here it is at the main menu, right after /launch connects to the game:

The client at the main menu after /launch

In combat it shows your hand, enemies, HP, energy, and a running action log.

The client during combat — hand, enemies, and the action log

Out of combat it shows the current screen's choices (rewards, shops, events) with the commands you can type.

The client on a combat-reward screen — choices and available commands


What you need

  • A Windows gaming PC with Slay the Spire installed (Steam).
  • Python 3.11 or newer — during install, tick “Add Python to PATH.”
  • A Java JDK (used once to build the helper). The Quick Start installs it for you.
  • About 10 minutes for first-time setup.

You do not need Tesseract, Ollama, or any AI models for the recommended setup.


Quick Start (everything on one PC)

Open PowerShell (press Win, type PowerShell, hit Enter) and run these one at a time.

1. Get a Java JDK (skip if you already have one):

winget install EclipseAdoptium.Temurin.17.JDK

2. Download TSpire and go into its folder:

git clone <this-repo-url> TSpire
cd TSpire

(No git? Download the project as a ZIP, unzip it, then cd into the folder.)

3. Install TSpire:

pip install -e ".[host,client]"

4. Build the read-only helper (one time):

.\tools\build_agent.ps1

If Windows blocks the script, run it this way instead: powershell -ExecutionPolicy Bypass -File tools\build_agent.ps1

5. Turn on the recommended mode. Create a file named tspire_host.json in the TSpire folder with exactly this content:

{ "vision_mode": "jvm" }

6. Start the host (leave this window open):

python -m tspire.host.server -v

7. Open a second PowerShell window, cd back into the TSpire folder, and start the client:

cd TSpire
python -m tspire.client.app

8. Launch the game from the client. In the client window, type:

/launch

TSpire starts Slay the Spire with the helper attached. Start a run, and your hand, enemies, HP, and energy appear in the client. You're playing! Type ? any time for help.

Tip: Set the game to Borderless or Windowed mode (Settings → Video). 1920×1080 works best.


How to play

You type short commands. Every card, enemy, and choice shows a number in the dashboard — that's the index you use.

Command What it does Shortcut
play 2 Play card 2 (non-targeted) p 2
play 2 0 Play card 2 on enemy 0 p 2 0
end End your turn e
choose 1 Pick option/card/reward 1 (maps, events, shops, rewards) c 1
potion use 0 / potion discard 0 Use or throw away potion 0
proceed Confirm / continue space
back Cancel / go back b
state Re-read the screen r

Handy extras (type with a leading slash):

  • /define <name> — look up any card, relic, potion, or monster's rules text.
  • /log — toggle an old-school RPG combat action log (e.g. You play Strike. / Jaw Worm takes 6 damage. / Jaw Worm hits you for 11 damage. / You win the fight!). Ground truth from the JVM agent, so it only fills in when vision_mode is jvm. While it's on, typed command echoes are hidden (the log already narrates each play) and the log pane grows.
  • /map, /deck, /draw, /discard, /exhaust — pop open a full-screen list (Esc closes it).
  • /launch, /exit-game, /game — start, close, or check the game.
  • /help — full command list.

Nice touches: cards and relics are color-coded by rarity (rare = yellow, uncommon = cyan, common = gray; curses are purple, status cards a muted gray) so good picks stand out on reward screens. Press / for command history and Tab to autocomplete. Chain combat moves with semicolons — e.g. p 0 0; p 0 0; e. Ctrl+C quits the client.


Playing from another device (optional)

Want to play from a laptop while the game runs on your gaming PC? By default the host only listens on the gaming PC itself (it drives your real mouse and keyboard, so it isn't exposed to the network unless you say so). To allow LAN play, edit tspire_host.json on the gaming PC to open it up and set a token so only your own client can connect:

{ "vision_mode": "jvm", "host": "0.0.0.0", "auth_token": "pick-any-secret" }

Restart the host (steps 6–8 above), then run the client on the other device:

pip install -e ".[client]"
python -m tspire.client.app --host <gaming-pc-ip-address> --token pick-any-secret

Find the gaming PC's IP with ipconfig (Windows). Both devices must be on the same network. (The client can also read the token from the TSPIRE_AUTH_TOKEN environment variable.)


Troubleshooting

  • python or pip not found — reinstall Python and make sure “Add Python to PATH” is ticked, then reopen PowerShell.
  • The build script won't run — use powershell -ExecutionPolicy Bypass -File tools\build_agent.ps1. If it says javac is missing, install the JDK (Quick Start step 1) and reopen PowerShell.
  • Client says it can't connect — start the host first (it prints host listening on ws://…), then the client. On the same PC no --host is needed. From another device, the host must be opened up for LAN play first (see Playing from another device), and if the host sets auth_token the client must pass the matching --token.
  • /launch doesn't start the game — make sure Slay the Spire is installed via Steam. You can also start the game normally; TSpire will read it as long as the helper is attached (see Advanced).
  • The dashboard shows [stale] or numbers look wrong — press r to re-read. Confirm your tspire_host.json contains { "vision_mode": "jvm" } and that you rebuilt the helper after updating TSpire.
  • Nothing happens when I play a card — the game window must be visible (not minimized). TSpire foregrounds it automatically, but a full-screen exclusive mode can block input; use Borderless/Windowed.

Advanced & reference

Everything below is optional — the Quick Start is all most players need.

Screen-reading modes (vision_mode)

  • jvm (recommended) — a tiny read-only Java agent loaded into the game's own JVM reports ground-truth state (exact HP/energy/block, hand, monster intents, relics, potions) over a localhost socket, plus every card's/monster's exact on-screen hitbox for pixel-perfect input. No pixels, no OCR, no guessing, sub-millisecond reads. It never writes game fields and never sets Settings.isModded, so achievements/unlocks/metrics stay enabled. If the agent isn't loaded it falls back to agent_fallback_mode (default llm).
  • llm — a local Ollama vision model reads the combat scene; fixed HUD numbers use local OpenCV+Tesseract OCR (ocr_hud_numbers, default on). Runs only during combat and on demand.
  • cv — OpenCV template matching + Tesseract OCR, with optional EasyOCR for stylised text (use_easyocr). Fast but fragile on the cluttered scene and needs calibration + a Tesseract install.

Input backends (input_backend)

  • mouse (default) — plays a card by click-dragging it to the target (or the play zone for non-targeted cards) and clicks End Turn. Card positions come from Slay the Spire's own hand-layout math, so they're exact and resolution-independent. Nothing to enable in-game.
  • keyboard — uses StS number-key hotkeys (needs Settings → “Show Card keys” on). Handy as an automatic fallback for tricky multi-enemy targets.
  • gamepad — a virtual Xbox 360 pad (last-resort/debug; see controller notes below).

Dry-run without touching the game:

TSPIRE_INPUT_DRY_RUN=true python -m tspire.host.server -v

Check where clicks will land on a live combat:

python -m tspire.host.input_probe --mouse                 # writes mouse_points.png
python -m tspire.host.input_probe --mouse --play-card 0 --target 0

If a targeted drop misses, TSpire cancels targeting with a right-click (Escape could open the settings menu); if the menu ever appears, type back to close it.

The JVM state agent (details)

agent/TSpireAgent.java reflects over the game's own singletons and serves a JSON snapshot on 127.0.0.1:8731 (GET /state). A background sampler also diffs successive combat reads into ground-truth events served at GET /events?since=<seq> — this is what feeds the client's /log action log. It stays pure read-only reflection (it never hooks or patches the game), so enemy-hit attribution in a multi-enemy turn is best-effort while damage, powers, turns and deaths are exact. Build it with a JDK (the game's bundled JRE can't compile):

winget install EclipseAdoptium.Temurin.17.JDK   # if needed
.\tools\build_agent.ps1                          # -> agent/tspire-agent.jar

/launch auto-detects SlayTheSpire.exe next to desktop-1.0.jar, injects the agent, and passes -Dtspire.agent.port=8731. Check it any time:

curl 127.0.0.1:8731/state

Tunables: TSPIRE_AGENT_URL, TSPIRE_AGENT_TIMEOUT, TSPIRE_AGENT_FALLBACK_MODE, TSPIRE_AGENT_PORT, TSPIRE_GAME_LAUNCH_STATE_GRACE_SECONDS.

Attaching the helper yourself

If you start the game outside TSpire, set JAVA_TOOL_OPTIONS so the JVM loads the agent at startup (no attach, no files modified). Steam → right-click the game → Properties → Launch Options:

env JAVA_TOOL_OPTIONS="-javaagent:C:\path\to\TSpire\agent\tspire-agent.jar" %command%

On startup the game log prints [tspire-agent] read-only state agent listening on 127.0.0.1:8731.

Game art (relics / intents)

Relic and intent identity is matched against the game's own art, read from the installed desktop-1.0.jar at runtime — nothing is bundled, and it only works when the game is installed. The jar is auto-detected (project dir, then Steam libraries); override with jar_path or TSPIRE_JAR_PATH.

Calibration (only for cv / llm modes)

Region coordinates ship as estimates for 1920×1080 and may need tuning for those two modes (jvm mode generally needs no calibration):

python -m tspire.host.calibrate                   # live capture
python -m tspire.host.calibrate --image shot.png  # or a saved screenshot

Controller backend (only for input_backend = "gamepad")

  • Start the host before launching the game. StS only detects controllers present at startup, so the virtual pad must exist first.
  • Disable Steam Input for Slay the Spire (Steam → game → Properties → Controller → Disable Steam Input), or Steam captures the virtual pad and the game gets nothing.
  • Confirm Controller Enabled is on in the in-game settings.

Verify the setup and input:

python -m tspire.host.input_probe --controller-check
python -m tspire.host.input_probe --sequence left,left,right,right

Configuration

Host config loads from tspire_host.json in the working directory (see tspire/host/config.py), overridable via TSPIRE_* env vars. Common ones: TSPIRE_VISION_MODE, TSPIRE_INPUT_BACKEND, TSPIRE_INPUT_DRY_RUN, TSPIRE_JAR_PATH, TSPIRE_HOST, TSPIRE_AUTH_TOKEN, TSPIRE_AGENT_FALLBACK_MODE, and the mouse tunables (TSPIRE_MOUSE_DRAG_SECONDS, TSPIRE_MOUSE_PLAY_ZONE_X/_Y, TSPIRE_MOUSE_KEYBOARD_FALLBACK, …).

Project layout

Path Role
tspire/common/ Shared state schema + wire protocol
tspire/host/ Screen capture, vision, mouse/keyboard/gamepad input, WebSocket server
tspire/client/ Terminal UI and command parsing
agent/ The read-only JVM state agent (TSpireAgent.java)
tools/ One-off tooling (build the agent, extract art)
tests/ Parser/schema tests + fixtures

Develop

pip install -e ".[dev]"
pytest

About

A solution to play Slay the Spire remotely through the terminal (not a mod)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages