MCP HubMCP Hub
스킬 목록으로 돌아가기

conduct-empirical-wire-capture

pjt222
업데이트됨 2 days ago
5 조회
17
2
17
GitHub에서 보기
디자인design

정보

이 스킬은 CLI 도구의 런타임 HTTP 및 텔레메트리 데이터를 트랜스크립트 파일이나 프록시와 같은 다양한 채널을 통해 수집하여 diff에 적합한 JSONL 형식으로 출력합니다. 개발자가 정적 분석 결과를 확인하거나 재구현을 위한 페이로드 구조를 획득하거나 실제 네트워크 동작을 명확히 이해하는 데 도움을 줍니다. 주요 기능으로는 타겟을 가장 효율적인 수집 방법에 매핑하는 가시성 테이블과 이벤트 단위 및 세션 기반 수집을 모두 지원하는 점이 포함됩니다.

빠른 설치

Claude Code

추천
기본
npx skills add pjt222/agent-almanac -a claude-code
플러그인 명령대체
/plugin add https://github.com/pjt222/agent-almanac
Git 클론대체
git clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/conduct-empirical-wire-capture

Claude Code에서 이 명령을 복사하여 붙여넣어 스킬을 설치하세요

문서

Conduct Empirical Wire Capture

Set up reproducible wire-capture harness for CLI tool outbound HTTP and telemetry. Match each observability target to cheapest channel that captures it.

Scope and Ethics

Read this before configuring any capture.

  • Wire capture is for your own requests against your own account, on your own machine. Capturing other users' traffic is exfiltration, not research, out of scope.
  • Credentials almost always appear in raw wire output. Redact at capture time (Step 6) — never "capture now, redact later."
  • Capture is observation, not modification. Do not use captured payloads to bypass server-side rate limits, replay another user session, or activate dark-launched capability without authorization.
  • Output of this skill is internal artifact. Public publication of wire findings goes through redact-for-public-disclosure (Phase 5 of parent guide), not this skill.

When Use

  • Static finding (flag, endpoint reference, telemetry-event name) needs runtime confirmation it actually fires.
  • Payload shape needed for client re-implementation, tracing instrumentation, or cross-version diff.
  • Dark-vs-live disambiguation requires watching what binary actually sends, not what bundle suggests it might.
  • Behavior changed silently between versions, want reproducible artifact to compare against future versions.

Do not use this skill for: version baselining (use monitor-binary-version-baselines), flag-state probing (use probe-feature-flag-state), or preparing redacted artifacts for public publication (use redact-for-public-disclosure).

Inputs

  • Required: CLI harness binary you can run locally against your own account.
  • Required: Specific question to answer (e.g., "does endpoint X fire on event Y?", "what is payload shape for telemetry event Z?"). Capture without a question produces log nobody reads.
  • Optional: Static findings from prior phases (marker catalog, candidate flag list, suspected endpoints) that scope capture targets.
  • Optional: Private workspace path for capture artifacts. Default is ./captures/ — must be in .gitignore.

Steps

Step 1: Build Observability Table First

Before configuring any capture, enumerate questions you need to answer and map each to capture channel. One row per target.

targetobservable viablocker
Outbound HTTP to endpoint Xverbose-fetch stderrTUI noise pollutes terminal
Telemetry event Y on user actionhook-driven subprocessrequires harness hook surface
Token-refresh handshakeoutbound HTTP proxycert trust required
Scheduled-task lifecycle eventlong-running session capturewallclock alignment
Local config mutationon-disk state diffnone — cheapest channel

Common channels, cheapest first:

  • On-disk state file mutation — harness writes its state to known path? diff between snapshots is free.
  • Transcript file — harness already writes session transcript? Parse directly. No instrumentation.
  • Verbose-fetch stderr — bundler-provided env var (e.g., bun's BUN_CONFIG_VERBOSE_FETCH=curl) routes every fetch to stderr. Noisy but captures every fetch.
  • Hook-driven subprocess — harness exposes lifecycle hooks (UserPromptSubmit, Stop, etc.)? Spawn short capture subprocess per event.
  • Long-running session capture — one process across session, wallclock-tagged. Use for sequences.
  • Outbound HTTP proxy — clean separation, but requires CA cert trust and breaks when harness pins certificates.

Pick cheapest channel that captures target. 3-target capture that answers one specific question beats 20-target capture that answers none.

Got: Observability table with one row per question, each annotated with channel, known blockers. Targets without viable channel flagged "out of scope this session."

If fail: Every target lands in proxy column? Table too ambitious. Trim to one or two highest-value questions, revisit lower-cost channels for them.

Step 2: Prepare Disposable Workspace

Wire capture pollutes terminals, leaves files in unexpected places, may leak credentials into logs.

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"

Confirm capture session not your primary working session — verbose-fetch and TUI rendering interfere with each other.

Got: Timestamped capture directory, git-ignored, separate from working session.

If fail: git check-ignore reports directory as not ignored? Fix .gitignore before running any capture command. Do not proceed with credentials at risk.

Step 3: Hook-Driven Capture for Per-Event Targets

Target is discrete event (tool invocation, prompt submission, session stop)? Use harness hook surface. Spawn short-lived capture subprocess per event; do not sit in-process.

Pattern (synthetic example):

# 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"

Why subprocess-per-event:

  • No token state, no session coupling — each invocation independent.
  • Failure of one capture does not contaminate next.
  • Subprocess overhead acceptable because events rare (per-user-action, not per-byte).

Got: One JSONL line per fired event in events.jsonl, each well-formed JSON parseable with jq.

If fail: jq reports parse errors? Payload contains unescaped control chars or binary data — pipe through jq -R (raw input), base64-encode payload field instead.

Step 4: Long-Running Session Capture for Sequential State

Target is sequence (multi-turn handshake, scheduled-task lifecycle, retry/backoff state machine)? One capture process across session, wallclock-tagged.

# 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"
)

Wallclock prefix makes ordering unambiguous when multiple captures run concurrently. TSV (tab-separated) is intentional — survives shells that mangle JSON quoting on stderr.

Convert TSV to JSONL after session ends (Step 5), not during.

Got: TSV log with monotonically increasing timestamps, one stderr line per row.

If fail: Timestamps go backwards? Harness is buffering stderr — re-run with stdbuf -oL -eL or bundler equivalent line-buffer flag.

Step 5: Normalize to JSONL

JSONL is artifact format: one JSON object per line, fields timestamp, source, target, payload. Diff-friendly, jq-filterable, stable across editor reloads.

# 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

Validate every line parses:

while IFS= read -r line; do
  echo "$line" | jq -e . > /dev/null || echo "BAD LINE: $line"
done < session.jsonl

Typical filter usage:

# 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

Got: Every line of *.jsonl parses with jq -e .; no BAD LINE warnings.

If fail: Some lines fail validation? Source TSV had embedded tabs in payload — re-run Step 4 with different delimiter or base64-encode second field.

Step 6: Redact at Capture Time

Strip auth headers, session IDs, bearer tokens, PII before writing to disk. events.jsonl and session.jsonl files should not, on first write, contain a single secret.

# 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

After capture, verify nothing slipped through:

# 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"

captured-then-redacted artifact always leaks something. Only safe pattern is redacted-as-captured. Discover unredacted token in finalized artifact? Treat entire capture as compromised — delete it, rotate credential, re-run.

Got: LEAK DETECTED check exits 0 (no matches). grep for known credential prefixes returns nothing.

If fail: Leak check finds hit? Do not edit file in place. Delete entire capture directory, extend redactor regex to cover leaked pattern category, re-run from Step 3 or 4.

Step 7: Classify Response Categories Before Recording

HTTP status codes carry different semantic weight in different contexts. Classify before recording so downstream jq filters operate on intent, not raw codes.

Observed statusChannel contextClassification
200 / 201Anysuccess
401 on token-refresh endpointHandshakeexpected handshake step
401 on data endpointAfter authauth failure (real)
404 on lazy-loaded resourceFirst fetchexpected miss
404 on documented endpointAfter feature gategate-induced absence
429Anyrate-limit (back off; do not retry tight)
5xxAnyserver failure (record, do not assume)

Add class field at capture time:

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

A 401 on token-refresh channel is not failure — it is first half of handshake. Misclassifying handshake steps as failures produces false-positive findings that waste reviewer attention.

Got: Every line in *.classified.jsonl has class field with known value.

If fail: Classification produces many other entries? Table above incomplete for this harness — extend with one row per recurring other pattern before continuing analysis.

Step 8: Persist the Capture Manifest

Capture run reproducible only if inputs recorded alongside outputs. Write manifest:

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

Manifest is what makes capture diff-able against future versions.

Got: capture-manifest.json exists, parses with jq, lists every artifact file in capture directory.

If fail: Harness has no version flag? Record binary sha256sum instead. Unidentified binary produces uncomparable captures.

Checks

  • Observability table built before any capture command was run
  • Capture directory is git-ignored and timestamped
  • Every *.jsonl file parses with jq -e . line-by-line
  • Redaction leak-check returns no matches for known credential prefixes
  • Each captured event has class field with known value
  • capture-manifest.json records harness version (or sha256), channel, question
  • Capture directory contains only targets enumerated in Step 1 (no incidental traffic from other apps)

Pitfalls

  • Capture-first, question-later: Log nobody reads is wasted disk and wasted attention. Build observability table first; capture only what answers specific question.
  • Reaching for mitmproxy first: Outbound proxy is most invasive channel. Requires cert trust, breaks on certificate pinning, pollutes harness environment. Use it only when on-disk, transcript, verbose-fetch, and hook channels all blocked.
  • Capturing in your primary working session: Verbose-fetch stderr bleeds into TUI rendering and can leak fragments of your other work into capture. Always use disposable shell.
  • "We'll redact later": Every captured-then-redacted artifact has leaked a credential at least once. Redact at capture time or do not capture.
  • Treating 4xx as failure uniformly: 401 on token-refresh channel is handshake step, not failure. Classify response categories per channel context (Step 7) before drawing conclusions.
  • Long-running capture for per-event targets: Session-long process to capture three discrete events couples token state across captures, makes one bad event poison next. Use hook-driven subprocesses for events; reserve session capture for sequences.
  • No manifest: JSONL file without capture-manifest.json is not reproducible — cannot diff against next month's binary if you do not know which version produced it.
  • Capturing other users' traffic: Out of scope. Wire capture is for your own account on your own machine. Capture incidentally records another user request? Delete capture, tighten channel.

See Also

  • monitor-binary-version-baselines — Phase 1 of parent methodology; produces version baseline this skill manifest references.
  • probe-feature-flag-state — Phases 2-3; wire capture is one of its evidence prongs, this skill teaches capture half.
  • instrument-distributed-tracing — shares JSONL-over-wallclock philosophy; applied here to single binary instead of service mesh.
  • redact-for-public-disclosure — Phase 5; this skill only covers capture-time redaction for internal use, not publication-bar redaction needed before any capture leaves a private workspace.

GitHub 저장소

pjt222/agent-almanac
경로: i18n/caveman/skills/conduct-empirical-wire-capture
0
agentsagentskillsai-assisted-developmentclaude-codeskillsteams

연관 스킬

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 또는 모바일 환경 전환 시 세션 상태와 컨텍스트를 관리하여 워크플로를 최적화합니다. 다양한 단계에서 서로 다른 도구가 필요한 복잡한 프로젝트에 사용하세요.

스킬 보기