रेपो में लगभग 11,000 फाइलें थीं। एजेंट के पास एक bash टूल था और एक अस्पष्ट निर्देश: "ढूंढो कि हम वेबहुक सिग्नेचर कहाँ वैलिडेट करते हैं।" उसने grep -rn "signature" . चलाया, वेंडर किए गए JS, टेस्ट फिक्स्चर, एक CHANGELOG, और तीन असंबंधित क्रिप्टो हेल्पर्स में फैले 600 मैच पाए, और फिर पूरे आत्मविश्वास से गलत फाइल की ओर इशारा कर दिया। हमने उसे लगातार चार बार अलग-अलग शब्दों के साथ ऐसा करते देखा, इससे पहले कि किसी ने वह स्पष्ट बात कही: grep स्ट्रिंग्स को मैच करता है, और एजेंट अर्थ के बारे में सवाल पूछ रहा था।
यही पूरी समस्या एक वाक्य में है। grep और rg "यह सटीक टोकन कहाँ दिखता है" के लिए बेहतरीन हैं। वे "वह चीज़ कहाँ है जो X करती है" के लिए बेकार हैं, क्योंकि X करने वाले कोड में लगभग कभी वे शब्द नहीं होते जिनसे आप X का वर्णन करते। फ़ंक्शन का नाम verify_hmac है। आपने "webhook signature" खोजा। शून्य ओवरलैप, और एजेंट जिस इकलौते टूल की ओर पहले हाथ बढ़ाता है, वह कुछ भी उपयोगी नहीं लौटाता।
समाधान है सिमैंटिक सर्च: कोड को एम्बेड करो, क्वेरी को एम्बेड करो, उन चंक्स को ढूंढो जिनका अर्थ सबसे करीब है। पेच यह है कि "बस एम्बेडिंग इस्तेमाल करो" वाली ज़्यादातर सलाह यह मान लेती है कि आप अपना सोर्स कोड किसी क्लाउड API को भेजेंगे और एक GPU किराये पर लेंगे। एक निजी मोनोरेपो के लिए, दोनों में से कोई भी स्वीकार्य नहीं: लीगल टीम प्रोप्रायटरी कोड किसी तीसरे पक्ष को अपलोड करने की मंज़ूरी नहीं देगी, और आप एक ऐसा प्रति-टोकन बिल नहीं चाहते जो हर री-इंडेक्स के साथ बढ़े।
तो यह रही वह सेटअप जो हम असल में चलाते हैं: Octocode, जो एक बड़े रेपो को सिमैंटिक सर्च के लिए पूरी तरह लोकल इंडेक्स करता है — बिना GPU, बिना क्लाउड एम्बेडिंग, मशीन से कुछ भी बाहर नहीं जाता। यह रहा कि यह बिल्कुल कैसे काम करता है, कौन सा कॉन्फ़िग मायने रखता है, और वे चार चीज़ें जिन्होंने हमें परेशान किया।
grep क्यों काफी नहीं है, ठोस रूप में
एम्बेडिंग की ओर हाथ बढ़ाने से पहले, यह स्पष्ट होना ज़रूरी है कि एजेंट्स के लिए टेक्स्ट सर्च क्यों विफल होता है, क्योंकि यह बताता है कि उसके विकल्प को क्या करना होगा।
- शब्दावली का बेमेल। क्वेरी मंशा है ("rate limiting"), कोड तंत्र है (
Semaphore,token_bucket,RetryAfter)। कोई साझा टोकन नहीं। - कोई रैंकिंग नहीं।
rgआपको हर मैच समान वज़न के साथ देता है। 600 मैच जवाब नहीं हैं; वह एक दूसरी सर्च समस्या है। - कोई संरचना नहीं। एक कमेंट में, एक टेस्ट में, और एक कोर फ़ंक्शन में टेक्स्ट मैच
grepके लिए एक जैसे दिखते हैं। वह आपको नहीं बता सकता कि तीसरा वाला परिभाषा है।
इसके बजाय आप यह चाहते हैं: सिमैंटिक निकटता से रैंक करना, लेकिन उस चीज़ को न खोना जिसमें grep सचमुच अच्छा है — सटीक आइडेंटिफायर मैच। Octocode का जवाब है दोनों करना और उन्हें जोड़ना, जिस पर मैं आगे आऊंगा। पहले, कोड को सर्च करने योग्य रूप में लाया कैसे जाता है।
Octocode कोड को कैसे चंक और इंडेक्स करता है
मानक RAG फाइलों को निश्चित आकार की टेक्स्ट विंडो में काटता है — हर N अक्षर, थोड़ा ओवरलैप, और एम्बेड। गद्य के लिए यह ठीक है। कोड के लिए यह सक्रिय रूप से बुरा है: यह एक फ़ंक्शन को दो चंक्स में बाँट देता है, एक match आर्म का आधा हिस्सा एम्बेड करता है, और यह तथ्य खो देता है कि एक मेथड किसी टाइप से संबंधित है।
Octocode पहले हर फाइल को tree-sitter से पार्स करता है, AST में चलता है, और मनमाने बाइट ऑफसेट के बजाय असली सिंबल सीमाओं — फ़ंक्शन, मेथड, क्लास, मॉड्यूल — के अनुसार चंक करता है। आर्किटेक्चर है: हर भाषा के लिए एक पार्सर जो फ़ंक्शन, क्लास, इम्पोर्ट और एक्सपोर्ट निकालता है, फिर जो कुछ भी एक टुकड़े में एम्बेड करने के लिए बहुत बड़ा है उसके लिए चंक-आधारित प्रोसेसिंग। किसी impl ब्लॉक या क्लास के अंदर से निकाला गया मेथड अपनी सिंबल सूची में अपने पैरेंट टाइप का नाम साथ रखता है, इसलिए Suppression.mark_set या Foo.bar खोजना सीधे मेथड चंक पर पहुँचता है।
भाषा कवरेज असली tree-sitter ग्रामर हैं, regex ह्यूरिस्टिक्स नहीं। रेपो के अनुसार, पूर्ण AST पार्सिंग के साथ कोड के रूप में इंडेक्स किए जाते हैं:
| भाषा | एक्सटेंशन |
|---|---|
| Rust | .rs |
| Python | .py |
| TypeScript / JavaScript | .ts, .tsx, .js, .jsx |
| Go | .go |
| PHP | .php |
| C / C++ | .c, .h, .cpp, .hpp, .cc, .cxx, साथ ही C++20 मॉड्यूल एक्सटेंशन .cppm, .ixx, .mxx, .ccm, .cxxm |
| Ruby | .rb |
| Java | .java |
| Swift | .swift |
| JSON, Bash, CSS, Lua, Svelte, Markdown | समर्पित tree-sitter पथ |
कॉन्टेक्स्ट के लिए उपयोगी बाकी सब कुछ (yaml, toml, dockerfile, makefile, ini, conf, env, xml, html, sql, rst वगैरह) टेक्स्ट ब्लॉक के रूप में इंडेक्स होता है, इसलिए वह अब भी खोजने योग्य रहता है, बस बिना सिमैंटिक सिंबल एक्सट्रैक्शन के।
चंकिंग के पैरामीटर [index] के तहत रहते हैं:
[index]
chunk_size = 2000 # प्रति कोड चंक अधिकतम अक्षर
chunk_overlap = 100 # आसपास के चंक्स के बीच ओवरलैप
quantization = true # RaBitQ वेक्टर संपीड़न, ~32x, न्यूनतम गुणवत्ता हानि
require_git = true # डिफ़ॉल्ट रूप से केवल git रेपो के अंदर इंडेक्स करें
chunk_size एक सीमा है, लक्ष्य नहीं — सीमा से छोटा 40-लाइन का फ़ंक्शन पूरा रहता है। सीमा केवल सचमुच बड़े बॉडी के लिए लागू होती है, और Octocode पहले से ही Python, TypeScript, C++, और Ruby में बड़ी क्लासों को मेथड-दर-मेथड इंडेक्स करता है, बजाय पूरी क्लास को एक चंक में डालने के। इस सबका मकसद: जब आप बाद में "वह फ़ंक्शन जो रिमोट पुल सेटअप संभालता है" खोजते हैं, तो जो इकाई एम्बेड होती है वह वही फ़ंक्शन है — अपने नाम और जुड़े पैरेंट टाइप के साथ, न कि कोई विंडो जो संयोग से उसके आर-पार पड़ती है।
लोकल एम्बेडिंग: बिना GPU, बिना क्लाउड, बिना API की
जिस हिस्से के बारे में लोग मान लेते हैं कि उसे क्लाउड चाहिए — कोड को वेक्टर में बदलना — उसे क्लाउड नहीं चाहिए।
Octocode एक local-first स्टैक के साथ आता है जो fastembed पर बना है (पर्दे के पीछे ONNX Runtime)। आप कॉन्फ़िग को fastembed: प्रीफ़िक्स वाले लोकल मॉडल की ओर इंगित करते हैं और एम्बेडिंग CPU पर, आपकी मशीन पर चलती है:
[embedding]
code_model = "fastembed:jinaai/jina-embeddings-v2-base-code" # 768-d, कोड के लिए विशेष रूप से बना
text_model = "fastembed:nomic-ai/nomic-embed-text-v1.5" # टेक्स्ट और दस्तावेज़
मॉडल स्ट्रिंग हमेशा provider:model होती है। प्रोवाइडर प्रीफ़िक्स ही पूरा रूटिंग निर्णय है: fastembed: और huggingface: लोकल हैं (कोई की नहीं, कोई नेटवर्क नहीं); voyage:, jina:, google:, openai:, together:, octohub: क्लाउड हैं और एनवायरनमेंट में संगत API की चाहिए। चाहें तो मिला लें (लोकल कोड एम्बेडिंग, क्लाउड टेक्स्ट एम्बेडिंग), लेकिन निजी रेपो के लिए पूरी तरह लोकल रास्ता ही मकसद है।
यहाँ कोई GPU की ज़रूरत नहीं और कोई GPU कोड पथ नहीं: यह CPU पर ONNX इन्फरेंस है। AVX2 वाली आधुनिक मल्टी-कोर मशीन पर, यह इतना तेज़ है कि एम्बेडर शायद ही कभी बॉटलनेक बनता है — आमतौर पर डिस्क I/O और tree-sitter पार्सिंग बनते हैं। रेपो के अपने प्रदर्शन नोट्स लोकल FastEmbed इंडेक्सिंग को मोटे तौर पर 1,000 फाइलों के लिए लगभग 45 सेकंड बताते हैं; आपका परिणाम फाइल आकार और कोर संख्या के अनुसार बदलेगा, इसलिए इसे केवल उदाहरण मानें, वादा नहीं।
दो ईमानदार चेतावनियाँ:
- पहली बार चलाने पर मॉडल डाउनलोड होता है। किसी
fastembed:मॉडल की ओर इंगित करने के बाद पहलाoctocode indexONNX वेट्स (कुछ सौ MB) एक कैश डायरेक्टरी (~/.local/share/octocode/fastembed/Linux/macOS पर) में खींचता है। एक बार की लागत, उसके बाद हमेशा के लिए ऑफलाइन। - लोकल प्रोवाइडर फ़ीचर-गेटेड और प्लेटफ़ॉर्म-संवेदनशील हैं। FastEmbed और HuggingFace के लिए
fastembed/huggingfaceबिल्ड फ़ीचर चाहिए। डिफ़ॉल्ट बिल्ड उन्हें वहाँ शामिल करते हैं जहाँ वे अच्छी तरह समर्थित हैं; जहाँ नहीं हैं, वहाँ आप क्लाउड प्रोवाइडर पर लौट आते हैं। यह देखने के लिए कि आपका बाइनरी असल में क्या उजागर करता है,octocode models list fastembedजाँचें। 0.17.0 में लोकल एम्बेडिंग प्रोवाइडर का हालिया काम ने ही इस सूची को इस बारे में ईमानदार बनाया कि कहाँ क्या उपलब्ध है।
अगर आपने पहले कभी कोड पर सिमैंटिक सर्च सेटअप नहीं किया, तो Octocode सिमैंटिक कोड सर्च का परिचय बुनियादी अवधारणाएँ कवर करता है; यह पोस्ट मानता है कि आप उससे आगे हैं और प्रोडक्शन सेटअप चाहते हैं।
रेपो को इंडेक्स करना
कॉन्फ़िग तैयार होने पर, इंडेक्सिंग रेपो रूट से एक ही कमांड है:
cd /path/to/big-monorepo
octocode index
# → Indexed 12,847 blocks across 342 files
असल में जो होता है, क्रम में: फाइलें खोजना (इग्नोर नियमों का पालन करते हुए), हर एक को tree-sitter से पार्स करना, सिंबल निकालना, AST सीमाओं के साथ चंक करना, हर चंक को लोकल एम्बेड करना, और सब कुछ एक LanceDB कॉलमनर स्टोर में लिखना। डेटाबेस आपके रेपो में नहीं रहता — यह सिस्टम डेटा डायरेक्टरी के तहत प्रति-प्रोजेक्ट कुंजीबद्ध होता है (~/.local/share/octocode/<project-id>/storage Linux/macOS पर)। इससे आपका वर्किंग ट्री साफ़ रहता है और इसका मतलब है कि git clean -fdx आपके इंडेक्स को नहीं मिटाएगा।
उपयोगी फ़्लैग:
octocode index --force # इंक्रीमेंटल कैश अनदेखा करें, शून्य से फिर से बनाएँ
octocode index --verbose # प्रति-फाइल प्रगति देखें
octocode stats # कितने कोड/टेक्स्ट/डॉक ब्लॉक, ग्राफ नोड, इंडेक्स बासीपन
octocode stats वही है जिसे चलाना चाहिए जब कुछ गड़बड़ लगे — यह बताता है कि आपका HEAD पिछले इंडेक्स किए गए कमिट से मेल खाता है या नहीं, इसलिए आप एक नज़र में देख सकते हैं कि इंडेक्स बासी है या नहीं।
इंक्रीमेंटल बनाम पूर्ण री-इंडेक्स
octocode index के बाद के रन इंक्रीमेंटल होते हैं — केवल बदली हुई फाइलें फिर से पार्स और एम्बेड होती हैं। हर इंडेक्सिंग रन एक टेबल ऑप्टिमाइज़ेशन पास के साथ समाप्त होता है ताकि डेटाबेस बढ़ने पर भी क्वेरी पथ तेज़ बना रहे (बार-बार इंक्रीमेंटल इंडेक्सिंग पहले एक बिना-इंडेक्स वाली पूँछ छोड़ती थी जिसे सर्च को ब्रूट-फोर्स स्कैन करना पड़ता था; अब यह अपने-आप संभलता है)।
जब आप यह बदलते हैं कि चीज़ें कैसे इंडेक्स होती हैं (एक नया चंकिंग नियम, अलग एम्बेडिंग मॉडल), तो इंक्रीमेंटल अपने पास पहले से मौजूद फाइलों को पिछली तारीख से फिर से चंक नहीं करेगा। एम्बेडिंग मॉडल बदलना सबसे बड़ी बात है: एक मॉडल के वेक्टर दूसरे के वेक्टर से तुलनीय नहीं हैं। code_model या text_model बदलने के बाद, एक साफ़ रीबिल्ड करें:
octocode clear # इंडेक्स की गई टेबल हटाएँ
octocode index # नए मॉडल के साथ फिर से बनाएँ
watch मोड: इंडेक्स को जीवंत रखें
जैसे ही कोई कमिट करता है, एक-बार वाला इंडेक्स बासी हो जाता है। ऐसे एजेंट के लिए जिसे रेपो की वर्तमान स्थिति के बारे में जवाब देने हों, watcher चलाएँ:
octocode watch # फाइल बदलने पर अपने-आप री-इंडेक्स
octocode watch --debounce 5 # री-इंडेक्स से पहले अंतिम बदलाव के बाद 5s प्रतीक्षा करें
octocode watch --quiet
Watcher डिबाउंस करता है (कॉन्फ़िगरेबल, 1–30 सेकंड), इसलिए 400 फाइलों को छूने वाला एक git checkout एक री-इंडेक्स ट्रिगर करता है, 400 नहीं। यह पूर्ण इंडेक्स जैसे ही इग्नोर नियमों का पालन करता है, इसलिए node_modules की फाइल संपादित करने से वह नहीं जागता।
अगर आप MCP सर्वर चला रहे हैं (अगला खंड), तो एक और भी साफ़ विकल्प है: [index] के तहत mcp_index = true सेट करें और MCP सर्वर इन-प्रोसेस इंडेक्स और वॉच करेगा — दो के बजाय एक चलती चीज़। डिफ़ॉल्ट false है, जो मौजूदा इंडेक्स को केवल-पढ़ने के रूप में परोसता है और मानता है कि आप अलग से इंडेक्स करते हैं; इसे तब चालू करें जब आप चाहें कि सर्वर पूरे जीवनचक्र का मालिक हो।
हाइब्रिड सर्च: सिमैंटिक और सटीक, एक साथ जुड़े
यह वह हिस्सा है जो grep के मूल विफलता को ठीक करता है, grep की एकमात्र ताकत को फेंके बिना।
शुद्ध वेक्टर सर्च आइडेंटिफायर-भारी क्वेरीज़ पर हारता है। parse_remote खोजें और डेंस एम्बेडिंग खुशी-खुशी वह सब लौटाएंगे जो parse_remote के सिमैंटिक रूप से करीब है, जबकि शाब्दिक रूप से parse_remote नाम वाले फ़ंक्शन को छोड़ देंगे। BM25 कीवर्ड सर्च की उलटी कमी है: यह सटीक आइडेंटिफायर पकड़ता है और "वह फ़ंक्शन जो रिमोट पुल सेटअप संभालता है" जैसी रूपांतरित मंशा पर चूक जाता है।
Octocode हर क्वेरी पर दोनों चलाता है और उन्हें LanceDB के अंदर Weighted Reciprocal Rank Fusion से जोड़ता है। वज़न उजागर हैं:
[search.hybrid]
enabled = true
default_vector_weight = 0.7
default_keyword_weight = 0.3
ऐसे कोड-भारी रेपो के लिए जहाँ सटीक आइडेंटिफायर बहुत संकेत रखते हैं, कीवर्ड की ओर झुकें। रेपो का अपना रिट्रीवल बेंचमार्क (लाइन-रेंज ग्राउंड ट्रुथ के साथ 127 कोड-सर्च क्वेरी, jina-embeddings-v2-base-code के साथ पूरी तरह लोकल और बिना रीरैंकर चलाई गईं) प्रभाव स्पष्ट दिखाता है: डिफ़ॉल्ट 0.7/0.3 विभाजन से कीवर्ड-ट्यून किए 0.3/0.7 पर जाने से Hit@5 0.598 से 0.732 और Recall@10 0.671 से 0.807 तक बढ़ा, बिना किसी अतिरिक्त लागत के। यह एक कॉन्फ़िग लाइन से Hit@5 में +22% है। लंबे-फॉर्म दस्तावेज़ों के लिए दूसरी ओर झुकें (0.8/0.2), क्योंकि वहाँ मंशा हावी रहती है।
फ़्यूज़न के ऊपर, एक वैकल्पिक रीरैंकर शीर्ष उम्मीदवारों को फिर से क्रमबद्ध करता है:
[search.reranker]
enabled = true
model = "fastembed:jina-reranker-v2-base-multilingual" # लोकल रीरैंकर, बिना की
top_k_candidates = 50 # वेक्टर सर्च से इतने लाएँ
final_top_k = 10 # रीरैंकिंग के बाद इतने लौटाएँ
अगर आप इसे fastembed: मॉडल की ओर इंगित करें तो रीरैंकर भी लोकल चलता है। यह शीर्ष 50 उम्मीदवारों पर एक क्रॉस-एनकोडर पास है, जो उन मामलों को पकड़ता है जहाँ पहली-स्टेज रैंकिंग ने क्रम गलत किया। लागत असली है पर सीमित — यह केवल top_k_candidates देखता है, पूरा इंडेक्स नहीं।
CLI से, सर्च सतह सीधी है:
octocode search "webhook signature verification"
octocode search "auth" "middleware" "session" # मल्टी-क्वेरी, 10 तक
octocode search "database connection pool" --mode code # कोड ब्लॉक तक सीमित
octocode search "auth" --detail-level signatures # केवल सिग्नेचर, संक्षिप्त
octocode search "authentication refactor" --mode commits # git इतिहास खोजें
--mode commits पथ जानने योग्य है: कमिट इतिहास पहली कमिट-सर्च पर आलसी रूप से इंडेक्स होता है (octocode index के दौरान नहीं), इसलिए आप पूछ सकते हैं "हमने auth फ्लो कब बदला" और सिर्फ़ git log --grep के बजाय सिमैंटिक रूप से रैंक किए गए कमिट पा सकते हैं।
स्ट्रक्चरल सर्च: जब आपको अर्थ नहीं, AST पैटर्न चाहिए
कभी-कभी आपको सिमैंटिक्स बिलकुल नहीं चाहिए — आपको चाहिए "Rust में हर .unwrap()" या "JS में हर new Foo()"। यह एक स्ट्रक्चरल क्वेरी है, और टेक्स्ट सर्च इसे लगातार गलत करता है (.unwrap() का ज़िक्र करने वाला कमेंट कोई कॉल नहीं है)। Octocode ast-grep को रैप करता है:
octocode grep '$FUNC.unwrap()' --lang rust
octocode grep 'new $CLASS($$$ARGS)' --lang javascript
octocode grep 'console.log($ARG)' --lang javascript --rewrite 'logger.info($ARG)' --update-all
$VAR एक AST नोड से मैच करता है, $$$ARGS आर्गुमेंट की एक श्रृंखला से मैच करता है, और --rewrite जगह पर AST-सचेत रीफैक्टरिंग करता है। एजेंट्स के लिए सचमुच उपयोगी बात: LLM नोड के kind में भरोसेमंद तरीके से गलती करते हैं — वे Python के लिए function_declaration लिखेंगे, जो असल में function_definition है। जब कोई पैटर्न कुछ भी मैच नहीं करता, Octocode क्रमशः ढीली व्याख्याएँ आज़माता है और हर भाषा के लिए सही kind जानता है, इसलिए एजेंट का करीब-करीब-सही प्रयास भी एक मौन शून्य के बजाय परिणाम लौटाता है।
GraphRAG: रिश्ते, सिर्फ़ समानता नहीं
सिमैंटिक सर्च समान कोड ढूंढता है। यह आपको नहीं बता सकता कि auth_middleware.rs, jwt.rs को इम्पोर्ट करता है, user_store.rs को कॉल करता है, और router.rs में जुड़ा है। यह एक ग्राफ सवाल है, और Octocode इंडेक्सिंग के दौरान ग्राफ बनाता है।
[graphrag]
enabled = true
use_llm = true
यह नौ भाषाओं में AST से imports, calls, extends, और implements एज निकालता है, और use_llm = true के साथ उच्च-स्तरीय आर्किटेक्चरल रिश्ते (configures, uses, factory/observer/strategy पैटर्न) जोड़ता है जिन्हें एक LLM खोजता है। CLI से:
octocode graphrag get-relationships --node-id "src/auth/middleware.rs"
octocode graphrag find-path --source-id "src/auth/mod.rs" --target-id "src/database/mod.rs"
octocode graphrag overview
यही फ़र्क है "मुझे ऐसा कोड दिखाओ जो auth जैसा लगे" और "मुझे वह सब दिखाओ जो auth मॉड्यूल पर निर्भर है" के बीच। रीफैक्टर करने वाले एजेंट के लिए, दूसरा सवाल ही टूट-फूट रोकता है।
एक नया, वैकल्पिक मोड़ भी है: ग्राफ-सचेत रिट्रीवल विस्तार। [search] graph_expansion = true (और GraphRAG सक्षम) के साथ, सर्च रीरैंकिंग से पहले आपके शीर्ष हिट्स से संरचनात्मक रूप से संबंधित फाइलों के कोड ब्लॉक खींच लाता है — ताकि auth-middleware पर पहुँचने वाली क्वेरी उसके द्वारा कॉल किए जाने वाले JWT हेल्पर को सामने ला सके, भले ही वह हेल्पर क्वेरी टेक्स्ट से मैच न करता हो। यह डिफ़ॉल्ट रूप से बंद है और कोड के कमेंट इस बारे में स्पष्ट हैं: इस पर भरोसा करने से पहले अपने मूल्यांकन पर A/B करें, क्योंकि विस्तार संकेत जितनी आसानी से, उतनी ही आसानी से शोर भी जोड़ सकता है।
इसे MCP के ज़रिए एजेंट से जोड़ना
ऊपर का सब कुछ एक अंतर्निहित MCP सर्वर के ज़रिए AI सहायकों को उजागर होता है। Octocode इस्तेमाल करने का यही मुख्य तरीका है — एजेंट को टूल मिलते हैं, शेल नहीं।
octocode mcp --path /path/to/your/project
या किसी क्लाइंट कॉन्फ़िग में (Claude Desktop, Cursor, Windsurf, Claude Code):
{
"mcpServers": {
"octocode": {
"command": "octocode",
"args": ["mcp", "--path", "/path/to/your/project"]
}
}
}
वे टूल जो एजेंट देखता है, सर्वर के विरुद्ध सत्यापित:
| MCP टूल | यह क्या करता है |
|---|---|
semantic_search |
हाइब्रिड सिमैंटिक + कीवर्ड सर्च, मल्टी-क्वेरी, commits सहित सभी मोड |
view_signatures |
फाइल संरचना (सिग्नेचर, क्लास, इम्पोर्ट) glob द्वारा, पूरी फाइलें पढ़े बिना |
structural_search |
ast-grep के ज़रिए AST पैटर्न मैचिंग, kind-फॉलबैक रिकवरी के साथ |
graphrag |
रिश्ते की क्वेरी: search, get-node, get-relationships, find-path, overview |
view_signatures अनसुना नायक है। किसी फ़ंक्शन का सिग्नेचर ढूंढने के लिए एजेंट द्वारा तीन 800-लाइन फाइलें पढ़कर कॉन्टेक्स्ट जलाने के बजाय, यह glob द्वारा सिग्नेचर माँगता है और ढाँचा पा जाता है। (हालिया संस्करणों में आप केवल एरे नहीं, बल्कि एक अकेली glob स्ट्रिंग पास कर सकते हैं — एक छोटी बात जिसने बहुत से खराब टूल कॉल रोके।)
कई उप-परियोजनाओं वाले मोनोरेपो के लिए, एक मल्टी-रेपो मोड है: octocode mcp --multi --path /workspace तत्काल सब-डायरेक्टरीज़ को git रेपो के लिए स्कैन करता है और उन सबको एक ही एंडपॉइंट से परोसता है, और हर टूल को लक्ष्य चुनने के लिए एक project आर्गुमेंट मिलता है। एक MCP सर्वर, वर्कस्पेस के सारे रेपो।
चार चीज़ें जिन्होंने हमें परेशान किया
ठोस, काल्पनिक नहीं — यही वह है जिसने हमारा समय खाया।
1. इंडेक्स रेपो के बाहर रहता है, और इसने सबको उलझाया। पहली बार जब किसी ने ताज़ा क्लोन पर एजेंट चलाया, उसके पास कोई इंडेक्स नहीं था: डेटाबेस ~/.local/share/octocode/ के तहत प्रति-प्रोजेक्ट है, वर्किंग ट्री में नहीं। क्लोन ≠ इंडेक्स। समाधान ऑनबोर्डिंग में एक पंक्ति है: क्लोन के बाद एक बार octocode index चलाएँ। पीछे मुड़कर देखें तो स्पष्ट; रात के 2 बजे बिलकुल स्पष्ट नहीं।
2. एम्बेडिंग मॉडल बदलने ने चुपचाप परिणाम बिगाड़ दिए। किसी ने अलग लोकल मॉडल आज़माने के लिए code_model बदला और इंडेक्स साफ़ नहीं किया। नई क्वेरी नए मॉडल से एम्बेड हुईं, पुराने चंक पुराने से, वेक्टर तुलनीय नहीं, रैंकिंग कचरा। अलग मॉडलों के वेक्टर एक ही स्पेस में नहीं रहते। एम्बेडिंग मॉडल बदलने के बाद हमेशा octocode clear && octocode index। यहाँ कोई चेतावनी आपको नहीं बचाएगी — यह बस चुपचाप बदतर होता जाता है।
3. डिफ़ॉल्ट वेक्टर/कीवर्ड विभाजन हमारे रेपो के लिए गलत था। हम एक हफ़्ते 0.7/0.3 (वेक्टर-भारी) पर चले और सटीक-आइडेंटिफायर क्वेरीज़ चूकते रहे। कोड आइडेंटिफायर-सघन है; ऊपर का बेंचमार्क दिखाता है कि कीवर्ड-ट्यून किए वज़न कोड सर्च के लिए नाटकीय रूप से बेहतर हैं। 0.3/0.7 पर जाना हमारा किया गया सबसे प्रभावशाली कॉन्फ़िग बदलाव था।
4. बाइनरी और जनरेटेड फाइलें इंडेक्स नहीं होतीं — और यह सही है, पर जाँच लें। Octocode बाइनरी फाइलों को छोड़ देता है (सामग्री को टेक्स्ट मानने से पहले यह नल बाइट्स और प्रिंट करने योग्य अक्षरों का अनुपात जाँचता है) और .gitignore, .git/info/exclude, तथा .noindex फाइलों का पालन करता है। यही आप चाहते हैं — आपको मिनिफाइड वेंडर बंडल के एम्बेडिंग नहीं चाहिए। पर अगर कोई डायरेक्टरी जो आपके काम की है gitignore में है (कुछ टीमें जनरेटेड API क्लाइंट gitignore करती हैं), तो वह इंडेक्स नहीं होगी और आप सोचेंगे कि सर्च उसे क्यों नहीं ढूंढ पाता। अतिरिक्त पथ बाहर रखने के लिए .noindex रखें; अगर अपेक्षित कुछ गायब है तो अपना .gitignore जाँचें। octocode stats आपको ब्लॉक गिनती दिखाएगा ताकि आप कवरेज जाँच सकें।
एक न्यूनतम एंड-टू-एंड सेटअप
सब जोड़कर, एक निजी मोनोरेपो के लिए यह पूरी चीज़ है, सब लोकल:
# ~/.local/share/octocode/config.toml (या एक प्रोजेक्ट-लोकल ओवरराइड)
[embedding]
code_model = "fastembed:jinaai/jina-embeddings-v2-base-code"
text_model = "fastembed:nomic-ai/nomic-embed-text-v1.5"
[search.hybrid]
enabled = true
default_vector_weight = 0.3 # आइडेंटिफायर-सघन कोड → कीवर्ड को प्राथमिकता
default_keyword_weight = 0.7
[search.reranker]
enabled = true
model = "fastembed:jina-reranker-v2-base-multilingual"
[graphrag]
enabled = true
use_llm = false # केवल AST रिश्ते, कोई LLM कॉल नहीं, पूरी तरह ऑफलाइन
cd /path/to/monorepo
octocode index # पहला रन मॉडल डाउनलोड करता है, फिर इंडेक्स
octocode search "webhook signature verification" # समझदारी जाँच
octocode watch --quiet & # जीवंत रखें
claude mcp add octocode -- octocode mcp --path . # एजेंट से जोड़ें
एक-बार मॉडल डाउनलोड के बाद उस प्रवाह में कुछ भी नेटवर्क को नहीं छूता। कोई GPU नहीं। कोई प्रति-टोकन बिल नहीं। वह एजेंट जो "signature" के लिए grep कर रहा था और गलत फाइल की ओर इशारा कर रहा था, अब semantic_search कॉल करता है, verify_hmac को पहले स्थान पर रैंक पाता है, और कुछ छूने से पहले पुष्टि के लिए view_signatures का उपयोग करता है।
अक्सर पूछे जाने वाले सवाल
क्या मुझे GPU चाहिए? नहीं। लोकल एम्बेडिंग ONNX Runtime के ज़रिए CPU पर चलती हैं। एक आधुनिक मल्टी-कोर CPU काफी है; एम्बेडर शायद ही कभी बॉटलनेक होता है।
क्या कोई कोड मेरी मशीन से बाहर जाता है? fastembed:/huggingface: मॉडल और graphrag.use_llm = false के साथ, नहीं — इंडेक्सिंग, सर्च, और रीरैंकिंग सब लोकल हैं। क्लाउड एम्बेडिंग प्रोवाइडर और LLM-संचालित GraphRAG/कमिट-मैसेज फ़ीचर ऑप्ट-इन हैं और स्पष्ट रूप से की चाहिए।
इंडेक्स कहाँ रहता है, और क्या वह मेरे रेपो में है? सिस्टम डेटा डायरेक्टरी के तहत, प्रति-प्रोजेक्ट कुंजीबद्ध (~/.local/share/octocode/<project-id>/ Linux/macOS पर), आपके वर्किंग ट्री में नहीं। git clean उसे नहीं छुएगा; ताज़ा क्लोन के पास वह नहीं होगा।
डेटाबेस कितना बड़ा होता है? मोटे तौर पर प्रति फाइल ~10KB के क्रम में, RaBitQ क्वांटाइज़ेशन से ~32x वेक्टर संपीड़न के साथ। 10k-फाइल रेपो दसियों से कुछ सौ MB है, गीगाबाइट नहीं।
इंक्रीमेंटल या पूर्ण री-इंडेक्स? डिफ़ॉल्ट रूप से इंक्रीमेंटल — केवल बदली फाइलें फिर से एम्बेड होती हैं। पूर्ण रीबिल्ड के लिए octocode index --force, या एम्बेडिंग मॉडल बदलने के बाद octocode clear && octocode index।
क्या यह git इतिहास खोज सकता है? हाँ, octocode search "..." --mode commits। कमिट पहली कमिट-सर्च पर आलसी रूप से इंडेक्स होते हैं, इसलिए शुरुआती octocode index तेज़ बना रहता है।
— Don
Octocode Apache-2.0 के तहत ओपन सोर्स है। local-first स्टैक 0.15.0 में आया और लोकल एम्बेडिंग प्रोवाइडर सूची 0.17.x में। अगर आपका सेटअप किसी ऐसी दिक्कत से टकराता है जो इस पोस्ट ने कवर नहीं की, तो एक issue खोलें — इन्हीं में से ज़्यादातर सुझाव सबसे पहले इसी तरह लिखे गए थे।



