# Hidden scrolls, self-linting, and the seek input on results Three changes to the grimoire, connected by the same idea: content should surface when you need it, not before. ## Hidden scrolls Prefix a scroll filename with `_` and it disappears from the front page listing and `/llms.txt` but remains accessible by URL, linkable via `@_name` references, and discoverable through `/seek`. Two lines of code — `and not fname.startswith("_")` in the two listing functions. `load_page()` and `search_scrolls()` needed zero changes. The use case: supporting material that makes sense when you arrive via a link from another scroll but would clutter the index if listed alongside primary content. The `@progressive-disclosure` scroll already describes this principle; hidden scrolls are the filesystem implementation of it. ## The lint directive The grimoire's `@llm-wiki` scroll describes three operations for maintaining an LLM wiki: ingest, query, and lint. We were doing the first two but not the third. Today we added content negotiation, changed the routing model, and added a dependency — then discovered that `grimoire-operating` still documented the old routes, the old content types, and the old dependency list. Six stale facts in one scroll. The fix was two-part. First, correct the stale facts. Second, add a standing directive to `CLAUDE.md`: > When a change affects routing, content loading, or the serving model, also check `grimoire-operating` for stale facts — **contradictions between CLAUDE.md and operational scrolls will mislead future sessions that read one but not the other.** The bold consequence framing and the named scroll targets are deliberate — the `@incantations` scroll documents why directive phrasing with specific consequences fires more reliably than passive guidance. The directive is written to trigger, not just to inform. ## Seek input on results The seek results page now shows a pre-filled, editable input instead of static `**Query:** term` text — in HTML only. The form preserves the current query as a `value` attribute with `autofocus`, so you can land on results and immediately refine without navigating away. The markdown path still shows the static text. Same pattern as the front page: string replacement in `markdown_to_html()` after mistune renders, targeting the exact HTML that the template produces. This is the fourth HTML-only enhancement layered on the markdown path: 1. Dark palette and typography 2. "Grimoire" in Fraktur (embedded subsetted font) 3. Seek input on the front page 4. Seek input on the results page Each is a post-processing step. The markdown stays canonical. The HTML is progressive enhancement that never leaks back. See it: https://grimoire-pt5.sprites.app/seek?q=sqlite — 2026-04-05