Skip to main content

Overview

The BattleStream class provides a stream-based interface for running Pokemon battles. It extends ObjectReadWriteStream<string> and handles battle initialization, player inputs, and battle outputs.
import { BattleStream } from 'pokemon-showdown';

const stream = new BattleStream();

Constructor

options
object
Optional configuration for the battle stream
const stream = new BattleStream({
  debug: true,
  replay: 'spectator'
});

Properties

battle
Battle | null
The current Battle instance, or null if no battle is active
debug
boolean
Whether debug mode is enabled
noCatch
boolean
Whether error catching is disabled
replay
boolean | 'spectator'
Replay mode setting
keepAlive
boolean
Whether to keep the stream alive after battle ends

Methods

write()

Write commands to the battle stream.
stream.write('>start {"formatid":"gen9ou"}');
stream.write('>player p1 {"name":"Alice","team":"..."}');
stream.write('>player p2 {"name":"Bob","team":"..."}');
message
string
required
Command message starting with >

Reading Output

The stream outputs battle messages that can be read using async iteration:
(async () => {
  for await (const output of stream) {
    console.log(output);
  }
})();

Input Commands

Start Battle

stream.write('>start {"formatid":"gen9randombattle"}');
formatid
string
required
Format identifier (e.g., “gen9ou”, “gen9randombattle”)
seed
number[]
Optional RNG seed [a, b, c, d] for reproducible battles

Add Player

stream.write('>player p1 {"name":"Alice","team":"..."}');
playerid
'p1' | 'p2' | 'p3' | 'p4'
required
Player identifier
name
string
Player name
team
string
Team in packed format or JSON

Player Choices

stream.write('>p1 move 1');
stream.write('>p2 switch 3');

Output Messages

The stream outputs messages in the format:
update
|start
|switch|p1a: Pikachu|Pikachu, L50|100/100
...

Message Types

update
string
Battle state updates visible to all players
sideupdate
string
Player-specific updates (like choice requests)
end
string
Battle end message with JSON data

Complete Example

import { BattleStream } from 'pokemon-showdown';

const stream = new BattleStream();

// Handle battle output
(async () => {
  for await (const output of stream) {
    console.log(output);
  }
})();

// Start a random battle
stream.write('>start {"formatid":"gen9randombattle"}');
stream.write('>player p1 {"name":"Alice"}');
stream.write('>player p2 {"name":"Bob"}');

// Make choices (after receiving choice requests)
stream.write('>p1 move 1');
stream.write('>p2 move 1');

Player Streams

For multi-process battles, use getPlayerStreams() to get separate streams for each player:
import { getPlayerStreams } from 'pokemon-showdown';

const streams = getPlayerStreams(new BattleStream());
const p1stream = streams.p1;
const p2stream = streams.p2;
const omniscient = streams.omniscient;
Player streams allow you to run players in separate processes for isolation and sandboxing.

Battle

The core Battle class

Simulator Usage

Guide to using the simulator

Protocol

Battle protocol messages

Teams

Team formatting and validation

Build docs developers (and LLMs) love