neuron-explorer
Qwen3.5‑4B 전용 조향형 뉴런 탐색기, 모든 MLP 뉴런을 밀어 결과를 보관·탐색
git log unfolds code into knowledge.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
git log, unfolds code into knowledge. 커밋 로그라는 시간의 주름을 따라 접힌 코드가 펼쳐진다 — 읽고, 비교하고, 이해하는 행위 끝에 지식이 남는다. 바이너리 이름 glc는 손가락이 기억하는 명령어: home row에서 벗어나지 않고 g l c. gluck은 그 뒤에 *u*nfolding과 *k*nowing을 더한, 프로젝트의 온전한 이름이다. Git history file viewer — 터미널에서 git history의 파일을 탐색하고 읽는 TUI 도구. Intel Mac(x86_64)용 바이너리는 GitHub Actions 지원 중단으로 제공하지 않습니다. Intel Mac 사용자는 아래 Cargo 설치 방법을 이용해 주세요. Linux용 바이너리는 별도로 제공되지 않습니다. Rust 툴체인이 설치되어 있다면 직접 빌드할 수 있습니다.README 전문 보기 ↗
git log, unfolds code into knowledge.
커밋 로그라는 시간의 주름을 따라 접힌 코드가 펼쳐진다 — 읽고, 비교하고, 이해하는 행위 끝에 지식이 남는다.
바이너리 이름
glc는 손가락이 기억하는 명령어: home row에서 벗어나지 않고g l c. gluck은 그 뒤에 unfolding과 knowing을 더한, 프로젝트의 온전한 이름이다.
Git history file viewer — 터미널에서 git history의 파일을 탐색하고 읽는 TUI 도구.
홈페이지(키 치트시트 포함): https://soomtong.github.io/gluck/
cargo install --git https://github.com/soomtong/gluck
Intel Mac(x86_64)용 바이너리는 GitHub Actions 지원 중단으로 제공하지 않습니다. Intel Mac 사용자는 아래 Cargo 설치 방법을 이용해 주세요.
brew tap soomtong/tap
brew install glc
Linux용 바이너리는 별도로 제공되지 않습니다. Rust 툴체인이 설치되어 있다면 직접 빌드할 수 있습니다.
cargo install --git https://github.com/soomtong/gluck
또는 소스를 받아 빌드:
git clone https://github.com/soomtong/gluck
cd gluck
cargo build --release
# 빌드 결과: ./target/release/glc
glc # 현재 디렉토리의 git history 열기
glc /path/to/repo # 특정 저장소 열기
glc index # 시맨틱 검색 인덱스 빌드
glc index --force # 인덱스 강제 재빌드
glc ignore # 기본 제외 목록으로 .glcignore 생성 (--force: 덮어쓰기)
| 키 | 동작 |
|---|---|
j / k / ↑ / ↓ | 커밋 이동 |
^N / ^P | 이전(older)/다음(newer) 커밋 이동 |
Enter / l | 선택 커밋 View 모드 |
Tab | 선택 커밋 Diff 모드 |
/ | 커밋 검색 |
s | 시맨틱 검색 모달 열기 (glc index 선행 필요) |
^T | 색상 테마 전환 |
q | 종료 |
| 키 | 동작 |
|---|---|
j / k / ↑ / ↓ | 파일 트리 이동 |
u / d | 내용 스크롤 (3줄) |
J / K | 내용 페이지 스크롤 |
H / L / ← / → | 이전/다음 변경 파일(* 표시)로 이동 |
. | .gitignore 파일 필터 토글 |
w | 긴 줄 word wrap 토글 (기본 on) |
Tab | Diff 모드 전환 |
Esc / h | Pick 모드 |
^N / ^P | 이전(older)/다음(newer) 커밋 이동 |
s | 시맨틱 검색 모달 열기 |
a / A | 화면(또는 선택 영역)을 LLM에게 설명 요청 / 자세히 |
| 키 | 동작 |
|---|---|
h / l / ← / → | 변경 파일 이동 |
j / k | diff 내용 스크롤 (1줄, Ask 패널이 열려 있으면 답변 스크롤) |
u / d | diff 내용 스크롤 (3줄) |
J / K / ↑ / ↓ | diff 내용 페이지 스크롤 |
v | side-by-side / unified 토글 |
w | 긴 줄 word wrap 토글 (기본 on) |
Tab | View 모드 |
Esc | Pick 모드 |
^N / ^P | 이전(older)/다음(newer) 커밋 쌍 이동 |
s | 시맨틱 검색 모달 열기 |
a / A | 화면(또는 선택 영역)을 LLM에게 설명 요청 / 자세히 |
s 키를 누르면 커밋 메시지와 파일/심볼을 동시에 검색하는 모달이 열립니다.
ctrl+n/p로 결과 탐색, Enter로 선택I 키로 빌드 가능: force rebuild index사용 전 glc index로 인덱스를 먼저 빌드할 수 있습니다.
처음 보는 언어, 낯선 이디엄, 변경 의도를 TUI 안에서 바로 물어봅니다. View/Diff 모드에서 동작합니다.
a: 지금 화면에 보이는 diff/코드를 설명 (요약 · 변경 의도 · 낯선 구문/이디엄 · 리뷰 포인트)a: 선택 블록을 구문 단위로 설명 (무엇을 하나 · 구문 해설 · 왜 이렇게 썼나 · 관련 개념). side-by-side에서는 드래그한 pane(old/new)의 코드만 보냅니다.A: 같은 요청을 더 자세한 수준(deep)으로[ / ]로 페이지 스크롤, 휠로 3줄 스크롤 (Diff 모드에서는 j / k가 평소 diff 1줄 스크롤이고, 패널이 열려 있는 동안은 답변 1줄 스크롤), r 재요청, Esc 닫기 (선택이 있으면 Esc가 먼저 선택을 해제)cached 표시, 추가 과금 없음). r은 캐시를 무시하고 새로 요청합니다.OpenAI 호환 Chat Completions API를 사용합니다 (OpenRouter, DeepSeek, Gemini, Groq, Cerebras, Mistral, OpenAI 프리셋, 로컬 Ollama 등). 설정 파일 [ask]의 값이 우선이고, 비어 있는 항목은 프리셋 기본값과 환경변수(OPENROUTER_API_KEY, DEEPSEEK_API_KEY, GEMINI_API_KEY, GROQ_API_KEY, CEREBRAS_API_KEY, MISTRAL_API_KEY, OPENAI_API_KEY)로 채웁니다. provider를 비워 두면 이 순서대로 키가 있는 첫 프로바이더를 고릅니다. 요청할 때만 화면 내용이 전송되며, 패널 제목에 provider/model과 키 출처(config/env)가 표시됩니다.
프롬프트를 모델별로 비교하려면 cargo run --example ask_probe -- [파일명 일부] [--deep] [--dry]로 HEAD diff에 대한 프롬프트와 답변을 확인할 수 있습니다.
하이브리드 검색(hybrid search)으로 BM25 키워드 검색과 벡터 의미 검색을 결합합니다.
쿼리 입력
├── BM25 (Tantivy ngram_2_2 + LowerCaser) ──→ 키워드 매칭 결과
├── Embedding (potion-multilingual-128M) ──→ 벡터 검색 결과
└── RRF (Reciprocal Rank Fusion) ──→ 점수 융합 → 최종 결과
ngram_2_2)로 한국어·영문 키워드를 동시에 매칭합니다. LowerCaser 필터로 영문 대소문자가 정규화되어 ParseConfig를 parseconfig로도 찾을 수 있습니다.
"에러 처리" ↔ "에러처리"처럼 띄어쓰기 변형에도 부분 매칭됩니다.path:"src/search/error.rs" 같이 경로 정확 매칭을 지원합니다.path::symbol_name 형태로 인덱싱되어 "error.rs handle"처럼 파일 범위와 함수명을 한 쿼리로 좁힐 수 있습니다.is_binray_blob → binary). 철자가 맞는 단어는 건드리지 않습니다.· no strong match를 붙입니다. 이 저장소와 무관한 질문(예: django orm migrations)을 알아보기 위한 표시입니다.glc index는 커밋 메시지와 HEAD의 파일을 대상으로 인덱스를 빌드합니다.
WholeFile), 그보다 크면 tree-sitter로 심볼(함수, 메서드, 타입) 단위로 분할하여 인덱싱.glcignore)레포 루트에 .glcignore를 두면 해당 파일을 시맨틱 검색 인덱스에서 뺍니다. 문법은 .gitignore와 같습니다 (디렉터리 패턴, */** glob, ! 부정, # 주석).
glc ignore를 실행하면 기본 제외 목록이 담긴 .glcignore가 레포 루트에 생성됩니다. 인덱스는 HEAD에 커밋된 파일만 대상으로 하므로, 기본 목록은 커밋되어 있지만 검색에는 잡음인 것들입니다.
vendor/, third_party/, external/Cargo.lock, package-lock.json, yarn.lock, pnpm-lock.yaml, go.sum, poetry.lock, uv.lock 등dist/, build/, out/, *.min.js, *.min.css, *.map이미 파일이 있으면 덮어쓰지 않습니다 (glc ignore --force로 덮어쓰기). 생성 후 프로젝트에 맞게 고치면 됩니다. 직접 작성한 예:
# 생성물이나 검색에 방해되는 문서
vendor/
docs/reports/
*.lock
!Cargo.lock
.glcignore를 읽습니다.glc index(또는 모달의 I)에서 자동으로 전체 재빌드합니다..glc-index/
├── meta.toml # 버전, HEAD OID, 토크나이저 식별자, 도큐먼트 수, 인덱싱 시각, .glcignore 해시
├── bm25/ # Tantivy BM25 인덱스 (ngram_2_2 + LowerCaser, 구조화 필드)
└── vectors/ # turbovec 4-bit 양자화 벡터 인덱스
인덱스 스키마 또는 토크나이저가 변경되면 meta.toml의 식별자가 코드와 어긋나서 glc가 자동으로 재인덱싱을 안내합니다. glc index --force로 재구축하세요.
glc index 최초 실행 시 임베딩 모델(minishlab/potion-multilingual-128M, 약 500MB)을 자동으로 다운로드합니다.
모델은 HuggingFace Hub 기본 캐시에 저장됩니다:
~/.cache/huggingface/hub/같은 머신에서 다른 레포를 인덱싱할 때는 캐시에서 즉시 로드되므로 재다운로드가 없습니다.
.glc-index/는 .gitignore에 추가하는 것을 권장합니다:
echo '.glc-index/' >> .gitignore
설정 파일은 XDG config 경로에 저장됩니다.
~/Library/Application Support/gluck/config.toml~/.config/gluck/config.toml[theme]
# 색상 테마: plain (기본), catppuccin, tokyo-night, nord, gruvbox, one-light
name = "plain"
[ui]
# u/d 키 스크롤 줄 수 (기본: 3)
scroll_lines = 3
# View/Diff 긴 줄 word wrap (기본: true, `w` 키로 토글 시 저장됨)
word_wrap = true
[ask]
# 활성 프로바이더. 비우면 환경변수 키가 있는 첫 프리셋 자동 선택
provider = "deepseek"
# 답변 언어 (Korean이면 섹션 제목도 한국어)
language = "Korean"
# brief | normal | deep (A 키는 항상 deep)
detail = "normal"
# 0 = detail 기본값 (500 / 1200 / 2500)
max_tokens = 0
# 음수면 temperature 필드를 보내지 않음 (거부하는 모델용)
temperature = 0.2
# 선택 영역과 함께 보내는 앞뒤 줄 수
extra_context_lines = 20
max_context_chars = 12000
# 비우면 내장 system 프롬프트 ({language} 치환)
system_prompt = ""
[ask.providers.deepseek]
# 생략 시 DEEPSEEK_API_KEY. base_url / model 생략 시 프리셋 기본값
api_key = "sk-..."
[ask.providers.local]
base_url = "http://localhost:11434/v1"
model = "qwen2.5-coder:7b"
설정 파일에 API 키를 저장하면 저장 시 파일 권한을 0600으로 맞추고, 다른 사용자가 읽을 수 있는 상태면 경고 로그를 남깁니다.
오픈소스 프로젝트를 공부할 때 가장 좋은 방법 중 하나는 git history를 따라가며 코드가 어떻게 변해왔는지 읽는 것이다. 하지만 기존 도구들은 각각 한계가 있다:
gluck은 git history를 타임라인으로 삼아, 각 시점의 파일을 읽고 비교하는 데 집중한다.
모든 grammar는 glc 바이너리 하나에 정적으로 링크된다. 그래서 grammar가 늘수록 바이너리가 커진다. 위 언어 목록 기준 release 빌드는 약 52MB이고, 그중 Kotlin, Scala, C++, Ruby, Odin, PHP, Elixir, LLVM IR이 약 24MB를 차지한다.
크기의 대부분은 tree-sitter parse table이다. grammar마다 parser.c 안에 거대한 상수 배열로 생성되므로, strip으로 디버그 심볼을 없애도 3MB 정도만 줄어든다.
Helix도 tree-sitter를 쓰지만 hx 바이너리(약 27MB)에는 parser가 들어 있지 않다. grammar는 runtime/grammars/*.so로 따로 빌드되고(25.07.1 기준 245개, 195MB), 필요한 언어만 실행 중에 동적 로딩한다. 같은 grammar는 Helix의 .so와 gluck에 링크된 결과물이 거의 같은 크기다(예: Kotlin 약 5.5MB). 크기를 바이너리에서 runtime 디렉터리로 옮긴 차이일 뿐이다.
gluck은 아래 이유로 정적 링크를 유지한다.
cargo install에 grammar 빌드나 배포 단계가 필요 없다..dylib/.dll 빌드, 설치 경로 관리, libloading, release workflow와 Homebrew formula 변경이 함께 필요하다.크기가 문제가 되면 먼저 큰 grammar를 cargo feature로 분리하는 방안을 검토하고, 동적 로딩은 그다음에 별도 설계로 다룬다.