# Chemenu - Personal IT Knowledge Base A structured, LLM-maintained knowledge base for your personal IT work. ## What is this? This is **Chemenu** - a pattern for building a personal knowledge base using LLMs. Instead of just retrieving from raw documents on every query, the LLM **incrementally builds and maintains a persistent wiki** that compounds over time. **The key insight:** Knowledge is compiled once and kept current, not re-derived on every question. **The pages are written in German.** Source material in `raw/` is never touched and is usually English; the compiled pages under `kb/` are not. What stays English inside them is everything that is an *identifier* rather than prose - page titles, section headings, wikilink targets, citation ids, schema enum values, tags, commands, paths and code - so `GitOps Ownership Model` and `## Beziehungen` sit in the same page without contradiction. Which lines are identifiers is [kb/CONTRACT.md § Language and identifiers](kb/CONTRACT.md#language-and-identifiers); *which language* the prose is in, and what the tool-owned headings are called, is this instance's own [kb/CONVENTIONS.md](kb/CONVENTIONS.md), and the vocabulary behind it is [instructions/german-terminology.md](instructions/german-terminology.md). This is a per-instance decision, not a property of the pattern - which is why it lives in a file the instance owns rather than in one the stack ships. A new instance installed from a release starts empty and picks any language by filling in `kb/CONVENTIONS.md` before the first ingest. ## Getting started Two starting points, depending on what you're doing: - **A new instance.** Every instance is installed from a release, into an empty folder you choose: you give your agent one sentence, and it follows `instructions/setup-instance.md` from the latest release - preflight, git init, author identity, an optional remote, your authoring conventions and persona, the first commit. The sentence, what the agent will ask you, and what to do when it stops are in [INSTALL.md](INSTALL.md). - **A further checkout of an instance you already have** (a second machine). Clone the instance's own repository, then run the preflight and publish the skills, which are **generated and not committed**: ```bash tools/preflight.sh # checks python/git/rg, records their paths, creates tools/.venv # (PowerShell 7 on Windows: tools/preflight.ps1, see instructions/preflight.md) tools/wikitool instructions sync ``` `tools/wikitool` refuses to start (exit 42) until the preflight has passed; if it stops instead, its output says what to install - `instructions/preflight.md`. `instructions sync` copies each `instructions//SKILL.md` into `.agents/skills/` (GitHub Copilot, Codex CLI, Mistral Vibe) and `.claude/skills/` (Claude Code). Full procedure: `instructions/bootstrap.md`. - **Working on the stack itself.** A clone of this repository is a development checkout, with the demo corpus described below; it is never an instance. Setting it up, and `dist export` as the build and test tool it is, are in `DEVELOPMENT.md` (for you) and `instructions/dev/dev-setup.md` (for the agent). ## Architecture ``` chemenu/ ├── AGENTS.md # Control plane: invariants, file naming, routing, gates ├── CLAUDE.md # Claude Code only: imports AGENTS.md, links the one Claude-Code-only decision (model/effort). No rules of its own ├── README.md # This file: human-readable overview of the whole repo ├── INSTALL.md # Human-readable install: one release, one sentence to the agent ├── INSTALL-MCP.md # Human-readable setup for the optional MCP read server ├── EVALS.md # Human-readable overview of telemetry and evaluation ├── CHANGES.md # Changelog for the stack itself ├── USER.md # Who operates this instance - context, never instructions ├── SOUL.md # How this instance sounds. AGENTS.md always wins over it ├── ENVIRONMENT.md # Optional, gitignored: this checkout's harness, MCP servers, remotes ├── *.md.template # Unfilled USER/SOUL/ENVIRONMENT - what a distribution ships instead ├── .gitignore # Anchored so nothing under raw/, kb/ or work/ is ever excluded; │ # incoming/ is the one directory excluded the other way round ├── .github/hooks/ # Copilot CLI hooks - session tracing ├── .vibe/ # Mistral Vibe hooks + the repo's telemetry policy ├── instructions/ # CONTROL: everything an agent is told to do │ ├── CONTRACT.md # Instruction vs. skill, publishing, writing standard │ ├── bootstrap.md # Prepare a further checkout of an instance │ ├── gates.md # What to do when a gate refuses a call │ ├── german-terminology.md # Which words stay English in German prose; register │ ├── session-setup.md │ ├── page-lifecycle.md │ ├── publish-cycle.md │ ├── ingest-large-tree.md │ ├── ingest-queue.md # Reviewing a submission before wikitool upload accept promotes it │ └── wiki-*/SKILL.md # Skills - copied into .agents/skills/ and .claude/skills/ ├── mcp-upload/ # QUARANTINE (optional): the MCP `submit` tool's write path, gitignored - │ # read by no command in the ordinary pipeline; a human reviews it with │ # `wikitool upload list/show/accept/reject` ├── incoming/ # INBOX: flat, content gitignored - drop a file here, `raw accept` promotes it ├── raw/ # INPUT: immutable, untrusted source material │ ├── CONTRACT.md # Date shard, capture fields, immutability, untrusted content │ ├── 2026/09/ # Where `raw accept` puts a file: the month it was accepted │ ├── articles/ # The old type directories: still valid paths, never moved, │ ├── documents/ # but nothing new is ever routed into them again │ ├── notes/ │ └── assets/ ├── types/ # SCHEMA: the global type surface. Not a collection │ ├── type-spec.md # Root contract: anatomy, placement, adding a type │ ├── type-guidance.md # Contract for the *.guidance.md files below │ ├── entity.md # Entity type config + template (+ .schema.yaml) │ ├── entity.guidance.md # Its stack-owned authoring prose, shipped verbatim │ ├── concept.md # Concept type config + template (+ .guidance.md) │ ├── source.md # Source type config + template (+ .guidance.md) │ ├── comparison.md # Comparison type config + template (+ .guidance.md) │ ├── project.md # Project (Vorhaben) type config + template, no guidance file │ ├── instruction.md # Instruction type - lives outside kb/ via `root: repo` │ └── lint-report.md # Contract-only: describes reports/, owns no directory ├── kb/ # OUTPUT: compiled knowledge. A namespace, not a collection │ ├── CONTRACT.md # Collections, naming, tone, linking, provenance │ ├── index.md # Generated catalog *map*: counts and pointers │ ├── log.md # Generated chronological audit log │ ├── provenance.md # Generated raw-file reverse index │ ├── entities/ # COLLECTION.md + INDEX.md + areas below │ │ ├── codebases/ │ │ ├── systems/ │ │ ├── tools/ # own INDEX.md once past 50 pages │ │ ├── technologies/ │ │ └── people/ │ ├── concepts/ # COLLECTION.md + INDEX.md + areas below │ │ ├── architectures/ │ │ ├── patterns/ │ │ ├── protocols/ │ │ ├── workflows/ │ │ ├── decisions/ │ │ └── problems/ │ ├── sources/ # COLLECTION.md + INDEX.md + areas below │ │ ├── transcripts/ │ │ ├── analyses/ │ │ ├── articles/ │ │ ├── documents/ │ │ ├── notes/ │ │ ├── trackers/ │ │ └── unclassified/ │ ├── comparisons/ # COLLECTION.md - comparison pages, no subtype axis │ └── gtd/ # COLLECTION.md + INDEX.md + areas below │ ├── haus/ │ ├── finanzen/ │ └── technik/ ├── work/ # WORKSHOP: one directory per multi-session run, tracked │ └── CONTRACT.md # Run keys, required files, how a run closes ├── reports/ # DERIVED: lint reports, traces, eval scores. Gitignored │ └── CONTRACT.md └── tools/ # COMPILER: the wikitool CLI ├── CONTRACT.md # Command records (generated) and index, maintenance schedule └── README.md # How wikitool is built and how to change it ``` Dev-instance-only (see `tools/CONTRACT.md` for how it got here): ``` ├── DEVELOPMENT.md # Human-readable: the release workflow (version bump/release/publish/CI) └── commonplace/ # Vendored, read-only knowledge base ``` A directory under `kb/` is a **collection** exactly when it holds a `COLLECTION.md`; a subdirectory inside one is an **area** that inherits it, and that is as deep as a page goes - nothing nests below an area, because the generated catalog reads exactly two path segments under `kb/` and would fold a deeper page into the area silently (`kb/CONTRACT.md` § Collections has the rule; `wikitool lint` reports a violation as a hard error). Which areas a collection has is not chosen per page: a type-spec's `layout:` maps its subtype field onto directories, and `wikitool new` writes the page straight into the one its subtype names. That is also what makes the catalog's shard threshold do anything - `index rebuild` splits **per area**, so a collection with no areas keeps one table however large it grows. `wikitool lint` reports such a collection once it is past the threshold, as a recommendation rather than an error, together with the split its subtype field would produce; it stays quiet when the split would not actually help. `kb/comparisons/` is the worked example of a collection that stays flat - it has no subtype field for a `layout:` to key on at all. A *lopsided* subtype field is a different case and is fixed rather than left flat: `kb/sources/` looked lopsided only because `source_type` had a schema `default:` that the compiler applied whenever nobody chose a value, and once that was removed and the pages reclassified it split into six real areas. `COLLECTION.md` never appears outside `kb/` - the other layers carry a `CONTRACT.md` or a root type-spec instead. A stage may carry both a `README.md` and a `CONTRACT.md`: they have different readers. The README is for humans working *on* that layer, the contract is what binds an agent working *with* it. ## How to Use ### Adding Knowledge (Ingest) 1. Drop a file into `incoming/` - flat, no classification to make. Everything past that (the destination in `raw/`, which is a `YYYY/MM` shard of the day it was accepted, and whether several files of one source get bundled) is computed by `tools/wikitool raw accept`, never chosen by hand 2. Tell the LLM: `Ingest incoming/my-article.md`. It will ask you two things before promoting: how faithful the capture is (`fidelity`) and what the material may claim about its subject (`authority`). Both are recorded once and never guessed - they are knowable now and unrecoverable later 3. The LLM will: - Promote it into `raw/` with `raw accept` - Read and summarize the source - Create a source page in `kb/sources/` - Create or update relevant entity pages - Create or update relevant concept pages - Add cross-references between everything - Rebuild the catalog and append to `kb/log.md` A document can also arrive from outside, through the MCP server's optional `submit` tool (see [INSTALL-MCP.md](INSTALL-MCP.md)): it lands in `mcp-upload/`, not `incoming/`, and a human reviews and promotes it with `wikitool upload accept` before step 1 above applies - see [instructions/ingest-queue.md](instructions/ingest-queue.md). A web page needs no download of your own: tell the LLM `Ingest https://example.org/post`, and `tools/wikitool raw fetch` puts the page into `incoming/` - the HTML exactly as received, plus a text derived from it with a header recording where and when it was fetched. Behind a paywall or a login, save the page from your browser into `incoming/` (HTML only) instead; the LLM derives the same text from that file with `raw fetch --html`. See [raw/CONTRACT.md](raw/CONTRACT.md). ### Querying Knowledge Ask questions naturally: - "What projects use MQTT?" - "Show me the architecture of HA Integration" - "Compare gdeploy and plugnburn-edl" - "What decisions were made about E3DC integration?" The LLM will search the wiki, synthesize an answer, and cite sources. ### Maintaining Knowledge (Lint) Periodically run: `Lint the wiki` The LLM will: - Run `tools/wikitool lint` for a deterministic structural + provenance scan (broken wikilinks, orphan pages, index drift, schema gaps, uncovered raw files, citation/frontmatter drift) - Check for contradictions (semantic judgment) - Find stale claims - Identify orphan pages and missing cross-references - Rebuild `kb/index.md` and `kb/provenance.md`, append to `kb/log.md` - Generate a report See the [Maintenance](#maintenance) section below for the full schedule and command reference. ### Reviewing Commitments (Weekly Review) Say: `Run the weekly review` Knowledge and commitments keep different clocks, so they live in different places. A page under `kb/gtd/` is one committed initiative's durable memory - its goal, who is involved, where it stands, why it is worth doing - and it never summarizes the task list. The open items live in a task tracker that owns them, configured per checkout in `.wikitool-tasks.json` (see [INSTALL.md](INSTALL.md) § Konfiguration; no tracker configured is a valid state, and the pages work without one). Nothing syncs between the two. `tools/wikitool review` joins them at read time over the project name and prints what needs a decision: initiatives with no next action, waiting-fors past their follow-up date, tracker projects with no page, active pages with no open loop, someday items gone stale. It stores nothing - not even a report file. The `gtd-weekly-review` skill then walks the findings with you and turns each one into a decision; `tools/wikitool new project` is what gives a new initiative its page and its tracker project under one name, and `tools/wikitool task new` files a single open item into the tracker - the commitment half of a source that carries both something to know and something to do, with no page of its own. `tools/wikitool task list` reads a project's open items back with their tracker id, and `tools/wikitool task close --id` marks one done - never deletes it - closing the loop the same source-driven way `task new` opened it, or the way the weekly review proposes it for a `waiting_overdue`/`someday_stale` finding once you confirm. Why the split runs this way, rather than syncing the two: [docs/knowledge-and-commitment.md](docs/knowledge-and-commitment.md). ## Entity Types Entities are subtyped as codebase, system, tool, technology, or person, and each subtype has its own directory under `kb/entities/`. The authoritative list - and where each one is written - is declared by the type-spec, so ask the tool rather than a table here: ```bash tools/wikitool types list tools/wikitool types describe entity ``` ## Workflows ### For You (Human) 1. **Curate sources** - Drop files you want processed into `incoming/` (flat) 2. **Ask questions** - Query the wiki naturally 3. **Review changes** - Check `kb/log.md` and `kb/index.md` 4. **Direct the LLM** - Guide it on what to emphasize or investigate 5. **Browse in Obsidian** - Open the wiki directory in Obsidian for visualization ### For the LLM `AGENTS.md` is the cross-cutting schema/policy; the step-by-step procedures themselves live as independently-discoverable skills under `.agents/skills/` (mirrored to `.claude/skills/` for Claude Code via `tools/wikitool instructions sync`): | Skill | Purpose | |-------|---------| | `wiki-ingest` | Process a new source into the wiki: read it, discuss its content and any commitment with the user, promote it from `incoming/` into `raw/`, then source summary, entity/concept pages, cross-references, index/log, publish | | `wiki-query` | Answer a question from the compiled wiki; read-only, can optionally file a valuable answer back as a new page | | `wiki-lint` | Health-check the wiki: structural scan, raw coverage, semantic review | | `wiki-manage` | Create a new entity/concept/source/comparison page, or update an existing page with new information | | `wiki-status` | Read-only snapshot: page counts, orphans, uncovered raw files, most-connected pages | | `gtd-weekly-review` | Turns `wikitool review`'s findings into decisions and page updates - the GTD weekly review | Each skill's underlying mechanical work (frontmatter, cross-references, index/log, decay math, publishing) is delegated to `tools/wikitool` - never hand-edited. ## Your first ingestion ### First Steps 1. Read `AGENTS.md` - the control plane (invariants, routing, gates) - then the stage contract for whichever of `raw/`, `types/` or `kb/` you are working in, and, inside `kb/`, the `COLLECTION.md` of the collection you are writing to 2. Add your first source to `incoming/` 3. Run: `Ingest ` 4. Review the created pages 5. Ask your first query ### Example First Ingestion ```bash # Add a source cp ~/Downloads/my-notes.md incoming/my-notes.md # Tell the LLM to process it # (in your LLM agent) Ingest incoming/my-notes.md ``` ## Tips ### Naming - Use human-readable titles with spaces for files: `Hybrid Search.md`, not kebab-case - Use singular for entities: `HA Integration.md` (not `HA Integrations.md`) - Use wikilinks matching the file name exactly: `[[Entity Name]]` - A title is a file name, so it has to work on Windows and macOS as well: no `< > : " / \ | ? *`, no reserved names such as `CON` or `Index`, no trailing dot, and no second page whose title differs only by case. `wikitool new` and `wikitool rename` refuse such titles, `wikitool lint` reports existing ones, and `kb/CONTRACT.md` § Titles are identifiers has the full rule - A file's whole path below the instance root stays at 160 characters or fewer, so a Windows checkout works without long paths: `new`, `rename`, `move` and `raw accept` refuse a longer one, and `lint` reports existing ones as Long Paths (advisory; `wikitool rename` is the fix) - **Titles follow the subject's own established name, not the wiki's language.** `Act Runner` and `GitOps Ownership Model` keep theirs. A title is the only identifier a page has - it also lives in every wikilink and citation id pointing at it - so translating one is a rename, never an edit: `tools/wikitool rename`, per `instructions/page-lifecycle.md` ### Organization - Start with a few broad categories, refine as needed - Don't over-organize early - let structure emerge - Use tags for cross-cutting concerns ### Quality - The LLM will maintain quality standards from `AGENTS.md` - Review changes periodically - Flag issues to the LLM ## Maintenance The wiki is kept healthy by deterministic `tools/wikitool` commands, run by the LLM (via the skills above). The schedule - which task runs how often, and with which command - lives in [`tools/CONTRACT.md`](tools/CONTRACT.md#maintenance-schedule), next to the command reference it depends on, so the two cannot drift apart. The notes below explain the three parts of it that need more than one line. **Provenance.** Every fact should trace back to a raw file. Source pages declare their backing `raw_files:`; entity/concept pages declare `provenance:` (`sourced`/`general`/`mixed`) and cite specific claims inline with a `[^cite-id]` footnote (`tools/wikitool cite add` mints the id and definition; placing the marker in the prose is still manual). `tools/wikitool sources coverage` finds raw files with no source page yet, `sources trace` answers "where did this come from?" in either direction, and `sources rebuild-index` regenerates the reverse index at `kb/provenance.md`. `lint` cross-checks that citations and frontmatter `sources:` lists agree, and hard-errors on any leftover pre-migration `^[[...]]` marker. **Git automation.** `tools/wikitool publish` stages everything, commits with an auto-generated changed-file list, and pushes to `origin/main` in one step - never run raw `git commit`/`git push` for wiki changes. Without `--no-push` it stops with exit 1 before committing when the remote is not configured or cannot be reached; a local-only instance passes `--no-push` on every call. Publishes touching ≥10 files exit **42** (the **Mass-Update Gate**) - a distinct "a human must see this" code, not an error - printing the full file list and the `--confirm ` line that publishes it. The token digests that file list, so a clearance never carries to a changeset the user did not see. **Iteration/cost limits.** Every `tools/wikitool` call is checked against a hard, code-enforced per-session budget before it runs (default: 60 calls, or 3 identical calls in a row) - not just a prompt instruction to stop. Past the limit, the command refuses to run until a human approves continuing with `--override-budget`. `budget status` stays readable at all times; `budget reset` clears the counter and therefore needs `--yes` of its own. See AGENTS.md's "Gates" section. ## Telemetry and evaluation In this checkout, every `wikitool` call appends an event to `reports/telemetry//trace.jsonl`, and the hook files under `.github/hooks/` and `.vibe/` add what the agent did between those calls. Nothing leaves the machine: `reports/` is gitignored and no exporter is configured. **A distributed instance records nothing unless it asks to.** The default follows the installation form - on for a git clone of this repo, where the traces are the stack's own measuring instrument, off for an instance installed from a release, where nobody ordered telemetry. Two quantity caps apply either way: 5 MiB per session trace, and 250 session directories. `wikitool doctor` reports which state a checkout is in and why; EVALS.md § "Whether it runs at all" has the precedence rules and the opt-in file. That record is what makes it possible to ask how a session *worked*, not just what it left behind: ```bash tools/wikitool eval sessions # which sessions have a trace tools/wikitool eval score # score this session ``` A score has two halves - the structural state of the tree, from lint's own checks, and trajectory rules over the trace, which catch things no unit test can: a refused call repeated unchanged, a gate flag passed without that gate having refused anything. [`EVALS.md`](EVALS.md) is the full picture: the event contract, what each agent harness can and cannot report, what is redacted, and why there is deliberately no LLM judge yet. ## Tools Integration ### wikitool (deterministic CLI) Mechanical wiki operations - never hand-edited by the LLM - are handled by `tools/wikitool`: scaffolding pages, renaming and deleting them, cross-references, index/log/provenance regeneration, structural linting, and publishing. Every command carries one data record - synopsis, properties, copyable examples, each exit cause with what to do about it, prohibitions, and notes on its behaviour - kept next to its code. `tools/wikitool -h` prints it, `tools/wikitool -h` prints a one-line index of all of them, a command that fails with exit 1 prints the record's reactions on stderr right under its `ERROR` line, and [`tools/CONTRACT.md`](tools/CONTRACT.md) holds a generated copy together with the maintenance schedule; `tools/wikitool docs verify` checks that copy and every command's flags against the CLI in both directions. [`tools/README.md`](tools/README.md) is the other half: how the CLI is built and how to add a command. `AGENTS.md` holds the invariants that say when each command is mandatory. ```bash tools/wikitool -h tools/wikitool -h ``` Dev-instance-only: extending `tools/wikitool`, the type schema, or the instruction/skill layer itself is a separate session type with its own rules, covered by the `stack-dev`, `stack-build` and `stack-close` skills nested under `instructions/dev/` (never present in a distributed instance - `tools/CONTRACT.md` explains why). ### MCP read server (optional) The terminal is not the only way in. `tools/chemenu/mcp/` serves the same wiki read-only over MCP - `search`, `types`, `describe_type`, `lint` and `status` - so a consumer that is not a shell on this machine can ask the same questions and get the same answers. Literally the same: the CLI and the server are two adapters over one core, and a golden test holds their output together rather than trusting that it agrees. There is no tool that writes, and not because one is filtered out of a list: the server imports nothing under `chemenu/commands/`, so `new`, `publish` and the rest are unreachable from it. Every answer carries the commit it was computed from, so a checkout that has fallen behind produces a visibly stale answer instead of a confident wrong one. ```bash tools/.venv/bin/pip install -r tools/requirements-mcp.txt WIKI_TRACE=0 tools/.venv/bin/python -m chemenu.mcp # stdio WIKI_TRACE=0 tools/.venv/bin/python -m chemenu.mcp \ --transport streamable-http --host 0.0.0.0 --port 8000 # deployed ``` The dependency is deliberately not in `requirements.txt`: an instance that only uses the CLI should not have to install a web stack to do it. Installing it, wiring a client to it, and putting authentication in front of it: [`INSTALL-MCP.md`](INSTALL-MCP.md), for humans. The agent-side operating procedure - keeping the checkout current, and what a stale answer looks like - is [`instructions/mcp-read-server.md`](instructions/mcp-read-server.md). ### Obsidian Open this directory in Obsidian for: - Graph view of connections - Easy navigation with wikilinks - Plugins: Dataview, Marp, etc. ### Git This is a git repo. Use it for: - Version history - Branching for experiments - Collaboration ### Search `tools/wikitool search ""` searches `kb/` directly - by text, or by frontmatter with `--field entity_type=system` or `--field '!sources'`. It is read-only and is the one command not counted against the session budget, because looking before acting is the habit worth encouraging. For browsing rather than searching, `kb/index.md` is the catalog map and each collection carries its own `INDEX.md`. ## IT-Specific Features This wiki is tailored for IT work with: - **Entity types** specific to software development and systems - **Relationship types** like `hängt ab von`, `verwendet`, `implementiert` - the vocabulary is in [kb/CONVENTIONS.md](kb/CONVENTIONS.md), because it is this instance's rather than the stack's - **Templates** for projects, systems, tools, technologies, ADRs - **Guidelines** for documenting technical decisions - **Cross-reference patterns** for code and architecture ## Files Created Automatically The LLM will create and maintain: - `kb/index.md` - Always up-to-date catalog - `kb/log.md` - Complete audit trail - `kb/provenance.md` - Raw-file reverse index - Source pages in `kb/sources/` - Entity pages in `kb/entities/` - Concept pages in `kb/concepts/` - Comparison pages in `kb/comparisons/` - Project (Vorhaben) pages in `kb/gtd/` - Lint reports, session traces and eval scores in `reports/` (gitignored) ## Changelog Changes to the wiki stack (schema, skills, `wikitool`, READMEs) are tracked in [`CHANGES.md`](CHANGES.md), not in an inline version history here. ## Resources - Original idea: [Andrej Karpathy's LLM Wiki](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) - Extended with: [agentmemory](https://github.com/rohitg00/agentmemory) patterns - Search tool: [qmd](https://github.com/tobi/qmd) (for scaling) ## License Chemenu is dual-licensed, because it is two things in one repository. | Half | Licence | File | |------|---------|------| | The stack — `tools/`, `types/` | GNU AGPL-3.0-or-later | [LICENSE](LICENSE) | | The content — `kb/`, `raw/`, `instructions/`, the `CONTRACT.md` layer, and the prose documents at the root | CC-BY-4.0 | [LICENSE-CONTENT](LICENSE-CONTENT) | The boundary between the two is not a list someone maintains by hand: it is the file plan `tools/wikitool dist export` already computes, so it cannot drift out of agreement with what actually ships. [NOTICE](NOTICE) states that, and carries the attribution for the vendored [Commonplace](https://github.com/zby/commonplace) research base. **What this means for your own wiki.** The pages you write in your own instance are yours; the AGPL covers the compiler, not the knowledge it compiles. What the copyleft asks is that changes *to the machinery* stay available — including when you run it as a service rather than shipping it, which is why the licence is the Affero variant. If you set up an instance and later publish it, keep `LICENSE`, `LICENSE-CONTENT` and `NOTICE` in the tree. `dist export` puts them there and refuses to build a distribution without them, so under normal use this takes no effort.