codebasesearch 0.1.14 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prd +24 -0
- package/README.md +13 -3
- package/mcp.js +1 -1
- package/package.json +1 -1
- package/src/ignore-parser.js +13 -5
- package/src/scanner.js +2 -33
- package/src/search-worker.js +12 -8
package/.prd
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"project": "code-search",
|
|
3
|
+
"objective": "Display relative file paths in search results from current working directory",
|
|
4
|
+
"created": "2026-03-05",
|
|
5
|
+
"items": [],
|
|
6
|
+
"completed": [
|
|
7
|
+
{
|
|
8
|
+
"id": "1",
|
|
9
|
+
"subject": "Add relative path computation to search-worker.js result mapping",
|
|
10
|
+
"status": "completed"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"id": "2",
|
|
14
|
+
"subject": "Update mcp.js output formatting to display relative paths",
|
|
15
|
+
"status": "completed"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"id": "3",
|
|
19
|
+
"subject": "Test relative path display with real searches from different directories",
|
|
20
|
+
"status": "completed"
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"notes": "All work complete. Search results now display relative paths computed from repositoryPath to absolute file paths. Paths are easy to locate from the directory where the search command runs."
|
|
24
|
+
}
|
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ claude mcp add -s user codebasesearch -- bunx codebasesearch
|
|
|
24
24
|
- **Semantic search** across entire repositories using Jina embeddings (512-dim vectors)
|
|
25
25
|
- **Embedded vector database** (LanceDB) - no external servers or setup required
|
|
26
26
|
- **Auto-indexing** - automatically scans and indexes repository before each search
|
|
27
|
-
- **Comprehensive
|
|
27
|
+
- **Comprehensive file filtering** - respects .gitignore, ignores build artifacts, node_modules, dependencies across all languages; includes 102 code/markup/styling file types
|
|
28
28
|
- **Single-shot execution** - no persistent processes, no background daemons
|
|
29
29
|
- **MCP protocol support** - integrates with Claude Code and other MCP-compatible tools
|
|
30
30
|
- **Auto-gitignore** - automatically adds `.code-search/` to .gitignore on first run
|
|
@@ -71,9 +71,19 @@ search query="middleware validation" repository_path="/path/to/repo"
|
|
|
71
71
|
7. **Returns** ranked results with line numbers and code snippets
|
|
72
72
|
8. **Auto-adds** `.code-search/` to .gitignore
|
|
73
73
|
|
|
74
|
-
## Supported Languages
|
|
74
|
+
## Supported Languages (102 Extensions)
|
|
75
75
|
|
|
76
|
-
JavaScript, TypeScript, Python, Go, Rust, Java, C/C++, C#, Ruby, PHP,
|
|
76
|
+
**Programming**: JavaScript, TypeScript, Python, Go, Rust, Java, Kotlin, Scala, C/C++, C#, Ruby, PHP, Swift, Shell, PowerShell, Perl, Lua, R, Dart, Elixir, Erlang, Haskell, Clojure, Lisp, Fortran, Assembly, Groovy, Visual Basic, F#, OCaml, Objective-C, Arduino, CoffeeScript, Reason, Julia, MATLAB
|
|
77
|
+
|
|
78
|
+
**Markup & Data**: XML, XSD, HTML, YAML, TOML
|
|
79
|
+
|
|
80
|
+
**Styling**: CSS, SCSS, Sass, Less
|
|
81
|
+
|
|
82
|
+
**Database**: SQL
|
|
83
|
+
|
|
84
|
+
**Frontend**: Vue, Svelte
|
|
85
|
+
|
|
86
|
+
**Text & Docs**: Markdown, Plain Text
|
|
77
87
|
|
|
78
88
|
## Storage
|
|
79
89
|
|
package/mcp.js
CHANGED
|
@@ -140,7 +140,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
140
140
|
: `Found ${result.resultsCount} result${result.resultsCount !== 1 ? 's' : ''} for query: "${query}"\nRepository: ${result.repository}\n\n${result.results
|
|
141
141
|
.map(
|
|
142
142
|
(r) =>
|
|
143
|
-
`${r.rank}. ${r.
|
|
143
|
+
`${r.rank}. ${r.relativePath}:${r.lines} (score: ${r.score}%)\n${r.snippet
|
|
144
144
|
.split('\n')
|
|
145
145
|
.map((line) => ` ${line}`)
|
|
146
146
|
.join('\n')}`
|
package/package.json
CHANGED
package/src/ignore-parser.js
CHANGED
|
@@ -4,7 +4,7 @@ import { fileURLToPath } from 'url';
|
|
|
4
4
|
|
|
5
5
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
6
|
|
|
7
|
-
//
|
|
7
|
+
// Unified whitelist of code file extensions to include (102 supported)
|
|
8
8
|
const CODE_EXTENSIONS = new Set([
|
|
9
9
|
// JavaScript/TypeScript
|
|
10
10
|
'.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs', '.mts', '.cts',
|
|
@@ -15,13 +15,13 @@ const CODE_EXTENSIONS = new Set([
|
|
|
15
15
|
// C/C++
|
|
16
16
|
'.c', '.cpp', '.cc', '.cxx', '.h', '.hpp', '.hh', '.hxx',
|
|
17
17
|
// C#
|
|
18
|
-
'.cs',
|
|
18
|
+
'.cs', '.csx',
|
|
19
19
|
// Go
|
|
20
20
|
'.go',
|
|
21
21
|
// Rust
|
|
22
22
|
'.rs',
|
|
23
23
|
// Ruby
|
|
24
|
-
'.rb',
|
|
24
|
+
'.rb', '.erb',
|
|
25
25
|
// PHP
|
|
26
26
|
'.php', '.phtml',
|
|
27
27
|
// Swift
|
|
@@ -54,7 +54,7 @@ const CODE_EXTENSIONS = new Set([
|
|
|
54
54
|
'.hs', '.lhs',
|
|
55
55
|
// Clojure
|
|
56
56
|
'.clj', '.cljs', '.cljc',
|
|
57
|
-
// Lisp
|
|
57
|
+
// Lisp/Scheme
|
|
58
58
|
'.lisp', '.lsp', '.scm', '.ss', '.rkt',
|
|
59
59
|
// Fortran
|
|
60
60
|
'.f', '.for', '.f90', '.f95', '.f03',
|
|
@@ -79,7 +79,15 @@ const CODE_EXTENSIONS = new Set([
|
|
|
79
79
|
// CoffeeScript
|
|
80
80
|
'.coffee',
|
|
81
81
|
// Reason
|
|
82
|
-
'.re', '.rei'
|
|
82
|
+
'.re', '.rei',
|
|
83
|
+
// Markup/Data
|
|
84
|
+
'.xml', '.xsd', '.html', '.htm', '.yml', '.yaml', '.toml',
|
|
85
|
+
// Styling
|
|
86
|
+
'.css', '.scss', '.sass', '.less',
|
|
87
|
+
// SQL
|
|
88
|
+
'.sql',
|
|
89
|
+
// Markdown/Text
|
|
90
|
+
'.md', '.markdown', '.txt'
|
|
83
91
|
]);
|
|
84
92
|
|
|
85
93
|
function loadDefaultIgnores() {
|
package/src/scanner.js
CHANGED
|
@@ -1,36 +1,6 @@
|
|
|
1
1
|
import { readdirSync, statSync, readFileSync } from 'fs';
|
|
2
2
|
import { join, relative } from 'path';
|
|
3
|
-
import { shouldIgnore } from './ignore-parser.js';
|
|
4
|
-
|
|
5
|
-
const SUPPORTED_EXTENSIONS = new Set([
|
|
6
|
-
'.js', '.ts', '.tsx', '.jsx', '.mjs', '.cjs',
|
|
7
|
-
'.py', '.pyw', '.pyi',
|
|
8
|
-
'.go',
|
|
9
|
-
'.rs',
|
|
10
|
-
'.java', '.kt', '.scala',
|
|
11
|
-
'.cpp', '.cc', '.cxx', '.h', '.hpp', '.hxx',
|
|
12
|
-
'.c', '.h',
|
|
13
|
-
'.rb', '.erb',
|
|
14
|
-
'.php',
|
|
15
|
-
'.cs', '.csx',
|
|
16
|
-
'.swift',
|
|
17
|
-
'.m', '.mm',
|
|
18
|
-
'.sh', '.bash', '.zsh',
|
|
19
|
-
'.sql',
|
|
20
|
-
'.r', '.R',
|
|
21
|
-
'.lua',
|
|
22
|
-
'.pl', '.pm',
|
|
23
|
-
'.groovy',
|
|
24
|
-
'.gradle',
|
|
25
|
-
'.xml', '.xsd',
|
|
26
|
-
'.yaml', '.yml',
|
|
27
|
-
'.toml',
|
|
28
|
-
'.html', '.htm',
|
|
29
|
-
'.css', '.scss', '.sass', '.less',
|
|
30
|
-
'.vue', '.svelte',
|
|
31
|
-
'.md', '.markdown',
|
|
32
|
-
'.txt'
|
|
33
|
-
]);
|
|
3
|
+
import { shouldIgnore, isCodeFile } from './ignore-parser.js';
|
|
34
4
|
|
|
35
5
|
function getFileExtension(filePath) {
|
|
36
6
|
const lastDot = filePath.lastIndexOf('.');
|
|
@@ -71,8 +41,7 @@ function walkDirectory(dirPath, ignorePatterns, relativePath = '') {
|
|
|
71
41
|
if (entry.isDirectory()) {
|
|
72
42
|
files.push(...walkDirectory(fullPath, ignorePatterns, relPath));
|
|
73
43
|
} else if (entry.isFile()) {
|
|
74
|
-
|
|
75
|
-
if (SUPPORTED_EXTENSIONS.has(ext) && !isBinaryFile(entry.name)) {
|
|
44
|
+
if (isCodeFile(normalizedRelPath) && !isBinaryFile(entry.name)) {
|
|
76
45
|
try {
|
|
77
46
|
const stat = entry.isSymbolicLink ? null : statSync(fullPath);
|
|
78
47
|
const maxSize = 5 * 1024 * 1024;
|
package/src/search-worker.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parentPort } from 'worker_threads';
|
|
2
|
-
import { resolve } from 'path';
|
|
2
|
+
import { resolve, relative } from 'path';
|
|
3
3
|
import { existsSync } from 'fs';
|
|
4
4
|
import { loadIgnorePatterns } from './ignore-parser.js';
|
|
5
5
|
import { scanRepository } from './scanner.js';
|
|
@@ -53,13 +53,17 @@ async function performSearch(repositoryPath, query) {
|
|
|
53
53
|
query,
|
|
54
54
|
repository: absolutePath,
|
|
55
55
|
resultsCount: results.length,
|
|
56
|
-
results: results.slice(0, 10).map((result, idx) =>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
results: results.slice(0, 10).map((result, idx) => {
|
|
57
|
+
const absoluteFilePath = resolve(absolutePath, result.file_path);
|
|
58
|
+
return {
|
|
59
|
+
rank: idx + 1,
|
|
60
|
+
file: result.file_path,
|
|
61
|
+
relativePath: relative(repositoryPath, absoluteFilePath),
|
|
62
|
+
lines: `${result.line_start}-${result.line_end}`,
|
|
63
|
+
score: (result.score * 100).toFixed(1),
|
|
64
|
+
snippet: result.content.split('\n').slice(0, 3).join('\n'),
|
|
65
|
+
};
|
|
66
|
+
}),
|
|
63
67
|
};
|
|
64
68
|
} catch (error) {
|
|
65
69
|
return { error: error.message, results: [] };
|