codebasesearch 0.1.14 → 0.1.16
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 +31 -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,31 @@
|
|
|
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
|
+
{
|
|
7
|
+
"id": "3",
|
|
8
|
+
"subject": "Test relative path display with real searches from different directories",
|
|
9
|
+
"status": "pending",
|
|
10
|
+
"description": "Execute real searches from root, nested directory, and different locations. Verify relative paths are displayed correctly in each case. Test with files at various depths.",
|
|
11
|
+
"category": "feature",
|
|
12
|
+
"effort": "medium",
|
|
13
|
+
"blocking": [],
|
|
14
|
+
"blockedBy": ["2"],
|
|
15
|
+
"acceptance": [
|
|
16
|
+
"Search from /config/code-search shows relative paths",
|
|
17
|
+
"Search from /config shows paths like code-search/src/file.js",
|
|
18
|
+
"Search from nested dir shows correct relative paths",
|
|
19
|
+
"All file paths are correct and usable"
|
|
20
|
+
],
|
|
21
|
+
"scenarios": [
|
|
22
|
+
"Search from repository root",
|
|
23
|
+
"Search from parent directory",
|
|
24
|
+
"Search from nested directory within repo",
|
|
25
|
+
"Files at root level vs deep nesting"
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"completed": [],
|
|
30
|
+
"notes": "Results constructed in search-worker.js, formatted in mcp.js. Path.relative() available via path module already imported in search-worker.js."
|
|
31
|
+
}
|
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: [] };
|