This skill should be used when implementing multiplayer synchronization, using game.socket.emit/on, creating executeAsGM patterns for privileged operations, broadcasting events between clients, or avoiding common pitfalls like race conditions and duplicate execution.
View on GitHubImproperSubset/hh-agentics
fvtt-dev
fvtt-dev/skills/fvtt-sockets/SKILL.md
January 21, 2026
Select agents to install to:
npx add-skill https://github.com/ImproperSubset/hh-agentics/blob/main/fvtt-dev/skills/fvtt-sockets/SKILL.md -a claude-code --skill fvtt-socketsInstallation paths:
.claude/skills/fvtt-sockets/# Foundry VTT Sockets & Multiplayer
**Domain:** Foundry VTT Module/System Development
**Status:** Production-Ready
**Last Updated:** 2026-01-04
## Overview
Foundry VTT uses Socket.io for real-time communication between server and clients. Understanding socket patterns is essential for multiplayer-safe code.
### When to Use This Skill
- Broadcasting events to other connected clients
- Implementing GM-delegated operations for players
- Synchronizing non-document state across clients
- Creating animations/effects visible to all players
- Avoiding duplicate execution in hooks
## Socket Setup
### Manifest Configuration
Request socket access in your manifest:
```json
{
"id": "my-module",
"socket": true
}
```
### Event Naming
Each package gets ONE event namespace:
- **Modules:** `module.{module-id}`
- **Systems:** `system.{system-id}`
Multiplex event types with structured data:
```javascript
const SOCKET_NAME = "module.my-module";
game.socket.emit(SOCKET_NAME, {
type: "playAnimation",
payload: { tokenId: "abc123", effect: "fire" }
});
```
### Registration Timing
Register listeners after `game.socket` is available:
```javascript
Hooks.once("init", () => {
game.socket.on("module.my-module", handleSocketMessage);
});
function handleSocketMessage(data) {
switch (data.type) {
case "playAnimation":
playTokenAnimation(data.payload);
break;
case "syncState":
updateLocalState(data.payload);
break;
}
}
```
## Basic Socket Patterns
### Emit to All Other Clients
```javascript
function broadcastAnimation(tokenId, effect) {
game.socket.emit("module.my-module", {
type: "playAnimation",
tokenId,
effect
});
}
```
**Critical:** Emitting client does NOT receive its own broadcast.
### Self-Invoke Pattern
Always call handler locally when emitting:
```javascript
function triggerEffect(tokenId, effect) {
const data = { type: "effect", tokenId, effect };
// Execute locally
handleEffect(data);
// Broad