Use this skill to read ChatTwo chat logs as a debug console. Covers querying the SQLite database, finding script runs, and extracting debug evidence for bug analysis.
This skill enables reading and analyzing debug output from SND scripts stored in the ChatTwo plugin's SQLite database.
The SQLite MCP server must be configured in .mcp.json to connect to the ChatTwo database.
The database path is configured in .mcp.json:
{
"mcpServers": {
"sqlite": {
"command": "npx",
"args": [
"-y",
"mcp-server-sqlite-npx",
"PATH_TO_YOUR_CHATTWO_DB"
]
}
}
}
To change the database path: Edit the last argument in the args array in .mcp.json.
The typical ChatTwo database location is:
{XIVLauncher}/pluginConfigs/ChatTwo/chat-sqlite.db
You can also configure via CLI (adds to user-level config):
claude mcp add sqlite -- npx -y mcp-server-sqlite-npx "PATH_TO_CHAT_DB"
The ChatTwo database has a single messages table:
| Column | Type | Description |
|---|---|---|
| Id | BLOB | Primary key |
| Receiver | INTEGER | Character ID receiving the message |
| ContentId | INTEGER | Content identifier |
| Date | INTEGER | Timestamp (milliseconds since epoch) |
| Code | INTEGER | Chat channel code |
| Sender | BLOB | Sender name (binary encoded) |
| Content | BLOB | Message content (binary encoded with prefix) |
| SenderSource | BLOB | Original sender data |
| ContentSource | BLOB | Original content data |
| SortCode | INTEGER | Sorting order |
| ExtraChatChannel | BLOB | Extra channel info |
| Deleted | BOOLEAN | Soft delete flag |
| Code | Channel | Description |
|---|---|---|
| 56 | Echo | SND script /echo output - Primary debug channel |
| 57 | System | Game system messages (gearset changes, etc.) |
| 1 | Say | Public chat |
| 2105 | System | Job change notifications |
SELECT Date, CAST(Content AS TEXT) as Content
FROM messages
WHERE Code = 56
ORDER BY Date DESC
LIMIT 100
IMPORTANT: Content is stored as BLOB with a binary prefix. The readable text appears after the prefix characters. Example raw output:
���\u0000\u0000\u0000\u0000�\u0002�8��½[CosmicLeveling] === Done ===
The actual message is [CosmicLeveling] === Done ===.
Most SND scripts output a header when starting. Use this to find complete runs:
-- Find all script starts
SELECT Date, CAST(Content AS TEXT) as Content
FROM messages
WHERE Code = 56
ORDER BY Date DESC
LIMIT 500
Then filter for headers like:
[CosmicLeveling] === Cosmic Exploration Auto-Leveling ===[ScriptName] === Starting ===Once you find a header timestamp, get all messages from that run:
SELECT Date, CAST(Content AS TEXT) as Content
FROM messages
WHERE Code = 56
AND Date >= {HEADER_TIMESTAMP}
AND Date <= {HEADER_TIMESTAMP + 60000} -- Within 1 minute
ORDER BY Date ASC
LIKE queries don't work well with BLOB content:
-- This may return empty results even when data exists:
WHERE CAST(Content AS TEXT) LIKE '%DEBUG%'
Workaround: Fetch larger result sets and filter in your analysis.
Scripts output a versioned header at start and footer at end:
[ScriptName] === Script Title vX.Y.Z === <- Header with VERSION (start of run)
[ScriptName] Mode: Catch-up
[ScriptName] [DEBUG] ... <- Debug messages
[ScriptName] ... <- Status messages
[ScriptName] === Done === <- Footer (end of run)
The version in the header is critical for correlating debug output with the correct script code.
=== ... === patternsHeaders to look for:
[CosmicLeveling] === Cosmic Exploration Auto-Leveling v2.13.2 === - Run start (note version!)[CosmicLeveling] === Done === - Run endKey debug messages:
[DEBUG] Reference level: X | Reached breakpoint: Y[DEBUG] JobAbbr is Lv.X[DEBUG] Enabled Crafters: X/8[Catch-up] ... or [Strict] ... - Mode-specific logicBefore analyzing ANY debug output, ensure the local scripts match what's in SND:
# Check sync status
node sync.js status
# Push local scripts to SND (ensures SND has latest code)
node sync.js push
Why this matters:
[updated] for files that were out of syncExample output showing out-of-sync scripts:
[updated] CosmicLeveling.lua -> CosmicLeveling <- WAS OUT OF SYNC!
[unchanged] New_Macro.lua <- Already synced
If scripts were out of sync:
SELECT Date, CAST(Content AS TEXT) as Content
FROM messages WHERE Code = 56
ORDER BY Date DESC LIMIT 500
Look for === ... vX.Y.Z === pattern. The version is critical!
Red flag: If header has NO version (e.g., === Cosmic Exploration Auto-Leveling === without vX.Y.Z), the script is an old version that predates versioned headers.
e.g., v2.13.2
SCRIPT_VERSION constantUse timestamp range (header to footer)
Based on the CORRECT version's logic
Between what debug says happened vs what should have happened
CRITICAL: Always correlate the version in debug output with the script source code.
Scripts embed version in two places:
[ScriptName] === Title vX.Y.Z === (in chat logs)local SCRIPT_VERSION = "X.Y.Z" (at top of script)Extract version from debug header:
[CosmicLeveling] === Cosmic Exploration Auto-Leveling v2.13.2 ===
Version = 2.13.2
Check current script version:
-- In PlayRoom/CosmicLeveling.lua
local SCRIPT_VERSION = "2.13.2"
If versions match: Analyze using current script source
If versions differ:
git log or git show to find the correct version's code# Find commits that changed the script
git log --oneline -- PlayRoom/ScriptName.lua
# View script at a specific commit
git show <commit>:PlayRoom/ScriptName.lua
A bug report from debug output is only useful if you're looking at the same code that produced it. Example:
v2.12.0 behaviorv2.13.2