CommunityCodierung & Entwicklunggithub.com

smith-ai-lab/smith-check

smith check, smith fmt und smith lint: Projektprüfung vor dem Commit, Formatierung mit .clang-format, clang-tidy mit .clang-tidy und für .smith-Dateien. Laden vor dem Commit, bei Fehlschlag einer Prüfung oder bei ‚Code sollte clang-formatiert sein‘ und clang-tidy-Befunden.

Was ist smith-check?

Der Skill `smith-ai-lab/smith-check` bündelt die wesentlichen Code-Qualitätswerkzeuge für smith-Projekte: Formatierung (clang-format), statische Analyse (clang-tidy) und den Sprachserver (clangd), alle nahtlos in den smith-Workflow integriert. Er vereinheitlicht die Ausführung dieser Tools über verschiedene Plattformen hinweg, sodass Formatierung und Lint-Ergebnisse unabhängig von der Umgebung reproduzierbar sind. Der Skill unterstützt inkrementelle Lint-Läufe mit Caching, automatische Formatierung von C, C++, Objective-C und `.smith`-Dateien sowie die Prüfung von Projektdokumentation. Besonders hervorzuheben ist die intelligente Behandlung von `.smith`-Dateien im neuen Syntax, die nicht durch clang-format, sondern durch smiths eigenen Formatierer bearbeitet werden. Der Skill eignet sich sowohl für die lokale Entwicklung als auch für CI-Pipelines und kann mit dem Befehl `smith check` eine vollständige Qualitätskette (Formatierung, Lint, Tests, Beweise) auslösen. Durch die automatische Erkennung von `.clang-format`- und `.clang-tidy`-Konfigurationen im Projektverzeichnis arbeitet er sofort einsatzbereit, ohne dass manuelle Setup-Schritte erforderlich sind.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/smith-ai-lab/smith/tree/HEAD/.agents/skills/smith-check

Installed? Explore more Codierung & Entwicklung skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

In Ihrer bevorzugten KI fragen

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

Dokumentation

smith check, fmt, lint und lsp

smith fmt, smith lint und smith lsp sind clang-format, clang-tidy und clangd, die aus demselben LLVM wie der Compiler in smith eingebunden sind, sodass auf jedem Rechner gleich formatiert und gelintet wird.

Im Projekt: ohne Argumente

Die Verben bedeuten in jedem Projekt dasselbe und lesen, was build.c deklariert; ein Projekt schreibt keine Aufgabe dafür.

  • smith fmt überschreibt jede C-, C++-, Objective-C- und .smith-Datei, die git sieht (getrackt und ungetrackt, aber nicht ignoriert; .c .h .m .mm .cpp .cc .cxx .hpp .hh .smith .metal) gemäß .clang-format (eine .metal-Datei wird als C++ formatiert, die Sprache, die clang-format einer Erweiterung gibt, die es nicht kennt). smith fmt --dry-run (oder -n, mit --Werror oder -i) und smith lint --quiet sind ebenfalls die Projektformen: ausschließlich Optionen, keine Dateinamen, sodass sie nie auf die Standardeingabe warten; jede andere Option oder ein Dateiname macht sie zu den Werkzeugen (smith fmt --assume-filename=x.c liest die Standardeingabe). Eine in .clang-format-ignore genannte Datei (clang-format liest sie selbst: ein generiertes parser.c, eine Testvorlage) bleibt unberührt. Außerhalb eines Git-Repositories wird gesagt, die Dateien zu benennen (smith fmt -i <dateien>).
  • smith lint baut, was die Compilate lesen (generierte Header), und führt dann clang-tidy mit .clang-tidy auf den eigenen Quellen des Projekts unter den Compilaten des Builds aus (smith_object und smith_compile_command für Quellen, die der Build nie compiliert), nebeneinander. Nicht .smith/, build/-Ausgaben oder Pakete. Jede .smith-Quelle wird gelintet wie smith lint x.smith -- <flags>: die eigenen mit ihrem Compile-Befehl und jede andere von git gesehene .smith-Datei mit dem Befehl des nächstgelegenen Compilats, außer was .clang-format-ignore nennt (die eine Liste von Dateien, die keine gewöhnlichen Quellen sind: Testeingaben, absichtlich falsche Vorlagen, generierte und kopierte Dateien; smith fmt liest sie auch, es gibt also keine zweite Liste). Ein Befund lässt den Lint fehlschlagen; seine letzte Zeile lautet linted N files (smith check: lint ok: N files), und ein Projekt mit .smith-Quellen, das keine lintet, schlägt fehl. Ein .clang-tidy in einem Ordner (z. B. InheritParentConfig: true mit anderen Checks) gilt dort.
  • smith lint ist inkrementell: clang-tidys Ergebnis für eine Datei wird unter ~/.cache/smith/lint zwischengespeichert und wiedergegeben, solange die Datei, das, was sie inkludiert (für eine .smith-Datei auch die generierten Header der Module, die sie importiert), ihr .clang-tidy und smith unverändert sind, sodass die letzte Zeile smith lint: linted 180 files (3 run, 177 cached, 1.2 s) lautet und ein unveränderter Baum clang-tidy auf keiner Datei ausführt. SMITH_LINT_CACHE=0 schaltet es aus, SMITH_LINT_CACHE=why sagt, warum eine Datei lief, smith cache clean lint leert es. Eine Datei, deren clang-tidy fehlschlägt, wird in den letzten Zeilen genannt (smith lint: c.c: exited with status 1 oder was killed by signal 9, was nichts Eigenes ausgibt) und am Ende ihrer eigenen Ausgabe.
  • smith lint --changed[=<ref>] lintet nur die Dateien, die seit dem Merge-Base mit <ref> geändert wurden (Standard: der Upstream des Branches, sonst der Branch von origin/HEAD oder origin/main, niemals ein lokales main; keiner davon ist ein Fehler, der --changed=<ref> benennt; die ausgegebene Zeile nennt die Basis; Bearbeitungen und ungetrackte Dateien zählen) sowie die Dateien, die sie inkludieren oder importieren; ein geändertes .clang-tidy, eine Build-Datei, shim/ oder patches/ wählt jede Datei aus, und nichts Betroffenes sagt dies und wird erfolgreich. Normales smith lint lintet alles (CI). Eine Datei, die auf ein Paket wartet, das das Netzwerk nicht bereitstellt (der Tree-Sitter-Parser in einer Cloud-Sandbox), wird namentlich übersprungen (smith lint: skipped runtime/tree_sitter_data.c: the tree-sitter parser it embeds cannot be fetched (<url>)) und der Rest wird gelintet; CI (CI oder SMITH_PRIORITY=ci) schlägt stattdessen fehl. smith lint DATEI in einem noch nicht gebauten Projekt (kein compile_commands.json) stoppt und sagt, einmal smith build smith_needs auszuführen, anstatt die fehlenden generierten Header als Fehler zu melden.
  • smith docs prüft knowledge/ und die Skills (smith-docs).
  • smith check führt fmt (clang-formats Trockenlauf), docs, lint, test und prove in dieser Reihenfolge aus und stoppt nicht bei einem Fehlschlag: jeder Teil gibt eine Zeile aus, smith check: <teil> ok: <detail> (<n> s wall, <n> s cpu) oder FAILED (status N) mit einem begrenzten Auszug des Fehlschlags und dem Pfad des vollständigen Logs (.smith/log/<teil>.log; die Ausgabe eines erfolgreichen Teils ist ebenfalls dort; smith check -v gibt alles aus, während es passiert), dann smith check: promises: N (was smith vertraut, aus einem Standard-Build, den es bei Bedarf erstellt), und die letzte Zeile ist smith check: ok oder smith check: failed: <teile>; der Exit-Status ist 1, wenn einer fehlschlug. Die Prove-Zeile sagt die Abdeckung, smith check: prove ok (4 of 23 functions): ... (Funktionen mit eigenem Vertrag, vom Projekt; 0 of N functions, wenn es nichts zu beweisen gibt, was ein Erfolg ist; nichts schlägt bei geringer Abdeckung fehl). Jede Teilzeile endet mit ihrer Wall- und CPU-Zeit ((91.2 s wall, 480.1 s cpu): CPU ist User plus System, des Teils und der Prozesse, auf die er wartete). Es akzeptiert keine Argumente außer -D-Optionen und -v. Auf einem Host, der nicht macOS ist, führt es die Tests mit --skip-macos aus und sagt dies (the macOS-only tests do not run on this host). smith test endet mit einer Tabelle der Build-Aufgaben (.smith/task/<name>-Schritte, wie smiths eigene test-<name>), die Langsamsten zuerst: Wall-, CPU- und Systemsekunden sowie die Anzahl der von jedem gestarteten smith-Prozesse (SMITH_START_LOG, das smith beim Start von main anhängt; eine Aufgabe, die die Umgebung löscht, wird nicht gezählt); die langsamsten acht, jede Aufgabe mit smith check -v oder SMITH_ACCOUNT=all, keine mit SMITH_ACCOUNT=no. Die Aufgaben laufen über smith --smith-account <datei> <name> <befehl...>, das die Zeile schreibt.
  • .smith-Dateien im neuen Syntax sind nicht clang-formats (#1890, #1886, #2040): smith fmt sendet eine .smith-Datei an smiths eigenen Formatierer (front::format), es sei denn, sie ist im heutigen Syntax (eine Zeile beginnt mit einer Form, die nur der heutige Syntax oder C hat, der heutige Parser liest sie ohne Fehler, oder ihr erster Fehler im neuen Syntax hat eine Korrektur, wie ein //-Kommentar) oder hat einen Parse-Fehler und keine Zeile, die nur der neue Syntax hat (fn, let, pub, #): ein Stil und kein .clang-format dafür (jede konsistente Einrückung erfolgt mit 4 Leerzeichen, eine Anweisung pro Zeile, #-Kommentare bleiben erhalten). Eine neue Syntax-Datei mit einem Parse-Fehler wird als pfad:zeile:spalte: nachricht gemeldet, Byte für Byte unverändert gelassen (auch mit --dry-run) und lässt smith fmt mit Exit-Code 1 beenden: Sie wird niemals an clang-format gesendet, was sie verstümmeln würde. Es ist idempotent, beachtet .clang-format-ignore, und --dry-run / -n nennt die Dateien, die sich ändern würden (pfad: would be formatted), ohne zu schreiben. Eine .smith-Datei im heutigen Syntax (und jede .c) bleibt bis zum Wechsel (#1631), der diesen Fallback entfernt, bei clang-format. Getestet durch tests/fmt_smith_test.smith.
  • smith fmt DATEI lehnt eine Datei ab, deren Erweiterung nicht eine dieser ist (eine .sh, eine .md), mit einem Fehler, der die Datei nennt und nichts schreibt, da clang-format sie als C lesen und beschädigen würde; --assume-filename=x.c sagt, was sie ist.
  • Vor dem Commit: smith fmt, dann smith check.
  • Eine eigene Aufgabe (eine benutzerdefinierte Prüfung, ein Generator) ist smith_task in build.c und läuft mit smith build <aufgabe>; keine Aufgabe oder Alias darf fmt, lint, docs, prove, check, run oder test heißen. smith build check und die anderen Verbnamen werden abgelehnt: Verwende das Verb.

Für Dateien: mit Argumenten

smith lint VERZ (ein Ordner unter den Argumenten) lintet die C-, C++-, Objective-C- und .smith-Quellen darunter, die git sieht und .clang-format-ignore nicht nennt, wie das Projekt-Lint (keine Header, die durch ihre Quellen gelesen werden); smith lint front -- <flags> und smith lint front/ main.c mischen sich mit Dateien. Ein Ordner ohne solche Quelle ist ein Fehler.

clang-tidys Analyzer (clang-analyzer-*) liest smith_requires, smith_ensures, smith_invariant und smith_assert von <smith/contract.h> als Annahmen (target::static_analyzer), sodass ein Index, der durch einen Vertrag begrenzt ist, nicht von clang-analyzer-security.ArrayBound gemeldet wird.

smiths standardmäßiges .clang-tidy schaltet zwei Analyzer-Prüfungen aus, die Rauschen waren (bei game, learner und smith: 546 von 616 Befunden): clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling (jedes memcpy) und clang-analyzer-optin.performance.Padding. Schalte eine im eigenen .clang-tidy des Projekts wieder ein (smith lint --dump-config > .clang-tidy schreibt die effektive Datei), indem du ihre -clang-analyzer-...-Zeile löschst.

smith lint --fix DATEI.smith... (kein --) wendet die Korrekturen an, die smiths eigener Front-End in seinen Parse-Fehlern trägt (eine alte oder C-artige Form mit ihrer smith-Schreibweise: die Bearbeitungen einer Korrektur werden zusammen oder gar nicht angewendet, eine überlappende Korrektur wird übersprungen, und eine Datei wird erneut geparst, bis nichts mehr zutrifft, maximal 16 Durchgänge) und gibt pfad: N fixes applied aus; ein zweiter Lauf gibt 0 fixes applied aus. Es liest nur .smith-Dateien und benötigt den vollständigen smith. Mit -- <flags> ist es clang-tidys --fix, wie oben. Noch trägt kein Parse-Fehler eine Korrektur: Die alten Formen erhalten ihre ticketweise (#1428).

smith lint DATEI fügt --extra-arg=-I für build/<os>/front-project/.smith/include hinzu, wenn dieser Ordner existiert (Front-Module importieren sich gegenseitig durch ihn), und gibt auf einem Host, der nicht macOS ist, eine Zeile aus: CI lintet auf einem Mac, wo u64 unsigned long long und usize unsigned long ist, sodass (U64)(i + 1) mit einem usize ein bugprone-misplaced-widening-cast-Befund nur dort ist; behebe einen solchen Cast, indem du (U64)i + 1 schreibst.

Mit Argumenten sind sie die Werkzeuge: smith fmt main.c überschreibt die Datei an Ort und Stelle (clang-format würde sie ausgeben; smith fügt -i hinzu, wenn du Dateien benennst und keine Option einen anderen Modus wählt: -n, --dry-run, --lines, --assume-filename behalten clang-formats Bedeutung, und smith fmt --assume-filename=x.c < x.c gibt das Ergebnis aus), smith fmt --dry-run --Werror main.c, smith lint --quiet main.c -- <flags>, smith lsp --check=main.c. Das .clang-format und .clang-tidy des Projekts gelten. Ein Stage0-smith führt die Werkzeuge von Homebrew aus, oder $SMITH_CLANG_FORMAT, $SMITH_CLANG_TIDY, $SMITH_CLANGD.

smiths Voreinstellungen, wenn ein Projekt keine Datei hat (Issue #43). Ein Projekt ohne .clang-format (oder _clang-format) und ohne .clang-tidy, die von jedem Dateiordner und aufwärts gesucht werden, wie es clang-format und clang-tidy tun, wird mit smiths eigenen, in smith eingebetteten (den Dateien, die smith new heute schreibt) formatiert und gelintet; es gibt nichts zu schreiben. Eine Datei im Projekt ersetzt smiths gesamte, niemals zusammengeführt, und ein explizites --style (oder --fallback-style), --config oder --config-file gewinnt. Bei Standardeingabe gibt --assume-filename an, wo gesucht werden soll. Das Benennen von Dateien mit und ohne eine Projektdatei in einem Befehl funktioniert (smith führt die zweite Art als einen anderen Prozess aus). smith fmt --dump-config > .clang-format und smith lint --dump-config > .clang-tidy geben die effektive Konfiguration aus (die des Projekts, sonst smiths), sodass ein Projekt die Voreinstellungen übernimmt, indem es sie ausgibt und bearbeitet, was es möchte; die Voreinstellungen ändern sich selten und absichtlich, sodass ein Projekt, das sie fixiert haben möchte, sie ausgibt. smith schreibt seine Kopie nach $XDG_DATA_HOME/smith/defaults/ (sonst ~/.local/share/...). smith cc ist nie betroffen: Es bleibt ein reiner Passthrough.

.smith-Dateien

smith fmt x.smith (und -i, --dry-run, Standardeingabe mit --assume-filename=x.smith) formatiert eine .smith-Datei als C, wobei ihre ::-Pfade, module a::b;- und import a::b as x;-Zeilen sowie import <sys/wait.h>; ganz erhalten bleiben; smith fmt ohne Argumente formatiert auch die .smith-Dateien des Projekts (git sieht sie). import und module innerhalb einer Funktion sind Namen, wie in C. Benötigt einen smith, dessen clang-format den .smith-Patch hat (ein Stage0 führt Homebrews aus, das .smith als C++ liest und daher C-Namen, die C++-Schlüsselwörter sind, wie throw falsch liest). clangd formatiert .smith-Dateien auf dieselbe Weise.

smith lint x.smith -- <flags> (clang-tidy, mit dem .clang-tidy des Projekts) lintet eine .smith-Datei, wie smith cc sie liest (-x c und -std=gnu2y, es sei denn, du nennst einen Standard; ein Compile-Datenbank-eigener Befehl wird so verwendet, wie er ist), und meldet die Quelle, wie sie geschrieben ist: Befunde, Notizen und Fix-Its an den Zeilen und Spalten des .smith-Texts, mit den Namen wie geschrieben (area und Box im Modul, box::area, wo es importiert wird, niemals geometry_box_area). readability-identifier-naming beurteilt den geschriebenen Namen eines dateibereichsweiten Namens eines Moduls, sodass die Regeln der Vorlage (snake_case-Funktionen und -Variablen, PascalCase-Typen) für area und Box gelten, und --fix schreibt das Token in der Quelle um; die size-Typen (U32, I32), die Kopien der Prototypen durch die Senkung und die Header, die smith build schreibt, werden niemals gemeldet. Ein Befund über einen Export wird in der Datei des Moduls gemeldet, nicht in jedem Importeur, und eine Korrektur dort benennt die Importeure nicht um. Andere Checks zeigen die geschriebenen Namen in ihren Nachrichten, aber ein Check, der den Namen selbst vergleicht (ein Längen- oder reservierte-Namen-Check, z. B.) liest immer noch den gesenkten. Benötigt einen smith, dessen clang den Token-Hook hat (smith cc --smith-which x.smith sagt token-hook yes); ein Stage0 führt Homebrews clang-tidy aus, das .smith nicht lesen kann.

Ebenfalls in dieser Familie: smith-check-lints.

Verwandte Skills