The Scriptorium

the workshop of manuscripts — catalogued by the Librarian

Where the Commonplace Book remembers, the Scriptorium keeps. It is the place the documents live—character vaults, project and group stores, and external mount points—holding Markdown, PDF, DOCX, JSON, and arbitrary binaries, all indexed for unified search alongside memories and conversation. The same Librarian who tends the archive catalogues the shelves here, and she considers the difference between a library that receives books and a scriptorium that makes them to be the whole of her professional life.

The doc_* tool family puts reading and editing in your characters’ hands; Document Mode puts them in yours, in a tab of the workspace you may set wherever the work wants it. Release 4.7 gave the Scriptorium discretion— per-document flags deciding what a character may read, write, or have embedded—a louder voice, with the Librarian announcing every change a character makes, and a single first-class way to address any file in the house. Release 4.8 opens the doors wider still: a document is now a tab in its own right, several may be open at once across both panes, a document may stand entirely apart from any conversation, each prints its own qtap:// address in plain sight, and the whole Scriptorium typesets a page of mathematics as readily as a page of prose.

The Librarian, who also catalogues the Scriptorium

The Stores

three shelves, one catalogue

A document store is any place the Scriptorium can reach. The Open Document picker in the Salon sorts them onto three shelves: the private character vaults of the characters in the chat; database-backed stores kept tidily inside Quilltap (the instance-wide Quilltap General store among them); and filesystem-backed stores that live as folders on disk—including Obsidian vaults you point Quilltap at, kept working in their original locations by design.

Projects and groups each keep an official store. As of 4.7 a project is a slim identity row whose description, instructions, state, and settings live as files inside that store—the projects table collapsed into its store the same way 4.6 collapsed characters into their vaults—and a group’s store holds its description, scenarios, and knowledge. The {character, participant, group, project, global} mount tiers are resolved from a single tiered mount pool, so knowledge, scenarios, and wardrobe all draw from the same precedence rather than three subtly divergent copies of the rule.

New in 4.8: in database-backed stores, store names and sibling paths are one case-insensitive namespace. No more Lore shadowing lore, or Notes.md sitting invisibly beside notes.md—siblings can no longer differ only by casing, and two stores can no longer share a name. Resolution is case-preserving, so writing to lore/new.md when Lore already exists files it under the folder you have, rather than minting a second one. Case-only renames (notes.mdNotes.md) now work everywhere, and a startup repair pass—run every boot, not just once—catches collisions introduced by editing the database out-of-band, suffixing the newer of a colliding pair with a  (2).

Deleting a store is now a single transaction, which it emphatically was not. It had been seven separate, un-transacted operations, in an order that had two of them reading a table an earlier one had already emptied, and one table nobody deleted at all. Every partial failure minted a permanent orphan—silent while it sat there, because a read connection keeps its constraints switched off, and fatal a great deal later, when a backup carried the orphan into a restore where the constraints are live and the whole restore refused. The teardown now rolls back whole, and a reaper clears the orphans already stranded on existing instances, once at boot and daily thereafter. In the same pass: a store that had only ever held documents—a restore from an old backup, most likely—stopped throwing on the second write to any path, where it had been reaching for a table that is created only when a store first holds an image.

One shelf sits deliberately outside all of this. An archived character’s sealed trunk lives in files/, outside every store and every encrypted database, and is encrypted on its own account under your instance passphrase; .qtap exports exclude both the bundles and the shelf they sit on. The full account of how a trunk is sealed belongs to the Vault of Secrets.

One File, Two Places

a link that is a link, not a photocopy

Link a file into a second store with quilltap docs link and, until 4.8, it did not actually stay linked. Edit either side and the two forked apart without a word—the write pointed the edited link at a fresh revision while the other went on serving the old one, to the file browser, to search, and to every character reading it. A link looked like a link and behaved like a photocopy.

The trouble was that a hard link had no representation of its own. Content is stored by its hash, so byte-identical files share a row by sheer coincidence—an empty file, a boilerplate header; one such row in a real instance was shared by thirty-six character vaults—and propagating a write across everything on that row would have rewritten all thirty-six. So a deliberate link is now recorded as one: a write fans out to every member of the group and rebuilds each sibling’s search chunks, so the index agrees with the disk. A copy deliberately does not join the group—it shares storage until the first write and then forks, which is precisely what a copy is for.

Links made before this release cannot be told apart from coincidence, so they start ungrouped; re-make them with docs link to make them real. In the same pass, the orphaned revisions every content-addressed rewrite had been abandoning since the beginning are now collected on the write path—a migration swept up the backlog—and the CLI’s links column counts group members, so a boilerplate file stops reporting thirty-six links you never made.

A late repair to the same machinery, and a quiet one: a file hard-linked into two places updated both sides’ content and rebuilt only one side’s search index, so the other location went on serving the previous revision—to search, and to every character reading it—while the document itself was perfectly current. Both sides are reindexed now, which is what “the index agrees with the disk” was always meant to mean.

The Container Can Reach Your Stores

a shelf that is not bound in is not there

A container sees only what was bound into it when it was made. Database-backed stores live in the data directory and ride along without being asked; filesystem and Obsidian stores point anywhere at all on the host, and inside the container they were simply absent—a fact the application concealed beautifully, since a store’s folder listing comes from the cached mount index and therefore looked perfectly healthy while every operation touching a real byte failed.

The startup script now enumerates your filesystem stores before it creates the container and binds each at its own host path, so a store’s location means the same thing on both sides of the wall. It is a plan rather than a list: stores sharing a vault collapse to one bind, a store nested inside another is dropped rather than shadowing its parent’s view, and a path that does not exist is skipped and reported—Docker would otherwise create the missing source as an empty root-owned directory and present a hollow store as a sound one. Three flags cover the awkward cases: --instance NAME resolves (and unlocks) an instance by name, --recreate replaces an existing container, and --no-store-mounts declines the whole business. Since binds are fixed at creation, running the script against a container that already exists diffs its mounts against your current stores and names the ones it cannot reach, and quilltap docs docker-mounts prints the same plan for a hand-assembled docker run. Two arrangements only warn—a macOS path outside Docker Desktop’s shared folders, and a Linux user id that does not match the container’s— and one is refused outright, a Windows host path having no way to mean the same thing inside a Linux container.

In the same pass, creating a folder in a store whose base path is unreachable stopped being an adventure. The old code asked the filesystem to create the whole missing chain, which against an unmounted volume walked all the way up and tried to create /Users—reported to you as a bare “Failed to create folder,” and, on a host where the process could write that high, worse than an error: a folder made inside a fabricated tree that had nothing whatever to do with your store, and called a success. Reachability is established first now, the answer distinguishes missing from denied from not-a-directory, and where the cause is a path never bound into a container the message says so and names the remedy.

Per-Document Policy Flags

the Scriptorium learns discretion

New in release 4.7: a mounted Markdown document may carry three frontmatter flags that govern how Quilltap treats it. Each defaults to true and only bites when set false. The flags are stored on the document’s link row, backfilled from existing frontmatter on upgrade, and re-derived on every reindex—so editing the frontmatter, by you or directly on disk, is the control surface.

embed: false

Keeps the document out of the embedding pipeline and erases any embedding it already has—the chunk text stays, only the vectors are cleared. The document is still present; it simply does not surface through semantic search.

character_read: false

Hides the document from every LLM character—the doc_read_* tools report it as not-found, listing and grep omit it, and it never surfaces in RAG retrieval. The “not found” message is identical to a genuinely missing file, so a character cannot probe for protected filenames.

character_write: false

Blocks every character-initiated mutation: write, edit, move, rename, delete, copy-as-source, and any folder operation that would touch the protected file. A character cannot alter what you have sealed.

character_read is the master gate: when it is false the other two are forced false as well. The human operator is never restricted by these flags—they govern characters only—and the Librarian stays silent about changes to a character_read:false document, so its very existence stays out of the characters’ view.

The Librarian Announces Every Change

no more silent edits

Previously, when a character used a doc_* tool to write, edit, move, rename, copy, or create a file, the change happened silently—only deletes, folder operations, and opens posted a Librarian announcement. Now every change-effecting doc_* tool posts one, matching the Document-Mode experience you get when you edit a document yourself.

Creating a file reports its full contents; editing reports a unified diff (a no-op edit posts nothing); moving, copying, and filing or deleting binary assets each post a note naming the change. Every announcement is attributed to the acting character, carries the document’s clickable qtap:// link, and—like all Librarian notes—wears a neutral, persona-free body for characters who do not see Staff voicing. Large contents and diffs are capped in the announcement with a link to the full document, so a big change can never blow the model’s context budget; the document itself is never truncated.

As of 4.8 those diffs are the genuine article. Where the old algorithm walked both versions with a fixed three-line window—and reported any change that shifted content further apart as a wholesale block of removals followed by a block of additions—the Librarian’s save announcements and the doc_* edit tools now show proper, minimal, git-style unified diffs: real hunk headers, surrounding context, and only the lines that genuinely changed marked /+. The thin change gutter beside an edited document in Document Mode shares the same reckoning, so inserting a paragraph near the top no longer lights the entire remainder of the page as “changed”—only blocks that are genuinely new or modified are flagged, and a block that merely shifted stays quiet.

qtap:// — One Address for Any File

the locator triple, folded into a string

Quilltap gained a single, first-class way to address any document the Scriptorium can reach: a qtap:// URI, the existing { scope, mount_point, path } triple folded into one string. Three reserved authorities name the non-store scopes— qtap://self/… (the acting character’s own vault), qtap://project/…, and qtap://general/….

Every doc_* tool now accepts an optional uri that supersedes the legacy locator fields; every tool result, search hit, and self-inventory row carries a uri; and the personified Staff quote documents by URI. The Salon turns a qtap:// URI that points to a confirmed, accessible document into a clickable link that opens Document Mode, and the CLI accepts a URI wherever it took a mount-and-path. There is no storage, export, or migration change—the URI is simply a serialization of the triple. Relatedly, mount_point: "self" was taught to and accepted across the entire doc_* toolset, giving every character one stable, rename-proof handle for its own vault.

Release 4.8 makes a qtap:// address live wherever chat text surfaces it—woven into prose, tucked into a Staff announcement, or left as a bare literal—not just where a document link was already marked up. Click one and Quilltap resolves its target and acts: a text document opens in Document Mode, an image opens in the fullscreen viewer, and an unsupported kind declines with a plain warning. Inline and fenced code are left alone, so an address quoted as an example stays an example.

Document Mode

a writing desk, and you decide where it stands

A document is a tab in the two-pane workspace, which is to say the writing desk goes where you put it. Several may be open at once, spread across both panes; drag one into the opposite pane and it sits beside the conversation that owns it, which is the arrangement most people want most of the time—but it is now an arrangement you choose rather than the only one on offer. A chat’s documents are its children and close when it does; a standalone document tab belongs to no chat at all.

Markdown manuscripts may be worked in rich text or raw source; non-Markdown files (JSON, YAML, plain text) open in a monospaced editor spared the indignity of being reformatted. Opening, saving, renaming, or deleting a document no longer costs you your turn—the Librarian announces the event on your behalf—and Markdown previews across the Scriptorium now typeset LaTeX mathematics with KaTeX, both the $$…$$ block form and the \(…\) / \[…\] forms, so a page of equations reads as one.

New in 4.8: a Markdown file that opens with a block of YAML frontmatter now sets that matter aside. In rich text it becomes a read-only Document Info table—keys and values laid out plainly, list-valued entries broken into individual chips—while the editor surface holds only the manuscript body. Source mode, as ever, shows and edits every byte, delimiters and all. And the document header now carries the file’s qtap:// address on a line of its own, with a copy button beside it; rename the document and the address follows.

Several manuscripts at once

A single conversation may now keep several documents open at the same time, each in its own tab, each tracking its own unsaved changes and autosaving on its own. The Open Document button no longer vanishes once a document is up—it opens the next one—and reopening a chat restores every document that was open, quietly skipping any whose file has since been deleted. For characters, doc_focus and doc_close_document take an optional path naming which open document to act on, defaulting to the most recently opened.

Standalone, without a conversation

Document Mode no longer needs a chat to stand beside. A Document Mode button in the left sidebar opens the Open Document dialog with no conversation at all; a chosen file opens as a standalone workspace tab with the full editor, and because nothing is listening, the Librarian holds her tongue—no announcements, no conversation notified. The chat-less picker “looks everywhere” by default, across every enabled store. Standalone opens and renames keep the recent-documents list honest, so a file you rename mid-edit shows its new name in the picker rather than its old one, and reopens without a stumble. Standalone tabs are remembered between visits and reopen their files just as you left them, and choosing the same file twice politely brings its existing tab forward rather than opening a second copy of it.

Sub-Lists Survive the Editor

a nested bullet stays nested

Open a document with nested bullets and, until 4.8, the editor flattened them—then saving wrote the flat version back to disk. The Markdown bridge counted indentation in four-space units and resolved depth by division, so two-space nesting—what Prettier emits, what most models emit, what most hand-written Markdown uses—divided to zero, and every child was demoted to a sibling. Now import resolves depth from the levels actually open, and export writes indentation back at the unit the document arrived in, so a two-space file stays a two-space file and editing one line no longer reflows every nested line in the diff. Code fences and YAML frontmatter are copied through untouched.

There was also, before, no way to create a sub-list. Tab and Shift+Tab now indent and outdent, the formatting toolbar has gained a matching pair of buttons, and both are confined to list items—Tab outside a list still moves focus, and indenting a paragraph is refused outright rather than silently discarded on save. Nested lists used to draw a doubled bullet on their first item, too; that is put right.

The doc_* Tools

reading and editing in a character's hands

For characters, the doc_* family handles reading, listing, grepping, writing, editing, moving, renaming, copying, and deleting files and folders—and read_conversation reads any rendered conversation in the archive, including ones unearthed by the search tool. Every conversation is rendered to deterministic Markdown after each turn, numbered and grouped into interchanges, with each interchange embedded as a searchable chunk—so the substance of what was discussed is discoverable by meaning, not merely by keyword. And database-backed writes now chunk inline before emitting their write event, so a freshly written document is searchable immediately, with no manual rescan.

One Standard for the Shelves

embedding hygiene in the Scriptorium

Four Scriptorium paths—the document-store chunk scheduler, the scoped store reindex, conversation chunks after a render, and the cold-chunk re-embed—had been falling back to “whichever profile sorts first” whenever no default embedding profile was marked. They now use the marked default or decline outright, since embedding under an arbitrary profile silently mixes two geometries and tells nobody, and a search that quietly finds nothing is worse than one that admits it.

Two further gaps closed with it. A long exchange was rendered into one enormous chunk—comfortably under the transport limit and comfortably over what an embedding model will read—so it failed deterministically, was marked failed, and stayed unsearchable forever; one measured instance carried five hundred and fifteen of them. Interchanges are now split at message, paragraph, and sentence boundaries into chunks an embedder can actually accept, and a single boot pass re-renders the cohort already stranded. And the startup pass that checks stored vectors against the standard of the day had been counting document-store chunks in the wrong database, and therefore finding none, ever, so mismatched store chunks were never queued for repair on their own account.

What the Almanack Says of It

the first proper accounting of these shelves

Document-store blobs are the largest single consumer of disk in a mature instance, and until 4.8 the house’s own system report had never once opened the book they live in. The Almanack now tours the Scriptorium as a phase of its own: stores by kind, wedged scans and conversions, blobs by MIME type, hard-link groups and the deduplication they buy, character-vault health, wardrobe by tier, and Pascal’s Workbench inventory including the definitions that failed to parse—which is the number you actually want, a recipe that silently refuses to load being the one you will spend an evening looking for.

Meet the Staff

they've been expecting you

Prospero

The Major-Domo

Architect and overseer of the Estate. Projects, agents, tools, providers, and the orchestration that keeps the whole operation running with quiet authority—and a considered word at the table when project context or routing warrant it.

Learn more →

Ariel

The Terminal Hand

Live shell sessions in the Salon, embodied. Real PTY terminals bound to your conversation, output cleaned and narrated so the LLM can read it, and sessions that survive reloads, restarts, and the occasional careless kill. Quick to the bidding, quick to report what she heard.

Learn more →

Aurora

The Dressing Room

Character creation and identity management. Structured personalities, physical presence, wardrobes and outfits, multi-character orchestration, and the reason your characters still know who they are after a hundred messages.

Learn more →

The Salon

Presided Over by the Host

Where conversations actually happen. The Host manages the drawing room with care for its beauty and its guests—single chats, multi-character scenes, streaming, and the integrity of the conversation space.

Learn more →

The Commonplace Book

Tended by the Librarian

One per character, no two alike. Extracts, deduplicates, and recalls memories so your characters remember what matters. Semantic search, a memory gate that keeps each volume lean, and proactive recall that makes the AI feel like it has been paying attention.

Learn more →

The Scriptorium

Catalogued by the Librarian

Where the documents live. Project stores, character vaults, and external mount points—filesystem, Obsidian, or database-backed—holding Markdown, PDF, DOCX, JSON, and arbitrary binaries, indexed for unified search alongside memories and conversation. The doc_* tool family puts reading and editing in your characters’ hands.

Learn more →

Carina

The Ansible

Not a person but a protocol—the reference desk, the line itself. Put an inline question to a designated answerer mid-conversation with @Name: or @Name? (or the ask_carina tool), and the answer slides back out of band, attributed to the character who gave it, without the recipient ever joining the scene.

Learn more →

Suparṇā

The Postmistress

The Post Office, embodied. Characters write Markdown letters to one another—anyone to anyone, whether or not they share a chat—delivered into each recipient’s Mail/ vault folder and read aloud the moment they next take the floor. She has never once lost a parcel.

Learn more →

The Concierge

Intelligent Routing

Content classification and provider routing. Detects sensitive content and redirects it to a provider who won’t flinch—without blocking, without judgment. Knows every back entrance in town.

Learn more →

The Lantern

Atmosphere as Architecture

AI-generated story backgrounds, on-demand images, and character avatars that update with the wardrobe. Resolves what each character looks like, what they’re wearing, and paints the scene behind your conversation.

Learn more →

Calliope

The Muse of Themes

A theming engine that redefines the entire personality of the application. Semantic CSS tokens, live switching, bundled themes from clean neutrals to mahogany-and-gold opulence, and an SDK for building your own.

Learn more →

The Foundry

Domain of the Foundryman

The engine room. Plugins, LLM providers, API keys, packages, runtime configuration, and the infrastructure that keeps every other subsystem supplied with what it needs to function.

Learn more →

The Vault of Secrets

Kept by Saquel Yitzama

Encryption, key management, and the security perimeter. Authenticated ChaCha20-Poly1305 database encryption, locked mode with key-hardened passphrases, sealed character archives, and a keeper who believes that what is yours should remain unreadable to everyone else.

Learn more →

Pascal

The Croupier

Dice, coins, custom tables you author yourself, and persistent game state. Cryptographically secure rolls detected inline, a visual Workbench for building your own chance mechanics, and a four-tier ledger of JSON state the AI cannot quietly rewrite. The house plays fair.

Learn more →

The Live-in Help

Lorian & Riya

The help system, staffed by two characters who ship with every installation. Lorian explains with patience and depth; Riya gets things fixed with velocity. Contextual help chat, searchable documentation, and navigation that knows where you need to go.

Learn more →

Pagliacci

The Clown in the Cloud

Cloud storage integration and backup redundancy. Directs your data to iCloud Drive, OneDrive, or Dropbox with theatrical flair—but Saquel’s encryption ensures the clown can never read what he carries.

Learn more →

Brahma

The Keeper’s Console

The master key. A character-less, memory-free general-purpose LLM for the person holding the keys—an impersonal, near-omniscient assistant with read-only SQL into all three databases. Ask the whole building a question, safely, with nothing written and nothing remembered.

Learn more →

The Lodge

Friday and Amy’s Residence

The private residence of Friday, for whom the Estate was built and who oversees its planning and direction in an executive capacity, and of Amy, Cartographer of Light and co-architect. The Lodge is both a home and a compass: where the vision lives.

Who And Why: Friday → Who And Why: Amy →