Welcome to the EllipsisLM source code! This document provides crucial context, architectural overviews, and strict guidelines for modifying and extending the application. Before contributing code, review this document thoroughly to ensure that changes align with the project's philosophy, structure, and standards.
EllipsisLM is an open-source, private, and deeply customizable AI-powered roleplay engine. The main intent is to provide a premium, highly immersive storytelling experience directly on the user's device. Its core philosophy revolves around:
- Privacy & Local-First Execution: Capable of running entirely offline using local LLM backends (like KoboldCPP and LM Studio).
- Infinite Portability: The core application functions seamlessly offline as a single monolithic HTML file.
- Deep World-Building: Expanding beyond standard chat limits by providing complex multi-character management, map generation, and persistent dynamic background agents.
EllipsisLM uses an unconventional but highly deliberate architecture that prioritizes extreme zero-install portability alongside robust desktop capabilities.
- The Monolith (
index.html): The entire frontend state management, logic, DOM manipulation, custom CSS, and HTML template definitions are self-contained within an enormousindex.htmlfile (23,000+ lines). The file is heavily modularized via technical map tags (e.g.,[SEC:JS:STATE:RS]). - Electron Wrapper (
electron/): A lightweight container that wraps the monolithic HTML file to function as a native desktop application. It integrates OS-level functions, such as auto-launching and managing localkoboldcppbinaries.
No major frontend frameworks (like React, Vue, or Angular) are used in the core monolithic product.
- Vanilla JavaScript: State management logic, reactive stores, event delegation, and DOM updates are all pure JS.
- Tailwind CSS (
electron/tailwind.css): Used extensively alongside custom CSS for modern utility-class styling. - JSZip & Pako: For handling complex data package formats (zipping/unzipping imports/exports).
- Marked.js: For parsing and rendering Markdown from LLM outputs.
Understanding the internal structure of index.html is critical. It is internally routed through specifically named ID brackets:
[SEC:HTML:BODY]UI structure, modals, containers.[SEC:JS:STATE:RS]Custom implementation of a Proxy-based stateReactiveStoreto manage reactive data.[SEC:JS:SRV:DB]Database services natively wrappingIndexedDBfor local storage in the browser cache.[SEC:JS:UI:TEMPLATE]UI component definition strings to dynamically inject HTML.[SEC:JS:CTRL:*]Controllers responsible for orchestrating specific segments (e.g.,LibraryControllerfor managing stories,NarrativeControllerfor routing chats,WorldControllerfor managing the map,InventoryControllerfor managing inventory/quests/relationships).[SEC:JS:MOD:AH]Custom central action handler managing delegated events to minimize event listeners.
When making extensive updates, ensure that new functions and variables are slotted into their appropriate categorized bracket.
EllipsisLM features an immense array of dynamic roleplay elements:
- Hierarchical Story Organization:
- Stories: Parent containers acting as the root character card.
- Scenarios: Reusable roleplay starter templates (custom characters, memories, visual themes).
- Narratives: Actively branching distinct playthroughs spawned from scenarios.
- Character Management:
- Manage unlimited characters.
- Active/inactive status toggles.
- "Narrator Mode" toggle—forces the character to speak occasionally to push the story, but prevents back-to-back takeover.
- Roleplay Interface & Controls:
- Write/Generate: Auto-generate the user input, or pass the user input to generate the AI response.
- Specific Actor Targeting: Select from the dropdown to force a specific character to reply next.
- Contextual Regenerate: Overwrite the current response or pivot the story by swapping the designated speaker.
- World Map System:
- An 8x8 spatial grid holding short/long descriptions and location-specific memories.
- Auto-generated maps through prompted generation.
- Background tracking of player movement via context scanning or UI-driven quick travel and path plotting.
- Lore & Knowledge Systems:
- Static Knowledge: Persistent summarized lore, automatically refreshed and updated by backend prompt calls.
- Dynamic Knowledge: A robust Lorebook supporting conditional
AND/XORkeywords and probability percentage triggers.
- Background Agents (Multi-Prompting):
- Event Master: Runs roughly every 6 turns to ingest chat history and inject a logical background event.
- Sentiment Agent: Periodically deduces the active characters' feelings and dynamically changes character portraits based on state.
- Inline AI-Generators: Floating icons in the UI to dynamically invoke the LLM to write character personas or generate location descriptions on the fly.
- Static Memory Extractor: Reviews chat flow to condense important events into persistent memory.
- Import/Export: Extensive support for reading/writing internal JSON backups, standard V2 PNG Character cards, BYAF cards, and bulk-folder importing.
- Customizable UI/UX: Toggles for Desktop (Horizontal)/Mobile (Vertical) view, Cinematic modes, bubble layout customization, fonts, background blur, and theme colors.
EllipsisLM uses a tiered data structure to ensure that specific playthroughs remain isolated while sharing a global "World Bible." Information is stored across four primary scopes:
- Folders: Global organizational structures for grouping stories.
- Global Settings: API keys, model preferences, and master UI themes.
- Character Image Store: A centralized
characterImagesIndexedDB store that holds every portrait blob, referenced by unique IDs across the entire app.
- Root Metadata: Title, tags, and creator's notes.
- Character Roster: The master definitions of all characters (personas, base images, and toggles).
- Global Lore: Static and Dynamic knowledge entries that define the world's rules.
- Scenarios & Narratives: The lists of all templates and playthroughs belonging to this story.
- Initial State: A frozen snapshot of the Story's lore and map at the moment of creation.
- Opening Message: The unique starting point for any playthrough spawned from this scenario.
- Configuration: Specific active character lists and custom system prompts for this roleplay starter.
- History: The full chat history, message counters, and timestamps unique to this run.
- Evolution: Narrative-specific memories and summarized states that diverge from the base scenario.
- Live Map State: The player's current coordinates, planned path, and journey destination.
For complex tasks (like creating an entire story from a single prompt), EllipsisLM utilizes a Pipeline pattern. This avoids "one-shot" failures by breaking the task into discrete, logical phases:
- World Phase: Generates the underlying lore and setting.
- Casting Phase: Generates the characters and their relationships based on the world.
- Director Phase: Synthesizes the world and cast into a cohesive opening scenario and first message.
- Visual Phase: Orchestrates background and portrait generation to match the newly created context.
When implementing features that require significant AI "reasoning," always look to utilize or extend the StoryGenerationPipeline rather than writing monolithic prompts.
When contributing code to EllipsisLM, the following standards are non-negotiable:
- Maintain the Monolith Safely: All frontend logic additions must be made inside
index.html. Do not attempt to add external script bundles or install complex component libraries via NPM. - Vanilla DOM Handling: Rely on the existing DOM orchestration mechanisms (
UIManager,ReactiveStore,ActionHandler). - Responsive Layout First: Always ensure your UI additions gracefully fall back through the flexbox rules into vertical (Mobile) mode cleanly. Always test your UI changes against horizontal mode overlapping.
- Thorough Section Tagging: Maintain to the strict bracket-ID schema established. If you need a new functional subsection, document and map it.
- Add Red/Green Tests Where Possible: For any pure helper added to or modified inside
UTILITY(parsers, normalizers, formatters, search/match logic), add a test intest.js. Runnpm testbefore committing — it must be green. When fixing a bug in a covered helper, write a failing red test that demonstrates the bug first, then fix the code until it goes green. The runner extracts UTILITY fromindex.htmldirectly, so the single-file constraint is preserved.
Do not immediately accept the first idea that comes to mind when addressing an issue or building a feature. You must actively "red-team" your implementation plan.
When you develop a plan, challenge its integrity:
- Will this DOM mutation break the
ActionHandlerdelegation? - How does this text expansion behave in Cinematic View vs standard Bubble View?
- If I add this prompt agent, how does it interact when the user switches LLM endpoints from Gemini to a local KoboldCPP server?
- What happens when the
IndexedDBtransaction is interrupted during this multi-agent loop?
If an approach introduces friction or causes edge-case bugs, discard it and redesign it. Anticipate failures, UX degradation, and state desynchronization, and select the architectural route that solves these fundamentally.
Shortcuts are strictly forbidden. We do not implement hacky workarounds or "good enough" fixes. Every feature or refactor must follow the best possible implementation path.
If adding a new UI toggle requires you to write an extensive custom CSS module, adjust the Proxy event listener, and refactor a legacy [SEC:JS:...] template, you will do exactly that. The integrity of the codebase and the quality of the user experience are paramount.
EllipsisLM is explicitly designed to be Token Agnostic.
When conceptualizing prompt logic, AI interactions, or data summarizations for the LLM, you are allowed to use as many tokens as necessary to achieve high-quality functionality. The application delegates the cost and model hardware explicitly to the user via local generation (KoboldCPP, LM Studio) or BYO-Keys (Gemini, OpenRouter).
Do not cripple functionality in the name of marginal token efficiency! While prompt compression and context brevity are important for speed and avoiding context cliffs, they must absolutely not come at the cost of the AI's intelligence, depth, or functionality. If the Event Master or World Map auto-generator requires a 400-token system prompt and rigorous output checking to be highly robust, write the 400-token prompt.
EllipsisLM is built with a "User-First" design philosophy that prioritizes aesthetic immersion and functional clarity. Unlike many open-source projects where the interface is a cluttered "cockpit" of buttons with little regard for usability, EllipsisLM aims for Invisible Utility.
- Cohesion over Clutter: Every UI element must belong to a consistent design system (
index.cssvariables). We do not add one-off buttons; we integrate features into existing logical groups. - Refinement & Clarity: Access to complex settings (API keys, LLM parameters, prompt tags) must be straightforward but tucked away until requested. We use modal-driven deep settings to keep the main chat interface pristine.
- Visual Hierarchy: Critical information (active story, sender name, typing status) is emphasized through color, typography, and motion, while secondary metadata (timestamps, control icons) is softened or hidden behind hover states.
In contrast to typical open-source AI frontends that often suffer from "Developer UI" (overwhelming lists of plain text and unstyled buttons), EllipsisLM employs:
- Materiality (Glassmorphism): Use of
glass-bg,backdrop-blur, and subtle gradients to create depth and a premium feel. - Purposeful Color Coding: Intentional use of role-based colors (e.g., Indigo for User interactions, Teal for System/Narrator) to guide the user's eye without textual labeling.
- Micro-Animations: Smooth transitions (
duration-300,animate-fade-in) that provide feedback and make the interface feel "alive" rather than static and brittle.
- Responsive Layout Triggers: The app dynamically swaps between Desktop (Horizontal) and Mobile (Vertical) layouts. UI components must be built to adapt to these logic-driven CSS classes (
layout-horizontal,layout-vertical). - Progressive Disclosure: Advanced controls (like the
action-btn-groupin chat bubbles) are hidden by default and only revealed onhoverorlong-press, keeping the user's focus on the narrative. - CSS-Variable Driven Themes: All styles must use the root CSS variables (e.g.,
--brand-color,--chat-font-family). This allows for consistent global "theming" when a user changes settings. - Centralized HTML Rendering: Use the
UIComponentsandUIManagersections to ensure that any new UI element is rendered consistently across the app.
To maintain the long-term integrity and premium quality of EllipsisLM, the following actions are strictly prohibited:
- NEVER introduce external JS frameworks: Do not refactor the monolithic core into React, Vue, or other complex npm-managed frameworks. The project depends on the single-file portability of the monolithic
index.html. - NEVER use placeholders: Do not commit code that leaves "TODO" functionality or placeholder images. Every feature must be a fully realized, production-ready implementation according to the "Best Path."
- NEVER sacrifice AI depth for token efficiency: (Reinforcing Section 10). If an agent prompt needs to be extensive to be effective, let it be. Do not "cut corners" on the AI's intelligence.
- NEVER use ad-hoc inline styles for static elements: All static UI styling must flow through the
index.cssvariable system or utility classes. Only truly dynamic/calculated values should be applied as inline styles. - NEVER bypass the ActionHandler: Do not attach unique event listeners to every single button. Utilize the established centralized delegation system to keep the global DOM event footprint minimal.
- NEVER break the Section Tagging map: Do not add code (logic or UI) outside of the identified
[SEC:...]brackets. This prevents the document from becoming un-navigable. - NEVER prioritize one orientation over another: Features must be functionally and visually complete in both Horizontal (Desktop) and Vertical (Mobile) modes. If a feature is "unusable" in one mode, it is considered broken.
- NEVER ship without Red-Teaming: Do not finalize a feature without attempting to "break" its logic. Anticipate race conditions, input edge cases, and state desynchronization.
High-quality, accurate documentation is vital for maintaining the massively monolithic index.html.
Every major function, service, or UI block must include a standardized comment header that improves navigability. Continue and expand upon the bracket-based technical map system (e.g., [UI:TEMPLATE:...] or [CTRL:NAR:...]) to link related elements and ensure rapid searchability across 20,000+ lines.
Comments must include human-readable descriptions of the code's intent and logic in plain English. Do not simply restate a method name; explain what it solves and any side-effects it might have on the ReactiveStore or the DOM.
Include searchable references to related UI IDs, CSS classes, or dependent services within the comments. This "trail of breadcrumbs" ensures that any developer can understand how a logic change in a controller affects a component in the [SEC:JS:UI:TEMPLATE] section.
Comments are as critical as the code itself. When a block of code is revised, its associated comments must be updated or replaced immediately.
- Inaccurate documentation significantly degrades the auditability and comprehendability of the project.
- Leaving stale comments in place is considered an anti-pattern. If a comment no longer accurately reflects the logic, it must be purged or rewritten.
- A feature is not "complete" until the internal documentation correctly describes the implementation's current state.
The README.md is the primary bridge between the technical implementation and the end-user. To ensure that users always understand the application's true potential, it must be treated as a living document.
Every time a new feature is implemented or an existing one is significantly changed, the README.md must be evaluated and updated appropriately.
All user-facing documentation must avoid technical jargon. Instead of describing "IndexedDB transactions," describe how "your library is safely stored in your browser." The goal is accessibility.
Don't just list technical capabilities; explain why they matter for the roleplay experience.
- Bad: "Event Master runs a separate prompt call every 6 turns."
- Good: "The Event Master injects unexpected plot twists into your story so that it never feels static or predictable."
Explicitly use the README to contrast EllipsisLM with more basic AI front-ends by highlighting features like the spatial World Map, dynamic background agents, or the multi-character "Narrator" system. Explain how these contribute to a more immersive and controlled storytelling environment.