Show HN: CS – 코드, 주석, 문자열을 이해하는 인덱스 없는 코드 검색 도구
요약
codespelunker(cs)는 인덱싱 과정 없이 코드의 구조를 파싱하여 주석, 문자열, 실제 구현부를 구분하고 관련성에 따라 검색 결과를 정렬하는 CLI 도구입니다. 단순 텍스트 매칭을 넘어 BM25 기반의 순위 지정 기능을 제공하며, TUI 및 HTTP 모드를 통해 대화형 탐색을 지원합니다.
핵심 포인트
- 인덱싱(Indexing)이 필요 없는 즉석 파싱 방식의 코드 검색 엔진
- 주석, 문자열, 코드 구조를 구분하여 검색 결과의 관련성(Relevance) 순위 지정
- 구현부 가중치 부여(--gravity=brain) 및 특정 요소 전용 검색 기능 제공
- ripgrep과 같은 단순 텍스트 매처와 차별화된 검색 엔진 기능 수행
- TUI 및 HTTP 모드를 통한 인터랙티브한 코드 탐색 지원
codespelunker (cs)
코드 구조를 이해하고 관련성에 따라 결과를 순위 매기는 CLI 코드 검색 도구. 인덱싱(Indexing)이 필요 없음
authenticate를 검색했을 때, 실제 구현부를 찾기도 전에 설정 파일, 주석, 테스트 스텁(test stubs)에서 200개의 결과가 쏟아져 나온 적이 있나요? cs가 이를 해결합니다.
cs는 CLI 도구의 속도와 Sourcegraph 또는 Zoekt와 같은 무거운 인덱스 기반 검색 엔진(indexed search engines)에서나 볼 수 있는 관련성 순위 지정(relevance ranking) 기능을 결합하면서도, 인덱스를 유지 관리할 필요가 없습니다.
cs "authenticate" --gravity=brain # 인터페이스가 아닌 복잡한 구현부를 찾음
cs "FIXME OR TODO OR HACK" --only-comments # 코드나 문자열이 아닌 주석에서만 검색
cs "error" --only-strings # 에러 메시지가 정의된 위치를 찾음
...
MIT 라이선스 하에 배포됩니다.
cs TUI 데모
https://github.com/user-attachments/assets/3b7f4bb2-d542-406d-9c53-29c0430dd60a
핵심 가치: 왜 cs를 사용해야 하는가?
대부분의 검색 도구는 코드를 일반 텍스트(plain text)로 취급합니다. cs는 그렇지 않습니다.
cs는 모든 파일을 즉석에서 파싱(parse)하여 무엇이 주석이고, 무엇이 문자열이며, 무엇이 코드인지 이해합니다. 그런 다음 단순히 발생 횟수로 나열하는 것이 아니라, 그 구조를 사용하여 관련성에 따라 순위를 매깁니다.
cs "authenticate" # BM25 기반 순위 변형 결과, 가장 잘 일치하는 항목이 먼저 나옴
cs "authenticate" --gravity=brain # 인터페이스보다 복잡한 구현부에 가중치를 부여
cs "TODO" --only-comments # 주석 내부의 일치 항목만 검색
...
대화형 탐색(Interactive Exploration)을 위한 TUI 및 HTTP 모드가 포함되어 있습니다.
cs # 현재 위치에서 TUI 모드로 진입
cs -d # 기본적으로 8080 포트에서 HTTP 모드로 진입
ripgrep 또는 grep과 무엇이 다른가?
ripgrep은 빠른 텍스트 매처(text matcher)입니다. 줄을 찾고 출력합니다. 자신이 맡은 역할에는 최고의 도구입니다.
cs는 검색 엔진입니다. 파일들을 찾아내고, 관련성(relevance)에 따라 순위를 매기며, 최적의 스니펫(snippet)을 추출하여 가장 관련성이 높은 결과를 보여줍니다. 인덱스(index)가 필요 없는 CLI 도구로서, Sourcegraph 수준의 순위 기반 검색을 구현했다고 생각하면 됩니다.
이들은 서로 다른 문제를 해결합니다. 아마 두 도구 모두를 사용하고 싶어질 것입니다.
핵심 역량
- 구조적 인식 (Structural Awareness): 코드 내에서의 매치(match)는 주석 내의 동일한 단어보다 더 높은 순위를 갖습니다 (1.0 대 0.2) — 이 수치는 설정 가능합니다. 또는
--only-code,--only-comments,--only-strings를 통해 엄격하게 필터링할 수도 있습니다. - 복잡도 중력 (Complexity Gravity): 순환 복잡도 (cyclomatic complexity)를 순위 신호로 사용합니다.
Authenticate를 검색하시나요? 복잡한 구현 파일이 인터페이스 정의보다 높은 순위를 차지합니다. (--gravity=brain) - 스마트 랭킹 (Smart Ranking): 사전 구축된 인덱스 없이도 BM25 관련성 점수 산출, 파일 위치 부스팅 (file-location boosting), 데이터 블롭(data blobs)에 대한 노이즈 페널티, 그리고 테스트 파일 자동 감쇄 (automatic test-file dampening)를 즉석에서 수행합니다.
- 다양한 인터페이스: 콘솔 출력, 내장된 TUI, 구문 강조(syntax highlighting)가 포함된 HTTP 서버, 또는 LLM 도구용 MCP 서버를 지원합니다.
주요 기능
구조적 필터링 (Structural Filtering)
오탐(false positives)을 대상으로 grep 하는 일을 멈추세요.
cs "database" --only-code # 주석/문서 내 매치 무시
cs "FIXME" --only-comments # 코드/문자열 내 매치 무시
cs "error" --only-strings # 에러 메시지가 정의된 곳 찾기
...
이 옵션들은 --only-code, --only-comments, --only-strings와 상호 배타적입니다.
구조적 랭커(structural ranker)는 또한 선언 탐지(declaration detection)를 사용하여, 단순 사용(plain usages)보다 선언 라인(예: func, class, def)에 나타나는 매치에 가중치를 부여합니다. 현재 다음 언어들을 지원합니다:
Go, Python, JavaScript, TypeScript, TSX, Rust, Java, C, C++, C#, Ruby, PHP, Kotlin, Swift,
Shell, Lua, Scala, Elixir, Haskell, Perl, Zig, Dart, Julia, Clojure, Erlang, Groovy, OCaml,
MATLAB, Powershell, Nim, Crystal, V
지원되지 않는 언어의 경우, 모든 일치 항목은 사용 사례 (usages)로 취급되며 텍스트 관련성 (text relevance)에 의해서만 순위가 매겨집니다.
구조적 필터링 (--only-code, --only-comments, --only-strings)은 scc가 인식하는 모든 언어에 대해 여전히 작동합니다.
복잡도 중력 (Complexity Gravity)
실제 작업이 일어나는 곳을 찾으세요.
cs "login" --gravity=brain # 복잡한 파일(구현부)의 순위를 높임
cs "login" --gravity=low # 단순한 파일(설정/인터페이스)의 순위를 높임
랭킹 프로필 (Ranking Profiles)
여러 매개변수를 한 번에 조정하는 사전 설정된 랭킹 전략입니다.
cs "authenticate" --profile=precise # 짧고 집중된 소스 파일
cs "authenticate" --profile=broad # 넓은 범위를 탐색하며 테스트 파일 포함
cs "authenticate" # 균형 잡힌 설정 (기본값, 기존과 동일)
| 프로필 | 최적의 용도 | 기능 |
|---|---|---|
balanced | 일반적인 용도 (기본값) | 표준 BM25 조정, 적절한 복잡도 가중치 부여, 테스트 파일 감쇠 |
| ... | ||
--profile이 설정되면 --gravity, --noise, --test-penalty 설정을 무시하고 덮어씁니다. |
Git 동기화 (Git Sync)
검색 대상이 항상 최신 상태를 유지하도록 하세요. 장기 실행 모드 (TUI, HTTP 또는 MCP)에서 실행할 때, --git-sync는 검색 디렉토리에서 발견된 저장소들에 대해 주기적으로 git pull을 실행합니다.
# 단일 저장소 — /path/to/repo에 있는 저장소를 일정에 따라 가져옴
cs -d --git-sync --dir /path/to/repo
...
탐색 규칙:
- 디렉토리 자체에
.git이 포함되어 있으면, 해당 단일 저장소를 동기화합니다. - 그렇지 않은 경우,
.git을 포함하는 직계 하위 디렉토리를 동기화합니다 (단 한 단계 깊이까지만).
| 플래그 | 기본값 | 설명 |
|---|---|---|
--git-sync | off | 주기적인 git pull 활성화 |
| ... | ||
| 동기화는 시작 시 즉시 실행된 후, 설정된 간격에 따라 반복됩니다. 오류는 stderr에 기록되지만 프로세스를 중단시키지는 않습니다. 각 pull 작업에는 2분의 타임아웃이 적용되며 비대화형 (non-interactively, 자격 증명을 묻지 않음)으로 실행됩니다. 콘솔 모드에서는 즉시 종료되므로 이 기능이 무시됩니다. |
Sourcegraph와 유사한 방식: 팀의 리포지토리(repos)들을 하나의 디렉터리로 클론(clone)한 뒤, --git-sync 옵션을 사용하여 cs가 해당 디렉터리를 가리키게 하면 모든 리포지토리에 대해 자체 업데이트 및 관련성 순위가 매겨진 코드 검색 기능을 사용할 수 있습니다. 인덱싱 서버(indexing server), 인프라(infrastructure), 또는 단일 명령어를 제외한 별도의 설정이 전혀 필요하지 않습니다.
mkdir -p ~/code-search && cd ~/code-search
git clone https://github.com/your-org/repo-a.git
git clone https://github.com/your-org/repo-b.git
...
이를 통해 리포지토리를 클론하는 것 외에 별도의 설정 없이도, Sourcegraph나 Hound가 제공하는 것과 유사하게 전체 코드베이스에 걸친 순위 기반의 구조적 코드 검색(structural code search)을 수행할 수 있습니다.
중복 제거 (Deduplication)
바이트 단위로 완전히 일치하는 검색 결과들을 하나의 결과로 통합합니다.
cs "Copyright" --dedup # 고유한 저작권 고지당 하나의 결과만 표시
cs "error" --dedup # 포함된(vendored) 또는 복사된 중복 항목 건너뛰기
스마트 랭킹 (Smart Ranking)
결과는 BM25(관련성)에 따라 정렬되며, 파일 길이에 의해 감쇠(dampened)되고, 코드 구조에 의해 부스트(boosted)됩니다. (테스트 파일을 찾고 있지 않을 때를 대비하여) 테스트 파일을 감쇠시키기 위한 노력도 반영되어 있습니다.
비스마트 랭킹 (Non-Smart Ranking)
랭킹 알고리즘을 순수 BM25, TFIDF, 또는 단순 최다 일치(most match) 랭킹으로 즉시 전환할 수 있습니다.
설치 (Install)
설치 가능한 패키지를 만들고 싶다면 직접 만들어 주세요. 저에게 알려주시면 이곳에 추가하도록 하겠습니다.
Go Get
Go >= 1.25.2 버전이 설치되어 있는 경우:
go install github.com/boyter/cs/v3@latest
Nixos
nix-shell -p codespelunker
https://github.com/NixOS/nixpkgs/pull/236073
수동 설치 (Manual)
Windows, GNU/Linux, macOS용 바이너리는 releases 페이지에서 받을 수 있습니다.
FAQ
이것이 ~만큼 빠른가요?
아니요.
말을 끝내기도 전에 끊으셨는데, ~만큼 빠른지 물어보려던 참이었습니다.
아마도 아닐 것입니다. 직접적인 비교 대상이 아닙니다. 제가 아는 다른 도구 중 hound, searchcode, Sourcegraph 등과 같은 완전한 인덱싱 도구(full indexing tools)를 제외하고는 이와 같은 방식으로 작동하는 도구는 없습니다. 이 도구처럼 즉석에서(on the fly) 작동하는 것은 없습니다.
제가 알기로 cs가 수행하는 방식은 커맨드 라인 도구(command line tool)로서 독특합니다.
cs는 매칭되는 모든 파일에 대해 scc의 전체 어휘 분석(lexical analysis) 및 복잡도 계산(complexity calculation)을 실행합니다.
이는 ripgrep의 원시 바이트 스캐닝(raw byte-scanning)과 비교하면 비용이 많이 들지만, 아마 여러분이 생각하는 것만큼 느리지는 않을 것입니다.
최신 기기(Apple Silicon M1 등)에서는 전체 Linux 커널 소스를 약 3초 만에 검색하고 순위를 매길 수 있습니다.
9950x3D를 사용하면 커널을 약 400밀리초(milliseconds) 만에 검색할 수 있습니다.
일반 문서에서도 작동하나요?
텍스트 파일이기만 하면 됩니다. 코드를 검색하기 위해 작성했지만, 전체 텍스트 문서에서도 똑같이 잘 작동합니다. 예를 들어, 코드 스니펫(snippet) 추출 기능은 《오만과 편견》을 대상으로 테스트했는데, 제가 남성이라는 점을 고려하면 아마 제가 알면 안 될 정도로 이 텍스트에 대해 잘 알고 있습니다.
인덱스(index)는 어디에 있나요?
없습니다. 모든 것은 즉석에서(on the fly) 무차별 대입(brute force) 방식으로 계산됩니다. 속도를 높이기 위한 약간의 캐싱(caching)이 있지만, 실제로는 결과에 영향을 주지 않아야 합니다.
순위 매기기(ranking)는 어떻게 작동하나요?
cs는 가중치가 적용된 BM25 알고리즘을 사용합니다.
표준 BM25는 "필드(fields)"(예: 제목, 본문, 카테고리)를 기반으로 매칭에 가중치를 둡니다. cs는 코드 구문(syntax)을 파싱하여 동적으로 필드를 생성합니다.
- 코드 내의 매칭은 전체 가중치(1.0)를 받습니다.
- 문자열(string) 내의 매칭은 부분 가중치(0.5)를 받습니다.
- 주석(comment) 내의 매칭은 더 낮은 가중치(0.2)를 받습니다.
이는 검색어가 로직(logic)에 나타나는 파일이, 단어 수가 같더라도 검색어가 문서화(documentation)에만 나타나는 파일보다 더 높은 순위를 차지함을 의미합니다.
CLI를 통해 필요에 따라 값을 조정하거나, cs가 검색할 필드를 즉석에서 변경할 수 있습니다.
복잡도 중력(complexity gravity)이란 무엇인가요?
복잡도 중력은 각 파일의 순환 복잡도(cyclomatic complexity)를 사용하여 결과 순서에 영향을 주는 순위 부스트(ranking boost)입니다.
코드 검색에서 가장 좋은 결과는 대개 로직이 구현된 곳입니다. 이러한 파일들은 일반적으로 알고리즘 밀도(algorithmic density)(분기, 루프, 조건문)가 높습니다. cs는 이를 활용하여, 모든 조건이 동일할 때 구현(implementation) 파일이 데이터/설정/인터페이스 파일보다 일반적으로 더 높은 순위를 차지하도록 합니다.
--gravity 플래그는 다음과 같은 명명된 의도(named intent)를 허용합니다:
| 의도 (Intent) | 강도 (Strength) | 목적 (Purpose) |
|---|---|---|
brain | 2.5 | 복잡한 핵심 로직을 공격적으로 노출 |
| ... |
cs --gravity=brain "search term" # 복잡한 구현(implementation) 찾기
cs --gravity=off "search term" # 순수 텍스트 관련성(relevance)만 고려
스니펫(snippets)은 어떻게 가져오나요?
즐거운 과정은 아닙니다... https://github.com/boyter/cs/blob/master/pkg/snippet/snippet.go 와 https://github.com/boyter/cs/blob/master/pkg/snippet/snippet_lines.go 를 확인해 보세요.
이 방식은 스니펫을 추출할 문서 내용과 각 용어(term)에 대한 모든 일치 위치(match locations)를 전달하여 작동합니다.
그 다음 각 단어의 각 위치를 살펴보며, 그 주변에 인접한 용어가 있는지 양옆을 확인합니다.
이후 우리가 주변을 확인하고 있는 해당 용어의 용어 빈도(term frequency)에 따라 순위를 매기며, 더 희귀한 용어에 가산점을 부여합니다.
또한 더 많은 일치, 더 가까운 일치, 대소문자 일치, 그리고 전체 단어 일치(whole words)에 대해서도 가산점을 부여합니다.
더 자세한 정보는 이 블로그 포스트의 "Snippet Extraction AKA I am PHP developer" 섹션을 읽어보세요: https://boyter.org/posts/abusing-aws-to-make-a-search-engine/
HTTP 모드는 어떤 모습인가요?
약간 브루탈리즘(brutalist) 스타일입니다.
<img alt="cs http" src="https://github.com/boyter/cs/raw/master/cs_http.png">--template-style을 사용하여 내장된 테마(dark, light, bare)로 느낌을 바꿀 수 있으며, --template-display 및 --template-search를 통해 사용자 정의 템플릿을 제공할 수도 있습니다. 사용할 수 있는 예시 템플릿은 https://github.com/boyter/cs/tree/master/asset/templates 에서 확인하여 느낌을 수정할 수 있습니다.
cs -d --template-style light
cs -d --template-display ./asset/templates/display.tmpl --template-search ./asset/templates/search.tmpl
사용법 (Usage)
cs의 커맨드 라인 (Command line) 사용법은 가능한 한 단순하게 설계되었습니다.
상세한 내용은 cs --help 또는 cs -h에서 확인할 수 있습니다. 아래 내용은 릴리스 (release) 버전이 아닌 마스터 (master) 브랜치의 상태를 반영하고 있으므로, 아래에 나열된 기능이 사용자의 설치 버전에는 없을 수 있음에 유의하십시오.
$ cs -h
code spelunker (cs) code search.
Version 3.1.0
...
검색은 단일 또는 여러 단어에 대해 작동하며, 단어들 사이에는 논리적 AND (Logical AND)가 적용됩니다. 용어 앞에 NOT을 붙여 부정할 수 있습니다.
OR로 용어들을 결합할 수 있으며, 괄호를 사용하여 그룹화를 제어할 수 있습니다.
따옴표를 사용하여 정확한 일치 (Exact match)를 수행할 수 있으며, toothpicks (toothpick syntax)를 사용하여 정규 표현식 (Regular expressions)을 사용할 수 있습니다.
검색 예시:
cs t NOT something test~1 "ten thousand a year" "/pr[e-i]de/" file:test
cs (cat OR dog) AND NOT bird
cs path:vendor main # vendor/ 디렉토리 하위에서만 검색
...
AI 자동 생성 콘텐츠
본 콘텐츠는 HN Claude Code Search의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기