fix-jsonl-surrogates
Fix JSONL Surrogates
Repairs Claude Code JSONL chat files that contain lone Unicode surrogates (U+D800-U+DFFF), which cause the Anthropic API to reject requests with "invalid high surrogate in string".
Background
Node.js internally uses UTF-16 strings. JSON.stringify() doesn't validate surrogate pairs,
so lone surrogates from file reads, terminal output, or web content can end up serialized
as \uD8xx without a matching low surrogate — producing invalid JSON that the API rejects.
Common triggers on Windows:
- Emoji in code comments or terminal output
- Box-drawing characters from build logs
- Web content with malformed UTF-16 encoding
Upstream issue: anthropics/claude-code#44230
How to Use
Quick diagnosis
If the user has a specific session or request ID, find the JSONL file:
grep -rl "req_XXXXX" ~/.claude/projects/*/
Run the repair script
The bundled Python script handles scanning and fixing. It works on individual files, session directories, or entire project trees.
# Scan a specific JSONL file + its session directory (subagents, tool-results)
python {SKILL_DIR}/scripts/fix_surrogates.py <path-to-file.jsonl>
# Dry run first to see what would change
python {SKILL_DIR}/scripts/fix_surrogates.py <path-to-file.jsonl> --dry-run --verbose
# Scan all sessions in a project directory
python {SKILL_DIR}/scripts/fix_surrogates.py ~/.claude/projects/<project-dir>/
# Scan everything recursively (includes subagent files)
python {SKILL_DIR}/scripts/fix_surrogates.py ~/.claude/projects/<project-dir>/ --recursive
The script:
- Reads each file with
errors='surrogateescape'to preserve bad characters for detection - Parses JSON and recursively checks all string values for surrogate code points
- Replaces lone surrogates with U+FFFD (replacement character) via
str.encode('utf-8', 'surrogatepass').decode('utf-8', 'replace') - Backs up originals as
.bakbefore modifying - Reports a summary of what was found and fixed
Important notes
- Surrogates are often transient: They may exist only in Node.js memory during request construction, not in the stored JSONL. If the script finds nothing, the error was transient and retrying the session should work.
- Check all session artifacts: The script automatically scans the main JSONL plus any subagent files and tool-result cache in the session directory.
- Safe to re-run: The script is idempotent. Running it on already-clean files is a no-op.
Manual investigation
If the script finds nothing but the error persists, the surrogate may come from content loaded at request time (CLAUDE.md, memory files, etc.). Scan those too:
python {SKILL_DIR}/scripts/fix_surrogates.py ~/.claude/ --recursive --dry-run
What {SKILL_DIR} means
Replace {SKILL_DIR} with the actual path to this skill directory. When Claude invokes
this skill, it knows the skill's location and can substitute the correct path.
More from tebjan/agent-skills
caveman-smart
Intelligent token-efficiency mode. Compresses routine chat and thinking but stays in full prose for reasoning, architecture, and safety-critical topics. Applies per response, not per session. Use when the user says 'caveman', 'terse', 'kurz', 'kurz&knapp', 'kurz bitte', 'weniger text', 'less tokens', 'smart mode', or invokes /caveman-smart. Stays active until the user says 'normal mode', 'verbose', or 'ausführlich'. Built for HPC, real-time, graphics, embedded, and kernel work where technical precision matters more than word count but explanation-of-why still demands full prose.
2swarm-advisor
Advises on multi-agent swarm design using Claude Code's TeammateTool and Task system. Use when the user wants to parallelize work across agents, asks 'should I use a swarm for this?', wants help designing team topology, needs to break a task into parallel workstreams, or is getting started with swarm-orchestration. Assesses whether a swarm is worth the overhead, recommends team size and structure, helps decompose tasks with correct dependencies, and tracks swarm health. Complements the swarm-orchestration skill by adding the 'think before you spawn' layer.
1gsd-orchestrator
Orchestrates and advises on complete GSD (Get Shit Done) development workflows. Acts as both workflow driver and expert consultant — reads context, suggests the right tools, asks clarifying questions when intent is unclear, spawns subagents for each step, and never loses focus on workflow completion. Use when the user wants to build something, asks which GSD command to use, says 'help me with GSD', 'run the GSD workflow', 'let's start a project', 'what should I do next', or describes any dev task that might benefit from structured planning. Also triggers when the task scope is ambiguous and needs routing to fast/quick/full GSD flow.
1install-github-plugin
Installs Claude Code plugins from GitHub repos that lack a marketplace manifest. Use this skill whenever a `claude plugin install` fails due to SSH key errors, missing `.claude-plugin/marketplace.json`, or a GitHub repo that wasn't designed as a Claude plugin marketplace. Also use when the user says \"install plugin from GitHub\", \"add skills from a repo\", or \"the plugin install failed\". Handles the full workflow: cloning via gh CLI, inspecting repo structure, generating the marketplace manifest, and running the install.
1addy-orchestrator
Orchestrates end-to-end software development using the addyosmani/agent-skills framework. Guides the user through define → plan → build → verify → review → ship phases, spawns subagents for each step, tracks state persistently, and never loses focus on workflow completion. Use when the user says \"let's build X\", \"help me implement X\", \"walk me through X\", or wants structured multi-phase dev guidance. Also triggers when a task is clearly non-trivial and would benefit from phased execution.
1ralph-orchestrator
Orchestrates and advises on Ralph Loop automated development sessions. Use when the user wants to run ralph-loop, asks how to set up a Ralph task, wants iterative agent-driven development, says 'run this in a loop until it works', or has a task with testable acceptance criteria they want to automate. Helps write effective loop prompts, sets safe iteration limits, monitors loop progress, detects stuck loops, and advises on completion criteria. Keeps context short — the heavy work happens inside the loop.
1