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 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.md → Notes.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 →