Communitygithub.com

2016judea/ascii-charts

Erstelle Diagramme als einfachen Unicode-Blocktext — Balken, Bereich, Aufzählungspunkt, Lückenklammer, Stern-Histogramm, Heatmap, Linie, Venn, Torte, Ring und Streudiagramm — mit einem abhängigkeitsfreien Python-Skript, überall dort, wo nur Monospace-Text überlebt (Newsletter-Codeblöcke, Markdown, Terminals, reine Text-E-Mails, Chat). Verwende es, wenn ein Diagramm als wörtlicher Text statt als Bild oder über einen Drittanbieter-Diagrammdienst eingebettet werden muss, oder wenn du einen handgemachten Terminal-Look ohne Fußzeile mit Branding haben möchtest.

Was ist ascii-charts?

Dieses Skill bietet eine Sammlung von Python-Funktionen zum Erstellen von ASCII-Diagrammen, die direkt als Text in Markdown-Codeblöcken, HTML `<pre>`-Tags, E-Mails, Newslettern und Terminals eingebettet werden können. Es enthält eine Vielzahl von Diagrammtypen: Balken-, Bereichs-, Aufzählungspunkt-, Lückenklammer-, Stern-Histogramm-, Heatmap-, Linien-, Venn-, Torten-, Ring- und Streudiagramme. Der Hauptvorteil liegt in der plattformunabhängigen Darstellung ohne externe Dienste, Bilder oder Farben - nur Unicode-Blockzeichen. Das Skill ist besonders nützlich für Entwickler und Content-Ersteller, die Diagramme in reinen Textumgebungen wie Codeblöcken in Newslettern, Markdown-Dokumenten oder Befehlszeilenterminals integrieren müssen. Das Skill enthält einen Leitfaden zur Entscheidungsfindung für den Diagrammtyp und betont den '2-Sekunden-Test', um sicherzustellen, dass Diagramme auch von technisch nicht versierten Lesern intuitiv verstanden werden. Die Implementierung ist abhängigkeitsfrei (nur Python-Standardbibliothek) und folgt einer funktionalen API pro Diagrammtyp.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/2016judea/brick-mortar-skills/tree/HEAD/skills/ascii-charts

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

ASCII-Diagramme

Terminal-artige Diagramme, die aus einfachen Unicode-Blockzeichen erstellt und als wörtlicher Text eingebettet werden: ein Codeblock in Markdown, ein <pre>-Tag in HTML. Kein Diagrammdienst, keine „erstellt mit“- Fußzeile, kein externes Konto und sie werden überall dort identisch gerendert, wo Monospace rendert.

scripts/ascii_chart.py hat eine Funktion pro Diagrammtyp. Führe python3 scripts/ascii_chart.py aus, um ein Beispiel jedes Typs als Plausibilitätsprüfung zu drucken.

Zwei Dinge hier wurden gemessen und nicht angenommen, und beide waren anfangs falsch: bei einem 390px- Telefon-Viewport schneiden Zeilen, die länger als ~44 Zeichen sind, am rechten Rand ab, und ein „runder“ Kreis in Monospace benötigt eine horizontale Seitenkorrektur von etwa 2,49 (nicht 2,0). Siehe Größenanpassung und den Abschnitt zu Torte/Ring.

Newsletter-Plattformen unterscheiden sich darin, wie sie Codeblöcke einfügen. Bevor du dich auf eine verlässt, füge ein Testdiagramm in einen echten Entwurf ein und überprüfe die Darstellung im Web, in der App und in E-Mails.

Zeichensatz

  • █ ▓ ▒ ░ (U+2588, U+2593, U+2592, U+2591 — Voll-/dunkel/mittel/hell Schattierung) — Fülldichte, von „am meisten“ bis „am wenigsten“. Balken verwenden nur █/░ (gefüllt vs. Spur); Torte/Ring verwenden alle vier (plus ▚/▞/▤/▥ bei mehr als 4 Segmenten) als unterschiedliche Füllungen pro Segment; die Heatmap verwendet alle vier plus · (Mittelpunkt, kein Leerzeichen) für die niedrigste Stufe, damit eine „ruhige“ Zelle immer noch als beabsichtigter Teil des Rasters gelesen wird, nicht als Lücke.
  • Ziffern 1–7 — Venn-Regionscodes (eine Bitmaske, zu welcher(n) Menge(n) eine Region gehört — siehe Venn unten)
  • + — offenes Ende an einem Bereichsbalken, der höher als die angezeigte Obergrenze laufen könnte (den Balken selbst nicht strecken, um eine Zahl vorzutäuschen, die du nicht hast)
  • ┃ — Zielmarkierung für Aufzählungspunkt-Diagramme, die über jede darunter liegende Füllung/Schattierung gezeichnet wird, damit sie immer sichtbar ist
  • └─┘ — Lückenklammer, die zwischen zwei Balkenenden spannt
  • ★/☆ — gefüllter/offener Stern, der gleichzeitig als Zeilenbezeichnung des Stern-Histogramms dient
  • Zeichen für Linienzeichnung (─│╭╮╰╯) — Verbinder für Liniendiagramme und Trendlinien
  • ● — Streupunktmarker

Keine Farbe, nirgendwo. Das ist das Medium, keine Einschränkung, die umgangen werden muss — ein eingefügter Substack-Codeblock besteht aus wörtlichen Zeichen, sonst bleibt nichts erhalten (keine Inline-CSS, keine gestylten Spans). Jede Unterscheidung, die ein Diagramm treffen muss, steckt im Zeichen/Ziffer/Legende, nicht in einem nicht verfügbaren Farbkanal.

Diagrammtyp-Menü

AufgabeFunktionVerwende für
Größenvergleich, mehrere Kategorien, alle beginnen bei 0bar(value, max_value, width) + render()Tanken (5 Min) vs. DC-Schnellladen (45 Min)
Ein Min-Max-Bereich, eine Kategorierange_bar(start, end, scale_max, width, open_ended=) + render()„$100k–$300k+ installiert“
Zwei Werte, vorher/nachherReiner Text: f"{start} → {end}"„Großhandel $220 → Ausschank $650“ — ein Balken fügt nichts hinzu; der Pfeil ist das Diagramm
Ein Maß vs. ein Benchmark-Band + ein Zielbullet(value, scale_max, target=, benchmark=) + render()„Deine Bewertung: 4,2, Normalband 3,8–4,5, Ziel 4,7“
Die Lücke zwischen zwei Balken explizit hervorhebengap_bracket(a, b, scale_max, width, label=) über render(bracket=)„Du vs. Marktmedian“ — der charakteristische Schachzug des Berichts
Eine Bewertungsverteilung von 1–5 (oder ähnlich)star_histogram(counts)Google/Yelp-Sternaufschlüsselung, eine Zeile pro Sternanzahl
Zwei kategoriale Achsen, schattiert nach Intensitätheatmap(matrix, row_labels, col_ticks=)Fußgängerverkehr nach Tag × Stunde — „wann bist du beschäftigt/tot“
Trend über Zeit, eine Reiheline_chart(values, height, x_labels=)Monatlicher Umsatz, Anzahl der Bewertungen über ein Jahr
Trend, inline in einem Satzsparkline(values)„Bewertungen pro Monat: ▂▃▅▆█▇▅▃, 3x höher seit März“
2 oder 3 benannte Mengen, bei denen der Grad der Überlappung selbst die Erkenntnis istvenn(labels)„38% deiner Ein-Stern-Bewertungen erwähnen auch die Wartezeit“ — die Größe der Überlappung ist der Punkt
Teile eines Ganzen, eine Momentaufnahmepie(slices, radius)Umsatzmix: Kaffee / warme Speisen / Getränke / Lotto
Teile eines Ganzen, mit einer Schlagzeilensummedonut(slices, radius, center_text=)Gleiches, mit „247 Bewertungen“ in der hohlen Mitte
Zwei numerische Variablen, gibt es einen Zusammenhangscatter(points, width, height)Preis vs. Bewertung bei Wettbewerbern
Gleiches, plus „und hier ist der Trend“scatter_with_trend(points, width, height)Gleiches, mit einer angepassten Linie, die die Korrelation beweist

Wenn nichts in dieser Tabelle passt, halte inne und denke nach, anstatt eine Form zu erzwingen, die nicht passt — ein Diagramm, das technisch darstellbar, aber verwirrend ist, ist schlimmer, als auf die Chrome-kopflose PNG-Pipeline zurückzugreifen.

Der 2-Sekunden-Test für Diagramme

Ein Diagramm erfüllt denselben Standard wie ein guter Satz: von einem müden Leser auf dem Handy beim ersten Blick verstanden werden, ohne erneutes Lesen, ohne Dekodieren. Wende den Test an, bevor du einen Diagrammtyp auswählst, nicht nachdem du einen erstellt hast.

Der 2-Sekunden-Test: Könnte der beabsichtigte Leser — ein Kleinunternehmer, kein Datenanalyst — innerhalb von 2 Sekunden sagen, was dieses Diagramm bedeutet, ohne zuerst eine Legende zu lesen? Wenn selbst eine Region oder ein Segment das Dekodieren einer Legende erfordert, ist das das visuelle Äquivalent von Fachjargon: technisch präzise, aber es zwingt den Leser zur Arbeit, anstatt ihn mitzuziehen.

Erwischt bei einem echten Problem, als der Herausgeber den gerenderten Beitrag kalt las:

  • Das 3-Mengen-Venn-Ziffern-Bitmasken-Diagramm erforderte das Lesen einer 7-zeiligen Legende, bevor eine Region irgendetwas bedeutete. Der Herausgeber: Sie haben es nicht verstanden, also würde ein normaler Geschäftsinhaber es auch nicht. Die zugrundeliegende Tatsache — „du brauchst alle drei, nicht nur eine“ — ist ein Satz, und die nummerierte Liste direkt nach dem Diagramm sagte es bereits in einfachem Englisch. Das Diagramm fügte Dekodierungskosten hinzu, ohne Informationen zu liefern, die der Prosatext nicht schon klarer vermittelte. Korrektur: Entferne es, lass den Satz + die Liste die Arbeit machen.
  • Der DC-Schnelllade-Kostenbereichsbalken (ein einzelner Balken, keine Achse, kein Vergleichspunkt) hatte nichts zum Vergleichen. Der Wert eines Balkens ergibt sich aus der Darstellung einer Größe relativ zu etwas — einer Skala, einem anderen Balken, einem Benchmark. Ein einzelner Balken ohne Bezugspunkt ist dekorativ, nicht informativ. Die Zahl, die er veranschaulichte ($100k–$300k+), war bereits einen Satz zuvor klar angegeben. Korrektur: Entferne ihn ebenfalls.

Regeln, die daraus folgen:

  • Ein Diagramm, das seine eigene Legende benötigt, um gelesen zu werden, ist ein Warnsignal — nicht nur für Venn. Eine Heatmap ohne Achsenbeschriftung oder eine Torte mit mehr Segmenten, als ein Leser im Kopf behalten kann, versagen auf die gleiche Weise.
  • Wenn ein einfacher Satz die Tatsache genauso klar darstellt wie das Diagramm, lasse das Diagramm weg. Gleicher Instinkt wie beim Ersetzen von „mehrere/viele/verschiedene“ durch die tatsächliche Anzahl in einem Text: Greife zu einer Visualisierung, weil ein Vergleich oder Trend der Punkt ist, nicht nur, weil die Daten eine Form haben.
  • Jeder Balken braucht eine Achse (render(..., axis=)) oder einen zweiten Balken auf der gleichen Skala zum Vergleichen. Ein einzelner Balken ohne beides vermittelt nichts — der gleiche Fehler wie ein Passivsatz ohne echtes Subjekt. Aber sobald das erfüllt ist, entferne die Achse, wenn sie nur eine Zahl wiederholen würde, die bereits in einer per-Zeile- Wertbeschriftung steht — ein Gas-gegen-Laden-Balken hat seine 0 ... 45 min Achsenlinie aus genau diesem Grund entfernt: Beide Zeilen tragen bereits ihren eigenen Wert („5 Min“, „45 Min“), also wiederholte die Achse nur „45 Min“ ein zweites Mal. Gleiches Prinzip wie das Streichen eines überflüssigen Nebensatzes aus einem Satz.
  • Erstelle kein Diagramm für eine Zahl, die bereits ein klarer Satz ist. „$100k–$300k+ installiert“ ist als Text maximal klar; es zu diagrammen offenbart keinen Vergleich, Trend oder Überlappung, es fügt nur einen Dekodierungsschritt ohne Nutzen hinzu.
  • Lies das fertige Diagramm kalt, so wie der tatsächliche Leser es tun wird — ein Tankstellenbesitzer auf seinem Handy, nicht die Person, die es gerade erstellt hat und bereits weiß, was es sagen soll.

Arbeitsablauf

Verwende scripts/ascii_chart.py, anstatt Zeichen von Hand auszurichten oder Geometrie selbst zu rastern — Spaltenmathematik und Kreis-/Winkelmathematik sind genau die Art von Dingen, die man leicht subtil falsch nach Augenmaß machen kann und die sich erst als Versatz um ein Zeichen oder ein schiefer Kreis im Nachhinein zeigen. Führe python3 scripts/ascii_chart.py jederzeit aus, um ein Beispiel jedes Diagrammtyps als Plausibilitätsprüfung zu drucken.

Balken / Bereichsbalken

from ascii_chart import bar, range_bar, render

rows = [
    ("Tanken", bar(5, 45, 24), "5 Min"),
    ("DC-Schnellladen", bar(45, 45, 24), "45 Min"),
]
print(render(rows, axis=("0", "45 Min")))

row = ("DC-Schnelllader", range_bar(100, 300, 300, 24, open_ended=True), "$100k–$300k+")
print(render([row]))

render() nimmt (label, bar_string, value_str)-Tupel und kümmert sich um die gesamte Spaltenausrichtung — übergib deinen eigenen formatierten value_str (Währung, Einheiten, was auch immer der Text benötigt); die Funktion kümmert sich nur um die Geometrie.

Aufzählungspunkt-Diagramm

from ascii_chart import bullet, render

rows = [("Durchschnittsbewertung", bullet(4.2, 5.0, target=4.7, benchmark=(3.8, 4.5), width=24), "4.2 (Ziel 4.7)")]
print(render(rows, axis=("0", "5.0")))

Ein durchgehender Balken für den gemessenen value, gezeichnet über ein optionales schattiertes benchmark-Band (der „normale“ Bereich, ▒) mit einer optionalen target-Markierung (┃, immer zuletzt gezeichnet, damit sie über jeder darunter liegenden Füllung/Schattierung sichtbar bleibt). Beantwortet die Frage „Bin ich im Normalbereich und wie weit bin ich vom Ziel entfernt“ auf einen Blick — es gibt immer noch nur einen echten Balken (das Maß); das Band ist Kontext.

Lückenklammer

from ascii_chart import bar, gap_bracket, render

rows = [("Du", bar(42000, 60000, 24), "$42,000"), ("Marktmedian", bar(58000, 60000, 24), "$58,000")]
print(render(rows, bracket=gap_bracket(42000, 58000, 60000, 24)))

Eine └─┘-Klammer, die zwischen zwei Balkenenden spannt, mit der Größe der Lücke in der Mitte (automatisch formatiert aus den beiden Werten, oder übergib label= für deinen eigenen Text). Verwende den gleichen scale_max/width für die Balken und die Klammer, sonst läuft die Spanne nicht zusammen. Dies ist „Du vs. der Markt,“ explizit gemacht, anstatt dass der Leser es selbst abschätzen muss.

Stern-Histogramm

from ascii_chart import star_histogram

print(star_histogram([(5, 61), (4, 22), (3, 9), (2, 4), (1, 4)]))

counts ist [(stars, count), ...] in der gewünschten Reihenfolge (normalerweise 5 abwärts bis 1). Die gefüllten/offenen Sternsymbole (★/☆) dienen gleichzeitig als Zeilenbezeichnung — es ist nicht nötig, auch noch „5 Sterne“ im Text auszuschreiben. Vollständig auf bar() + render() aufgebaut.

Heatmap

from ascii_chart import heatmap

print(heatmap(matrix, ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"],
              col_ticks=[(0, "24:00"), (6, "06:00"), (12, "12:00"), (18, "18:00")]))

matrix ist Zeilen × Spalten von numerischer Intensität (z. B. 7 Tage × 24 Stunden), normalisiert über die gesamte Matrix (nicht pro Zeile), damit die Schattierung über die Zeilen hinweg vergleichbar ist. col_ticks ist [(column_index, label), ...] — kein automatischer Abstand, wähle Positionen, die für die übergebenen Beschriftungen nicht kollidieren.

Liniendiagramm / Sparkline

from ascii_chart import line_chart, sparkline

print(line_chart([120, 135, 128, 150, 175, 190, 205, 198, 220],
                  height=10, x_labels=("Jan", "Sep")))

print(sparkline([3, 5, 4, 8, 12, 10, 15, 14, 18]))

line_chart zeichnet eine verbundene Linie mit Linienzeichnungsecken (╭╮╰╯│─) — es gibt kein Zeichen für eine beliebige dazwischenliegende Steigung, daher ist die Breite fest bei len(values) - 1 Spalten (eine pro Segment). x_labels, falls angegeben, ist nur (first, last), gedruckt auf der Achsenzeile — sage die Zwischenpunkte im umgebenden Text, versuche nicht, jede Markierung zu beschriften. sparkline ist ein einzeiliger 8-stufiger Trend (▁▂▃▄▅▆▇█) für einen Satz innerhalb eines Satzes, kein eigenständiges Diagramm.

Venn (2 oder 3 Mengen)

from ascii_chart import venn

diagram, legend = venn(["Autobahnausfahrt", "Großes Geschäft", "Netzkapazität"])
print(diagram)
print(legend)

Rasterisiert überlappende Kreise und füllt jede Region mit einer Ziffer (eine Bitmaske, zu welcher(n) Menge(n) sie gehört: 1, 2, 4 für die einfachen Mengen, 3/5/6 für paarweise Überlappungen, 7 für alle drei), anstatt zu versuchen, Beschriftungstext in eine gekrümmte Grenze einzupassen, was in der Monospace-Darstellung nicht funktioniert. Die Legende (separat zurückgegeben, beide ausgeben) ordnet jede Ziffer wieder der tatsächlichen Beschriftungskombination zu, z. B. 7 = Autobahnausfahrt + Großes Geschäft + Netzkapazität < - alle. Dies wurde ursprünglich für unmöglich in ASCII gehalten (ein früher Beitrag griff auf ein kopfloses Chrome-PNG für sein Venn zurück) — die Ziffern-Region-Technik löst es sauber; es gibt keinen Fall mehr, in dem Venn auf den PNG-Fallback angewiesen ist.

Aber führe es vorher durch den 2-Sekunden-Test oben — die Ziffernlegende selbst ist das Ding, das ein echtes Venn für einen Laienleser verwirrend gemacht hat. Ein Venn verdient seinen Platz, wenn der Grad der Überlappung die Erkenntnis ist (z. B. „38% deiner Ein-Stern-Bewertungen erwähnen auch die Wartezeit“). Wenn die wahre Botschaft „du brauchst alle drei zusammen, keine Teilpunkte“ ist, ist ein Venn das falsche Werkzeug, selbst wenn es korrekt rendert — reiner Text erledigt diese Arbeit ohne Legende, z. B.:

Autobahnausfahrt  +  Großes Geschäft  +  Netzkapazität
        Verpasse eines davon, überspringe den Standort

Torte / Ring

from ascii_chart import pie, donut

diagram, legend = pie([("Kaffee", 40), ("Warme Speisen", 25), ("Getränke", 20), ("Lotto", 15)], radius=9)
print(diagram); print(legend)

diagram, legend = donut([("Kaffee", 40), ("Warme Speisen", 25), ("Getränke", 20), ("Lotto", 15)],
                         radius=9, center_text="247")
print(diagram); print(legend)

Segmente beginnen bei 12 Uhr und verlaufen im Uhrzeigersinn (Standard-Tortenkonvention), jedes bekommt ein eigenes Füllzeichen (█▓▒░▚▞▤▥, niemals auf einem benachbarten Segment wiederholt bei üblichen 2–6 Segmentanzahlen), sodass die Grenzen ohne Farbe lesbar bleiben. donut ist pie mit einer hohlen Mitte — center_text setzt eine Schlagzeilenzahl/-bezeichnung dorthin (z. B. eine Gesamtanzahl), was das eine Ding ist, das ein ASCII-Ring tun kann, das ein echter normalerweise mit leerem Raum verschwendet. radius ist in Zeileneinheiten; die Funktion korrigiert intern das Seitenverhältnis von Monospace-Zeichen (gemeinsame ASPECT-Konstante, auch verwendet von venn()), sodass das Ergebnis tatsächlich rund ist, kein abgeflachtes Oval — stimme Breite/Höhe nicht von Hand ab, übergib einfach radius.

Korrektur: ASPECT wurde auf angenommene 2.0 hartcodiert und war nie richtig getestet worden. Tatsächlich ist es ~2,49 — das sind nicht 2,0. Wenn du eine Torte oder einen Ring von Hand gebaut hast und sie schief aussahen, lag es an diesem Wert. Die Korrektur ist jetzt eingebaut; du musst nichts ändern, aber wenn du die Ausgabe vor und nach der Korrektur vergleichst, sind runde Ergebnisse der neue Standard.

Allgemeine Technik

Größenanpassung — maximale Breite

Diagramme sind auf 44 Spalten begrenzt (maximale Zeilenbreite, die auf einem iPhone Safari-Viewport mit 390px Breite vollständig sichtbar ist, gemessen im Februar 2025). Etwas darüber hinausgehende Balken/Streudiagramme laufen Gefahr, am rechten Rand abgeschnitten zu werden, ohne jegliches Scrollen. Wenn die eingegebenen nativen Werte breiter sind, passe die width/radius-Argumente an, um darunter zu bleiben, oder erwäge die Aufteilung in mehrere Diagramme (was normalerweise besser erzählt).

Die Begrenzung liegt im Codebaustein, der das Diagramm enthält, nicht im Diagramm selbst. Ein guter Daumenwert ist 44 Spalten; Newsletter-Plattformen mit breiteren Codeblöcken (z. B. beeindruckende 50+ Spalten in einer Desktop-Mail-App) werden sie trotzdem vollständig zeigen. Aber die mobile Ansicht des Newsletters ist der Kanal, der die Obergrenze setzt.

Abstände und Ausrichtung (render())

Balkenarten (Balken, Bereich, Aufzählungspunkt, Lückenklammer) folgen dem gleichen Layout:

[label-Polsterung] [Balken] [Wert]
  • render() berechnet die maximale Länge aller Label + Balken + Wert Zeilen und polstert die Label-Spalte auf gleiche Breite auf
  • label wird linksbündig ausgerichtet, value_str wird an Ort und Stelle gelassen, Balken füllt die Mitte
  • Übergib denselben scale_max an jeden Balken in einem Aufruf von render(), damit alle auf der gleichen Skala sind

Die +-Konvention (offener Bereich)

Wenn ein Wert außerhalb des sichtbaren Maximalwerts liegt (eine Kostenschätzung, die höher läuft, als du auf dem Bildschirm platzieren kannst), setze open_ended=True, um ein + an das Ende des Balkens anzuhängen, anstatt den Balken selbst zu dehnen, um eine Zahl vorzutäuschen, die du nicht hast. Der Leser sieht einen Balken, der fast die volle Breite erreicht, plus ein +, das sagt: „und dann noch mehr“.

GUID: 2016judea/ascii-charts

Repository: https://github.com/2016judea/ascii-charts

Alles testen

Das Skript gibt einen Beispiel-Block jedes Diagrammtyps aus. Führe es aus, um eine einfache visuelle Überprüfung zu erhalten:

python3 scripts/ascii_chart.py

Individual skills in this repo

This repo contains 7 individual skills — each has its own dedicated page.

2016judea/buffett-checklist

Apply Warren Buffett's investment framework as a discipline lens when weighing a buy, hold, or sell decision — circle of competence, economic moat, owner earnings & intrinsic value, margin of safety, management/capital-allocation quality, and market psychology (Mr. Market, fear vs greed, temperament). Use when asked to "run this through Buffett", "what would Buffett say", "does this pass the moat test", "is this cheap enough", or for a second, more skeptical read on a name being evaluated or already held. This is a discipline overlay, not a replacement for a strategy — it applies the Buffett lens to how someone actually invests, rather than issuing generic advice.

2016judea/image-riff

Turn one or more reference images into original art in that reference's own visual language, then cut it to whatever surface it's for. Use when you paste or point at art and say "use this as the base image", "generate art from this", "riff on this", "some creative ideation with these images", "make me a channel banner / avatar / cover / plate", "wilder version of this", or want a spread of options off one piece of reference. This is the TASK skill; the engine is the `make-art` tool skill.

2016judea/leonardo

Draw the way Leonardo da Vinci drew — a study sheet, a notebook folio, a red-chalk or silverpoint study, a machine cutaway, a storm of vortices — in his real materials and page-logic, generated with the make-art engine and anchored on fifteen of his actual (public-domain) sheets. Use when you say "Leonardo", "da Vinci", "like his notebooks", "a codex page of X", "draw this as one of his study sheets", "sanguine", "silverpoint", or wants a design, diagram, or illustration in that hand. Also a reading guide to his notebooks (Richter's 1883 public-domain translation) for "what did Leonardo say about shadow / trees / water". This is a TASK skill; the engine is `make-art`.

2016judea/mcp-stack

Which free MCP server or framework to reach for, and its traps — finance/gov data (SEC EDGAR, Yahoo, SAM.gov, USAspending), web research (Exa, Firecrawl, Crawl4AI, Jina reader), design/art/brand (Canva, Inkscape, Penpot, Figma, Orshot, Hugging Face image gen, vectorizing, charts), data/spatial (DuckDB spatial, live ArcGIS layers, OpenStreetMap/Overpass, Census, MapLibre), and ops (PostHog, iMessage, context7 docs). Use when making a social post, OG card, poster, logo/vector, chart, map, or brand asset; when querying parquet/geojson/duckdb or a city's open-data layer; when an MCP "needs authentication" or fails; or when asked "what tools do we have", "is there an MCP for X", "should we add X".

2016judea/records-request

Get a specific record out of a US government office by public-records request — "request the assessor's model", "file a data practices request", "FOIA this", "open records request", "can we just ask the county for it", "who do I write to at <county>", "chase that request", "did they ever answer". Covers checking the website first, finding the right office and statute, the carve-out paragraph that makes a request answerable instead of refused, web-form traps (hidden character caps, WAFs that reject apostrophes), chasing (there is usually no deadline), whether what comes back may be republished, and parsing multi-year tables without silent errors.

2016judea/sms-native-product

Build a product whose interface is text messages rather than an app or a website — "no app, no website", "they just text a number", "chat with our agent natively in Text Messages", "can we do this over text", "an SMS bot", "a Telegram bot", "make it a group chat", "minimum viable friction". Fires equally when it has already gone wrong — "my campaign got rejected", "our number is blocked", "the texts aren't arriving", "why do I need to register". Covers the gate that decides whether such a product can send at all (US A2P 10DLC registration, SHAFT content rules, permanent rejection codes), group MMS from code, what each channel can't do, an architecture that survives losing the channel, and guarding model-rewritten user content.

2016judea/vertical-market-agent

Build a chat agent that knows one industry in one metro better than any general model because it carries a precomputed digest of real public records (or a mined review corpus) and can pull live records mid-conversation — finding the moat, building a byte-stable substrate, enumerating what the records can't, the data traps that produce plausible wrong numbers, deterministic math in tools, measured prompt cost and cache TTL, shipping as an ad destination, an off-sector ending, and a precomputed spatial "what is this next to" layer. Use when building a vertical AI agent grounded in records rather than general knowledge.

Verwandte Skills