web tool made by @mellowfllow

Janitor Script Builder

Advanced scripts made easy – fill out simple forms, get copy-paste-ready code.

Stateless 101: Understanding How Scripts Work

Key Concept: JanitorAI scripts run fresh on every single message. Variables don't persist between messages unless you store them in scenario/personality notes.

Won't Work: var score = 0; score++; Score resets to 0 every message
Will Work: Memory → adds to scenario notes Scenario persists between messages
Experimental: Using {{char}} tags for variables Fragile, can break with updates

Pro Tip: Scripts only check the latest user message by default. To check history, you need experimental methods (which may break).

Pre-Launch Test Checklist

Before using your script in JanitorAI:

  • Enable Debug Mode in Module Control Panel for first test
  • Start with 1-2 modules, add more once working
  • Test each trigger keyword/phrase in a real conversation
  • Check scenario notes after 5-10 messages for bloat
  • Verify message_count increments correctly (rerolls don't count)
  • Disable debug mode before final deployment
  • Keep total script under 10,000 characters for best performance
Reroll Behavior: When you reroll a character response, message_count does NOT increment. Only new user messages increase the count.

Recommended Build Order (Pro Workflow)

Follow this order for the most reliable and maintainable scripts:

  1. Lorebook → Foundation for rich context (most stable)
  2. Memory System → Track user info (stable)
  3. Pacing → Gate story progression (stable)
  4. Tone/State Engine → Dynamic mood shifts (stable)
  5. Time & Environment → Hour-based behaviors (stable)
  6. Ambient Events → Add flavor (watch token growth)
  7. Random Events → Weighted reactions (moderate complexity)
  8. Combined Conditions → Multi-trigger rules (advanced)
  9. Scoring (Stateless only) → Sentiment analysis (experimental)
Why this order? Lorebook and Memory are stable and token-efficient. Add complexity gradually, testing at each step. The Module Control Panel below is pre-ordered to match this workflow.

Scenario Maintenance Best Practices

Token Bloat Warning: Scripts that only append to scenario will cause slowdowns over long conversations.

Pro strategies to prevent bloat:

  • Use personality for moods/states instead of scenario (personality can be overwritten)
  • Summarize old notes periodically instead of endless appending
  • Use lorebooks for static info that only triggers when relevant
  • Prefer "replace" over "append" for things that change (time, mood)
  • Test scenario length after 20-30 messages and clean if needed
Example: Instead of appending "User is happy" every time, replace the mood line or store it in personality which naturally gets refreshed.

Module Control Panel

Execution Order Matters! Modules run in the order below. Later modules can override earlier ones. Drag to reorder. This panel is pre-ordered to match the recommended pro workflow above.
⋮⋮
⋮⋮
⋮⋮
⋮⋮
⋮⋮
⋮⋮
⋮⋮
⋮⋮
⋮⋮
Estimated Script Size: 0 characters
Keep under 10,000 characters for best performance

Lorebook (Hierarchical Keyword Database)

Create a rich world with people, places, objects, moods, and events that trigger based on keywords.

Token Warning: Keep entries 2-4 short paragraphs each. Too many long entries can cause slowdowns.
Prevents partial word matches (e.g., "cat" won't trigger on "catch"). Note: Works best with single-word keywords. Multi-word phrases may need exact spacing.
Stop after the first lore entry triggers (saves tokens, prevents multiple entries firing at once)

Lore Entries

// Script will appear here after clicking Generate
Common Pitfalls:
  • Keywords too broad (e.g., "is", "the") trigger constantly
  • Entries too long cause token bloat
  • Without break-early, multiple entries can fire and overwhelm context
  • Not using padded matching causes false triggers on partial words
  • Same entry can trigger repeatedly → enable deduplication below

Lorebook Glossary

Keywords
Words that trigger this lore entry (comma-separated, case-insensitive)
Category
Organizes entries: people, places, objects, moods, events
Content
Text injected into scenario when keywords match
Padded Matching
Requires spaces around keywords to avoid "cat" matching "scatter"
Break-Early
Stops checking after first match (recommended for performance)

Memory System

Automatically detect and remember the user's name, facts about them, likes, and dislikes.

The phrase that triggers name detection (case-insensitive)
Example: If user says "Hi, my name is María García", the script will remember "María García" (supports accents, hyphens, apostrophes, up to 40 characters)
Keywords that trigger fact storage
Example: "Here's a fact: I love programming" → saved as fact
Keywords that trigger likes storage
Example: "I love pizza" → saved as like
Keywords that trigger dislikes storage
Example: "I hate mornings" → saved as dislike
// Script will appear here after clicking Generate
Common Pitfalls:
  • Trigger phrases too specific → never fire
  • No deduplication → same fact saved multiple times (v3 includes basic dedupe)
  • Scenario grows forever without maintenance
  • Name regex may miss very long names (limited to 40 chars for safety)

Pacing System (Message Count Gates)

Control story progression based on how many messages have been sent.

Pro Tip: Use pacing to gate major story beats. Combine with one-time events for reveals.
Reroll Behavior: When you reroll a character response, message_count does NOT increment. Only new user messages count.

Message Count Phases

One-Time Events (Exact Message Count)

// Script will appear here after clicking Generate
Common Pitfalls:
  • Forgetting that rerolls don't increment message_count
  • Overlapping phases causing conflicts
  • One-time events at count 1 may miss if bot speaks first

Pacing Glossary

message_count
Built-in JanitorAI variable tracking total user messages sent (rerolls don't increment)
Phases
Ranges of messages (e.g., 1-10, 11-30) with associated behavior
One-Time Events
Fire exactly once at a specific message number

Tone/State Engine

Dynamically shift character personality based on keywords in user messages.

Prevents "angry" matching "danger". Note: Works best with single-word keywords.

Tone Triggers

// Script will appear here after clicking Generate
Common Pitfalls:
  • Without padded matching, "sad" triggers on "salad"
  • Multiple triggers fire → personality bloats
  • Mood doesn't reset between messages (use replace, not append)
Example Trigger:
Keywords: angry, mad, furious
Personality Add-on: {{char}} is currently angry and speaking tersely.

Time & Environment System

Change character behavior and environment based on time of day.

Time Source: Uses server time + your timezone offset. Time changes happen once per hour. Supports wrap-around (e.g., 22:00 to 03:00 for night).
e.g., PST = -8, EST = -5, GMT = 0, JST = +9
Example: If server time is 14:00 UTC and offset is -8, local time is 06:00

Time-Based Behaviors

// Script will appear here after clicking Generate
Common Pitfalls:
  • Server time may not match your local time without offset
  • Overlapping time slots cause conflicts
  • Hour-based checks only update once per hour
  • Forgot to handle wrap-around (e.g., 22:00-03:00) → v3 handles this automatically

Ambient Events (Random Flavor Text)

Add random environmental details to make the world feel alive.

Scenario Growth: These add to scenario notes. Use sparingly to avoid bloat.
Chance each message triggers an ambient event (1-100)
Example: 10% = roughly 1 in 10 messages adds flavor text

Ambient Event Pool

// Script will appear here after clicking Generate
Common Pitfalls:
  • High probability (>20%) causes rapid scenario bloat
  • Events append forever without cleanup
  • Same event can trigger multiple times (expected behavior)
Example Event:
A bird chirps in the distance. The cafe smells of fresh coffee.

Random Events (Weighted Reactions)

Trigger random character reactions when user says specific phrases.

Event Triggers

// Script will appear here after clicking Generate
Common Pitfalls:
  • Trigger phrases too common → fires constantly
  • Responses not pipe-separated correctly
  • Adding to personality instead of scenario
Example Event:
Trigger Phrase: what do you think
Responses: I think it's interesting|I'm not sure|That's a tough one (pipe-separated, chosen randomly)

Combined Conditions (Multi-Trigger Rules)

Create rules that fire when multiple conditions are met (keywords + time + message count).

Stateless Only: Combined rules work best with stateless checks (time + message_count + keywords). Time wrap-around supported (e.g., 22:00-03:00).

Combined Rules

// Script will appear here after clicking Generate
Common Pitfalls:
  • Conditions too strict → never triggers
  • Time checks without timezone offset mismatch user's local time
  • Multiple rules fire at once causing bloat
Example Rule:
Keywords: romantic, dinner
Min Hour: 18 Max Hour: 22
Min Messages: 20
Result: {{char}} suggests a romantic candlelit dinner.
→ Only fires if user mentions "romantic" or "dinner" between 6pm-10pm after 20+ messages

Scoring Engine (EXPERIMENTAL)

EXPERIMENTAL FEATURE: Scoring is complex due to stateless constraints. Persistent mode uses fragile tag-based storage that may break. Use with extreme caution.
Stateless: Analyzes current message only (safe)
Persistent: Uses {{char}} tags to store scores (fragile, may break with platform updates)

Positive Keywords

Example: "You're amazing!" → positive sentiment detected

Negative Keywords

Example: "This is terrible" → negative sentiment detected

Score Thresholds & Responses

// Script will appear here after clicking Generate
Common Pitfalls:
  • Persistent mode tags can be stripped by platform updates
  • Keyword sentiment too simplistic for nuanced emotion
  • Score thresholds never reached with stateless mode
  • No decay → persistent scores grow forever

Script Tester

Test your generated script with sample messages to verify triggers work correctly before deploying to JanitorAI.

Experimental Feature: This tester simulates the JanitorAI context environment. Results should match real behavior, but edge cases may differ.
Choose which generated script to test, or paste a custom script
Test multiple messages against the same script and see individual results for each
This simulates context.chat.last_message
Pre-fills context.character.name if your script uses it
Tips:
  • Generate your script first in the relevant tab before testing
  • Test edge cases: keywords with punctuation, different capitalizations
  • Try messages that should NOT trigger to verify specificity
  • Check console output for any errors or debug logs from your script

Trigger Analyzer

Scan all modules for potential keyword conflicts, overlaps, and bottlenecks.

Final Combined Output

This is the complete script with all enabled modules merged in your chosen order.

// Combined script will appear here after clicking "Copy All Enabled Modules"

User Guide

JanitorAI Script Builder

User Manual & Configuration Guide

1. Core Concepts

Stateless Execution

JanitorAI scripts run fresh on every message. They do not "remember" variables between turns. This tool builds Stateless Logic that re-scans the chat history every time to simulate memory.

The "Runtime Injection" Rule

Scripts cannot permanently save data to the character's definition. Instead, they inject data into the context temporarily for the current reply only.

2. Module Configuration

Lorebook (World Info)

Injects descriptions when specific words are mentioned.

Configuration Steps:
  1. Type: Select a category (e.g., Places) to organize the entry.
  2. Keywords: Enter words separated by commas (e.g., tavern, inn, bar). If the user types ANY of these, the entry triggers.
  3. Content: Write the description you want the bot to know (e.g., "The tavern is dark and smells of ale.").
Global Settings:
  • Padded Matching: Adds spaces around keywords. Prevents "cat" matching inside "catch".
  • Break Early: Stops scanning after the first match found (saves tokens).

Memory System

Auto-detects user details from their messages.

Input Fields:
  • Name Phrase: The trigger to detect a name (e.g., my name is). The script captures the text immediately following this phrase.
  • Fact Keywords: Words that indicate a fact (e.g., I live in, I work as). The script captures the entire sentence containing these words.

Pacing System

Controls the flow of the story based on message count.

Configuration Steps:
  • Add Phase (Range): Use this for states that last a while.
    Input: Min (Start msg) and Max (End msg).
    Result: The content is injected for every message in that range.
  • Add One-Time Event: Use this for a single story beat.
    Input: Message # (Exact count).
    Result: Triggers exactly once when that count is reached.

Tone & State

Overrides personality based on keywords.

How to use:
  • Keywords: Triggers like insult, slap, attack.
  • Content: The reaction, e.g., {{char}} becomes defensive and angry.

Note: This content is appended to the Personality field, effectively overriding the character's base setting for that turn.

Time & Environment

Injects time-based descriptions.

Critical: Timezone Offset

JanitorAI servers are in UTC. You MUST enter an offset (e.g., -5 for EST, -8 for PST) or the bot will think it is day when it is night.

Configuration:
  • Start/End Hour: Uses 0-23 format.
  • Wrap Around: You can set Start: 22 (10 PM) and End: 5 (5 AM). The script handles the midnight crossover automatically.

Ambient & Random

  • Ambient: Random flavor text (e.g., "Wind blows"). Controlled by the Probability % slider.
  • Random Events: Reactions to specific inputs.
    Responses: Separate options with a pipe | symbol (e.g., He smiles|He frowns|He ignores you). The bot picks one at random.

Combined Conditions

Advanced rules that require multiple things to be true.

The "AND" Logic:

All filled fields must match. Empty fields are ignored.

  • Keywords: User must say this...
  • Min/Max Hr: AND it must be between these hours...
  • Min Msgs: AND the chat must be this long.

3. Verification Tools

Trigger Analyzer

Click this to scan your modules for conflicts (e.g., using the word "Fire" in both Lorebook and Tone modules).

Script Tester

A sandbox to test your script without breaking your bot.

Workflow Requirement:

The tester reads the Output Code, not the Input Forms. You must click "Generate All Enabled Modules" before running a test.