Community라이팅 & 에디팅github.com

로컬 검색

사용자 기기에서 완전히 실행되는 웹 검색 스킬입니다. Z.AI/클라우드 SDK 종속성이 없으며, DuckDuckGo/Bing/Google HTML 스크래핑과 자동 엔진 폴백을 지원합니다.

로컬 검색란 무엇인가요?

Local Search는 사용자의 로컬 머신에서 직접 공개 검색 엔진을 호출하는 AI 에이전트 스킬입니다. API 키나 클라우드 SDK가 전혀 필요하지 않아, 네트워크 홉을 최소화하고 종속성을 크게 줄일 수 있습니다. DuckDuckGo, Bing, Google 세 엔진을 지원하며, 기본 설정('auto')에서는 DuckDuckGo → Bing → Google 순으로 자동 폴백하여 요금 제한이나 IP 차단에도 검색이 성공할 가능성을 높입니다. 각 결과는 `SearchFunctionResultItem` 표준 스키마(url, name, snippet, host_name, rank, date, favicon)를 따르며, 추가로 source_engine, raw_html, score 필드를 제공합니다. CLI(`tsx bin/web-search.ts`)와 SDK(`import { search } from "local-search"`)를 모두 지원하며, TypeScript ESM으로 작성되어 Node 18+의 내장 `fetch`만으로 동작합니다. `--locale`로 언어/지역 설정, `--recency-days`로 최신 필터링이 가능해, 최신 뉴스, 문서 업데이트, 사실 확인 등 실시간 웹 정보가 필요한 모든 작업에 적합합니다.

지원 대상✓Claude Code~Codex CLI~Cursor
npx skills add Sakurakilove/local-search

Installed? Explore more 라이팅 & 에디팅 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

미리보기

스킬 README에서

ClawHub
버전
라이선스: MIT
Node

문서

로컬 검색 스킬

자동 엔진 폴백이 적용된 로컬 웹 검색. DuckDuckGo / Bing / Google 직접 HTML 스크래핑 · 요금 제한에 강함 · 표준 결과 스키마.

ClawHub 버전 라이선스: MIT Node

이 스킬은 사용자 기기에서 직접 공개 검색 엔진을 호출합니다. API 키, SDK, 네트워크 홉이 필요 없습니다. 한 엔진에서 요금 제한이 발생하면, 오케스트레이터가 자동으로 다음 엔진으로 전환합니다. 따라서 Google이 차단된 데이터센터 IP에서도, 첫 번째 시도에 성공하는 경우가 많습니다.

각 결과는 7개의 표준 필드(url, name, snippet, host_name, rank, date, favicon)와 3개의 선택적 확장 필드(source_engine, raw_html, score)를 가진 SearchFunctionResultItem입니다. 유사한 형태의 웹 검색 스킬을 사용하는 코드는 수정 없이 그대로 사용할 수 있습니다.

✨ 주요 특징

  • 제로 클라우드 SDK 종속성 — cheerio(HTML 파서)와 Node 내장 fetch만 사용.
  • 세 엔진, 자동 폴백 — engine: "auto"(기본값)일 때 DuckDuckGo → Bing → Google 순서.
  • 로케일 인식 — --locale en-US / zh-CN / ja-JP 등 모든 BCP-47 태그 지원. Bing이 영어 쿼리에도 지역화된 결과를 제공하는 비-US IP에서 중요함.
  • 최신 필터 — --recency-days 7로 지난주 결과로 제한. DDG는 정확한 N일을 지원하고, Bing/Google은 일/주/월 버킷을 사용.
  • 표준 결과 스키마 — url / name / snippet / host_name / rank / date / favicon 필드로, ClawHub 레지스트리의 다른 웹 검색 스킬과 동일한 형태.
  • CLI + SDK — 일회성 검색에는 tsx bin/web-search.ts <query>, 코드 내에서는 import { search } from "local-search" 사용.
  • 순수 TypeScript ESM — Node 18+에서 tsx로 실행하거나, bun으로 제로 설정 실행 가능.

🚀 빠른 시작

# 1. 설치 (런타임 종속성: cheerio)
cd skills/local-search && npm install

# 2. 검색 (DDG → Bing → Google 자동 폴백)
tsx bin/web-search.ts "인공지능"

# 3. 특정 엔진 및 로케일 지정
tsx bin/web-search.ts "머신러닝" --engine bing --locale en-US --num 5

# 4. 최신 뉴스를 JSON으로 저장
tsx bin/web-search.ts "AI 혁신" --recency-days 7 --json -o ai_news.json

프로그래매틱 사용:

import { search } from "local-search";

const outcome = await search("프랑스의 수도는?", { num: 5 });
if (outcome.success) {
  console.log(`${outcome.engine}에서 ${outcome.elapsedMs}ms만에 응답`);
  outcome.results.forEach(r => console.log(`- ${r.name}\n  ${r.url}`));
}

🎯 이 스킬을 사용해야 할 때

local-search는 사용자가 모델의 훈련 데이터에 없는 공개 웹 정보가 필요할 때 사용합니다:

  • 실시간 정보: 최신 뉴스, 주식 가격, 날씨, 스포츠 점수
  • 최신 문서: 프레임워크 릴리스 노트, API 변경 사항, 최근 발표된 논문
  • 사실 확인: 실시간 웹 소스로 주장 검증
  • 연구: 주제에 대한 여러 소스 수집, 관점 비교
  • 콘텐츠 발견: 튜토리얼, 블로그 포스트, 최근 발표 검색
  • 경쟁/시장 분석: 경쟁사 발표, 업계 트렌드
  • 학술 검색: 논문, 인용, 저자 페이지 검색

🔄 엔진 비교

엔진엔드포인트API 키거주용 IP데이터센터 IP최신성
DuckDuckGohtml.duckduckgo.com/html/ (GET)없음✅ 높음⚠️ 부하 시 요금 제한df=d<N> (정확한 일)
Bingwww.bing.com/search없음✅ 높음✅ 높음freshness=d1|w1|m1 (버킷)
Googlewww.google.com/search없음⚠️ 중간❌ 낮음 (enablejs 장벽)tbs=qdr:d|w|m|y (버킷)

engine: "auto"는 DuckDuckGo → Bing → Google 순서로 시도하며, 첫 번째 비어 있지 않은 결과 세트를 반환합니다. 데이터센터 IP에서 유효 체인은 DDG → Bing입니다(Google은 보통 차단됨). 거주용 IP에서는 세 엔진 모두 사용 가능합니다. src/engines/index.ts의 AUTO_ENGINE_ORDER를 편집하여 우선순위를 변경할 수 있습니다.

📦 설치 경로

권장 위치: {project_path}/skills/local-search

이 스킬 패키지를 프로젝트의 위 경로에 압축 해제하세요.

사전 요구 사항

  • Node.js >= 18 (내장 전역 fetch 사용).
  • 하나의 npm 종속성: cheerio (HTML 파서).
  • 작동하는 인터넷 연결 — 스킬이 공개 검색 엔진을 직접 호출합니다.

스킬 디렉토리에서 한 번 설치:

cd {project_path}/skills/local-search
npm install            # 또는: bun install / pnpm install

이 스킬은 순수 TypeScript ESM입니다. tsx(권장, 개발자 친화적) 또는 bun(제로 설정)으로 실행할 수 있습니다. 런타임에 구애받지 않는 node --experimental-strip-types bin/web-search.ts도 Node 22+에서 작동합니다.

로컬인 이유는?

항목클라우드 검색 스킬이 스킬 (local-search)
검색 백엔드클라우드 함수 / APIDuckDuckGo / Bing / Google 직접 HTTP
API 키 / SDK필수없음
네트워크 경로클라이언트 → 클라우드 → 검색 엔진클라이언트 → 검색 엔진
실패 처리SDK 종속3개 엔진 자동 폴백
결과 스키마SearchFunctionResultItem (7개 필드)동일 7개 필드 + 3개 선택적 확장 필드
CLISDK 특화tsx bin/web-search.ts

아키텍처

local-search/
├── SKILL.md                 ← 현재 위치
├── LICENSE.txt
├── package.json             ← `cheerio` 종속성 선언
├── tsconfig.json
├── bin/
│   └── web-search.ts        ← CLI 진입점
├── src/
│   ├── index.ts             ← 공개 SDK 내보내기
│   ├── search.ts            ← 자동 폴백 오케스트레이터
│   ├── types.ts             ← SearchFunctionResultItem + 옵션
│   └── engines/
│       ├── _shared.ts       ← fetch/파싱 헬퍼
│       ├── duckduckgo.ts    ← POST https://html.duckduckgo.com/html/
│       ├── bing.ts          ← GET https://www.bing.com/search
│       ├── google.ts        ← GET https://www.google.com/search
│       └── index.ts         ← 엔진 레지스트리 + AUTO_ENGINE_ORDER
└── scripts/
    └── web_search.ts        ← 빠른 시작 예제

유일한 런타임 종속성은 cheerio(HTML 파서)이며, package.json에 선언되어 있습니다. Node 18+의 내장 fetch가 네트워크 계층을 처리하므로, 이 패키지에는 다른 SDK가 전혀 임포트되지 않습니다.

CLI 사용법

CLI는 bin/web-search.ts에 있습니다. tsx, bun 또는 TypeScript를 지원하는 모든 실행기로 실행하세요.

기본 검색

# 기본: 자동 엔진, 10개 결과, 사람이 읽기 쉬운 출력
tsx bin/web-search.ts "인공지능"

# 결과 개수 제한
tsx bin/web-search.ts "머신러닝" --num 5
# (짧은 옵션도 작동)
tsx bin/web-search.ts "머신러닝" -n 5

특정 엔진 지정

# DuckDuckGo만 사용
tsx bin/web-search.ts "최신 기술 뉴스" --engine duckduckgo
# Bing만 사용
tsx bin/web-search.ts "최신 기술 뉴스" --engine bing
# Google만 사용 (가장 높은 품질, 요금 제한 가능성 높음)
tsx bin/web-search.ts "최신 기술 뉴스" --engine google
# 기본 — DDG → Bing → Google 시도, 첫 번째 비어 있지 않은 결과 반환
tsx bin/web-search.ts "최신 기술 뉴스" --engine auto

최신 필터

# 지난 7일간의 결과
tsx bin/web-search.ts "암호화폐 뉴스" --num 10 --recency-days 7
# (짧은 옵션)
tsx bin/web-search.ts "암호화폐 뉴스" -r 7

결과를 JSON으로 저장

# JSON을 파일로 쓰기 (사람이 읽기 쉬운 배너는 출력되지 않음)
tsx bin/web-search.ts "기후 변화 연구" --num 5 --json -o search_results.json

# 또는 JSON을 stdout으로 파이프
tsx bin/web-search.ts "AI 혁신" --num 3 --recency-days 1 --json > ai_news.json

조용한 모드 (스크립트/파이핑)

# "엔진/시간" 배너를 출력하지 않고 결과만 출력
tsx bin/web-search.ts "react hooks" --quiet

CLI 매개변수

플래그짧은 옵션설명
--num <N>-n결과 개수 (기본값: 10, 최대: 50)
--engine <id>-educkduckgo | bing | google | auto (기본값: auto)
--recency-days <N>-r지난 N일 이내 결과로 제한 (기본값: 0 = 필터 없음)
--timeout <ms>—엔진별 타임아웃(ms) (기본값: 8000)
--json—사람이 읽기 쉬운 대신 JSON 출력
--output <경로>-ostdout 대신 JSON을 파일로 쓰기
--pretty—JSON 예쁘게 출력 (기본값: 켜짐; --no-pretty로 끄기 — 아직 미지원, 대신 --json 생략)
--quiet-q엔진 정보 배너 숨기기
--help-h도움말 표시

검색 결과 구조

각 결과 항목은 SearchFunctionResultItem입니다:

interface SearchFunctionResultItem {
  // ----- 표준 필드 (ClawHub 웹 검색 스킬 간 공유) -----
  url: string;          // 결과의 전체 URL
  name: string;         // 페이지 제목
  snippet: string;      // 미리보기 텍스트/설명
  host_name: string;    // 도메인 이름 (예: "ko.wikipedia.org")
  rank: number;         // 엔진 결과 세트 내 1부터 시작하는 순위
  date: string;         // 게시/업데이트 날짜; 알 수 없는 경우 "N/A"
  favicon: string;      // 파비콘 URL (Google S2)

  // ----- 확장 필드 (local-search 신규) -----
  source_engine: "duckduckgo" | "bing" | "google";
  raw_html?: string;    // 스니펫 요소의 원본 HTML (선택적)
  score?: number;       // 휴리스틱 관련성 점수 [0, 100] (선택적)
}

SDK 사용법

TypeScript/JavaScript 코드를 작성 중이라면(CLI를 실행하는 것이 아니라면), src/index.ts에서 임포트하세요:

간단한 검색

import { search } from "local-search";

const outcome = await search("프랑스의 수도는?", { num: 5 });

if (outcome.success) {
  console.log(`사용 엔진: ${outcome.engine}`);
  console.log(`시도 순서: ${outcome.enginesTried.join(" → ")}`);
  console.log(`경과 시간: ${outcome.elapsedMs}ms`);
  for (const item of outcome.results) {
    console.log(`- ${item.name}  [${item.source_engine}]`);
    console.log(`  ${item.url}`);
    console.log(`  ${item.snippet}`);
  }
} else {
  console.error("검색 실패:", outcome.error);
  if (outcome.errors) {
    // 자동 모드: 어떤 엔진이 시도되었고 무엇을 보고했는지 확인
    for (const e of outcome.errors) {
      console.error(`  ${e.engine}:`, e.error);
    }
  }
}

실패 시 예외 발생 변형

import { searchOrThrow, AllEnginesFailedError } from "local-search";

try {
  const results = await searchOrThrow("JavaScript 프레임워크", { num: 10 });
  console.log(results);
} catch (err) {
  if (err instanceof AllEnginesFailedError) {
    console.error("모든 엔진 실패:", err.errors);
  } else {
    console.error("단일 엔진 오류:", err);
  }
}

특정 엔진 지정

import { search } from "local-search";

// 폴백 체인을 건너뛰고 DuckDuckGo만 사용.
const outcome = await search("양자 컴퓨팅 응용", {
  num: 8,
  engine: "duckduckgo",
});

최신 필터

const outcome = await search("유전체학 연구", {
  num: 5,
  recency_days: 30, // 지난 30일
});

사용자 정의 fetch (테스트/에지 런타임)

const outcome = await search("hello world", {
  fetchImpl: myMockFetch, // WhatWG-fetch 호환 함수
  userAgent: "my-bot/1.0",
  timeoutMs: 5000,
});

엔진 백엔드

DuckDuckGo (duckduckgo)

  • 엔드포인트: https://html.duckduckgo.com/html/ (POST 폼 q=...)
  • API 키 없음. 대략적인 요금 제한이 있음 — 지속적인 과도한 요청은 빈 결과 세트를 반환함.
  • 최신성: df=d<N> 폼 필드.
  • 최적 용도: 기본 첫 번째 시도; 거의 완전히 차단되지 않음; 개인정보 보호.

Bing (bing)

  • 엔드포인트: https://www.bing.com/search?q=...&count=...
  • API 키 없음. HTML 레이아웃이 안정적이고 파싱하기 쉬움.
  • 최신성: freshness=d1 / w1 / m1 버킷 (Bing에는 임의 N일 URL 필터가 없음).
  • 최적 용도: 두 번째 폴백; 좋은 영어 결과; 가끔 로케일 문제 발생 ( ensearch=1로 완화).

Google (google)

  • 엔드포인트: https://www.google.com/search?q=...&num=...
  • API 키 없음, 하지만 Google이 스크래퍼를 가장 적극적으로 차단함. 데이터센터/클라우드 IP에서 Google은 일반적으로 "enable JS" 리디렉션 페이지(/httpservice/retry/enablejs)를 반환하며 파싱 가능한 결과가 없음 — 엔진은 이를 소프트 실패로 처리하고 자동 체인이 넘어감. 거주용 IP에서는 Google HTML 스크래핑이 잘 작동하는 경우가 많음.
  • 최신성: tbs=qdr:d|w|m|y 버킷.
  • 최적 용도: 거주용 IP에서 최후의 폴백; 클라우드 IP에서는 보통 실패함(DDG+Bing이 이미 요구를 충족).

자동 폴백 전략

engine: "auto"(기본값)일 때, 오케스트레이터는 다음 순서로 엔진을 시도합니다:

  1. DuckDuckGo — 가장 덜 적극적인 차단, 가장 세밀한 날짜 필터
  2. Bing — 모든 IP(데이터센터 포함)에서 일반적으로 안정적
  3. Google — 도달 가능할 때 최고 결과 품질; 데이터센터 IP에서 자주 차단됨

결과가 ≥ 1개인 첫 번째 엔진을 반환합니다. 세 엔진 모두 실패하면 { success: false, errors: [...] } 결과가 각 엔진의 오류와 함께 반환됩니다. searchOrThrow 모드에서는 AllEnginesFailedError가 발생합니다.

실제 신뢰성 표(테스트 중 관찰):

호출자 IP 유형DDGBingGoogle유효 자동 체인
거주용높음높음중간DDG → Bing → Google (3개 사용 가능)
데이터센터/클라우드중간 (부하 시 요금 제한)높음낮음 (enablejs 장벽)실질적으로 DDG → Bing

순서는 src/engines/index.ts (AUTO_ENGINE_ORDER)에 정의되어 있으며, 다른 우선순위를 원하면 해당 배열을 편집하세요.

일반적인 사용 사례

  1. 실시간 정보 수집 — 최신 뉴스, 주식 가격, 날씨 확인
  2. 최신 문서 참조 — 프레임워크 업데이트, API 변경 사항 확인
  3. 사실 확인 — 클레임을 라이브 웹 소스와 대조
  4. 연구 — 여러 소스에서 정보 수집 및 비교
  5. 콘텐츠 발견 — 튜토리얼, 블로그 게시물, 최근 발표 검색
  6. 경쟁 분석 — 경쟁사 발표, 업계 트렌드 파악
  7. 학술 검색 — 논문, 인용, 저자 페이지 찾기

관련 스킬