llm-scan은(는) 무엇을 하나요?
이 스킬은 저장소의 모든 LLM 호출 지점과 사용 로그를 work/<repo>/routes.json에 매핑합니다. 읽기 전용이며: 대상 저장소 내에서 어떤 것도 편집, 포맷, 커밋 또는 실행하지 않습니다.
0. 설정
- 자신이 어떤 코딩 에이전트인지 확인하세요: Claude Code 또는 Codex (또는 다른 코딩 에이전트). 이 팩에서 해당하는 파일인
delegation/claude.md또는delegation/codex.md만 읽으세요. 어떤 단계가 저렴하고 빠른 헬퍼로 가고 어떤 단계가 당신에게 남는지 알려줍니다. <pack>을scripts/calc.py가 있는 폴더(이 파일보다 두 단계 위)로 설정하고<repo>는 대상 저장소의 폴더 이름으로 설정하세요.<pack>/work/<repo>/디렉토리를 생성하고; 모든 출력은 여기에 저장됩니다. 대상 저장소에는 절대 쓰지 마세요.
1. 모든 호출 지점 찾기
전체 저장소를 검색하세요(node_modules, .venv, dist, build, .git, 잠금 파일은 건너뜁니다). 다음을 모두 세십시오:
- SDK 호출: 모델에 프롬프트를 전송하는 모든 클라이언트 라이브러리 호출(채팅, 메시지, 완성, 응답, 임베딩, 스트리밍 헬퍼, 에이전트 프레임워크).
- CLI 서브프로세스 호출: 코드에서 비대화형 모드로 실행되는 에이전트 또는 모델 CLI(출력 플래그
-p,exec,--prompt등), 장기 실행 웜 워커 및 스트림 JSON 파이프를 포함합니다. - HTTP 호출: 모델 API URL, 게이트웨이, 프록시 또는 자체 호스팅 엔드포인트에 대한 직접 요청.
- 결정, 게이트, 분류기, 라우터, 리랭커 및 판단 모델: 작거나 저렴하더라도 모두 LLM 호출입니다.
- 모델을 호출하는 웜업, 연결 유지 및 상태 확인 호출: 경로로 기록합니다(종종 로그에 사용량이 없습니다.
usage_gaps참조). - 테스트, 스크립트, 노트북 및 크론 작업의 호출: 나열하되, 프로덕션에서 실행되지 않으면
"live": false로 표시합니다. - 비LLM 모델 호출(음성-텍스트, 텍스트-음성, OCR, 분당 또는 이미지당 청구되는 비전 서비스): 가격 책정 범위를 벗어납니다.
"kind": "non_llm"으로 나열하여 보고서에서 확인되었지만 가격이 책정되지 않았음을 알 수 있도록 합니다.
클라이언트 임포트, API 호스트 이름, model= / "model": 문자열, max_tokens, stream, cache_control 및 모델 CLI의 서브프로세스 생성을 검색하세요. 그런 다음 각 적중 결과를 열고 주변 함수를 읽으세요.
2. 각 경로 기록하기
호출 지점당 하나의 항목을 작성하세요. 경로 ID는 relative/path.ext:function_name입니다. 메서드의 경우 relative/path.ext:Class.method; 최상위 레벨이면 <module>을 사용하세요. 모든 곳(routes.json, 행, 보고서)에서 동일한 ID 철자를 사용하세요.
| 필드 | 의미 |
|---|---|
id | file:function 또는 file:Class.method |
kind | sdk, cli, http, non_llm |
provider | 코드에 표시된 대로, 그렇지 않으면 null |
model | 정확히 작성된 모델 문자열, 또는 이를 설정하는 구성 키/환경 변수(그런 다음 model_source도 포함). 하나의 경로 모델이 런타임에 달라지면 "varies"를 쓰고 model_source에 구성 또는 소스를 지정합니다. |
streaming | true / false / null |
cache_markers | explicit(코드가 프롬프트 캐시 지점을 표시함), implicit(표시는 없지만 안정적인 접두사, 웜 프로세스 또는 제공자 기본값이 캐시할 수 있음), none(캐싱을 시사하는 항목 없음), unknown |
max_tokens | 숫자, 설정되지 않았으면 null |
retries | 횟수 및 위치(SDK 기본값, 래퍼, 루프), 또는 0 |
user_waits | 사람이 답변을 기다리고 있으면 true(채팅, 음성, 라이브 UI); 배치, 백그라운드, 크론의 경우 false; 알 수 없으면 "unknown" |
decision_model | 게이트, 라우터, 분류기, 판단 모델의 경우 true |
decision_shaped | 답변이 코드 분기를 제공하는 매우 작은 판정(열거형, 부울, 레이블, 점수)이고 경로가 이벤트 또는 항목별로 실행되면 true; 답변이 자유 텍스트 또는 긴 구조화된 출력이면 false; 알 수 없으면 "unknown". 모든 경로에 대해 기록합니다. calc는 또한 로그에서 이를 감지합니다(50회 이상 호출에서 출력 p50이 5 토큰 이하). |
tools | 도구 또는 함수 정의가 빌드되어 전송되는 위치(파일:함수, 코드에 표시되면 호출당 전송된 개수), 또는 해당 경로가 아무것도 전송하지 않으면 null. 사실만; 숫자는 로그에서 가져옵니다. |
live | true; 테스트 전용이면 false; 알 수 없으면 "unknown" |
stateless | 모든 호출이 독립적이면 true(이전 턴을 보내지 않는 이벤트별 게이트 또는 분류기); 대화 또는 메모가 호출 간에 커지면 false; "unknown" |
notes | 한 줄의 간단한 메모, 당신이 본 사실만 |
알 수 없을 때는 null(또는 테이블이 허용하는 경우 "unknown")을 사용하세요. 값을 추측하지 마세요.
3. 사용 로그 찾기
앱이 이미 사용량(토큰, 비용, 지연 시간, 첫 토큰까지의 시간, 성공)을 기록하는 위치를 찾으세요. 로그 파일, JSONL, CSV, SQLite 또는 데이터베이스 테이블, 추적 및 메트릭 호출, 응답에서 저장된 제공자 사용 필드를 찾으세요. 각각에 대해 기록하세요:
- 경로 또는 테이블 및 형식;
- 필드 이름만, 값은 절대 안 됩니다;
- 프롬프트 또는 응답 텍스트를 보유하는 필드가 있는지 여부(
has_text_fields); - 어떤 경로 ID를 포함하는지.
필드 이름을 알아내는 데 필요한 처음 몇 줄 이상으로 로그 값을 열지 말고, 로그에서 텍스트를 복사하지 마세요.
또한, 필드 이름으로만 로그가 호출당 도구 정의 또는 도구 사용을 기록하는지 확인하세요(전송된 도구 수, 도구 정의의 토큰 크기, 응답의 도구 호출 수). llm-capture는 이를 tools_defined, tool_schema_tokens 및 tool_calls로 변환합니다. 로그에 없으면 usage_gaps에 명시하세요.
또한 usage_gaps를 기록하세요: 호출이 발생하지만 로그에 토큰 사용량이 없거나 기록된 숫자를 있는 그대로 신뢰할 수 없는 경우에 대한 짧은 일반 메모(각각 한 줄, 사실만). 예: "경로 X의 웜업 호출이 사용량 없이 기록됨", "기록된 비용은 프로세스당 총 실행 합계임", "경로 Y가 전혀 기록되지 않음". 필드 이름과 개수만으로 읽을 때 횟수도 환영합니다("N회 확인됨").
4. routes.json 작성하기
<pack>/work/<repo>/routes.json을 작성하세요:
{
"repo": "<repo>",
"root": "<대상 저장소의 절대 경로>",
"scanned": "<YYYY-MM-DD>",
"routes": [
{"id": "path/file.py:Class.method", "kind": "cli", "provider": null, "model": "<string>", "model_source": null,
"streaming": true, "cache_markers": "implicit", "max_tokens": null, "retries": 0,
"user_waits": true, "decision_model": false, "decision_shaped": false, "tools": null, "live": true, "stateless": false, "notes": ""},
{"id": "path/stt.py:transcribe", "kind": "non_llm", "live": true, "notes": "음성-텍스트, 가격 책정되지 않음"}
],
"usage_logs": [
{"path": "<상대 경로 또는 테이블>", "format": "jsonl", "fields": ["<이름만>"],
"has_text_fields": true, "covers_routes": ["path/file.py:Class.method"]}
],
"usage_gaps": ["<각각 한 줄의 짧은 메모>"]
}
5. 완료
사용자에게 몇 줄로 발견한 경로 수, 사용자 대면 경로, 존재하는 사용 로그 및 usage_gaps를 알려주세요. 여기에서 비용이나 속도를 추정하지 마세요. 숫자는 오직 scripts/calc.py에서만 나옵니다.
그런 다음 다음 스킬인 llm-capture를 실행하세요.