code_nav.coverage
Show git-visible file coverage to identify tracked files in the repository.
Instructions
Show git-visible file coverage; no semantic index exists.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/tools/coverage.ts:5-23 (handler)The main handler function for the code_nav.coverage tool. Gets repo root, loads config, lists candidate files (via git ls-files or glob), counts files by extension, and returns coverage metadata including repo root, file counts, extensions, skipped info, and warnings.
export async function coverage(cwd = process.cwd()) { const repo = await getRepoRoot(cwd); const loaded = await loadConfig(repo.repoRoot); const listed = await listCandidateFiles(repo.repoRoot, repo.isGitRepo, loaded.config); const extensions: Record<string, number> = {}; for (const file of listed.files) { const ext = file.extension || "[none]"; extensions[ext] = (extensions[ext] ?? 0) + 1; } return { repo_root: repo.repoRoot, mode: "no-semantic", tracked_and_untracked_files: listed.files.length, extensions: Object.fromEntries(Object.entries(extensions).sort()), skipped: listed.skipped, code_navrc: loaded.path, warnings: [...repo.warnings, ...loaded.warnings, ...listed.warnings], }; } - src/mcp.ts:106-114 (schema)MCP tool registration for code_nav.coverage with no input schema (empty object), marking it as read-only.
server.registerTool( "code_nav.coverage", { description: "Show git-visible file coverage; no semantic index exists.", inputSchema: {}, annotations: { readOnlyHint: true, openWorldHint: false }, }, async () => mcpJson(await coverage()), ); - src/core/files.ts:13-76 (helper)Helper function that lists candidate files by running git ls-files (for git repos) or fast-glob fallback. Handles extra_include/extra_exclude, marks binary/skipped files.
export async function listCandidateFiles( repoRoot: string, isGitRepo: boolean, config: CodeNavConfig, ): Promise<FileListResult> { const warnings: string[] = []; let paths: string[] = []; if (isGitRepo) { const result = await runCommand( "git", ["ls-files", "-co", "--exclude-standard", "-z"], { cwd: repoRoot, maxBuffer: 50 * 1024 * 1024 }, ); if (result.ok) { paths = result.stdout.split("\0").filter(Boolean); } else { warnings.push(`git ls-files failed: ${result.stderr}`); } } if (paths.length === 0) { paths = await fg(["**/*"], { cwd: repoRoot, onlyFiles: true, dot: true, ignore: [".git/**", "node_modules/**", "dist/**", "coverage/**"], }); if (!isGitRepo) warnings.push("used fast-glob fallback because repo is not git"); } const includeSet = new Set(paths.map(normalizeRel)); for (const include of config.extra_include) { const matches = await fg(include, { cwd: repoRoot, onlyFiles: true, dot: true }); for (const match of matches) includeSet.add(normalizeRel(match)); } const files: CandidateFile[] = []; const skipped = { binary: 0, too_large: 0 }; for (const relPath of [...includeSet].sort()) { if (matchesAny(relPath, config.extra_exclude)) continue; if (config.markdown === "off" && isMarkdown(relPath)) continue; const absPath = path.join(repoRoot, relPath); let stat; try { stat = await fs.stat(absPath); } catch { continue; } if (!stat.isFile()) continue; const binary = await isBinaryFile(absPath); const tooLarge = stat.size > config.max_file_bytes; if (binary) skipped.binary += 1; if (tooLarge) skipped.too_large += 1; if (binary || tooLarge) continue; files.push({ path: normalizeRel(relPath), absPath, size: stat.size, extension: path.extname(relPath), binary, tooLarge, }); } return { files, skipped, warnings }; } - src/cli.ts:28-30 (registration)CLI registration of the coverage command, allowing direct invocation via 'code-nav-mcp coverage'.
if (command === "coverage") { console.log(jsonText(await coverage())); return; - src/core/repo.ts:5-24 (helper)Helper that resolves the git repo root, used by the coverage handler.
export async function getRepoRoot(cwd = process.cwd()): Promise<RepoInfo> { const resolvedCwd = path.resolve(cwd); const result = await runCommand("git", ["rev-parse", "--show-toplevel"], { cwd: resolvedCwd, }); if (result.ok && result.stdout.trim()) { return { cwd: resolvedCwd, repoRoot: path.resolve(result.stdout.trim()), isGitRepo: true, warnings: [], }; } return { cwd: resolvedCwd, repoRoot: resolvedCwd, isGitRepo: false, warnings: ["not a git repo; using cwd as repo_root"], }; }