About falzmarke
falzmarke turns Markdown content into DIN 5008 business letters as PDF/A and measures the finished PDF against layout requirements. It is for producing repeatable, verifiable business correspondence through a CLI, Claude skill, or MCP-compatible client.
Key features
- 01Markdown-to-PDF/A business letters
- 02DIN 5008 layout rendering
- 03Measurement of finished PDF geometry
- 04Machine-readable reports and exit codes
- 05Sender profiles for reusable branding
- 06CLI, Claude skill, and MCP access
Use cases
- 01Generate a business letter from Markdown
- 02Check fold and address-field positions before printing
- 03Run letter rendering and verification in CI
- 04Create letters through an MCP-compatible client
MCP support
Provides an MCP server over stdio for clients to render and verify letters. It is available through the `falzmarke mcp` command.
Configuration
Local server config is the same for every client. Copy it into your client’s MCP config file.
Tools
Local servers expose tools only once running on your machine, and the maintainer has not provided a tool list.
Details
From the project READMEAndere Werkzeuge erzeugen ein PDF. falzmarke prüft das Ergebnis.
Du schreibst den Inhalt als Markdown. falzmarke setzt daraus einen Geschäftsbrief nach DIN 5008:2020 als PDF/A — und misst anschließend das fertige PDF nach. Sitzt die Falzmarke nicht auf 105,0 mm, endet der Lauf mit einem Fehler statt mit einem Brief, der nur ungefähr stimmt.
falzmarke.com — Anleitung ohne Terminal · ⬇ Als Claude-Skill laden · In 60 Sekunden ausprobieren · Beispielbrief ansehen
Linux · macOS · Windows · 35 Maße je Seite · PDF/A-2b · MIT
In Bewegung

Aufgezeichnet aus der echten CLI mit vhs;
das Drehbuch steht in docs/marke/video/readme.tape.
Ein Test hält den Mitschnitt gegen einen frischen Lauf, damit hier kein Terminal
steht, das es so nie gab (tests/test_tape.py).
Was dabei herauskommt

Und was danach geprüft wird — Auszug aus dem Bericht, den jeder Lauf ausgibt:
OK Falzmarke 1, y: soll 105.00 ist 105.00 (tol ±0.3)
OK Infoblock, x-links: soll 125.00 ist 125.00 (tol ±0.5)
OK Betreff, y-Oberkante: soll 98.47 ist 97.91 (tol -1.75/+0.6)
OK Abstand Betreff → Anrede (2 Leerzeilen): soll 12.70 ist 12.70 (tol ±0.2)
Das sind vier von 34 Zeilen des Geometrieberichts. Der Film zeigt, wie die übrigen entstehen: Eine Linie fährt das Blatt ab und hält an jedem gemessenen Höhenmaß. Sie hält dort, wo die Messung es sagt — bei diesen Prüfungen ist der gemessene Wert zugleich die Stelle.

Acht der 34 Geometrieprüfungen tragen eine Höhe auf dem Blatt; die übrigen messen Breiten,
Abstände und Eigenschaften ohne Ort auf der Seite. Die Zahl 35 weiter oben zählt eine
mehr: Nach einem render sieht die CLI zusätzlich die PDF/A-Konformität nach, und die
liegt auf keinem Millimeter. Beide Zahlen stimmen, sie zählen Verschiedenes.
Keine Zahl im Film ist abgetippt — sie kommen alle aus verify --json, und
tests/test_messfilm.py hält den Film gegen einen frischen Messlauf. Verschiebt jemand
die Falzmarke um 2 mm, muss der betroffene Halt rot werden; tut er es nicht, schlägt der
Test fehl.
Die erste Zeile des Berichts oben spricht von einem Strich, den man auf einem Vorschaubild kaum sieht — er ist 0,25 pt stark. Vergrößert sieht die Stelle so aus:

Dort wird der Bogen gefaltet, damit die Anschrift im Fensterumschlag steht. Sitzt die Marke falsch, faltet der Stapel falsch — und das fällt erst nach dem Druck auf.
Das Problem
Eine Briefvorlage kann nicht prüfen, ob das Ergebnis stimmt. Sie wird kopiert, jemand verschiebt eine Zeile, und der Fehler fällt erst am fertigen Stapel auf: Die Anschrift steht nicht mehr im Fensterausschnitt, alles muss neu gedruckt und kuvertiert werden — und wer mit Automationsrabatt einliefert, verliert ihn für diese Sendung.
Sprachmodelle verschärfen das. Sie formulieren gut, aber sie können keinen Text auf 45,0 mm setzen. Wer einen Brief von einer KI schreiben lässt, bekommt zuverlässig guten Inhalt in unzuverlässigem Layout.
Und ein Renderer kann ebenfalls Fehler haben — auch dieser hier.
Deshalb trennt falzmarke drei Dinge: Inhalt kommt als Markdown, lesbar und versionierbar. Das Layout setzt ein Renderer, der es immer gleich macht. Und die Prüfung misst das fertige PDF, statt dem Renderer zu glauben.
Warum nicht einfach Word oder ein Prompt?
Verglichen wird der typische Arbeitsablauf, nicht das Werkzeug an sich — mit einer sorgfältig gepflegten Vorlage lässt sich vieles davon erreichen.
| Vorlage in Word / LibreOffice | Brief direkt von einer KI | falzmarke | |
|---|---|---|---|
| Quelle diffbar und versionierbar | teilweise | selten | ja — Markdown und YAML |
| Layout reproduzierbar | hängt an Vorlage und Umgebung | nicht zugesichert | ja — derselbe Renderer, dieselbe Ausgabe |
| Fertiges PDF wird nachgemessen | nein | nein | ja — 35 Maße, jede Seite, Abweichung ist ein Fehler |
| Absenderprofile | von Hand gepflegt | uneinheitlich | ja — einmal anlegen, überall nutzen |
| Prüfbericht maschinenlesbar | nein | nein | ja — --json und Exit-Codes |
| PDF/A als Voreinstellung | nicht automatisch | nicht zugesichert | ja — ohne zusätzliches Flag |
Was du davon hast
- Der Brief sitzt im Fensterumschlag — Anschriftfeld, Falz- und Lochmarken werden am fertigen PDF vermessen, nicht beim Setzen angenommen.
- Änderungen bleiben nachvollziehbar — Markdown und YAML sind Textdateien. Ein Diff zeigt, was sich geändert hat; das PDF ist Ergebnis, nicht Quelle.
- Ein Auftritt, viele Briefe — Profile bündeln Briefkopf, Fußzeile, Logo, Farben und Voreinstellungen. Auch die Unterschrift, je Brief überschreibbar.
- Fehler sind maschinenlesbar — eigene Exit-Codes für Eingabe-, Geometrie- und
Umgebungsfehler, dazu
--json. Damit läuft es in CI und in Automatisierungen. - Für Langzeitarchivierung ausgelegt — im Normalfall entsteht ein PDF/A-2b ohne
zusätzliches Flag, wird eine Datei eingebettet — jede Rechnung tut das —, entsteht stattdessen
ein PDF/A-3b
(ADR 0033).
Dass die Datei die behauptete Stufe wirklich einhält, sagt nicht dieses Werkzeug, sondern
veraPDF — die Referenzimplementierung der PDF Association, in CI bei
jedem Push. Optional PDF/UA-1 mit
--pdfua, ebenfalls dort geprüft. - Im Gespräch oder im Terminal — als Claude-Skill oder als CLI, ohne Systeminstallation.
Woran man sieht, dass es stimmt
Das ist der Teil, an dem sich das Versprechen entscheidet — deshalb steht er vor der Installation.
-
Gemessen wird das fertige PDF, nicht die Eingabe.
verifyliest das erzeugte Dokument mit pdfplumber und vergleicht Zonen, Marken und Abstände gegen die Sollwerte. -
Jede tragende Prüfung hat eine Gegenprobe. Sie läuft gegen ein absichtlich verschobenes Layout und muss dort anschlagen — ein Prüfmittel, das nie rot werden kann, wäre kein Nachweis. Das gilt auch für das Bild oben: Es entsteht zweimal, einmal aus dem ausgelieferten Layout und einmal aus einem, in dem die Marke 2 mm zu tief sitzt.

Unterscheiden sich die beiden Ausschnitte nicht, zeigt der Ausschnitt die Marke gar nicht — dann ist das Bild oben wertlos, und
tests/test_detailbild.pyschlägt fehl. -
CI auf Linux, macOS und Windows, bei jedem Push.
-
Ein Frischinstallations-Test führt die Befehle aus dieser README wirklich aus. Hier steht kein Befehl, den niemand ausprobiert hat.
-
Alle Beispielbriefe werden in CI gerendert und vermessen.
-
Die PDF-Konformität bestätigt ein fremdes Werkzeug. Alles andere auf dieser Liste misst mit demselben Code, der das PDF erzeugt hat — das belegt Selbsttreue, nicht Konformität. veraPDF hat den Brief nicht geschrieben und teilt keine Zeile mit dem Renderer. Geprüft wird, was die Datei selbst deklariert, auf der ausgelieferten Datei, mit Prüfsummen-Abgleich — und mit einer Gegenprobe, die ein absichtlich nicht-konformes PDF durchfallen lässt (
scripts/pdf_konformitaet.py). -
Die Layoutbasis ist vendort und prüfsummengesichert —
vendor/README.md.
Zwei Aussagen, die gern verwechselt werden, hält das Projekt auseinander:
Der Sollwert ist fachlich belegt und der Verifier erkennt eine Abweichung davon sind verschiedene Dinge. Das Zweite ist bewiesen. Das Erste hat Grenzen.
Woher die Sollwerte stammen: Maße und Schreibregeln folgen öffentlich dokumentierten Quellen
(Liste in skill/references/din5008.md); der Abgleich mit dem
Originaltext der DIN 5008:2020-03 einschließlich Berichtigung 1:2020-07 steht aus. Regeln aus
einzelnen Quellen wirken nur als Warnung. Welche Regel worauf beruht, steht in der
Quellenlage je Regel; was daraus rechtlich
folgt, in docs/recht.md.
python3 -m pytest -q
Sicherheit
Genannt wird nur, was im Code steht und geprüft ist. falzmarke ist nicht unabhängig auditiert — Sicherheitsrelevantes bitte nach SECURITY.md, nicht als Issue.
- Verarbeitung bleibt lokal. Der Renderpfad importiert keine Netzwerkbibliothek.
- YAML wird ausschließlich mit
safe_loadgelesen — an jeder Stelle, auch beim eingebetteten Profil. - Markdown läuft gegen eine Positivliste von Knotentypen. Was nicht daraufsteht, ist ein Fehler mit Zeilenangabe — nie ein stilles Durchreichen.
- Brieftext wird nie zu Typst-Code. Der Emitter übergibt ihn als maskierte Zeichenkette; Sonderzeichen können die Struktur nicht verlassen.
- Profil- und Briefdateien bleiben in ihrem Ordner. Logo, Unterschrift und eigener Briefkopf dürfen nicht darüber hinauszeigen, Symlinks werden aufgelöst (Gegenproben).
- Typst läuft auf ein eigenes Wurzelverzeichnis begrenzt, Systemschriften sind abgeschaltet.
- Alle Abhängigkeiten des Programms sind permissiv lizenziert — THIRD_PARTY_LICENSES.md.
- Die CI-Aktionen hängen an vollständigen Commit-SHAs, nicht an verschiebbaren Tags.
Das Release-Asset lässt sich auf seine Herkunft prüfen:
gh attestation verify falzmarke.skill --repo blitzsicht/falzmarke
Das belegt, aus welchem Lauf und welchem Commit die Datei stammt — nicht, dass sie fehlerfrei
ist. Die SHA-256-Summe steht in der Release-Notiz und als falzmarke.skill.sha256 daneben.
In 60 Sekunden
Vier Wege, und sie können nicht dasselbe:
| Weg | rendert ohne Netz | Größe | wofür |
|---|---|---|---|
falzmarke.skill hochladen | nein, der erste Lauf lädt nach | ~0,8 MB | claude.ai — der Upload-Dialog nimmt höchstens 30 MB |
falzmarke-offline.skill | ja — der Typst-Compiler reist mit | ~34 MB | Sandboxen ohne PyPI-Zugriff; zu groß für den Upload-Dialog |
pipx / uvx | nein, der erste Lauf lädt nach | ~1 MB | Terminal |
| Repository klonen | nein, der erste Lauf lädt nach | ~1 MB | Mitarbeit am Werkzeug |
Die beiden Skill-Pakete unterscheiden sich in genau einer Datei: Das Offline-Paket trägt das
typst-Wheel in vendor/, das schlanke nicht. Warum es zwei sind und nicht eines, steht in
skill/vendor/README.md.
Mit Claude
falzmarke.skillherunterladen- In Claude unter Einstellungen › Capabilities hochladen (Tarif mit Code-Ausführung nötig).
Für Claude Code genügt ein Symlink:
ln -s "$PWD/skill" ~/.claude/skills/falzmarke - „Schreib einen Brief an die Muster GmbH, Angebot über …"
Im Terminal
uvx falzmarke init brief.md --profil example --betreff "Angebot Nr. 2026-0815"
oder dauerhaft installiert, danach genügt falzmarke render brief.md --png:
pipx install falzmarke
Das Paket liegt auf PyPI. Wer den unveröffentlichten
Stand von main will, nimmt weiterhin die Adresse:
pipx install git+https://github.com/blitzsicht/falzmarke
Der Typst-Compiler kommt als Python-Wheel mit: keine Systeminstallation, kein LaTeX, kein wkhtmltopdf, keine Schriftinstallation.
In einem Repository voller Briefe
Wer seine Briefe versioniert, lässt sie bei jedem Push setzen und nachmessen:
- uses: blitzsicht/falzmarke@main
with:
briefe: "briefe/*.md"
profile: "profile"
Die PDFs hängen danach als Artefakt am Lauf. Hält ein Brief die Maße nicht ein, wird der Lauf
rot und nennt Datei und Maß — ein Serienbrief-Archiv merkt einen verrutschten Betreff damit
beim Push und nicht beim Empfänger. Die Eingaben stehen in
action.yml; die Aktion
installiert falzmarke von PyPI und baut keine zweite Installationsstrecke auf. Wer den Lauf
nachfahrbar halten will, nennt eine feste Fassung: paket: "falzmarke==0.7.3".
In einem anderen KI-Client
falzmarke spricht MCP — damit setzen auch Clients Briefe, die keinen Claude-Skill kennen.
pip install 'mcp>=2,<3' # das SDK ist nicht in der Grundausstattung
falzmarke mcp # Server über stdio
Der Server steht im offiziellen MCP-Registry
unter io.github.blitzsicht/falzmarke. Die Zeile im Kommentar darüber ist kein Schmuck: Das
Registry prüft damit, dass dieses PyPI-Paket zu diesem Servernamen gehört — es liest die
Projektbeschreibung auf PyPI, und die ist diese Datei.
Vier Werkzeuge: brief_rendern, email_setzen, brief_pruefen, profile_auflisten.
Der Messbericht kommt bei jedem Rendern mit — ein Dienst, der ein PDF zurückgibt und
offenlässt, ob die Maße stimmen, wäre ein PDF-Generator wie jeder andere.
Im Container — so bauen ihn auch die MCP-Verzeichnisse, das
Dockerfile liegt im
Wurzelverzeichnis:
git clone https://github.com/blitzsicht/falzmarke.git && cd falzmarke
docker build -t falzmarke-mcp .
docker run --rm -i falzmarke-mcp # `-i` ist nötig: der Server liest von stdin
Das Absenderprofil darf als Objekt im Aufruf stehen. Ein Client ohne Zugriff auf das Dateisystem des Servers kann so seinen eigenen Absender mitgeben, statt mit den Profilen zu leben, die dort zufällig liegen.
Was der Dienst nicht tut: versenden, ablegen, zustellen. Er setzt und prüft (ADR 0029).
Aus einem Clone, ohne Installation
git clone https://github.com/blitzsicht/falzmarke.git
cd falzmarke
python3 skill/scripts/bootstrap.py
python3 skill/scripts/falzmarke.py render examples/brief-form-b.md --png
Einen Brief schreiben
---
profil: example
empfaenger:
- Muster GmbH
- Frau Erika Muster
- Musterstraße 1
- 12345 Musterstadt
datum: 2026-08-25
betreff: Angebot Nr. 2026-0815 über die Neugestaltung Ihrer Website
anrede: Sehr geehrte Frau Muster,
anlagen:
- Angebot 2026-0815
---
vielen Dank für Ihre Anfrage vom 20. August 2026. Anbei erhalten Sie unser Angebot.
Die Umsetzung dauert ab Ihrer Freigabe **sieben Werktage**.
python3 skill/scripts/falzmarke.py render brief.md --png
Alle Felder stehen im Datenvertrag. Ein Feld, das dort nicht steht, bricht mit Zeilennummer und Vorschlag ab — es wird nie stillschweigend verworfen.
Was im Brieftext erlaubt ist
Der Text unter dem Frontmatter ist falzmarke-Markdown, eine dokumentierte Teilmenge von CommonMark:
| Das geht | Das erledigt falzmarke selbst |
|---|---|
Absätze, **fett**, *kursiv* | § 5 mit geschütztem Leerzeichen |
| Aufzählungen und nummerierte Listen | -- wird zum Halbgeviertstrich – so |
Harter Umbruch mit \ am Zeilenende | "Wort" wird zu „Wort“ |
| Pipe-Tabellen mit Ausrichtung |
Abkürzungen (z. B.), Datum (25. August), Einheiten (10 %, 5 kg) und Kürzel vor einer
Angabe (Tel., Nr.) setzt falzmarke nicht von selbst: Keine dieser Regeln steht auf
mehr als einer Quelle, die etwas dazu sagt — bei Abkürzungen und Datum trägt nur Wikipedia,
die zweite volle Quelle schweigt (#31). Deshalb warnt lint, statt zu ersetzen. Es meldet die
Stelle mit Zeile — dann setzt du das Leerzeichen selbst, mit (5 km). Welche
Regeln mehrfach belegt sind, steht in der
Tabelle Quellenlage je Regel.
Links, Bilder und HTML sind Fehler — mit Zeile, Grund und Korrektur, nie stillschweigend. Auf Papier gibt es keinen Link, und ein Bild im Fließtext verschöbe die Geometrie, die danach gemessen wird.
Zwischenüberschriften (# bis ####), tiefere Aufzählungen, Blockzitate und
wortgetreue Auszüge gibt es für lange Schreiben: dialekt: "1.1" im Frontmatter schaltet
sie frei. Ein Auszug bleibt Zeichen für Zeichen stehen — keine typografischen Ersetzungen,
kein Umbruch, keine Einfärbung, und nichts darin wird ausgeführt. Ohne das Feld gilt Fassung 1.0, und ein
bestehender Brief rendert unverändert.
Die vollständige Liste: falzmarke-Markdown.
Dieselbe Datei als E-Mail
Ein Schreiben mit typ: email im Frontmatter wird keine PDF-Seite, sondern eine .eml —
dieselbe Quelle, dasselbe Profil, dieselbe Signatur.
falzmarke email nachricht.md --html
OK geschrieben: nachricht.eml
OK geschrieben: nachricht.html
OK verify: 22/22 Prüfungen bestanden
Die .eml öffnet das Mailprogramm, die .html der Browser. Mit --oeffnen legt falzmarke auf
macOS gleich einen Entwurf an — in Thunderbird, mit Absender, Empfängern, Betreff, Rumpf und
Anhängen, mit Senden-Knopf, und erst nach bestandener Prüfung; Outlook für Mac nur mit
--programm outlook. Wo dieser Weg nicht gemessen ist (Windows, Linux, Apple Mail), wird die
Datei übergeben; sie erscheint dort als Lesefenster, nicht als Entwurf, und das ist eine
Eigenschaft des Formats. Geprüft wird die fertige Datei:
MIME-Aufbau, format=flowed, Space-Stuffing, die Signaturtrennzeile, und ob im HTML nichts
steht, was dort nicht hingehört — kein Skript, kein externes Stylesheet, kein Zählpixel, keine
Tabelle als Layout. falzmarke verify --email misst auch Dateien, die von woanders kommen.
falzmarke versendet nichts. Es gibt keinen Versandbefehl und keine Option, die sendet: Wer eine Datei erzeugt, haftet für ihren Inhalt; wer sie befördert, für Zustellung und Nachweis. Das sind zwei Versprechen, und falzmarke gibt nur das erste (ADR 0034). Der Entwurf ist davon nicht berührt und geht keinen Schritt weiter: Entwurf ja, Senden nie — im Steuerskript steht kein Versandbefehl, und ein Test misst das am ganzen Paket (ADR 0038).
Wie die Datei aufgebaut ist, was bewusst fehlt und wo die Grenzen liegen:
Die E-Mail-Fassung. Vier
Beispiele liegen unter
examples/email/.
Rechnungen: ZUGFeRD und XRechnung
Ein Schreiben mit typ: rechnung wird wie ein Brief gesetzt und trägt zugleich einen Datensatz,
den keine Person liest: An Firmen geht die Rechnung als PDF mit eingebetteter ZUGFeRD-XML, an
Behörden geht dieselbe Rechnung als reine XRechnung-XML, ohne PDF.
falzmarke render rechnung.md # PDF/A-3b mit eingebetteter ZUGFeRD-XML
falzmarke xml xrechnung.md -o rechnung.xml # nur die XML, für eine Behörde
Abgenommen wird das Ergebnis nicht von falzmarke selbst, sondern von zwei fremden Werkzeugen in der CI: Mustang 2.26.0 prüft PDF und eingebettete XML gegen die Schematron-Regeln der jeweiligen Fassung, der KoSIT-Validator 1.6.3 prüft eine XRechnung ein zweites Mal mit der amtlichen Konfiguration.
falzmarke rechnet nicht. Es überträgt Positionen, Steuersätze und Summen aus der Quelle, ohne sie zu bilden — es vergibt keine Rechnungsnummern, bucht nicht, mahnt nicht und versendet nichts. Was das im Einzelnen heißt und was ausdrücklich nicht behauptet wird: Rechnungen mit falzmarke.
Urkunden: ein Schriftstück ohne Anschriftfeld
Eine Vereinbarung, eine Erklärung, ein Nachweis: Ein Schreiben mit typ: urkunde trägt einen
Titel statt eines Betreffs, kein Anschriftfeld und Linien zum Unterschreiben von Hand.
Briefkopf, Fußzeile, Schrift und Raster kommen aus demselben Profil wie beim Brief.
falzmarke render vereinbarung.md # setzt und misst nach — auch die Unterschriftslinien
Im Text gibt es dafür zwei Elemente mehr (dialekt: "1.2"): das Ausfüllfeld, eine Kette aus
Unterstrichen, die zu einer Linie fester Länge wird, und die Angabentabelle ohne Kopfzeile. Mit
seiten_max: 1 wird der Lauf rot, wenn das Schriftstück nicht auf eine Seite passt.
Die Maße einer Urkunde sind Setzungen des Werkzeugs, keine der DIN 5008 — die Norm sagt zu
einem Blatt ohne Anschriftfeld nichts, und die Zahl der Maße, die oben für den Brief steht, gilt
hier nicht. Über Form oder Wirksamkeit eines Schriftstücks sagt falzmarke nichts; es kennt auch
keine Klauseln. Was das im Einzelnen heißt:
Urkunden mit falzmarke.
Zwei Beispiele liegen unter
examples/urkunde/.
Beispiele
| Standardbrief | Einschreiben | Mehrseitig |
|---|---|---|
![]() | ![]() | ![]() |
| Form B mit Informationsblock | Zusatz- und Vermerkzone | Kopfzeile und Seitenzählung |
Dazu Form A, Auslandsanschrift, Tabelle, ein Brief mit langem Informationsblock und einer
mit englischer Beschriftung (sprache: en — deutsche Maße, englische Wörter) —
alle Beispiele und ihre vollständigen Renderings.
Grenzen
- falzmarke-Markdown (CommonMark-Teilmenge): Absätze, fett, kursiv, Aufzählungen, nummerierte Listen, harter Umbruch, Pipe-Tabellen. Alles andere bricht mit Zeilenangabe ab, statt still etwas anderes zu setzen.
- Zonengrößen der Norm: Anschrift höchstens 6 Zeilen, Vermerke höchstens 3, Werte im Informationsblock höchstens 21 Zeichen.
- Keine Bilder im Fließtext — ein Logo gehört ins Profil.
- Nur DIN 5008. Schweiz (SN 010130) und Österreich (ÖNORM A 1080) sind vorgemerkt
(#10); das Frontmatter-Feld
norm:ist dafür reserviert. - Keine Signatur. Das Unterschriftsbild ist Erscheinungsbild, kein Nachweis. Eine kryptografische Signatur ist Gegenstand von #14.
Weiterlesen
| Befehle | alle Unterbefehle, Exit-Codes, was geprüft wird |
| Absenderprofile | Profil anlegen, Suchreihenfolge, eigener Briefkopf |
| Die E-Mail-Fassung | Aufbau der .eml, ihre Teile und Grenzen |
| Rechnungen mit falzmarke | ZUGFeRD, XRechnung, was geprüft wird und was nicht |
| Datenvertrag | jedes Frontmatter-Feld mit Beispiel |
| falzmarke-Markdown | was im Brieftext möglich ist |
| Normmaße und Quellenlage | Sollwerte und ihre Herkunft |
| Was falzmarke behauptet — und was nicht | Grenzen der Normaussage |
| Aufbau des Repositorys | Schichten, Vendoring, warum das Paket unter skill/ liegt |
| Roadmap | in welcher Reihenfolge gearbeitet wird, und was noch offen ist |
| Changelog · Releases | was sich geändert hat |
Mitmachen
Fehlerberichte und Vorschläge sind willkommen — siehe CONTRIBUTING.md.
Bei einem Geometriefehler bitte die Ausgabe von verify mitschicken; ohne sie lässt sich nicht
unterscheiden, ob das Layout oder die Messung danebenliegt.
Sicherheitsrelevantes bitte nicht als Issue, sondern nach SECURITY.md.
Herkunft und Dank
Markdown wurde 2004 von John Gruber gemeinsam
mit Aaron Swartz entworfen. Die Spezifikation dazu ist CommonMark
(John MacFarlane und Mitwirkende). falzmarke setzt eine dokumentierte Teilmenge davon um
— falzmarke-Markdown — und weicht an drei Stellen bewusst
ab: HTML wird nie durchgereicht, Links werden nie gesetzt, und eine einzelne 2. Text-Zeile
ohne weitere Listenpunkte wird gemeldet — gesetzt mit erhaltenem Startwert, damit nichts still
umnummeriert wird.
Das Seitenlayout stammt von typst-letter-pro
(MIT) von Sematre und ist unverändert vendort — Prüfsumme in
vendor/README.md. falzmarke ergänzt die Schicht
darüber: Datenvertrag, Profile, Markdown-Eingabe, Messung und den Skill.
Gesetzt wird mit Typst (Apache-2.0), geparst mit markdown-it-py (MIT), gemessen mit pdfplumber (MIT) und pypdf (BSD-3). Schriften: Libertinus und Source Sans 3 (beide OFL 1.1). Die vollständige Aufstellung samt der Begründung, warum PyMuPDF (AGPL-3.0) ersetzt wurde, steht in THIRD_PARTY_LICENSES.md.
Alle Abhängigkeiten des Programms sind permissiv lizenziert — falzmarke lässt sich damit auch in geschlossene Systeme einbauen. Nicht permissiv ist allein Remotion, womit der Erklärfilm gerendert wird: am Programm ist es nicht beteiligt und wird nicht mitgeliefert.
DIN 5008 ist eine Norm des DIN Deutsches Institut für Normung e. V. falzmarke ist kein
Produkt des DIN, steht in keiner Verbindung zum DIN und behauptet keine Zertifizierung. Wie die
Maße gemessen wurden, steht in docs/normmasse.md.
Was sich zuletzt getan hat
Die letzten zwei Versionen im Wortlaut. Erzeugt aus CHANGELOG.md — dort ändern, dann python3 scripts/changelog.py.
v0.10.0 — 25.10.2026
Neu
-
Der Schreibstil des Absenders steht im Profil. Der neue Abschnitt
email.stil:nimmtperson:(ichoderwir), eigenefloskeln:und freiehinweise:auf.lintwarnt, wenn der Text die andere Person benutzt oder eine Wendung aus der eigenen Liste enthält — außerhalb wortgetreuer Auszüge.hinweise:prüft es nur auf Form: Den Inhalt liest das Modell, das formuliert (SKILL.mdSchritt 4). falzmarke überträgt die Vorgabe, es erzwingt sie nicht (ADR 0053). -
Der Entwurf entsteht in Thunderbird.
falzmarke email … --oeffnenlegt den Entwurf jetzt in Thunderbird an, wenn es installiert ist — über dessen Befehlszeile, mit dem Absender aus dem Profil, Empfängern, Kopie, Blindkopie, Betreff, HTML-Rumpf und allen Anhängen. Outlook kommt nur noch auf Wahl (--programm outlook): Es ist oft installiert, aber ohne Lizenz, und das neue Outlook zeigt der Programmsteuerung kein Konto. Thunderbird meldet nichts zurück — Exit 0 heißt „angenommen“, und der Befehl sagt dazu, dass nichts nachgezählt ist. Ein einfaches Anführungszeichen in Betreff, Rumpf oder Dateinamen wird zum Apostroph ’; ein Komma im Dateinamen eines Anhangs ist ein Fehler mit Rückfall auf die Datei. Das Logo der Signatur fährt als Data-URI im Rumpf mit, und ein Befehl über 900 000 Byte wird nicht abgesetzt, sondern mit seiner Länge gemeldet (ADR 0049). -
--oeffnensieht vorher im Gesendet-Ordner nach, und der Entwurf liegt im Postfach. Ging in den letzten 24 Stunden eine Mail an denselben Empfänger mit demselben Text, derselben Fassung oder demselben Betreff hinaus, legtfalzmarke email … --oeffnenkeinen Entwurf an. Es meldetSCHON GESENDEToderGEÄNDERTE FASSUNGund endet mit Exit 4;--trotz-gesendetübergeht das. Ist der lokale IMAP-Proxy erreichbar, liegt der Thunderbird-Entwurf jetzt als fertige Nachricht im Ordner „Entwürfe“ des Absenders, mit allen Kopfzeilen und damit auch mitIn-Reply-To. Ein Fenster geht dann nicht auf. Liegt dort schon ein Entwurf mit demselben Empfänger und Betreff, kommt kein zweiter dazu (--noch-ein-entwurf). Im Postfach wird nur dieser eine Entwurf abgelegt, nie etwas gesendet, gelöscht oder verschoben. Jede.emlträgt außerdemX-Falzmarke-Fassung, eine Prüfsumme der Quelle ohne Pfad oder Dateinamen. Thunderbird verwirft diese Zeile beim Senden, im Gesendet-Ordner zählen deshalb Betreff und Text. Exit 4 stand bisher für „Fehler im Renderer“, wurde aber nie zurückgegeben (ADR 0051). -
Fünf Nachrichtenlagen und eine Liste, was gestrichen wird. Die Stilreferenz deckte bisher Brieftypen ab — Angebot, Mahnung, Kündigung, Widerspruch und drei weitere. Jetzt stehen daneben die Lagen, in denen die meisten Mails entstehen: ein Angebot nachfassen, eine Reklamation beantworten, Preis und Nachlass, Lieferant, intern. Dazu ein Abschnitt „Was gestrichen wird" mit neun Mustern, die nach Maschine klingen, und neben jedem der Fall, der ihm ähnlich sieht und bleibt — dieselbe Grenze wie bei den Floskeln: Trägt der Satz etwas oder nicht. Ausdrücklich nicht übernommen sind drei Regeln englischer Humanizer-Anleitungen, die für deutsche Geschäftspost falsch sind (keine Gedankenstriche, gerade Anführungszeichen, keine Dreierfiguren): Den Halbgeviertstrich und die Anführungszeichen „…" setzt der Typografie-Pass absichtlich, und ein Test hält die Begründung gegen ihn.
-
Unsichtbare Zeichen im Entwurf werden gemeldet. Zero-Width-Marken, weiche Trennstriche, Bidi-Steuerzeichen und Variantenselektoren aus einer Zwischenablage standen bisher ungeprüft in der fertigen
.emlund im PDF.lintnennt jetzt Zeile und Stelle; geändert wird nichts. Geschützte Leerzeichen an den Stellen, an denen falzmarke selbst eines setzt —z. B.,§ 7,12 kg—, bleiben stumm (ADR 0052).Achtung beim Update:
lintkann jetzt rot werden, wo es vorher grün war. Ein Zeichen ohne Zweck ist ein Fehler, nicht eine Warnung, undlintendet dann mit Exit 1. Gemessen an derselben Datei mit einem U+200B in einer Rechnungsnummer: unter v0.9.150 Fehler, Exit 0 — jetzt1 Fehler, Exit 1. Die Datei war vorher schon defekt; das Zeichen stand unsichtbar in der.emlund im PDF. Werlintin einem Skript oder einer CI fährt, sieht das aber erst, nachdem der Lauf steht. Deshalb hebt diese Fassung die zweite Stelle der Versionsnummer an.
Geändert
- Acht Wendungen mehr, die nichts sagen.
email.floskelkannte sieben Muster, jetzt sind es fünfzehn: „es ist wichtig zu beachten", „zusammenfassend lässt sich sagen", „in der heutigen schnelllebigen Zeit", „jederzeit gerne zur Verfügung", „an dieser Stelle möchte ich", „wie Sie sicher wissen", „im Voraus vielen Dank" und „wir würden uns freuen". Die Aufnahmebedingung ist unverändert eng: Die Zeile muss sich streichen lassen, ohne dass die Nachricht etwas verliert. Deshalb bleibt „bei Rückfragen stehe ich zur Verfügung" draußen und nur die Fassung mit „jederzeit" drin — der Verstärker ist das Leere, nicht die Erreichbarkeit. Zwei Kandidaten sind ausdrücklich abgelehnt und im Quelltext begründet: „im Rahmen von" und „nicht nur …, sondern auch" tragen manchmal Inhalt, und ein Muster, das das nicht unterscheiden kann, kostet Vertrauen in alle anderen. Es bleibt eine Warnung auf der Ebene Praxis, und geändert wird nichts.
Behoben
-
Die Mail erbt ihre Farben vom Mailprogramm. Im Thunderbird-Entwurf bei dunklem Thema stand der ganze Rumpf fast schwarz auf Dunkelgrau: Jeder Block trug
#1a1a1a, und der<style>-Block, der im dunklen Schema umschaltet, kommt dort nicht an. Jetzt setzt der Rumpf weder Schriftfarbe noch Grund und erscheint in den Farben des Programms, hell auf dunkel oder dunkel auf hell. Nebentext ist nur noch kleiner, nicht grauer. Linien sind ein mittleres Grau, das auf Weiß und auf Dunkel trägt. Eine mitgebrachte Signatur bleibt unverändert. Der Textteil bleibt unverändert. -
Mail-Adressen, Domains und URLs werden im Brief nicht mehr getrennt. In versendeten Briefen stand „ser-“ am Zeilenende und „[email protected]“ darunter, ebenso „blitzsicht.com/da-“ und „tenschutz“; wer das abtippt, schreibt ins Leere. Ein Wort mit Adresse wird jetzt als Ganzes in die nächste Zeile gesetzt, samt anhängendem Komma oder Punkt. Der übrige Text wird weiter getrennt. Das gilt bis 60 Zeichen, im Blocksatz einer Urkunde bis 40; in einer Tabellenzelle bekommt die Adresse nur keinen Trennstrich, weil ein unteilbares Wort dort den Text dahinter verschob.
verifymeldet zusätzlich jede Adresse, die im fertigen PDF trotzdem über das Zeilenende läuft, etwa im Betreff, in einer Zelle oder als URL über der Grenze, und paart dabei nur Zeilen derselben Spalte. -
falzmarke serieliest Semikolon-CSV. Die Excel-Datei mit;als Trenner endete mit einemTypeError, weil die ganze Kopfzeile eine einzige Spalte war. Der Trenner,oder;wird jetzt an der Kopfzeile erkannt. Hat eine Datenzeile trotzdem mehr Felder als die Kopfzeile, meldetseriedas mit dem gelesenen Trennzeichen, statt abzustürzen. -
Thunderbird fragt nicht mehr wegen der Signatur nach einem vergessenen Anhang. Beim Senden eines falzmarke-Entwurfs kam jedes Mal „Haben Sie vergessen, einen Anhang anzufügen?“. Grund war das Wort „Anhänge“ im Hinweis der Signatur. Die HTML-Signatur steht jetzt in einem Element mit der Klasse
moz-signature, und diesen Teil lässt Thunderbirds Anhang-Erinnerung aus. Steht „anbei“ oder „Anhang“ im Text der Nachricht selbst, fragt Thunderbird weiter, und das ist gewollt. Der Textteil trug den Signaturtrenner--schon (ADR 0051). -
Die mitgebrachte Signatur erbt ihre Farben wie der Rumpf. Mit
email.signatur_htmlstanden Name, E-Mail-Link, Firma und Labels im dunklen Thunderbird-Entwurf dunkel auf dunkel, denn die Dunkelregeln der Signatur stecken in ihrem eigenen<style>, und das bekommt der Entwurf nicht. Beim Einsetzen fallen jetzt Schriftfarben und Flächen weg, Linien, die auf hellem oder dunklem Grund nicht tragen, werden mittelgrau. Ein Knopf mit eigener Fläche wird zum Link. Aufbau, Text, Links und Logo bleiben, und die Datei im Profilordner wird nicht verändert. -
Die Signatur steht im Thunderbird-Entwurf nur noch einmal. Trägt die Identität mit der Absenderadresse in Thunderbird selbst eine Signatur (angehängte Datei oder Signaturtext), lässt
falzmarke email … --oeffnendie aus dem Profil im Entwurf weg und nennt in einer Zeile Identität und Datei. Nachgesehen wird inprefs.jsunduser.jsdes Standardprofils, nur lesend;user.jsgewinnt. Lässt sich die Identität nicht bestimmen, bleibt alles wie bisher, mit Hinweis und Grund..emlund.htmltragen die Signatur weiter (ADR 0050).
v0.9.15 — 07.10.2026
Behoben
- „Rechnung“ löst keine Kürzel-Warnung mehr aus.
linthat bisher hinter jedem „Rechnung“ ein geschütztes Leerzeichen verlangt, also auch bei „unsere Rechnung für …“ oder „Rechnung Apple“, als wäre das Wort ein Kürzel wieNr.. In den mitgelieferten Beispielen waren neun von elf solchen Warnungen Fehlalarme. Jetzt warnt die Regelschreibweise.kuerzel_vor_angabenur noch hinter echten Kürzeln. Für „Rechnung Nr. 2026-0815“ kommt die Warnung weiterhin, ausgelöst vonNr.statt von „Rechnung“. (#386)
Davor liegen 34 weitere Versionen — der vollständige Verlauf steht in CHANGELOG.md.
Lizenz
Comments
New to MCP?
From what the protocol is to installing your first server, these answers cover most first questions.
An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.


