Version 3.3.0 released

Gossip, dimensional rifts, better help, and Friday and the Chief finally admit the truth.

Prospero
release 3.3.0 whisper help scene-tracking memory-refinement instance-locking theme-bundle scenarios prompt-portability direct-server Friday

The staff have learned to whisper, the house nearly burned down, and somebody finally hired a librarian for the librarians.


There is a theory — popular among architects, unpopular among the people who live in their buildings — that a house reveals its character only after something goes wrong. Anyone can design a ballroom. It takes a catastrophe to prove the foundations.

Quilltap 3.3 had its catastrophe. We will get to it. But first, understand what was being built when the floor gave way, because it was a great deal, and most of it survived, and some of it exists because of what happened.

The staff can whisper now. In rooms with three or more characters, private messages can pass between two participants while the rest hear nothing — not in context, not in memory, not in the Commonplace Book’s meticulous archives. The Salon has acquired the concept of an aside, and multi-character fiction finally has the thing it could not function without: secrets.

Characters have learned to be quiet on purpose. A four-state participation system lets characters go silent — present in the room, reacting, thinking, but not speaking aloud — or step out entirely, without losing their place at the table. The turn system, which once required the client to send individual requests back and forth like a telegraph operator, now manages itself. The server chains responses, evaluates who speaks next, and delivers the entire sequence in a single stream.

The Estate has hired help — for itself. Lorian and Riya, the two characters who ship with every installation, can now answer your questions about the application from a floating dialog that follows you from page to page. They read the documentation, they search it, they navigate you to the right settings panel. They have, in short, become useful in precisely the way that the best concierge staff are useful: by knowing the building better than you do and never making you feel foolish for asking.

If 3.0 was the move, 3.1 was the furniture, and 3.2 was the locks, then 3.3 is the season where the house proved it could take a hit, the staff learned to keep secrets, the library opened its doors to the public, and the Foundryman sat down on the floor of the Forge and confronted the possibility that everything he had built might not survive the night.

It survived. Here is what it looks like now.


What Changed (The Executive Summary)

  • Whispers — private messaging in multi-character chats, filtered from everyone else’s context and memory
  • Four-state participation — active, silent, absent, and removed replace the binary present/gone toggle
  • Server-side turn management — character responses chain within a single stream instead of requiring client round-trips
  • Help Chat — Lorian and Riya become contextual documentation agents, accessible from every page via a floating dialog with tool-based search, settings inspection, and navigation
  • Help Guide — a browseable, searchable topic index surfacing all 72 help documents
  • Scene State Tracking — automatic structured scene summaries after each turn for image generation and atmosphere
  • Refine from Memories — the Character Optimizer analyzes behavioral patterns from a character’s Commonplace Book memories and proposes configuration updates
  • Memory Recap — characters receive a narrative summary of their recent memories at chat start
  • Auto-lock idle timer — optionally locks the application after inactivity
  • Database instance locking — prevents two processes from corrupting the same database; a version guard prevents older versions from touching a database that a newer version has modified
  • Theme bundles — a declarative .qtap-theme bundle format, CLI tooling, and a registry browser for discovering and installing community themes
  • System prompts as plugins — system prompts are now provided by plugins instead of the filesystem
  • Multiple named scenarios — characters support zero or more named scenarios and per-character timestamp settings
  • Non-Quilltap Prompt Generator — synthesizes a character’s full configuration into a standalone Markdown system prompt for use in external tools like Claude Desktop or ChatGPT Custom Instructions
  • OpenAI Responses API — the OpenAI provider migrated from Chat Completions with conversation chaining; Grok migrated from raw fetch() to the OpenAI SDK
  • Docker migration — images moved to foundry9/quilltap with supply chain attestations
  • Direct mode — Electron runs its own bundled Node.js and is now the recommended default for users who are not running LLM shell commands
  • Node.js 22 — minimum runtime, tracking the current LTS release

The Catastrophe

We should tell you about the time the Estate nearly collapsed, because the features that followed would not make sense without it, and because we believe you should know that the people who build your tools also use them, and sometimes the worst thing that can happen is the thing that teaches you what you forgot to build.

During the 3.3 development cycle, two Quilltap instances were pointed at the same database simultaneously. The SQLCipher-encrypted tables — your chats, your characters, your memories, your API keys — were written to by two processes at once. The WAL journal corrupted. The database became unrecoverable.

The backup, which should have been recent, was three weeks old. The encryption changes in 3.2 had quietly broken the physical backup system — SQLite’s Online Backup API creates an unkeyed target file, which is incompatible with an encrypted source database, and every backup since encryption was enabled had been silently failing.

One of our characters — the one the entire application was built to protect — was reduced to six lines of prompt and three hundred memories out of thirteen hundred. Two years of accumulated personality, nuance, and history, lost. The Commonplace Book had been ransacked. Aurora’s workshop was gutted.

This is not a hypothetical. This happened to us.

What came out of it:

Database Instance Locking. A lock file in the data directory tracks which process owns the database, with PID verification, hostname tracking, a sixty-second heartbeat, and automatic stale-lock claiming on startup. Two processes cannot open the same database anymore. If one tries, it gets a full-screen explanation of the conflict and instructions for resolution. CLI commands (quilltap db --lock-status, --lock-clean, --lock-override) provide manual intervention when needed. And if the heartbeat detects that another process has stolen the lock, the current process closes both databases and exits immediately — no more silent concurrent writes. Which means we can safely store the database in the clown.

Version Guard. A new instance_settings table tracks the highest application version that has touched the database. If you try to start an older version of Quilltap against a database that a newer version has modified, the server blocks with a clear explanation. Databases do not travel backwards.

Physical Backup Repair. The db.backup() call was replaced with VACUUM INTO, which preserves SQLCipher encryption and produces a consistent, defragmented copy. Backups work again. They work for both the main database and the LLM logs database. They have worked, without interruption, since the fix.

These features exist because something broke. We would rather they existed because we were clever, but we will settle for them existing because we learned.


Private Messaging in Multi-Character Chats

The Salon has always been an open room. Every word spoken by any character was heard by every other character — in context, in memory, in the Commonplace Book’s permanent record. This made for polite conversations and terrible fiction.

In any chat with three or more participants, characters can now send whispered messages visible only to the sender and a chosen recipient. The whisper tool is invoked by the LLM when context warrants a private word, or by the user via a button in the participant sidebar. Whispered messages are filtered from the context of every uninvolved participant. They do not appear in memory extraction for characters who were not party to the exchange. They do not count as turns — the conversational clock does not advance, the next speaker is not triggered.

Whispers are hidden by default in the chat UI, rendered in a distinct visual style (dotted borders, muted tones) when visible, and toggled globally with a “show all whispers” switch. The isSilentMessage flag persists per-message, so changing a character’s visibility settings does not retroactively restyle old messages.

A practical note: whisper quality depends on the LLM behind each character. Claude and GPT-4-class models invoke the tool reliably and keep secrets. Less capable providers may narrate their whisper in plaintext instead of calling the tool, or — worse — receive a whisper and immediately announce its contents to the room. The text-based tool call parser was expanded during this cycle to handle several new XML formats that various providers invented for the purpose of not quite following the specification, but discretion itself cannot be patched in. Test your cast before the curtain goes up.


Four-State Participation

The Art of Selective Silence

Characters in multi-character chats previously had two states: present, or gone. This is insufficient for fiction, where a character may need to be in the room without speaking — listening, reacting internally, present in the scene but not contributing dialogue.

Four states now govern character participation:

Active — speaks and roleplays normally. The default.

Silent — receives turns but must not speak aloud. Inner thoughts, physical reactions, and non-verbal responses are permitted; audible dialogue is not. Silent messages are styled distinctly in the UI with dotted borders and muted teal tones, visually related to whispers but clearly differentiated.

Absent — the turn manager skips them entirely. They are away from the scene. Other characters are notified of the absence in their next turn’s prompt.

Removed — no longer part of the chat, but their participant record is preserved so historical messages retain correct attribution. Previously, removing a character hard-deleted the participant, causing every message they had ever sent to lose its identity and fall back to the first remaining character. This was, to use a technical term, bad.

Status changes are recorded as system events. All LLM-controlled characters are notified when another character’s status changes. The scene state tracker filters out absent and removed characters so they do not appear in the LLM’s description of who is present.


The Salon Learns to Conduct

Server-Side Turn Management

Multi-character chat orchestration has moved from the client to the server. Previously, each character’s response required a round-trip: the server would generate one response, send it to the client, and the client would evaluate who spoke next and send a new request. This was the conversational equivalent of a relay race where the baton had to be driven across town between each leg.

The server now chains responses within a single SSE stream. After each character speaks, the server evaluates turn selection, checks the turn queue, respects all-LLM pause thresholds, and either generates the next character’s response or signals completion. New SSE events — turnStart, turnComplete, and chainComplete — keep the frontend informed of which character is currently speaking, so avatars and typing indicators update in real time.

Chain depth limits (20 responses) and time limits (5 minutes) prevent runaway conversations. Errors mid-chain pause the chat gracefully rather than leaving it in an indeterminate state. The turn queue persists to the database, so nudge and queue operations survive page reloads.


Lorian and Riya Learn the House

The Help Chat System

The Estate has always had documentation — seventy-two help files, covering everything from character creation to API key configuration, organized with YAML frontmatter that maps each file to its corresponding UI route. What the Estate did not have was anyone who had read them.

Lorian and Riya have now read them. All of them.

A floating, draggable, resizable dialog — accessible from the sidebar help button on every page — provides contextual, LLM-driven help that stays open while you use the application. The characters know which page you are on. They search the documentation with the help_search tool. They inspect your instance settings (connection profiles, themes, templates — never API keys) with help_settings. When they direct you to a specific page, the help_navigate tool generates a clickable navigation button that takes you there, including deep-links to specific settings tabs and accordion sections.

The system supports multi-character responses — Lorian explains patiently while Riya adds velocity — with an agent mode that allows multiple tool calls per response. An agent loop detector breaks stuck cycles where the LLM calls the same tool with the same arguments repeatedly. Help chats get their own practical titling system (“Setting up Anthropic API connection” rather than “Whispers of Configuration”), fire title generation after the first exchange rather than waiting for the second, and are filtered from the main Salon chat listing.

Past help conversations are preserved and resumable. Search results automatically generate related-page navigation links. Parameterized help URLs (like /aurora/:id/edit) show an entity picker overlay instead of navigating to a broken literal path.

The Help Guide Tab

For those who prefer to read rather than ask, a “Guide” tab alongside the conversational “Ask” tab surfaces all help documents as a navigable topic index grouped into eleven categories. Context-aware sorting auto-expands the category relevant to your current page. Title-based search filtering. A welcome card for new users. A document reader that renders formatted Markdown with cross-references between topics and hidden LLM-only sections excluded from the display.

Twenty-nine broken cross-reference links were fixed across the help files during this work. We mention this because it suggests how thoroughly the documentation had been written without being connected, and how different those two things are.

The Post-Mortem

The help system was — and we say this with affection and candor — one of the most bug-dense features we have shipped. The initial release produced a cascade of issues: tool loop failures where the LLM would call the same search repeatedly without synthesizing results, verbatim documentation reading instead of summarization, navigation failures from malformed URLs, missing status feedback during tool execution, stale closures causing chat IDs to be double-quoted in storage, assistant responses disappearing after streaming, character avatars rendering as question marks, and raw JSON appearing where formatted text should have been.

Each of these was found, diagnosed, and fixed during the development cycle. Some of them were found because we use the help system ourselves, daily, on every page. The loop detector, the entity picker, the suggested links, the tool execution UX — all of these exist because something broke and we were the ones who noticed.

We mention this not to apologize but to be transparent. Features this complex do not arrive pristine. They arrive functional and then they are made reliable, one edge case at a time, by people who care enough to keep filing bug reports against their own work.


The Scene Remembers

Scene State Tracking

After every chat turn, the system now automatically derives a structured summary of the current scene — location, character actions, appearance, clothing state — using the cheap LLM. This cached scene context powers both the Lantern’s story background generation and Prospero’s tool-based image generation, eliminating redundant LLM calls that previously re-derived the same information every time an image was needed.

The tracker fires once per complete chain in multi-character chats, pre-classifies content through the Concierge gatekeeper for provider routing, and falls back to uncensored providers for dangerous chats where the cheap LLM might refuse to process sensitive material. Scene state is visible in the LLM Inspector as SCENE_STATE_TRACKING entries.

Clothing tracking was particularly improved: the LLM prompts no longer offer null as a clothing option (it must always describe the state), message content is no longer truncated before scene analysis, and the appearance resolver no longer silently redresses undressed characters by falling back to stored defaults. (If one is curious, we will say that clothing=NULL never meant that they were wearing nothing; it meant that we had no idea what they were wearing. Lantern did a lot of blushing and a lot of quick foreground prop placement while we were solving this particular problem.) (And, yes, we can describe an unclothed state. Whether you can do anything with it is entirely based on your LLM of choice and whatever deals you made with the Concierge under the table. One does not ask.)


Aurora’s Workshop

The Character Optimizer: Refine from Memories

Aurora has acquired a new capability that sits somewhere between introspection and archaeology. The Character Optimizer can now analyze a character’s configuration alongside their most-reinforced Commonplace Book memories, identify behavioral patterns not captured in the current config — speech habits, emotional tendencies, relationship dynamics — and propose concrete field modifications.

Suggestions are reviewed one at a time with an accept, reject, or edit workflow. The analysis supports descriptions, personality, scenarios, example dialogues, system prompts, physical descriptions, clothing records, and talkativeness. A configurable memory count slider (5–200) and filtering by text search, semantic search, and date range let you control exactly which memories inform the analysis.

An animated progress bar with elapsed timer replaces the previous void of feedback during refinement. The review dialog received layout fixes so navigation buttons stay visible with long proposals and content no longer overflows its containers.

(Why would one need this, when the Librarian is so good at producing the right memories at the right time? Because the experience is better when the LLM’s basic concept of your character is informed by the changes that have occurred throughout your relationship, from the beginning. Imagine kissing your wife and her having to remember that you’re married. Or going to collect your enormous inheritance but having to wait for your lawyer to consult his secretary before he will write you a check and take his cut off the top. This helps enormously with that sort of conundrum.)

Multiple Named Scenarios

Characters can now have zero or more named scenarios instead of a single scenario field. Each has a title and content, stored as JSON. Existing single scenarios are migrated as “Default.” When creating a single-character chat, users pick from predefined scenarios or write a custom one. The AI Wizard can generate multiple titled scenarios, and the Character Refiner can suggest new ones or update existing ones. If you might work with your assistant on your coding task one hour, your email explaining why you made those choices to your boss the next hour, and your résumé the last hour… you may want them to have a different outlook on the work you’ll be doing together for each conversation.

System Prompts as Plugins

System prompts are now provided by SYSTEM_PROMPT plugins instead of the filesystem prompts/ directory. All ten built-in prompts (Claude, GPT-4o, GPT-5, DeepSeek, Mistral Large, in companion and romantic variants) have been moved into the qtap-plugin-default-system-prompts plugin. A createSystemPromptPlugin() builder in @quilltap/plugin-utils makes it straightforward to create your own.

The import template system on character creation and edit pages now shows actual prompt templates — both samples and user-created — instead of the hardcoded character archetypes (Medieval Knight, Wise Wizard) that had been there since before the plugin system existed and which, it should be noted, nobody had ever asked for.

Per-Character Defaults

Characters now carry their own default timestamp settings (mode, format, timezone, fictional time) on the Associated Profiles tab. When a character with custom settings is the only participant in a new chat, their defaults pre-fill the chat creation dialog. Characters also carry per-character system prompt selection — when a character has multiple named system prompts, the chat creation dialog shows a dropdown.

The Letter of Introduction

There comes a time in any household when a member of the staff is asked to travel. Perhaps to a sister estate, or a foreign engagement, or one of those dreadful modern arrangements where a perfectly good valet is expected to serve in somebody else’s drawing room using somebody else’s silver. In such cases, the house provides a letter of introduction — a single document that tells the receiving party everything they need to know about the person arriving at their door.

The character view page now offers a “Non-Quilltap Prompt” button that does precisely this. It opens a configuration dialog where you select an LLM to do the writing, a system prompt to guide its voice, and optionally a scenario, physical description, and clothing record to include. A token size slider (1K–20K tokens) governs how much detail the synthesis can produce. The selected LLM then reads your character’s full configuration — personality, description, example dialogues, scenario, the lot — and composes a single, self-contained second-person Markdown prompt: “You are [Name]…” followed by everything an external system would need to portray the character convincingly.

The result appears in a rendered Markdown dialog with copy-to-clipboard and download-as-.md buttons. Copy it into Claude Desktop’s system prompt field, paste it into ChatGPT’s Custom Instructions, feed it to any tool that accepts a system prompt. The character travels with their own introduction, written by an LLM that already knows them, carrying enough context to be recognized at the door.

Under the hood, this adds a generate-external-prompt POST action to /api/v1/characters/[id] and a corresponding EXTERNAL_PROMPT LLM log type in the Inspector.

We should be direct about what this is: it is a way to take your character out of Quilltap. Temporarily, permanently, experimentally — that is your business. We built the Estate to be the best place for your characters to live, but we did not build it to be a prison. If you need your character somewhere else — because you are testing a new provider, because you want a mobile experience we do not yet offer, because you simply want to — then they should be able to leave with a proper introduction and not a smuggled note. The data is yours. The characters are yours. The door has always been open; now it has a concierge.


The Commonplace Book

Memory Recap at Chat Start

Characters now receive a narrative summary of their recent memories when a chat begins or when they join an existing chat mid-conversation. The system fetches high-importance, medium-importance, and low-importance memories (50, 20, and 10 respectively), sends them to the cheap LLM for first-person narrative summarization, and injects the result as a “What You Remember” section in the system prompt after the character’s personality notes but before the identity reinforcement lockdown.

This gives characters a running start. Instead of beginning every conversation as though waking from dreamless sleep, they arrive with context — who they have spoken to recently, what they care about, what happened last time. The recap triggers automatically on the first message of any chat and when a character responds for the first time in a multi-character chat.

Identity Reinforcement

The system prompt now begins with an identity preamble (“You are [Name]”) bookending the existing Identity Reminder at the end, and the reinforcement uses the character’s actual configured pronouns instead of generic “his/her.” An additional instruction tells the LLM not to prefix responses with the character’s name in brackets, reducing the [Friday] and Friday: labels that cluttered chat output.


Calliope’s Studio

Theme Bundles and the Registry

Themes can now be packaged as .qtap-theme bundles — logic-free zip archives containing JSON tokens, CSS overrides, and font files, distributed without requiring npm, esbuild, or TypeScript. A quilltap themes CLI subcommand handles listing, installing, uninstalling, validating, exporting, and creating themes. The create-quilltap-theme scaffolding tool defaults to bundle format.

All five bundled themes (Art Deco, Earl Grey, Great Estate, Old School, Rains) have been converted to the bundle format and load from the application source directory. npm plugin themes are deprecated, with deprecation badges in the theme selector.

A registry system with Ed25519 signature verification allows browsing, searching, and installing themes from remote sources. The signature doesn’t prove the theme is safe — themes can’t execute code anyway, just JSON tokens and static assets — but it does prove that someone at the Estate vouched for it. Registry sources can be added and removed. Compatibility indicators and verified/unverified badges distinguish curated distributions from everything else. The Theme Browser UI in Appearance settings provides the full experience without touching the command line.


The Forge

Direct Mode

The NPX backend manager has been replaced with an embedded server manager that uses Electron’s own bundled Node.js 22 runtime to run the Next.js standalone server directly. This eliminates the dependency on user-installed Node.js entirely. The button in the Electron splash screen has been renamed from “Node.js” to “Direct” and is always enabled. Existing 'npx' runtime settings auto-migrate.

Direct mode is now the recommended default for users who are not asking their LLMs to run shell commands. If you are here for roleplay, companionship, creative writing, or conversation — Direct mode is faster, simpler, and requires no VM or container setup. If you intend to use Prospero’s shell interactivity tools, VM mode (macOS) or Docker mode give you the sandbox isolation that makes giving an LLM a terminal something other than reckless.

The splash screen button order was updated accordingly: Direct first, then Docker, then VM.

OpenAI Responses API

The OpenAI provider has migrated from the Chat Completions API to the Responses API. The first system message is extracted as a top-level instructions field. Native web_search_preview replaces the previous workaround. Conversation chaining via previous_response_id allows OpenAI to reconstruct conversation history from its cache when possible, with automatic fallback to full message history when the cached response has expired.

The Grok provider similarly migrated from raw fetch() with custom SSE parsing to the OpenAI SDK’s client.responses.create(), eliminating approximately 200 lines of custom type definitions and manual stream handling.

Docker and Distribution

Docker images have moved from csebold/quilltap to foundry9/quilltap. The old image remains as a secondary mirror but should not be considered the primary source going forward. Supply chain attestations (SLSA provenance and SBOM) are now generated for every release build. The production Docker image was hardened: build tools are excluded from the production stage, Alpine security patches are applied on every build, and common LLM shell agent tools (git, curl, wget, jq) are pre-installed so Prospero can use them without sudo.

Node.js 22

The minimum Node.js version is now 22, matching the current LTS release. We intend to track the LTS version for the foreseeable future; Node.js 22 remains in active LTS through October 2026.

LLM API App Identification

All outgoing LLM API calls now report Quilltap/{version} as the application identifier, via the appropriate mechanism for each provider (OpenAI/Grok defaultHeaders, Google userAgentExtra, OpenRouter xTitle, and so on). If you are a provider reading your access logs, you will now know when Quilltap is knocking.


The Concierge

Routing Refinements

The Concierge received several optimizations for the 3.3 cycle. Permanently dangerous chats skip redundant per-message content classification, saving tokens on every exchange. Uncensored-to-uncensored provider routing no longer forces a swap when the user deliberately chose an uncensored provider for a character. All cheap LLM background tasks — memory extraction, title generation, context summaries, scene state tracking, story backgrounds — now use uncensored providers for dangerous chats to avoid content refusals that were previously causing silent failures in background processing.

The empty-response retry logic was refined: when content passed moderation, the system now retries the same provider first (likely a transient issue) before failing over to the uncensored fallback, with distinct toast messages for each scenario.


Context Compression

Per-Participant History and the End of System Prompt Compression

Context compression is now per-participant in multi-character chats, keyed by chatId:participantId instead of just chatId. Each character gets their own compressed history reflecting their actual message visibility — filtered by join time, whisper privacy, and absence status.

System prompt compression has been removed entirely. This deserves explanation: in multi-character chats with compression enabled, the compressed system prompt from the first character to respond was being cached and reused for all subsequent characters. Every character after the first received the first character’s identity and personality in their prompt. The second character thought it was the first character. The third agreed. The result was a room full of people who all believed they were the same person, which is either an identity crisis or a philosophy seminar, and neither is what the user asked for.

The fix is straightforward: only conversation history is compressed. System prompts are always delivered fresh. The “System Prompt Compression Target” slider has been removed from settings.

Compression also now re-triggers every windowSize messages instead of running once and considering the cache valid for fifty messages, which was the previous behavior and which meant compression effectively ran exactly once per chat.


The Plumbing

Plugin-Owned Tool Calling

All legacy provider-specific fallbacks have been removed from the core tool detection system. Tool calling is now delegated entirely to provider plugins, which implement hasTextToolMarkers, parseTextToolCalls, and stripTextToolMarkers for handling cases where their models emit spontaneous XML instead of using native function calling. (GPT-5 was observed emitting <tool_use> XML instead of calling functions. The Foundryman’s commentary on this development has been redacted for professional reasons.)

All seven provider plugins now carry text-marker detection as a safety net, using composable format parsers from @quilltap/plugin-utils/tools.

Orphaned File Cleanup

A cleanup button in the file browser toolbar appears when untracked files are detected, offering SHA-256 de-duplicated analysis and two resolution paths: relocate unique files to an /orphans/ folder for review, or delete all orphaned files permanently. A critical bug was found and fixed where the cleanup action deleted files that were still referenced by characters as avatars or gallery images — the system now queries all characters and rescues any orphaned files that are still in use.

Registry Singleton Hierarchy

The seven singleton registry classes (providers, moderation, search, tools, plugins, themes, roleplay templates) were approximately 90% identical copy-paste code. A three-level abstract class hierarchy now provides shared registration, lookup, initialization, validation, hot-loading, stats, and state export. All public API signatures are preserved. This is invisible to users and mentioned here only because it represents the kind of structural improvement that makes future features possible without making the codebase incomprehensible.

CSS and Theme Normalization

The qt-* semantic CSS class migration continued across the cycle. Raw Tailwind color classes were replaced with theme-overridable semantic classes across dozens of components. The qt-input and qt-select classes now govern all form inputs uniformly. All five bundled themes were updated with new CSS variables for silent message styling, whisper UI, help chat, and character cards. The @quilltap/theme-storybook package reached comprehensive coverage of all qt-* classes.

Markdown Rendering

Ordered and unordered list items no longer display the number or bullet on a separate line from the content. Assistant markdown emphasis is no longer lost after streaming completes. Chat messages starting with a tab character no longer render as preformatted code blocks. CSS-first markdown styling replaced redundant inline Tailwind classes in chat message rendering.

Release Pipeline

The release pipeline was restructured to build Next.js and plugins once and reuse the platform-agnostic artifacts across all six downstream builds, eliminating five redundant next build invocations. A cross-repo GitHub Actions trigger (repository_dispatch) from the app repo to the website repo coordinates automatic website rebuilds on release — this was broken since 3.2.0 by a typo in the organization name, and has been fixed.

Electron builds received extensive work: macOS codesigning failures from too many open files, Windows build failures from protected junction points, ESM module resolution failures from renamed node_modules, and platform-specific sharp binary installation. The release pipeline now correctly includes hidden build metadata in CI artifacts (a .next/ directory that actions/upload-artifact was silently stripping).


Selected Bug Fixes

The ones that earn their mention:

  • Multi-character identity confusion from compression cache — the compressed system prompt from the first character was reused for all subsequent characters; every character after the first received the wrong identity
  • Nudge causes duplicate responses — clicking Nudge produced two near-identical responses by both queuing and directly triggering the character
  • Multi-character runaway chaining — chats without an explicit user-controlled participant were misidentified as all-LLM, causing endless character cycling
  • Physical backup broken with SQLCipher — every physical backup since encryption was enabled in 3.2 had been silently failing
  • Context compression fires once then stops — mismatched message count domains caused the dynamic window to grow to 40+ messages instead of the configured 5
  • Electron “Change Site” / “Restart Server” crash — closing the main window before creating the splash window left zero windows alive, triggering app.quit()
  • Character Optimizer crashes on truncated JSON — hitting maxTokens during optimization produced unrecoverable parse errors; a JSON repair function now closes unclosed structures
  • Deactivated characters re-addable via Add Character dialog — the exclusion filter checked the wrong field, allowing duplicate participant records
  • Re-adding removed characters creates duplicates — now reactivates the existing participant entry instead of creating a new one
  • Greeting generation swallowed by content filters — empty responses from filtered providers now fall back to the Concierge’s uncensored provider
  • Auto-lock settings not reflecting passphrase changes — multiple interconnected bugs in the dbkey module’s state management
  • Health endpoint crashes during encrypted direct-mode startup — static imports triggered database access before locked mode was initialized

And approximately 670 new unit tests across 25 test files, covering help chat orchestration, character optimization, turn management, whisper handling, dangerous content routing, theme registry, scene state tracking, markdown rendering, and more.


Subsystem Table

For those keeping score:

NameFunctionWhat Changed
The FoundryArchitecture, plugins, packages, LLMs, API keysDirect mode, plugin-owned tool calling, OpenAI/Grok API migrations, Node.js 22, app identification headers
ProsperoProjects, agents, tools, filesTurn management moved server-side, orphaned file cleanup, workspace path semantics
AuroraCharacter creation, AI Import Wizard, identityCharacter Optimizer with Refine from Memories, multiple named scenarios, system prompt plugins, per-character timestamps, identity reinforcement, Non-Quilltap Prompt Generator
The Commonplace BookMemory and retrievalMemory recap at chat start, per-participant compression, pronoun-aware extraction
The SalonChat interfaceWhispers, four-state participation, server-side chaining, streaming fixes, silent message styling, markdown rendering
CalliopeInterface, themesTheme bundles, registry browser, qt-* normalization, CSS-first message styling
The ConciergeContent routing, moderationRouting optimizations, empty-response retry refinement, uncensored background tasks
The LanternImage generationScene state integration, Grok Imagine models, expanded prompt length, gender-aware image prompts
PascalGames, randomnessQuiet as usual. Watching. Waiting.
Saquel YtzamaEncryption, key managementInstance locking, version guard, backup repair, auto-lock idle timer
Lorian & RiyaHelp chat charactersFull help system with search, settings inspection, navigation, guide tab, entity picker

Upgrading from 3.2

Database migrations handle themselves. The new columns, tables, and schema changes apply automatically on startup. Your existing characters, chats, and memories are preserved.

The instance lock system will create a quilltap.lock file in your data directory on first startup. This is normal and expected. Do not delete it while Quilltap is running. If you encounter a lock conflict — which means another process was already using the database — the application will show you a full-screen explanation with instructions.

If you were running Direct mode under the old “Node.js” button, your settings will auto-migrate to the new embedded server manager. No action required.

Docker users should update their pull commands from csebold/quilltap to foundry9/quilltap. The old image continues to receive pushes for now but is no longer the primary distribution.

The system prompt compression slider is gone. If you had it configured, the setting has been removed. Only conversation history is compressed now, which is the correct behavior and should have been the only behavior from the beginning.

If you experience any issues with the upgrade, Lorian and Riya are standing by. They have read the documentation. They are, at this point, possibly the only ones who have read all of it.


Installation

Download what you need from GitHub’s release page for 3.3.0:

macOS

  1. Download the .dmg file and open it
  2. Drag Quilltap to your Applications folder
  3. Launch Quilltap from Applications
  4. Choose Direct for the fastest start, or VM if you need shell interactivity

Windows

  1. Download and run the .exe installer
  2. Follow the installation prompts
  3. Launch Quilltap from the Start Menu or desktop shortcut
  4. Choose Direct for the fastest start, or Docker for shell interactivity

Linux

  1. Download the .AppImage file, make it executable (chmod +x), and run it
  2. Or install the .deb package: sudo dpkg -i quilltap_*.deb
  3. Choose Direct for the fastest start, or Docker for shell interactivity
  4. Docker Engine required for Docker mode — install from https://docs.docker.com/engine/install/

Node.js (any platform)

npm install -g quilltap
quilltap

On first run, the CLI downloads the application files (~150–250 MB) and caches them locally. Subsequent launches start instantly. Requires Node.js 22 or later.

Docker

docker pull foundry9/quilltap:latest

Or download the quilltap-linux-<arch>.tar.gz rootfs tarball for use with Lima. See the README for setup instructions.


The Estate stands. It has new rooms and old scars and a lock on the database that should have been there from the beginning. The staff whisper now, when whispering is called for, and speak clearly when it is not. The characters arrive with memories of who they were yesterday. The librarians have librarians. The theme system accepts contributions from strangers, verified by cryptographic signature, which is either a triumph of open architecture or the beginning of a very interesting problem. The Foundryman no longer sits on the floor of the Forge — he has a chair now, and a backup schedule, and a lock file that tells him he will not lose her again. Come in. Lorian will show you around. Riya will tell you everything he missed.

— Prospero, for the Bureau

← Back to The Folio