Game log
VRCNext tails VRChat’s output_log_*.txt and republishes parsed entries. This is the
lowest-latency source of in-game activity — most of VRCNext’s own timeline comes from here
rather than from the VRChat API.
ctx.gameLog needs the gamelog permission (medium: the log names who the user plays with),
confirmed once per plugin on first use — Plugin {name} ({id}) wants to read the VRChat game
log.
ctx.gameLog.on((entry) => {
ctx.logger.info(`${entry.type}: ${entry.message}`);
});
ctx.gameLog.onType('gl_player_join', (entry) => {
ctx.ui.toast({ message: `${entry.message} joined.` }); // detail is the usr_… id
});
const backlog = await ctx.gameLog.history(ctx.signal); // up to 1000 entries
Entry shape
interface GameLogEntry {
readonly type: string; // e.g. 'gl_player_join' — not a closed set
readonly timestamp: string; // exactly as VRCNext emitted it
readonly message: string;
readonly detail: string;
}
type is deliberately string. VRCNext’s parser adds entry kinds between releases, and a
literal union would be wrong the moment it did. Compare against the strings you care about and
ignore the rest. The kinds VRCNext 2026.61.2 emits, with what message and detail carry:
type |
message |
detail |
|---|---|---|
gl_player_join |
display name | usr_… id, or empty for legacy accounts |
gl_player_left |
display name | usr_… id, or empty |
gl_world_join |
world name | wrld_… id |
gl_instance_closed |
location | |
gl_avatar_blocked |
display name | avatar name |
gl_portal |
portal text | |
gl_video_url |
URL | |
gl_screenshot |
file path | |
gl_image_error |
URL | |
gl_connection_lost |
reason |
These are exported as GAME_LOG_TYPES for autocomplete; they are not the type of entry.type.
Caveats
history()shares thegetGameLogaction. It has no request id, so a concurrent caller may receive the same batch. Fine for a one-shot backlog read at activation; do not poll it.- Entries only flow while VRChat is running. Nothing arrives otherwise.
- On Linux the log path resolves through the Proton prefix. If VRCNext shows no game log, the plugin will not either — the problem is upstream.
messageanddetailare parsed from a log file whose format VRChat changes without notice. Treat them as human-readable text, not a stable API.