Merge pull request #10 from midweste/midweste-dotfiles

feat: add env support for controlling indexing of dotfiles
This commit is contained in:
Giancarlo Erra
2026-03-18 12:32:13 +00:00
committed by GitHub
3 changed files with 73 additions and 4 deletions
+2 -1
View File
@@ -163,7 +163,7 @@ I built SocratiCode because I regularly work on existing, large, and complex cod
- **Live file watching** — Optionally watch for file changes and keep the index updated in real time (debounced 2s). Watcher also invalidates the code graph cache.
- **Parallel processing** — Files are scanned and chunked in parallel batches (50 at a time) for fast I/O, while embedding generation and upserts are batched separately for optimal throughput.
- **Multi-project** — Index multiple projects simultaneously. Each gets its own isolated collection with full project path tracking.
- **Respects ignore rules** — Honors all `.gitignore` files (root + nested), plus an optional `.socraticodeignore` for additional exclusions. Includes sensible built-in defaults. `.gitignore` processing can be disabled via `RESPECT_GITIGNORE=false`.
- **Respects ignore rules** — Honors all `.gitignore` files (root + nested), plus an optional `.socraticodeignore` for additional exclusions. Includes sensible built-in defaults. `.gitignore` processing can be disabled via `RESPECT_GITIGNORE=false`. Dot-directories (e.g. `.agent`) can be included via `INCLUDE_DOT_FILES=true`.
- **Custom file extensions** — Projects with non-standard extensions (e.g. `.tpl`, `.blade`) can be included via `EXTRA_EXTENSIONS` env var or `extraExtensions` tool parameter. Works for both indexing and code graph.
- **Configurable infrastructure** — All ports, hosts, and API keys are configurable via environment variables. Qdrant API key support for enterprise deployments.
- **Auto-setup** — On first use, automatically checks Docker, pulls images, starts containers, and pulls the embedding model. Only prerequisite: Docker.
@@ -725,6 +725,7 @@ Artifacts are chunked and embedded into Qdrant using the same hybrid dense + BM2
| Variable | Default | Description |
|----------|---------|-------------|
| `RESPECT_GITIGNORE` | `true` | Set to `false` to skip `.gitignore` processing. Built-in defaults and `.socraticodeignore` still apply. |
| `INCLUDE_DOT_FILES` | `false` | Set to `true` to include dot-directories (e.g. `.agent`, `.config`) in indexing. By default, directories and files starting with `.` are excluded. Useful for projects where important code lives in dot-directories. |
| `EXTRA_EXTENSIONS` | *(none)* | Comma-separated list of additional file extensions to scan (e.g. `.tpl,.blade,.hbs`). Applies to both indexing and code graph. Files with extra extensions are indexed as plaintext and appear as leaf nodes in the code graph. Can also be passed per-operation via the `extraExtensions` tool parameter. |
| `MAX_FILE_SIZE_MB` | `5` | Maximum file size in MB. Files larger than this are skipped during indexing. Increase for repos with large generated or data files you want indexed. |
| `SEARCH_DEFAULT_LIMIT` | `10` | Default number of results returned by `codebase_search` (1-50). Each result is a ranked code chunk with file path, line range, and content. Higher values give broader coverage but produce more output. Can still be overridden per-query via the `limit` tool parameter. |
+1 -1
View File
@@ -615,7 +615,7 @@ export async function getIndexableFiles(
const allFiles = await glob("**/*", {
cwd: projectPath,
nodir: true,
dot: false,
dot: (process.env.INCLUDE_DOT_FILES ?? "false").toLowerCase() === "true",
absolute: false,
});
+70 -2
View File
@@ -1,9 +1,12 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Giancarlo Erra - Altaire Limited
import { beforeAll, describe, expect, it } from "vitest";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
import { CHUNK_SIZE, MAX_CHUNK_CHARS } from "../../src/constants.js";
import { ensureDynamicLanguages } from "../../src/services/code-graph.js";
import { chunkFileContent, chunkId, hashContent, isIndexableFile } from "../../src/services/indexer.js";
import { chunkFileContent, chunkId, getIndexableFiles, hashContent, isIndexableFile } from "../../src/services/indexer.js";
// Register dynamic language grammars once for AST-aware chunking tests
beforeAll(() => {
@@ -286,4 +289,69 @@ describe("indexer utilities", () => {
}
});
});
// ── getIndexableFiles (INCLUDE_DOT_FILES) ─────────────────────────────
describe("getIndexableFiles", () => {
let tmpDir: string;
beforeAll(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "socraticode-dotfiles-test-"));
// Regular file
fs.mkdirSync(path.join(tmpDir, "src"), { recursive: true });
fs.writeFileSync(path.join(tmpDir, "src", "index.ts"), "export const x = 1;\n");
// Dot-directory with an indexable file
fs.mkdirSync(path.join(tmpDir, ".agent", "rules"), { recursive: true });
fs.writeFileSync(path.join(tmpDir, ".agent", "rules", "config.ts"), "export const rule = true;\n");
// Dot-file at root (e.g. .gitignore)
fs.writeFileSync(path.join(tmpDir, ".gitignore"), "node_modules/\n");
});
afterAll(() => {
fs.rmSync(tmpDir, { recursive: true, force: true });
});
it("excludes dot-directory files by default", async () => {
const files = await getIndexableFiles(tmpDir);
const hasDotDir = files.some((f) => f.includes(".agent"));
expect(hasDotDir).toBe(false);
});
it("includes dot-directory files when INCLUDE_DOT_FILES=true", async () => {
vi.stubEnv("INCLUDE_DOT_FILES", "true");
try {
const files = await getIndexableFiles(tmpDir);
const dotFiles = files.filter((f) => f.includes(".agent"));
expect(dotFiles.length).toBeGreaterThan(0);
expect(dotFiles.some((f) => f.includes("config.ts"))).toBe(true);
} finally {
vi.unstubAllEnvs();
}
});
it("treats INCLUDE_DOT_FILES case-insensitively", async () => {
vi.stubEnv("INCLUDE_DOT_FILES", "True");
try {
const files = await getIndexableFiles(tmpDir);
const hasDotDir = files.some((f) => f.includes(".agent"));
expect(hasDotDir).toBe(true);
} finally {
vi.unstubAllEnvs();
}
});
it("excludes dot-directory files for non-true values", async () => {
vi.stubEnv("INCLUDE_DOT_FILES", "yes");
try {
const files = await getIndexableFiles(tmpDir);
const hasDotDir = files.some((f) => f.includes(".agent"));
expect(hasDotDir).toBe(false);
} finally {
vi.unstubAllEnvs();
}
});
});
});