Labs · ST regex tester
Debug regex scripts live —
stop “edit, restart, squint”.
Paste a script and a sample reply; the replacement renders as you type — matches in yellow, output in green. Every script field (placement, markdownOnly, promptOnly) gets translated into plain words. And the catastrophic-backtracking patterns that freeze chat UIs get caught right here, by the same guard logic the app runs.
Fill in a regex and some test text — the replacement preview appears here, live.
Where this tool comes from
Script parsing and execution semantics are ported from the regex engine inside the Foreverse app — field mapping (scriptName / findRegex / replaceString / numeric placement codes / trimStrings) aligns field-by-field with SillyTavern's Regex panel export format, and the three-step replacement chain (backrefs → {{match}} → variable macros) plus cross-script variable state follow the app implementation that its unit tests pin down. Representative cases were carried into this engine's self-test. Ported 2026-07.
The regex dialect is ECMAScript (JavaScript) — the same dialect SillyTavern's web build speaks natively, so "runs here = runs in tavern" holds by construction. The Android app approximates with the Java dialect; a few notations (like inline (?i) flags) differ between the two, and this page sides with the tavern.
What it can't do
It tests one text against one set of scripts. Stacking-order effects across a long chat, and macros that only have values at runtime ({{user}} inside a replaceString, say) can't be reproduced here — variable macros start from an empty environment, and context macros like {{char}} are left as-is.
minDepth / maxDepth are judged against the single depth you set, not simulated across a whole message history.
FAQ
Why isn't my SillyTavern regex doing anything?
Check three fields first: ① placement — the script declares which lane it runs on (user input / AI output / world info…); if your test context doesn't match, the whole script is skipped, and the context dropdown here reproduces that exactly; ② disabled — exported collections routinely carry entries the author switched off; ③ markdownOnly — it only touches the display layer, so you'll never see the change in the outgoing prompt. If all three check out, the pattern itself probably isn't matching — the before-pane highlights will tell you instantly.
What's the /pattern/gi notation in findRegex?
A JavaScript regex literal: pattern between the slashes, flags after (g global, i ignore-case, m multiline, s dot-matches-newline). SillyTavern's web build speaks this dialect natively, and this tool matches it exactly. Bare patterns without slashes work too, treated as global replace.
What can go inside replaceString?
Three families: $1/$2 numbered backrefs and $<name> named groups (referencing a group that doesn't exist yields an empty string); {{match}} for the whole matched text; and variable macros like {{setvar}}, {{incvar}}, {{getvar}} — beautifier cards number their option lists with {{incvar}} this way. All supported here, and the counter carries across matches just like the runtime.
What kind of regex freezes the chat UI?
Nested unbounded quantifiers — (a+)+ or (.*)*. On long text they backtrack exponentially; one bad script can pin the UI for minutes. This tool blocks them at compile time with the same structural guard the app ships, plus a 350ms execution timeout as backstop — and tells you why, so you can rewrite the pattern.