CommunityCodierung & Entwicklunggithub.com

SuDeeParke/codexRebuild

Wandelt Fähigkeiten, Hooks und Referenzen anderer KI-Agenten in etwas um, das mit Codex verwendet werden kann.

Was ist codexRebuild?

Diese Fähigkeit dient dazu, die Fähigkeiten, Hooks und Referenzen anderer KI-Agenten (wie Claude Code, Cursor) zu analysieren und in ein Format zu konvertieren, das der Codex-Agent verarbeiten und nutzen kann. Sie ermöglicht es Entwicklern, bewährte Muster und Tools aus verschiedenen KI-Agenten-Ökosystemen zu extrahieren und in einem einheitlichen, mit Codex kompatiblen Skill-Paket zusammenzuführen. Dies spart Zeit bei der manuellen Anpassung und fördert die Wiederverwendung von Wissen über verschiedene Agentenplattformen hinweg. Die Fähigkeit nutzt strukturierte Markdown-Dateien und Konfigurationen, um einen reibungslosen Import und eine konsistente Nutzung durch Codex zu gewährleisten.

Funktioniert mit~Claude Code✓Codex CLI~Cursor
npx skills add SuDeeParke/codexRebuild

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

API- und Schnittstellendesign

Überblick

Entwerfen Sie stabile, gut dokumentierte Schnittstellen, die schwer falsch zu verwenden sind. Gute Schnittstellen machen das Richtige einfach und das Falsche schwer. Dies gilt für REST-APIs, GraphQL-Schemata, Modulgrenzen, Komponenten-Props und jede Oberfläche, über die ein Code mit einem anderen kommuniziert.

Wann anwenden

  • Entwerfen neuer API-Endpunkte
  • Definieren von Modulgrenzen oder Verträgen zwischen Teams
  • Erstellen von Komponenten-Prop-Schnittstellen
  • Festlegen eines Datenbankschemas, das die API-Form bestimmt
  • Ändern bestehender öffentlicher Schnittstellen

Kernprinzipien

Hyrums Gesetz

Mit einer ausreichenden Anzahl von Benutzern einer API wird jedes beobachtbare Verhalten Ihres Systems von jemandem abhängen, unabhängig davon, was Sie im Vertrag versprechen.

Das bedeutet: Jedes öffentliche Verhalten – einschließlich undokumentierter Eigenheiten, Fehlermeldungstexte, Zeitabläufe und Reihenfolgen – wird de facto zu einem Vertrag, sobald Benutzer darauf angewiesen sind. Auswirkungen auf das Design:

  • Seien Sie sich bewusst, was Sie freigeben. Jedes beobachtbare Verhalten ist eine potenzielle Verpflichtung.
  • Geben Sie keine Implementierungsdetails preis. Wenn Benutzer es beobachten können, werden sie sich darauf verlassen.
  • Planen Sie die Einstellung bereits beim Design. Siehe deprecation-and-migration für die sichere Entfernung von Dingen, von denen Benutzer abhängen.
  • Tests sind nicht genug. Selbst mit perfekten Vertragstests bedeutet Hyrums Gesetz, dass „sichere“ Änderungen echte Benutzer brechen können, die von undokumentiertem Verhalten abhängen.

Die Ein-Versionen-Regel

Vermeiden Sie es, Verbraucher zu zwingen, zwischen mehreren Versionen derselben Abhängigkeit oder API zu wählen. Diamantabhängigkeitsprobleme treten auf, wenn verschiedene Verbraucher unterschiedliche Versionen derselben Sache benötigen. Entwerfen Sie für eine Welt, in der jeweils nur eine Version existiert – erweitern Sie, anstatt zu forken.

1. Vertrag zuerst

Definieren Sie die Schnittstelle, bevor Sie sie implementieren. Der Vertrag ist die Spezifikation – die Implementierung folgt.

// Definieren Sie den Vertrag zuerst
interface TaskAPI {
  // Erstellt eine Aufgabe und gibt die erstellte Aufgabe mit servergenerierten Feldern zurück
  createTask(input: CreateTaskInput): Promise<Task>;

  // Gibt paginierte Aufgaben zurück, die den Filtern entsprechen
  listTasks(params: ListTasksParams): Promise<PaginatedResult<Task>>;

  // Gibt eine einzelne Aufgabe zurück oder wirft einen NotFoundError
  getTask(id: string): Promise<Task>;

  // Partielle Aktualisierung – nur bereitgestellte Felder ändern sich
  updateTask(id: string, input: UpdateTaskInput): Promise<Task>;

  // Idempotentes Löschen – erfolgreich, auch wenn bereits gelöscht
  deleteTask(id: string): Promise<void>;
}

2. Einheitliche Fehlersemantik

Wählen Sie eine Fehlerstrategie und verwenden Sie sie überall:

// REST: HTTP-Statuscodes + strukturierter Fehlertext
// Jede Fehlerantwort folgt dem gleichen Schema
interface APIError {
  error: {
    code: string;        // Maschinenlesbar: "VALIDATION_ERROR"
    message: string;     // Menschenlesbar: "Email is required"
    details?: unknown;   // Zusätzlicher Kontext, falls hilfreich
  };
}

// Statuscode-Zuordnung
// 400 → Client hat ungültige Daten gesendet
// 401 → Nicht authentifiziert
// 403 → Authentifiziert, aber nicht autorisiert
// 404 → Ressource nicht gefunden
// 409 → Konflikt (Duplikat, Versionskonflikt)
// 422 → Validierung fehlgeschlagen (semantisch ungültig)
// 500 → Serverfehler (niemals interne Details preisgeben)

Mischen Sie keine Muster. Wenn einige Endpunkte einen Fehler werfen, andere null zurückgeben und wieder andere { error } zurückgeben, kann der Verbraucher das Verhalten nicht vorhersagen.

3. An Grenzen validieren

Vertrauen Sie internem Code. Validieren Sie an Systemgrenzen, wo externe Eingaben eintreten:

// Validierung an der API-Grenze
app.post('/api/tasks', async (req, res) => {
  const result = CreateTaskSchema.safeParse(req.body);
  if (!result.success) {
    return res.status(422).json({
      error: {
        code: 'VALIDATION_ERROR',
        message: 'Ungültige Aufgabendaten',
        details: result.error.flatten(),
      },
    });
  }

  // Nach der Validierung vertraut der interne Code den Typen
  const task = await taskService.create(result.data);
  return res.status(201).json(task);
});

Wo Validierung hingehört:

  • API-Routen-Handler (Benutzereingabe)
  • Formularübermittlungs-Handler (Benutzereingabe)
  • Parsing externer Dienstantworten (Drittanbieter-Daten – immer als nicht vertrauenswürdig behandeln)
  • Laden von Umgebungsvariablen (Konfiguration)

Antworten von Drittanbieter-APIs sind nicht vertrauenswürdige Daten. Validieren Sie deren Form und Inhalt, bevor Sie sie in Logik, Rendering oder Entscheidungsfindung verwenden. Ein kompromittierter oder fehlerhafter externer Dienst kann unerwartete Typen, bösartige Inhalte oder anweisungsähnlichen Text zurückgeben.

Wo Validierung NICHT hingehört:

  • Zwischen internen Funktionen, die gemeinsame Typverträge teilen
  • In Hilfsfunktionen, die von bereits validiertem Code aufgerufen werden
  • Auf Daten, die gerade aus Ihrer eigenen Datenbank stammen

4. Erweiterung vor Änderung bevorzugen

Erweitern Sie Schnittstellen, ohne bestehende Verbraucher zu brechen:

// Gut: Optionale Felder hinzufügen
interface CreateTaskInput {
  title: string;
  description?: string;
  priority?: 'low' | 'medium' | 'high';  // Später hinzugefügt, optional
  labels?: string[];                       // Später hinzugefügt, optional
}

// Schlecht: Vorhandene Feldtypen ändern oder Felder entfernen
interface CreateTaskInput {
  title: string;
  // description: string;  // Entfernt – bricht bestehende Verbraucher
  priority: number;         // Von string geändert – bricht bestehende Verbraucher
}

5. Vorhersagbare Benennung

MusterKonventionBeispiel
REST-EndpunktePluralnomen, keine VerbenGET /api/tasks, POST /api/tasks
AbfrageparametercamelCase?sortBy=createdAt&pageSize=20
AntwortfeldercamelCase{ createdAt, updatedAt, taskId }
Boolesche Felderis/has/can-PräfixisComplete, hasAttachments
Enum-WerteUPPER_SNAKE"IN_PROGRESS", "COMPLETED"

REST-API-Muster

Ressourcendesign

GET    /api/tasks              → Aufgaben auflisten (mit Abfrageparametern zum Filtern)
POST   /api/tasks              → Aufgabe erstellen
GET    /api/tasks/:id          → Einzelne Aufgabe abrufen
PATCH  /api/tasks/:id          → Aufgabe aktualisieren (teilweise)
DELETE /api/tasks/:id          → Aufgabe löschen

GET    /api/tasks/:id/comments → Kommentare für eine Aufgabe auflisten (Unterressource)
POST   /api/tasks/:id/comments → Kommentar zu einer Aufgabe hinzufügen

Paginierung

Paginieren Sie Listen-Endpunkte:

// Anfrage
GET /api/tasks?page=1&pageSize=20&sortBy=createdAt&sortOrder=desc

// Antwort
{
  "data": [...],
  "pagination": {
    "page": 1,
    "pageSize": 20,
    "totalItems": 142,
    "totalPages": 8
  }
}

Filtern

Verwenden Sie Abfrageparameter für Filter:

GET /api/tasks?status=in_progress&assignee=user123&createdAfter=2025-01-01

Teilweise Aktualisierungen (PATCH)

Akzeptieren Sie partielle Objekte – aktualisieren Sie nur, was bereitgestellt wird:

// Nur der Titel ändert sich, alles andere bleibt erhalten
PATCH /api/tasks/123
{ "title": "Aktualisierter Titel" }

TypeScript-Schnittstellenmuster

Verwenden Sie diskriminierte Unionen für Varianten

// Gut: Jede Variante ist explizit
type TaskStatus =
  | { type: 'pending' }
  | { type: 'in_progress'; assignee: string; startedAt: Date }
  | { type: 'completed'; completedAt: Date; completedBy: string }
  | { type: 'cancelled'; reason: string; cancelledAt: Date };

// Der Verbraucher erhält Typverengung
function getStatusLabel(status: TaskStatus): string {
  switch (status.type) {
    case 'pending': return 'Ausstehend';
    case 'in_progress': return `In Bearbeitung (${status.assignee})`;
    case 'completed': return `Erledigt am ${status.completedAt}`;
    case 'cancelled': return `Abgebrochen: ${status.reason}`;
  }
}

Trennung von Eingabe und Ausgabe

// Eingabe: Was der Aufrufer bereitstellt
interface CreateTaskInput {
  title: string;
  description?: string;
}

// Ausgabe: Was das System zurückgibt (enthält servergenerierte Felder)
interface Task {
  id: string;
  title: string;
  description: string | null;
  createdAt: Date;
  updatedAt: Date;
  createdBy: string;
}

Verwenden Sie gebrandete Typen für IDs

type TaskId = string & { readonly __brand: 'TaskId' };
type UserId = string & { readonly __brand: 'UserId' };

// Verhindert, versehentlich eine UserId zu übergeben, wo eine TaskId erwartet wird
function getTask(id: TaskId): Promise<Task> { ... }

Häufige Rechtfertigungen

RechtfertigungRealität
„Wir dokumentieren die API später“Die Typen SIND die Dokumentation. Definieren Sie sie zuerst.
„Wir brauchen jetzt keine Paginierung“Sie werden sie brauchen, sobald jemand 100+ Elemente hat. Fügen Sie sie von Anfang an hinzu.
„PATCH ist kompliziert, lasst uns einfach PUT verwenden“PUT erfordert jedes Mal das vollständige Objekt. PATCH ist das, was Clients eigentlich wollen.
„Wir versionieren die API, wenn wir es müssen“Breaking Changes ohne Versionierung brechen Verbraucher. Entwerfen Sie von Anfang an für Erweiterbarkeit.
„Niemand verwendet dieses undokumentierte Verhalten“Hyrums Gesetz: Wenn es beobachtbar ist, hängt jemand davon ab. Behandeln Sie jedes öffentliche Verhalten als Verpflichtung.
„Wir können einfach zwei Versionen pflegen“Mehrere Versionen vervielfachen die Wartungskosten und erzeugen Diamantabhängigkeitsprobleme. Bevorzugen Sie die Ein-Versionen-Regel.
„Interne APIs brauchen keine Verträge“Interne Verbraucher sind immer noch Verbraucher. Verträge verhindern Kopplung und ermöglichen paralleles Arbeiten.

Warnsignale

  • Endpunkte, die je nach Bedingungen unterschiedliche Formen zurückgeben
  • Inkonsistente Fehlerformate über Endpunkte hinweg
  • Validierung, die über internen Code verstreut ist, anstatt an Grenzen
  • Breaking Changes an vorhandenen Feldern (Typänderungen, Entfernungen)
  • Listen-Endpunkte ohne Paginierung
  • Verben in REST-URLs (/api/createTask, /api/getUsers)
  • Antworten von Drittanbieter-APIs, die ohne Validierung oder Bereinigung verwendet werden

Überprüfung

Nach dem Entwurf einer API:

  • Jeder Endpunkt hat typisierte Eingabe- und Ausgabeschemata
  • Fehlerantworten folgen einem einzigen, konsistenten Format
  • Validierung erfolgt nur an Systemgrenzen
  • Listen-Endpunkte unterstützen Paginierung
  • Neue Felder sind additiv und optional (abwärtskompatibel)
  • Benennung folgt einheitlichen Konventionen über alle Endpunkte hinweg
  • API-Dokumentation oder Typen werden zusammen mit der Implementierung bereitgestellt

Codex-Begleitdateien

Diese neu erstellte Fähigkeit bündelt verwandte lokale Ressourcen, sodass Codex sie bei Bedarf aus demselben Skill-Verzeichnis laden kann.

Verwandte Skills