conduct-empirical-wire-capture
정보
이 스킬은 CLI 도구의 런타임 중 발생하는 아웃바운드 HTTP 트래픽과 텔레메트리를 포착합니다. 여러 캡처 채널과 형식을 지원하며, 각 대상에 가장 효율적인 방법을 매핑합니다. 정적 분석 결과를 검증하거나, 클라이언트 재구현을 위한 페이로드를 캡처하거나, 다크 테스트와 라이브 테스트 간 실제 바이너리 동작을 관찰하는 데 사용할 수 있습니다.
빠른 설치
Claude Code
추천npx skills add pjt222/agent-almanac -a claude-code/plugin add https://github.com/pjt222/agent-almanacgit clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/conduct-empirical-wire-captureClaude Code에서 이 명령을 복사하여 붙여넣어 스킬을 설치하세요
문서
Conduct Empirical Wire Capture
Einen reproduzierbaren Wire-Capture-Harness für den ausgehenden HTTP-Verkehr und die Telemetrie eines CLI-Werkzeugs einrichten und dabei jedes Observability-Ziel dem kostengünstigsten Kanal zuordnen, der es erfasst.
Geltungsbereich und Ethik
Vor der Konfiguration jeglicher Erfassung lesen.
- Wire Capture ist ausschließlich für eigene Anfragen gegen das eigene Konto auf der eigenen Maschine gedacht. Das Erfassen des Datenverkehrs anderer Nutzer ist Exfiltration, keine Forschung, und liegt außerhalb des Geltungsbereichs.
- In rohen Wire-Ausgaben tauchen fast immer Zugangsdaten auf. Redaktion zum Zeitpunkt der Erfassung durchführen (Schritt 6) — niemals nach dem Motto „erst erfassen, später redigieren".
- Erfassung ist Beobachtung, keine Modifikation. Erfasste Payloads nicht dazu nutzen, serverseitige Rate-Limits zu umgehen, die Sitzung eines anderen Nutzers zu replayen oder eine dunkel ausgerollte Fähigkeit ohne Autorisierung zu aktivieren.
- Das Ergebnis dieses Skills ist ein internes Artefakt. Die öffentliche Veröffentlichung von Wire-Befunden läuft über
redact-for-public-disclosure(Phase 5 des übergeordneten Leitfadens), nicht über diesen Skill.
Wann verwenden
- Ein statischer Befund (ein Flag, eine Endpunkt-Referenz, ein Telemetrie-Ereignisname) benötigt eine Laufzeitbestätigung, dass er tatsächlich ausgelöst wird.
- Eine Payload-Form wird für eine Client-Neuimplementierung, eine Tracing-Instrumentierung oder einen versionsübergreifenden Diff benötigt.
- Eine Dark-vs-Live-Unterscheidung erfordert die Beobachtung dessen, was das Binary tatsächlich sendet — nicht dessen, was das Bundle nahelegt.
- Ein Verhalten hat sich zwischen Versionen stillschweigend geändert und ein reproduzierbares Artefakt wird benötigt, um gegen zukünftige Versionen zu vergleichen.
Diesen Skill nicht verwenden für: Versions-Baselining (dafür monitor-binary-version-baselines), Flag-Zustandsprüfung (dafür probe-feature-flag-state) oder das Vorbereiten redigierter Artefakte zur öffentlichen Veröffentlichung (dafür redact-for-public-disclosure).
Eingaben
- Erforderlich: Ein CLI-Harness-Binary, das lokal gegen das eigene Konto ausgeführt werden kann.
- Erforderlich: Eine konkrete Frage, die beantwortet werden soll (z. B. „feuert Endpunkt X bei Ereignis Y?", „wie sieht die Payload-Form für Telemetrie-Ereignis Z aus?"). Eine Erfassung ohne Fragestellung erzeugt ein Log, das niemand liest.
- Optional: Statische Befunde aus vorangegangenen Phasen (Marker-Katalog, Kandidaten-Flag-Liste, verdächtige Endpunkte), die die Erfassungsziele eingrenzen.
- Optional: Ein privater Arbeitsbereich-Pfad für Erfassungsartefakte. Standard ist
./captures/— muss in.gitignorestehen.
Vorgehen
Schritt 1: Zuerst die Observability-Tabelle aufbauen
Bevor irgendeine Erfassung konfiguriert wird, die zu beantwortenden Fragen auflisten und jede einem Erfassungskanal zuordnen. Eine Zeile pro Ziel.
| target | observable via | blocker |
|---|---|---|
| Outbound HTTP to endpoint X | verbose-fetch stderr | TUI noise pollutes terminal |
| Telemetry event Y on user action | hook-driven subprocess | requires harness hook surface |
| Token-refresh handshake | outbound HTTP proxy | cert trust required |
| Scheduled-task lifecycle event | long-running session capture | wallclock alignment |
| Local config mutation | on-disk state diff | none — cheapest channel |
Gängige Kanäle, kostengünstigster zuerst:
- Mutation der Zustandsdatei auf Platte — wenn der Harness seinen Zustand auf einen bekannten Pfad schreibt, ist
diffzwischen Snapshots kostenlos. - Transkriptdatei — wenn der Harness ohnehin ein Sitzungstranskript schreibt, dieses direkt parsen. Keine Instrumentierung nötig.
- Verbose-Fetch-stderr — vom Bundler bereitgestellte Umgebungsvariable (z. B. Buns
BUN_CONFIG_VERBOSE_FETCH=curl) leitet jeden Fetch an stderr. Laut, erfasst aber jeden Fetch. - Hook-getriebener Subprozess — wenn der Harness Lifecycle-Hooks exponiert (
UserPromptSubmit,Stopusw.), für jedes Ereignis einen kurzen Erfassungs-Subprozess starten. - Langlaufende Sitzungserfassung — ein Prozess über die gesamte Sitzung, mit Wallclock versehen. Für Sequenzen verwenden.
- Ausgehender HTTP-Proxy — saubere Trennung, erfordert aber CA-Zertifikatsvertrauen und bricht, wenn der Harness Zertifikate pinnt.
Den kostengünstigsten Kanal wählen, der das Ziel erfasst. Eine Erfassung mit 3 Zielen, die eine konkrete Frage beantwortet, schlägt eine Erfassung mit 20 Zielen, die keine beantwortet.
Expected: eine Observability-Tabelle mit einer Zeile pro Frage, jeweils mit Kanal und bekannten Blockern annotiert. Ziele ohne tragfähigen Kanal werden als „außerhalb des Geltungsbereichs dieser Sitzung" gekennzeichnet.
On failure: landet jedes Ziel in der Proxy-Spalte, ist die Tabelle zu ambitioniert. Auf die ein oder zwei wertvollsten Fragen reduzieren und für diese nochmals günstigere Kanäle prüfen.
Schritt 2: Einen verwerflichen Arbeitsbereich vorbereiten
Wire Capture verschmutzt Terminals, hinterlässt Dateien an unerwarteten Orten und kann Zugangsdaten in Logs lecken.
mkdir -p captures/$(date -u +%Y-%m-%dT%H-%M-%S)
cd captures/$(date -u +%Y-%m-%dT%H-%M-%S)
echo 'captures/' >> ../../.gitignore
git check-ignore captures/ || echo "WARNING: captures/ not git-ignored"
Sicherstellen, dass die Erfassungssitzung nicht die primäre Arbeitssitzung ist — Verbose-Fetch und TUI-Rendering stören sich gegenseitig.
Expected: ein zeitgestempeltes Erfassungsverzeichnis, git-ignoriert, getrennt von der Arbeitssitzung.
On failure: meldet git check-ignore das Verzeichnis als nicht ignoriert, die .gitignore korrigieren, bevor ein Erfassungsbefehl ausgeführt wird. Nicht mit gefährdeten Zugangsdaten fortfahren.
Schritt 3: Hook-getriebene Erfassung für Einzelereignis-Ziele
Wenn das Ziel ein diskretes Ereignis ist (ein Tool-Aufruf, eine Prompt-Einreichung, ein Sitzungsstopp), die Hook-Oberfläche des Harness nutzen. Für jedes Ereignis einen kurzlebigen Erfassungs-Subprozess starten; nicht in-process verweilen.
Das Muster (synthetisches Beispiel):
# Hook script, registered with the harness's hook config.
# Invoked once per event; writes one JSONL line; exits.
#!/usr/bin/env bash
set -euo pipefail
TS=$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)
EVENT="${1:-unknown}"
PAYLOAD=$(jq -c --arg ts "$TS" --arg ev "$EVENT" \
'{ts:$ts, source:"hook", target:$ev, payload:.}' < /dev/stdin)
echo "$PAYLOAD" >> "$CAPTURE_DIR/events.jsonl"
Warum Subprozess pro Ereignis:
- Kein Tokenzustand, keine Sitzungskopplung — jeder Aufruf ist unabhängig.
- Das Fehlschlagen einer Erfassung kontaminiert die nächste nicht.
- Der Subprozess-Overhead ist akzeptabel, weil Ereignisse selten sind (pro Nutzeraktion, nicht pro Byte).
Expected: eine JSONL-Zeile pro ausgelöstem Ereignis in events.jsonl, jede wohlgeformt und per jq parsebar.
On failure: meldet jq Parse-Fehler, enthält die Payload unescapte Steuerzeichen oder Binärdaten — stattdessen durch jq -R (raw input) leiten und das Payload-Feld base64-kodieren.
Schritt 4: Langlaufende Sitzungserfassung für sequentiellen Zustand
Wenn das Ziel eine Sequenz ist (mehrstufiger Handshake, Lifecycle geplanter Aufgaben, Retry/Backoff-Zustandsautomat), einen Erfassungsprozess über die gesamte Sitzung, mit Wallclock versehen.
# Run the harness with verbose-fetch routed to a tee-d log.
BUN_CONFIG_VERBOSE_FETCH=curl harness-cli run-task 2> >(
while IFS= read -r line; do
printf '%s\t%s\n' "$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)" "$line"
done >> "$CAPTURE_DIR/session.tsv"
)
Das Wallclock-Präfix macht die Reihenfolge eindeutig, wenn mehrere Erfassungen gleichzeitig laufen. TSV (tab-getrennt) ist bewusst gewählt — es übersteht Shells, die JSON-Quoting auf stderr verstümmeln.
TSV erst nach Sitzungsende (Schritt 5) nach JSONL konvertieren, nicht währenddessen.
Expected: ein TSV-Log mit monoton steigenden Zeitstempeln, eine stderr-Zeile pro Reihe.
On failure: laufen Zeitstempel rückwärts, puffert der Harness stderr — mit stdbuf -oL -eL oder dem Line-Buffer-Flag des Bundlers neu ausführen.
Schritt 5: Auf JSONL normalisieren
JSONL ist das Artefaktformat: ein JSON-Objekt pro Zeile, Felder timestamp, source, target, payload. Diff-freundlich, per jq filterbar und stabil über Editor-Reloads hinweg.
# Parse the TSV from Step 4 into JSONL.
awk -F'\t' '{
printf "{\"timestamp\":\"%s\",\"source\":\"verbose-fetch\",\"target\":\"%s\",\"payload\":%s}\n",
$1, "session", $2
}' < session.tsv | jq -c . > session.jsonl
Prüfen, ob jede Zeile parst:
while IFS= read -r line; do
echo "$line" | jq -e . > /dev/null || echo "BAD LINE: $line"
done < session.jsonl
Typische Filter-Verwendung:
# Show only requests to a specific endpoint pattern.
jq -c 'select(.payload | tostring | test("/api/v1/example"))' session.jsonl
# Show timing between consecutive captures.
jq -r '.timestamp' session.jsonl | sort | uniq -c
Expected: jede Zeile von *.jsonl parst mit jq -e .; keine BAD LINE-Warnungen.
On failure: scheitern einzelne Zeilen an der Validierung, enthielt die Quell-TSV eingebettete Tabs in der Payload — Schritt 4 mit einem anderen Trennzeichen neu ausführen oder das zweite Feld base64-kodieren.
Schritt 6: Redaktion zum Erfassungszeitpunkt
Auth-Header, Sitzungs-IDs, Bearer-Tokens und PII vor dem Schreiben auf Platte entfernen. Die events.jsonl- und session.jsonl-Dateien sollen beim ersten Schreibvorgang kein einziges Geheimnis enthalten.
# Stream the raw capture through a redactor before persisting.
redact() {
sed -E \
-e 's/(authorization:[[:space:]]*Bearer[[:space:]]+)[A-Za-z0-9._-]+/\1<REDACTED>/gi' \
-e 's/(x-api-key:[[:space:]]*)[A-Za-z0-9._-]+/\1<REDACTED>/gi' \
-e 's/(cookie:[[:space:]]*)[^;]+/\1<REDACTED>/gi' \
-e 's/("password"[[:space:]]*:[[:space:]]*)"[^"]*"/\1"<REDACTED>"/g' \
-e 's/("token"[[:space:]]*:[[:space:]]*)"[^"]*"/\1"<REDACTED>"/g'
}
cat raw-capture.txt | redact > session.tsv
Nach der Erfassung verifizieren, dass nichts durchgerutscht ist:
# Patterns that must not appear in any *.jsonl file.
grep -Ei 'bearer [A-Za-z0-9]{20,}|sk-[A-Za-z0-9]{20,}|ghp_[A-Za-z0-9]{20,}' captures/ \
&& { echo "LEAK DETECTED"; exit 1; } \
|| echo "redaction clean"
Das Muster „erst erfassen, dann redigieren" lässt immer etwas durchsickern. Das einzig sichere Muster ist „redigiert beim Erfassen". Wird ein nicht redigiertes Token in einem finalisierten Artefakt entdeckt, die gesamte Erfassung als kompromittiert behandeln — löschen, die Zugangsdaten rotieren und neu ausführen.
Expected: die LEAK DETECTED-Prüfung endet mit Exitcode 0 (keine Treffer). grep nach bekannten Zugangsdaten-Präfixen liefert nichts.
On failure: findet die Leck-Prüfung einen Treffer, die Datei nicht in-place editieren. Das gesamte Erfassungsverzeichnis löschen, die Redaktor-Regex um die geleckte Musterkategorie erweitern und ab Schritt 3 oder 4 neu ausführen.
Schritt 7: Antwortkategorien vor dem Aufzeichnen klassifizieren
HTTP-Statuscodes tragen in verschiedenen Kontexten unterschiedliches semantisches Gewicht. Vor dem Aufzeichnen klassifizieren, damit nachgelagerte jq-Filter auf Intention und nicht auf Rohcodes operieren.
| Observed status | Channel context | Classification |
|---|---|---|
| 200 / 201 | Any | success |
| 401 on token-refresh endpoint | Handshake | expected handshake step |
| 401 on data endpoint | After auth | auth failure (real) |
| 404 on lazy-loaded resource | First fetch | expected miss |
| 404 on documented endpoint | After feature gate | gate-induced absence |
| 429 | Any | rate-limit (back off; do not retry tight) |
| 5xx | Any | server failure (record, do not assume) |
Ein class-Feld zum Erfassungszeitpunkt hinzufügen:
jq -c '. + {class: (
if (.payload.status == 401 and (.target | test("token|refresh"))) then "handshake"
elif (.payload.status >= 200 and .payload.status < 300) then "success"
elif (.payload.status == 401) then "auth-fail"
elif (.payload.status == 429) then "rate-limit"
elif (.payload.status >= 500) then "server-fail"
else "other" end)}' session.jsonl > session.classified.jsonl
Ein 401 auf einem Token-Refresh-Kanal ist kein Fehler — es ist die erste Hälfte eines Handshakes. Handshake-Schritte fälschlich als Fehler zu klassifizieren produziert falsch-positive Befunde, die die Aufmerksamkeit der Reviewer verschwenden.
Expected: jede Zeile in *.classified.jsonl hat ein class-Feld mit einem bekannten Wert.
On failure: erzeugt die Klassifizierung viele other-Einträge, ist die obige Tabelle für diesen Harness unvollständig — vor weiterer Analyse um eine Zeile pro wiederkehrendem other-Muster erweitern.
Schritt 8: Das Erfassungs-Manifest persistieren
Ein Erfassungslauf ist nur dann reproduzierbar, wenn die Eingaben neben den Ausgaben festgehalten sind. Ein Manifest schreiben:
cat > capture-manifest.json <<EOF
{
"captured_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"harness_version": "$(harness-cli --version 2>/dev/null || echo unknown)",
"channel": "verbose-fetch",
"question": "Does endpoint X fire on event Y?",
"targets": ["endpoint-X", "event-Y"],
"files": ["session.jsonl", "session.classified.jsonl"],
"redaction_check": "passed"
}
EOF
Das Manifest ist das, was die Erfassung gegen künftige Versionen diff-fähig macht.
Expected: capture-manifest.json existiert, parst mit jq und listet jede Artefaktdatei im Erfassungsverzeichnis auf.
On failure: hat der Harness kein Versions-Flag, stattdessen den sha256sum des Binaries festhalten. Ein nicht identifiziertes Binary erzeugt nicht vergleichbare Erfassungen.
Validierung
- Observability-Tabelle vor jedem Erfassungsbefehl erstellt
- Erfassungsverzeichnis ist git-ignoriert und zeitgestempelt
- Jede
*.jsonl-Datei parst zeilenweise mitjq -e . - Redaktions-Leckprüfung liefert keine Treffer für bekannte Zugangsdaten-Präfixe
- Jedes erfasste Ereignis hat ein
class-Feld mit bekanntem Wert -
capture-manifest.jsonhält Harness-Version (oder sha256), Kanal und Fragestellung fest - Das Erfassungsverzeichnis enthält nur die in Schritt 1 aufgezählten Ziele (kein beiläufiger Verkehr anderer Apps)
Häufige Fallstricke
- Erst erfassen, später fragen: ein Log, das niemand liest, ist verschwendeter Speicherplatz und verschwendete Aufmerksamkeit. Erst die Observability-Tabelle bauen; nur das erfassen, was eine konkrete Frage beantwortet.
- Zuerst zu
mitmproxygreifen: ein ausgehender Proxy ist der invasivste Kanal. Er erfordert Zertifikatsvertrauen, bricht bei Certificate Pinning und verschmutzt die Umgebung des Harness. Nur einsetzen, wenn On-Disk-, Transkript-, Verbose-Fetch- und Hook-Kanäle allesamt blockiert sind. - Erfassen in der primären Arbeitssitzung: Verbose-Fetch-stderr blutet ins TUI-Rendering und kann Fragmente anderer Arbeit in die Erfassung lecken. Stets eine verwerfliche Shell verwenden.
- „Wir redigieren später": jedes „erst erfasste, dann redigierte" Artefakt hat mindestens einmal Zugangsdaten geleckt. Zum Erfassungszeitpunkt redigieren — oder gar nicht erfassen.
- 4xx pauschal als Fehler behandeln: ein 401 auf einem Token-Refresh-Kanal ist ein Handshake-Schritt, kein Fehler. Antwortkategorien pro Kanalkontext klassifizieren (Schritt 7), bevor Schlüsse gezogen werden.
- Langlaufende Erfassung für Einzelereignis-Ziele: ein sitzungslanger Prozess zur Erfassung dreier diskreter Ereignisse koppelt den Tokenzustand über die Erfassungen hinweg und lässt ein schlechtes Ereignis das nächste vergiften. Für Ereignisse hook-getriebene Subprozesse; Sitzungserfassung für Sequenzen reservieren.
- Kein Manifest: eine JSONL-Datei ohne
capture-manifest.jsonist nicht reproduzierbar — sie lässt sich nicht gegen das Binary des nächsten Monats diffen, wenn unbekannt ist, welche Version sie erzeugt hat. - Datenverkehr anderer Nutzer erfassen: außerhalb des Geltungsbereichs. Wire Capture gilt dem eigenen Konto auf der eigenen Maschine. Wird die Anfrage eines anderen Nutzers beiläufig aufgezeichnet, die Erfassung löschen und den Kanal enger fassen.
Verwandte Skills
monitor-binary-version-baselines— Phase 1 der übergeordneten Methodik; erzeugt die Versions-Baseline, auf die das Manifest dieses Skills verweist.probe-feature-flag-state— Phasen 2–3; Wire Capture ist einer ihrer Evidenz-Zweige, und dieser Skill lehrt die Erfassungshälfte.instrument-distributed-tracing— teilt die Philosophie „JSONL über Wallclock"; hier auf ein einzelnes Binary angewandt statt auf ein Service-Mesh.redact-for-public-disclosure— Phase 5; dieser Skill deckt nur die Erfassungszeit-Redaktion für den internen Gebrauch ab, nicht die Publikationsschwelle, die vor dem Verlassen eines privaten Arbeitsbereichs nötig ist.
GitHub 저장소
연관 스킬
executing-plans
디자인executing-plans 스킬은 검토 체크포인트가 포함된 통제된 배치로 실행할 완전한 구현 계획이 있을 때 사용합니다. 이 스킬은 계획을 불러와 비판적으로 검토한 후, 소규모 배치(기본값 3개 작업)로 작업을 실행하면서 각 배치 사이에 진행 상황을 아키텍트 검토를 위해 보고합니다. 이를 통해 내재된 품질 관리 체크포인트를 갖춘 체계적인 구현이 보장됩니다.
requesting-code-review
디자인이 스킬은 코드 변경 사항을 요구 사항에 따라 분석하기 위해 코드 리뷰어 하위 에이전트를 호출합니다. 작업 완료 후, 주요 기능 구현 후, 또는 메인 브랜치에 병합하기 전에 사용해야 합니다. 이 리뷰는 현재 구현체와 원래 계획을 비교하여 문제를 조기에 발견하는 데 도움이 됩니다.
connect-mcp-server
디자인이 스킬은 개발자들이 HTTP, stdio 또는 SSE 전송 방식을 통해 MCP 서버를 Claude Code에 연결하는 포괄적인 가이드를 제공합니다. GitHub, Notion 및 사용자 정의 API와 같은 외부 서비스를 통합하기 위한 설치, 구성, 인증 및 보안을 다룹니다. MCP 통합 설정, 외부 도구 구성 또는 Claude의 모델 컨텍스트 프로토콜 작업 시 활용하세요.
web-cli-teleport
디자인이 스킬은 작업 분석을 기반으로 개발자가 Claude Code 웹 인터페이스와 CLI 인터페이스 중 선택할 수 있도록 돕고, 두 환경 간 원활한 세션 텔레포트를 가능하게 합니다. 웹, CLI 또는 모바일 환경 전환 시 세션 상태와 컨텍스트를 관리하여 워크플로를 최적화합니다. 다양한 단계에서 서로 다른 도구가 필요한 복잡한 프로젝트에 사용하세요.
