Metrik-Paket
Was Sie tun
Sie wurden gebeten, die Umsatzdaten eines Startups in die Zahlen umzuwandeln, die ein Fondsanalyst zuerst liest:
MRR, Kohorten, NRR – auf einer Folie. Die Zahlen stammen aus metrics.py, niemals aus Ihrem Kopf.
Sie wählen die Eingabe aus, führen den Helfer aus, lesen seine CSVs und schreiben die Worte darum herum.
EINGABE HELFER (metrics.py) SIE
───── ─────────────────── ───
updates/ (a) ──┐
kundenexport (b) ─┼──► mrr.csv cohorts.csv ──► metrics.md (einfaches Englisch)
vertragsregister (c) ┘ nrr.csv excluded.csv metrics-slide.png (eine Folie)
Liefergegenstände in <unternehmens-slug>/metrics-pack/, relativ zum aktuellen Arbeitsverzeichnis:
metrics.md– die Notiz. Beginnt mit „Auf Deutsch:“.mrr.csv,cohorts.csv,nrr.csv(undexcluded.csvfür ein Vertragsregister) – vom Helfer geschrieben, von Ihnen unberührt.metrics-slide.png– eine 16:9-Folie.
In dieser Datei verwendete Abkürzungen: MRR = monatlich wiederkehrende Umsätze; NRR = Netto-Umsatzbindung;
CSV = kommagetrennte Wertedatei; PNG = Bilddatei; ISO = das internationale Datumsformat
(YYYY-MM-DD oder YYYY-MM für einen Monat); EUR = Euro; USD = US-Dollar; --as-of = die
Helfer-Option, die den letzten abgerechneten Monat benennt.
Eingaben
Aus $ARGUMENTS oder der Konversation: ein Unternehmen und optional eine Datei. Drei Arten von Eingaben,
in dieser Reihenfolge der Präferenz:
| Eingabe | Was es ist | Wie es in den Helfer gelangt |
|---|---|---|
| (b) Kundenexport | CSV kunden_id,monat,umsatz, Monat als YYYY-MM | --revenue <csv> |
| (c) Vertragsregister | CSV mit einer Kopfzeile Kunde, Vertragswert, Startmonat, Laufzeit (Monate); Zeilen über der Kopfzeile werden übersprungen; Monate wie Mai-26; Werte wie "1.550.000" | --contracts <csv> |
(a) <unternehmens-slug>/updates/ | Monatliche Update-Dateien mit einer Umsatzzeile, ohne Kundendetails | wie bei revenue-chart gelesen (Schritt 2 dort), schreibe kunden_id,monat,umsatz mit einem Kunden total, dann --revenue |
Bei Eingabe (a) gibt es keine Kunden. Der Helfer schreibt dann cohorts.csv und nrr.csv mit
nur einer Kopfzeile und lässt die Zellen new, expansion, contraction und churned von mrr.csv
leer, da sie mit einem Kunden nur das Gesamtwachstum wiederholen würden. Ignorieren Sie diese Spalten,
zeigen Sie keine Heatmap an und geben Sie „12-Monats-NRR: kann noch nicht berechnet werden“ aus (Grund: keine Kundendetails).
Gleiches gilt für jede --revenue-Datei mit einer einzigen Kunden-ID.
Wenn das Unternehmen mehrdeutig ist (zwei Firmen teilen sich den Namen), fragen Sie vor dem Lesen, welches gemeint ist.
Schritt 1 – Unternehmenssteckbrief und Eingabe
Der Unternehmenssteckbrief
<unternehmens-slug>/company-profile.md – lesen Sie ihn zuerst. Wenn er fehlt, erstellen Sie ihn. Wenn ein Feld leer
ist und Sie es erfahren, füllen Sie es und aktualisieren Sie updated / updated_by. Überschreiben Sie niemals ein gefülltes
Feld: Wenn Sie einen anderen Wert finden, fügen Sie eine Zeile in ## Konflikte mit beiden Werten und Quellen hinzu.
Der Steckbrief endet mit einem Abschnitt ## Konflikte (erstellen Sie ihn, falls er fehlt), dessen Tabellenkopf genau so ist:
| Feld | Steckbriefwert | Steckbriefquelle | Neuer Wert | Neue Quelle | Gefunden von | Datum |.
| Feld | Erlaubte Werte |
|---|---|
| Aufgabe für den Kunden | ein Satz, in den eigenen Worten des Unternehmens, in Anführungszeichen, mit URL |
| Wer zahlt | Freitext |
| Geschäftsmodell | B2B · B2C · B2G |
| Umsatzmodell | Abonnement · Transaktion · Werbung · Einmalig · k. A. |
| Markt | genau einer: Fintech & Versicherung · Gesundheit & Bio · Handel & Einzelhandel · Logistik & Lieferkette · KI & Dateninfrastruktur · Unternehmenssoftware · Cybersicherheit · Recht, Compliance & Governance · Vertrieb & Marketing · HR & Talente · Bildung · Medien, Gaming & Unterhaltung · Immobilien & Bau · Energie, Klima & Landwirtschaft · Industrie & Robotik · Verbraucher Lebensstil & Dienstleistungen · Sonstige |
| Vertikal | Freitext |
| Phase | Pre-Seed · Seed · Serie A · Serie B+ · k. A. |
| Geografie | Hauptsitzland; Länder, in denen es verkauft |
| Finanzierungsrunde | Betrag + Währung + Instrument, oder „nicht angegeben“ |
| Verfügbare Metriken | wo (updates/, Exporte), oder „keine“ |
Frontmatter: company, slug, website, updated (ISO-Datum), updated_by (Skill-Name).
Die Tabelle des Steckbriefs hat eine dritte Spalte, Quelle, die für jedes Feld ausgefüllt ist.
Nehmen Sie den Firmennamen, das Geschäftsmodell, das Umsatzmodell und die Geografie aus dem Steckbrief; die Geografie legt die zu erwartende Währung nahe. Füllen Sie „Verfügbare Metriken“ mit der von Ihnen verwendeten Datei aus. Wenn das Umsatzmodell nicht Abonnement ist, sagen Sie in der Notiz, dass MRR wiederkehrende Umsätze annimmt.
Finden Sie die Eingabe (obige Tabelle) und kopieren Sie sie in <unternehmens-slug>/metrics-pack/input/, damit der
Durchlauf nachvollziehbar ist. Veröffentlichen oder veröffentlichen Sie niemals eine Datei auf Kundenebene, es sei denn,
der Eigentümer hat gesagt, dass sie öffentlich sein darf. Währung: übernehmen Sie sie aus der Datei; ein Vertragsregister
gibt oft keine an. Wenn keine angegeben ist, schreiben Sie überall „Währung nicht angegeben“ und wählen Sie nie eine aus.
Heute und --as-of. --as-of ist der letzte Monat, der tatsächlich abgerechnet wurde – normalerweise
der aktuelle Monat, ausgehend vom heutigen Datum (ISO). Monate danach sind vertraglich vereinbart: unterschrieben, noch
nicht abgerechnet.
Schritt 2 – Den Helfer ausführen
Verwenden Sie /usr/bin/python3 oder ein Python 3.9+; metrics.py benötigt nur die Standardbibliothek und tätigt
keine Netzwerkaufrufe. Es befindet sich neben dieser Datei (skills/metrics-pack/metrics.py; in einem installierten
Plugin ${CLAUDE_PLUGIN_ROOT}/skills/metrics-pack/metrics.py).
python3 <pfad>/metrics.py --contracts <register.csv> --out-dir <unternehmens-slug>/metrics-pack \
--as-of 2026-11 --min-term 3
python3 <pfad>/metrics.py --revenue <export.csv> --out-dir <unternehmens-slug>/metrics-pack \
--as-of 2026-11
Was es schreibt:
| Datei | Spalten | Bedeutung |
|---|---|---|
mrr.csv | monat, mrr, new, expansion, contraction, churned, status | eine Zeile pro Kalendermonat; status ist billed bis --as-of, contracted danach |
cohorts.csv | cohort, month_offset, umsatz | Kohorte = erster Monat eines Kunden mit Umsatz; Offset = Monate seitdem |
nrr.csv | start_month, monate, nrr | 12-Monats-NRR für jeden Startmonat, in dem sie nur aus abgerechneten Monaten berechnet werden kann (ein Monat nach --as-of zählt nie); nur Kopfzeile, wenn keine berechnet werden kann. Auch nur Kopfzeile für einen Ein-Kunden-Export und für ein Vertragsregister ohne aufgezeichnete Verlängerung; für ein Register werden nur Startmonate aufgeführt, in denen ein Kunde eine aufgezeichnete Verlängerung hat (Regel in Schritt 2) |
excluded.csv | kunde, wert, start, laufzeit | Verträge kürzer als --min-term Monate (Standard 3) |
Wenn der Helfer mit error: stoppt, nennt er die fehlerhafte Spalte oder den fehlerhaften Wert. Beheben Sie die
Eingabe an der Quelle (oder fragen Sie den Eigentümer) – bearbeiten Sie sie niemals herum.
Was der Helfer annimmt (jeweils in der Notiz angeben):
- Der Vertragswert ist der Gesamtwert über die Laufzeit, gleichmäßig verteilt: Wert ÷ Laufzeit pro Monat, ab dem Startmonat. Wenn der Eigentümer sagt, es sei pro Monat oder pro Jahr, stoppen Sie und fragen Sie – die Antwort ändert jede Zahl.
- Ein Vertrag ist nur wiederkehrend, wenn seine Laufzeit mindestens
--min-termMonate beträgt. Kürzere sind nicht wiederkehrend: inexcluded.csvgemeldet, nicht in MRR. - Nichts verlängert sich, es sei denn, eine neue Zeile sagt es. Wenn die Laufzeit eines Vertrags endet, zeigt der
Helfer den wegfallenden Umsatz als
churnedan. In einem Vertragsregister ist dies Vertragsende, kein nachgewiesener Kundenverlust – sagen Sie dies für jeden solchen Monat. - Ein Vertragsregister erfasst Verträge, keine Verlängerungen. Vertragsende wird als verlorener Umsatz gelesen,
daher berechnet der Helfer
nrr.csvaus einem Register nur für Startmonate, in denen ein Kunde eine aufgezeichnete Verlängerung hat. Regel: Eine Verlängerung ist ein späterer wiederkehrender Vertrag (Laufzeit mindestens--min-term) desselben Kunden, dessen Startmonat mindestens einen Monat nach dem Endmonat eines früheren wiederkehrenden Vertrags liegt (Endmonat = Startmonat + Laufzeit - 1; ein nahtloser Vertrag, der im Monat nach dem Ende beginnt, zählt, und eine Lücke ist erlaubt). Ein zweiter Vertrag, der den ersten überlappt (ein Upsell oder Add-on), ist keine Verlängerung. Wenn kein Kunde eine Verlängerung hat, istnrr.csvnur eine Kopfzeile und die Antwort lautet „kann noch nicht berechnet werden“. Wenn einige dies tun, spiegelt die Zahl nur die Verlängerungen wider, die das Register erfasst, und die Notiz und die Folie müssen dies sagen. - Ein Kunde, der aufhört und später zurückkehrt, zählt wieder als
new.
Schritt 3 – Die Ausgaben lesen
Lesen Sie die CSVs mit dem csv-Modul. Jede Zahl, die Sie schreiben, stammt aus ihnen. Berechnen Sie nichts im
Fließtext; wenn Sie eine Zahl benötigen, die die CSVs nicht enthalten (z. B. einen Anteil), berechnen Sie sie mit
einem Befehl und zitieren Sie die Ausgabe des Befehls.
- MRR. Das
mrrdes letzten abgerechneten Monats; der Spitzenmonat und seinstatus; die Aufteilung abgerechnet-zu-vertraglich-vereinbart. Nennen Sie den ersten und letzten Monat in den Daten. - Auslauf. Monate nach dem letzten Vertragsstart verlieren nur noch Umsatz, da sich in den Daten nichts verlängert. Kennzeichnen Sie sie als Auslauf von Verträgen ohne Verlängerung, niemals als Kundenverlust.
- Kohorten. Zählen Sie Kohorten mit mindestens zwei Monaten abgerechneten Umsatzes. Die Heatmap auf der Folie benötigt mindestens zwei solche Kohorten; andernfalls überspringen Sie sie und sagen Sie warum.
- NRR. Überprüfen Sie zuerst die Eingabe. Bei Eingabe (a) oder einem Ein-Kunden-Export ignorieren Sie
nrr.csv,cohorts.csvund die Bewegungsspalten: Die Antwort lautet „kann noch nicht berechnet werden“. Andernfalls, wennnrr.csvDatenzeilen hat, zitieren Sie sie; fügen Sie für ein Vertragsregister „zählt nur im Register erfasste Verlängerungen“ hinzu. Wenn es nur die Kopfzeile hat, lautet die Antwort „12-Monats-NRR kann noch nicht berechnet werden“: Kein Kunde hat einen Umsatzmonat zwölf Monate nach seinem Start. Schätzen Sie ihn niemals, füllen Sie ihn niemals aus einem kürzeren Fenster. Geben Sie den Grund in einer Zeile an (z. B. „jeder Vertrag im Register beginnt 2026, daher hat keiner zwölf Monate durchlaufen und sich verlängert“). - Ausgeschlossene. Anzahl der ausgeschlossenen Verträge, ihr Gesamtwert und die Regel, die sie ausgeschlossen hat.
Schritt 4 – metrics-slide.png
Erfordert matplotlib und numpy (python3 -c "import matplotlib, numpy"). Wenn sie fehlen, fragen Sie vor der
Installation; der saubere Weg ist eine temporäre virtuelle Umgebung. Die Basis ist die Diagrammvorlage aus
revenue-chart (dunkles Thema, Kollisionsprüfung für Beschriftungen).
Eine 16:9-Folie, in diesem Layout:
┌─────────────────────────────────────────────────────────────┐
│ <Unternehmen> – Umsatzkennzahlen Stand <ISO-Datum>│
├──────────────────────────────┬──────────────────────────────┤
│ MRR-Linie: durchgezogen = │ Kohorten-Heatmap (abgerechnete│
│ abgerechnet, gestrichelt + │ Monate, % von Monat 0) – oder│
│ schattiert = vertraglich │ das NRR-Panel, wenn keine │
│ │ Heatmap │
├──────────────────────────────┴──────────────────────────────┤
│ NRR: <Zahl> oder "12-Monats-NRR: kann noch nicht berech- │
│ net werden" │
│ drei einzeilige Erkenntnisse │
└─────────────────────────────────────────────────────────────┘
Regeln für die Folie:
- Vertraglich vereinbart wird niemals wie abgerechnet dargestellt. Monate nach
--as-ofverwenden eine gestrichelte Linie, hohle Markierungen und ein beschriftetes schattiertes Band „vertraglich vereinbart, noch nicht abgerechnet“. - Für ein Vertragsregister trägt eine angezeigte NRR-Zahl den Hinweis „zählt nur im Register erfasste
Verlängerungen“ (das Skript fügt ihn hinzu, wenn
source = "register"). - Die NRR-Zeile zeigt die Zahl aus
nrr.csvoder die genauen Worte „12-Monats-NRR: kann noch nicht berechnet werden“. - Heatmap nur, wenn mindestens zwei Kohorten mindestens zwei abgerechnete Monate haben.
- Drei einzeilige Erkenntnisse, jede auf eine CSV-Zeile zurückführbar, keine Empfehlung oder Vorhersage.
- Währung in der Achsenbeschriftung; „Währung nicht angegeben“, wenn die Quelle keine nannte.
- Alle Zahlen auf der Folie werden vom Skript aus den CSVs gelesen, nicht eingegeben. Die Erkenntnisse sind der einzige eingegebene Text: Überprüfen Sie jede Zahl darin nach dem Zeichnen anhand der CSVs.
import csv, os
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
# KONFIGURIEREN ------------------------------------------------------------
company = "Unternehmen"
folder = "<unternehmens-slug>/metrics-pack"
currency = "Währung nicht angegeben" # oder "EUR", "USD" ...
as_of = "2026-11" # gleicher Wert wie --as-of
source = "register" # "register" (--contracts) oder "export" (--revenue)
takeaways = [ # drei Einzeiler, jeder gegen die CSVs geprüft
"Erkenntnis 1",
"Erkenntnis 2",
"Erkenntnis 3",
]
# ----------------------------------------------------------------------------
def read(name):
with open(os.path.join(folder, name), newline="", encoding="utf-8") as fh:
return list(csv.DictReader(fh))
mrr, coh, nrr_rows = read("mrr.csv"), read("cohorts.csv"), read("nrr.csv")
months = [r["month"] for r in mrr]
vals = [float(r["mrr"]) for r in mrr]
billed = [r["status"] == "billed" for r in mrr]
x = np.arange(len(months))
nb = sum(billed) # abgerechnete Monate zuerst
BG, FG, MUTED = '#0f1117', '#e0e0e0', '#9aa0b4'
BILLED, CONTR = '#4fc3f7', '#f2b84b'
fig = plt.figure(figsize=(13.333, 7.5), facecolor=BG) # 16:9
gs = fig.add_gridspec(3, 2, height_ratios=[0.5, 5.2, 1.9], width_ratios=[1.35, 1],
hspace=0.35, wspace=0.18, left=0.06, right=0.97, top=0.97, bottom=0.04)
ax_t = fig.add_subplot(gs[0, :]); ax_t.axis('off')
ax_t.text(0, 0.5, f"{company} – Umsatzkennzahlen", color='#fff', fontsize=20,
fontweight='bold', va='center')
ax_t.text(1, 0.5, f"abgerechnet bis {as_of}", color=MUTED, fontsize=11, ha='right', va='center')
# --- MRR-Linie ---
ax = fig.add_subplot(gs[1, 0]); ax.set_facecolor(BG)
if nb < len(months):
ax.axvspan(nb - 0.5, len(months) - 0.5, color=CONTR, alpha=0.10, zorder=0)
ax.text(nb - 0.35, 0.97, "vertraglich vereinbart,\
noch nicht abgerechnet", color=CONTR, fontsize=9,
transform=ax.get_xaxis_transform(), va='top')
ax.plot(x[:nb], vals[:nb], color=BILLED, lw=2.6, marker='o', ms=5, label='abgerechnetes MRR', zorder=3)
if nb < len(months):
j = max(nb - 1, 0) # verbinde die beiden Segmente
ax.plot(x[j:], vals[j:], color=CONTR, lw=2.2, ls='--',
label='vertraglich vereinbartes MRR (nicht abgerechnet)', zorder=3)
ax.scatter(x[j:], vals[j:], color=CONTR, s=30, marker='o', edgecolors='none', zorder=4)