{"id":45964356,"url":"https://github.com/phash/pindex","last_synced_at":"2026-02-28T14:02:31.607Z","repository":{"id":340994898,"uuid":"1168293033","full_name":"phash/PindeX","owner":"phash","description":null,"archived":false,"fork":false,"pushed_at":"2026-02-27T11:37:56.000Z","size":256,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-27T17:52:25.030Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phash.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-27T08:13:08.000Z","updated_at":"2026-02-27T11:36:51.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/phash/PindeX","commit_stats":null,"previous_names":["phash/pindex"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/phash/PindeX","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phash%2FPindeX","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phash%2FPindeX/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phash%2FPindeX/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phash%2FPindeX/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phash","download_url":"https://codeload.github.com/phash/PindeX/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phash%2FPindeX/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29936367,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-28T13:49:17.081Z","status":"ssl_error","status_checked_at":"2026-02-28T13:48:50.396Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-28T14:01:54.458Z","updated_at":"2026-02-28T14:02:31.506Z","avatar_url":"https://github.com/phash.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PindeX – MCP Codebase Indexer\n\n**Structural codebase indexing for AI coding assistants — 70–80% fewer tokens for code exploration queries.**\n\nPindeX is an [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that parses your project with `tree-sitter` and regex-based extractors, stores symbols, imports, and dependency graphs in a local SQLite database, and exposes 13 targeted tools so AI assistants can answer questions about your code — and your documentation — without reading entire files.\n\n**Supported languages:** TypeScript, JavaScript, Java, Kotlin, Python, PHP, Vue, Svelte, Ruby, C#, Go, Rust\n\n---\n\n## Contents\n\n- [How It Works](#how-it-works)\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Multi-Project \u0026 Federation](#multi-project--federation)\n- [MCP Tools](#mcp-tools)\n  - [Code tools](#code-tools)\n  - [Document \u0026 context tools](#document--context-tools)\n- [Environment Variables](#environment-variables)\n- [Integrations](#integrations)\n  - [Claude Code](#claude-code)\n  - [Goose](#goose)\n- [CLI Reference](#cli-reference)\n- [Monitoring Dashboard](#monitoring-dashboard)\n- [Development](#development)\n- [Project Structure](#project-structure)\n\n---\n\n## How It Works\n\n```\nYour project files\n       │\n       ├── .ts/.js  ──►  tree-sitter AST  ──►  symbols, imports, dependencies\n       │                                              │\n       └── .md/.yaml/.txt  ──►  chunker  ──────────► documents (heading/line chunks)\n                                                      │\n  Claude calls save_context(…)  ──────────────────► context_entries\n                                                      │\n                                                      ▼\n  SQLite (FTS5)  ← stored in ~/.pindex/projects/{hash}/index.db\n  ├── files            (path, hash, language, token estimate)\n  ├── symbols          (name, kind, signature, lines)       ─► search_symbols\n  ├── dependencies     (import graph)                       ─► get_dependencies\n  ├── usages           (symbol → call sites)                ─► find_usages\n  ├── documents        (text chunks from .md/.yaml/.txt)    ─► search_docs\n  ├── context_entries  (notes saved by Claude mid-session)  ─► search_docs\n  └── token_log        (per-session metrics)\n       │\n       ▼\n  14 MCP tools  ──── stdio ────► Claude Code / Goose / any MCP client\n```\n\nInstead of sending full file contents to the AI, PindeX lets it call `search_symbols`, `search_docs`, `get_context`, or `get_file_summary` — returning only what it actually needs.\nClaude can also persist important facts across sessions with `save_context`, then retrieve them later with `search_docs` instead of re-reading large files.\nToken savings are tracked per session and visible in a live web dashboard.\n\n\u003e **A note on the savings numbers:** PindeX can only measure tokens that flow through its own tools (`search_symbols`, `get_context`, `get_file_summary`, etc.). It has no visibility into tokens used by `Write`, `Read`, `Bash`, `Edit`, or other non-PindeX operations — those are handled directly by the AI client and never pass through PindeX.\n\u003e\n\u003e The \"70–80% savings\" refers specifically to those code-exploration queries: instead of reading an entire file, PindeX returns a targeted snippet — and that targeted snippet is typically 70–80% smaller than the raw file content. **The actual reduction in your total session token budget depends on how much of the session is spent navigating and understanding code** versus writing or running commands. In sessions focused on exploring an unfamiliar codebase, savings are most pronounced. In sessions that are mostly editing, PindeX reduces only the exploration portion of the bill.\n\n---\n\n## Requirements\n\n| Dependency | Version |\n|---|---|\n| Node.js | ≥ 18.0.0 |\n| npm | ≥ 8 |\n| Operating System | macOS, Linux, Windows (WSL recommended) |\n\n\u003e **Note:** `better-sqlite3` ships prebuilt binaries for most platforms. If your environment is unusual, `npm install` will compile from source — you'll need `python3` and a C++ compiler (`build-essential` / Xcode CLT).\n\n---\n\n## Installation\n\n### Install from npm (recommended)\n\n```bash\nnpm install -g pindex\n```\n\n### Install from source\n\n```bash\ngit clone https://github.com/phash/PindeX.git\ncd PindeX\nnpm install\nnpm run build\nnpm install -g .\n```\n\nThis makes three commands available globally:\n\n| Command | Purpose |\n|---|---|\n| `pindex` | CLI — init, federation, status |\n| `pindex-server` | MCP stdio server (Claude Code spawns this automatically) |\n| `pindex-gui` | Aggregated dashboard for all projects |\n\n---\n\n## Quick Start\n\n### 1. Set up a project\n\nRun `pindex` (with no arguments) in any project directory:\n\n```bash\ncd /my/project\npindex\n```\n\nPindeX will:\n1. Walk upward from your current directory to find the project root (`package.json`, `.git`, etc.)\n2. Assign a dedicated monitoring port for this project\n3. Write `.mcp.json` into the project root with absolute paths\n4. Register the project in `~/.pindex/registry.json`\n5. Inject a PindeX workflow section into `CLAUDE.md` (created if missing)\n6. Add a `PreToolUse` hook to `.claude/settings.json` to remind Claude to prefer PindeX tools\n\nOutput:\n```\n  ╔══════════════════════════════════════════╗\n  ║           PindeX – Ready                 ║\n  ╚══════════════════════════════════════════╝\n\n  Project   : /my/project\n  Index     : ~/.pindex/projects/a3f8b2c1/index.db\n  Port      : 7856\n  Config    : .mcp.json (written)\n  CLAUDE.md : section added\n  Hooks     : created\n\n  ── Next steps ─────────────────────────────\n  1. Restart Claude Code in this directory\n  2. Open the dashboard:  pindex-gui\n```\n\n### 2. Restart Claude Code\n\nClaude Code auto-discovers `.mcp.json`. On the next startup it will spawn `pindex-server` with the correct `PROJECT_ROOT` — the index is built automatically in the background.\n\n### 3. Use the tools\n\nOnce connected, your AI assistant can call tools like:\n\n```\nsearch_symbols(\"AuthService\")\nget_file_summary(\"src/auth/service.ts\")\nget_context(\"src/auth/service.ts\", 42, 20)\nfind_usages(\"validateToken\")\nget_dependencies(\"src/api/routes.ts\", \"both\")\n\n# Documentation and context memory:\nsearch_docs(\"authentication JWT\")          # search CLAUDE.md, README.md, …\nget_doc_chunk(\"CLAUDE.md\", 2)             # read one section only\nsave_context(\"Decision: use JWT …\", \"auth\")  # store for future sessions\n```\n\n### 4. Open the dashboard\n\n```bash\npindex-gui\n```\n\nOpens `http://localhost:7842` — an aggregated dashboard showing token savings, symbol counts, and session stats for **all** registered projects. The savings figures reflect tokens saved on PindeX tool calls; see the note in [How It Works](#how-it-works) for context.\n\n---\n\n## Multi-Project \u0026 Federation\n\n### Multiple independent projects\n\nEach project gets its own `.mcp.json` (pointing to its own `PROJECT_ROOT`) and its own SQLite database at `~/.pindex/projects/{hash}/index.db`. When Claude Code opens Project A, it spawns `pindex-server` with `PROJECT_ROOT=/path/to/project-a` — it never touches Project B's index.\n\n```bash\ncd /project-a \u0026\u0026 pindex   # registers project-a\ncd /project-b \u0026\u0026 pindex   # registers project-b, different port + different DB\n```\n\n### Linking repos (federation)\n\nIf you work on a monorepo split into separate repositories, or if one project imports types from another, you can link them:\n\n```bash\ncd /project-a\npindex add /project-b\n```\n\nThis updates `/project-a/.mcp.json` with `FEDERATION_REPOS=/project-b`. After restarting Claude Code in Project A, the MCP tools search **both** codebases:\n\n- `search_symbols` returns results from both projects (federated results include a `project` field)\n- `get_project_overview` shows stats for all linked projects\n\nAdd more repos at any time:\n\n```bash\npindex add /project-c   # links a third repo\n```\n\nRemove a link:\n\n```bash\npindex remove /project-b\n```\n\n### View all projects\n\n```bash\npindex status\n```\n\n```\n  3 registered project(s):\n\n  [idle]  project-a  + 1 federated repo\n           /home/user/project-a\n           port: 7856  index: ~/.pindex/projects/a3f8b2c1/\n\n  [idle]  project-b\n           /home/user/project-b\n           port: 7901  index: ~/.pindex/projects/f1e2d3c4/\n  ...\n```\n\n---\n\n## MCP Tools\n\nAll 14 tools are available over stdio transport.\n\n### Code tools\n\n### `search_symbols`\n\nFull-text search across all indexed symbols (names, signatures, summaries) using SQLite FTS5.\nWhen federation is active, results from linked repos include a `project` field.\n\n| Parameter | Type | Required | Description |\n|---|---|---|---|\n| `query` | string | ✓ | Search term (supports FTS5 syntax) |\n| `limit` | number | | Max results per project (default: 20) |\n\n**Returns:** List of matching symbols with name, kind, signature, file path, and line number.\n\n---\n\n### `get_symbol`\n\nDetailed information about a specific symbol including its signature, location, and the files it depends on.\n\n| Parameter | Type | Required | Description |\n|---|---|---|---|\n| `name` | string | ✓ | Symbol name |\n| `file` | string | | Narrow results to a specific file path |\n\n**Returns:** Symbol record + file-level dependency list.\n\n---\n\n### `get_context`\n\nRead a slice of a source file centred around a given line. Files are read from disk at call time — only metadata lives in the DB.\n\n| Parameter | Type | Required | Description |\n|---|---|---|---|\n| `file` | string | ✓ | File path (relative to `PROJECT_ROOT`) |\n| `line` | number | ✓ | Centre line |\n| `range` | number | | Lines above and below (default: 30) |\n\n**Returns:** Code snippet with detected language and line numbers.\n\n---\n\n### `get_file_summary`\n\nHigh-level overview of a file without loading its full content.\n\n| Parameter | Type | Required | Description |\n|---|---|---|---|\n| `file` | string | ✓ | File path |\n\n**Returns:** Language, summary text, all symbols (with kind + signature), imports, and exports.\n\n---\n\n### `find_usages`\n\nAll locations in the codebase where a symbol is referenced.\n\n| Parameter | Type | Required | Description |\n|---|---|---|---|\n| `symbol` | string | ✓ | Symbol name to look up |\n\n**Returns:** List of `{ file, line, context }` entries.\n\n---\n\n### `get_dependencies`\n\nImport graph for a file — what it imports, what imports it, or both.\n\n| Parameter | Type | Required | Description |\n|---|---|---|---|\n| `target` | string | ✓ | File path |\n| `direction` | `\"imports\"` \\| `\"imported_by\"` \\| `\"both\"` | | Default: `\"both\"` |\n\n**Returns:** Dependency list with resolved file paths and imported symbol names.\n\n---\n\n### `get_project_overview`\n\nProject-wide statistics — no parameters required.\nWhen federation is active, also includes stats for each linked repository.\n\n**Returns:** Total file count, dominant language, entry points (`index`, `main`, `app` files), module list with symbol counts, and (if federated) per-repo breakdowns.\n\n---\n\n### `reindex`\n\nRebuild the index for a single file or the entire project.\n\n| Parameter | Type | Required | Description |\n|---|---|---|---|\n| `target` | string | | File path or omit for full project reindex |\n\n**Returns:** Count of indexed / updated / error files.\n\n---\n\n### `get_token_stats`\n\nToken usage and savings statistics for a session.\n\n| Parameter | Type | Required | Description |\n|---|---|---|---|\n| `session_id` | string | | Defaults to `\"default\"` |\n\n**Returns:** Total tokens used, estimated tokens without the index, net savings, and savings percentage.\n\n---\n\n### `start_comparison`\n\nCreate a labelled A/B testing session to compare indexed vs. baseline token usage.\n\n| Parameter | Type | Required | Description |\n|---|---|---|---|\n| `label` | string | ✓ | Human-readable session name |\n| `mode` | `\"indexed\"` \\| `\"baseline\"` | ✓ | Tracking mode |\n\n**Returns:** `session_id` and the monitoring dashboard URL.\n\n---\n\n### `get_session_memory`\n\nQuery passive session observations — facts and patterns the system recorded automatically by observing tool calls and file changes. No `save_context` calls required.\n\n| Parameter | Type | Required | Description |\n|---|---|---|---|\n| `session_id` | string | | Filter by session ID |\n| `file` | string | | Filter by file path |\n| `symbol` | string | | Filter by symbol name |\n\n**Returns:** List of observations with type, content, linked symbol/file, and a `stale` flag (set when the linked symbol changed since the observation was recorded).\n\nObservations are also surfaced automatically inside `get_project_overview`, `get_symbol`, and `get_file_summary` — you rarely need to call this tool directly.\n\n---\n\n### Document \u0026 context tools\n\nThese three tools extend PindeX beyond code: documentation files are indexed automatically alongside source files, and Claude can persist notes to a persistent knowledge store.\n\n**What gets indexed as documents:**\n\n| File type | Chunking strategy |\n|---|---|\n| `.md` / `.markdown` | Split at `#` / `##` / `###` heading boundaries — each section is one chunk |\n| `.yaml` / `.yml` | Fixed 50-line chunks |\n| `.txt` | Fixed 50-line chunks |\n\nDocuments are discovered by `indexAll()` and kept in sync by the same MD5-hash incremental indexer used for code files.\n\n---\n\n### `search_docs`\n\nFull-text search (FTS5) across indexed document chunks **and** saved context entries.\nUse this instead of loading entire documentation files.\n\n| Parameter | Type | Required | Description |\n|---|---|---|---|\n| `query` | string | ✓ | Search term |\n| `limit` | number | | Max results (default: 20) |\n| `type` | `\"docs\"` \\| `\"context\"` \\| `\"all\"` | | Filter by source (default: `\"all\"`) |\n\n**Returns:** List of matches, each with:\n- `type` — `\"doc\"` (from a file) or `\"context\"` (saved by Claude)\n- `content_preview` — first 200 characters of the chunk\n- `file`, `heading`, `start_line` — for `\"doc\"` results, enables precise navigation\n- `tags`, `session_id`, `created_at` — for `\"context\"` results\n\n---\n\n### `get_doc_chunk`\n\nRetrieve the full content of one or all chunks of an indexed document.\nMore token-efficient than `get_context` for large documentation files because it returns pre-segmented sections.\n\n| Parameter | Type | Required | Description |\n|---|---|---|---|\n| `file` | string | ✓ | File path (project-relative) |\n| `chunk_index` | number | | Specific chunk to retrieve — omit for all chunks |\n\n**Returns:** `{ file, total_chunks, chunks: [{ index, heading, start_line, end_line, content }] }`\n\n**Typical workflow:**\n\n```\nsearch_docs(\"authentication JWT\")\n→ { file: \"CLAUDE.md\", heading: \"Authentication\", start_line: 12, chunk_index: 2 }\n\nget_doc_chunk(\"CLAUDE.md\", 2)\n→ full text of the Authentication section only\n```\n\n---\n\n### `save_context`\n\nPersist an important fact, decision, or snippet to the context store.\nEntries are searchable across all future sessions via `search_docs`.\n\nUse this to offload information from the context window — instead of keeping a long summary in the prompt, write it once and retrieve it on demand.\n\n| Parameter | Type | Required | Description |\n|---|---|---|---|\n| `content` | string | ✓ | The text to store |\n| `tags` | string | | Comma-separated keywords for better retrieval (e.g. `\"auth,jwt,security\"`) |\n\n**Returns:** `{ id, session_id, created_at }`\n\n**Example — saving a decision:**\n\n```\nsave_context(\n  \"JWT expiry: access=1h, refresh=7d. Refresh stored in Redis. See src/auth/tokens.ts.\",\n  \"auth,jwt,redis\"\n)\n```\n\n**Example — retrieving it in a later session:**\n\n```\nsearch_docs(\"JWT expiry\", type: \"context\")\n→ { content_preview: \"JWT expiry: access=1h, refresh=7d …\", tags: \"auth,jwt,redis\" }\n```\n\n---\n\n## Environment Variables\n\nThese are set automatically in the generated `.mcp.json` — you rarely need to change them by hand.\n\n| Variable | Default | Description |\n|---|---|---|\n| `PROJECT_ROOT` | `.` | Root directory of the project to index |\n| `INDEX_PATH` | `~/.pindex/projects/{hash}/index.db` | Path to the SQLite database |\n| `LANGUAGES` | `typescript,javascript` | Comma-separated list of languages to index. Supported values: `typescript`, `javascript`, `java`, `kotlin`, `python`, `php`, `vue`, `svelte`, `ruby`, `csharp`, `go`, `rust` |\n| `AUTO_REINDEX` | `true` | Watch for file changes and reindex automatically |\n| `MONITORING_PORT` | assigned per-project | Port for the live dashboard + WebSocket |\n| `MONITORING_AUTO_OPEN` | `false` | Open the dashboard in the browser on startup |\n| `BASELINE_MODE` | `false` | Disable the index entirely (for A/B baseline sessions) |\n| `GENERATE_SUMMARIES` | `false` | Generate LLM summaries per symbol (stub — not yet wired) |\n| `TOKEN_PRICE_PER_MILLION` | `3.00` | USD price per million tokens — used for cost estimates |\n| `FEDERATION_REPOS` | _(empty)_ | Colon-separated absolute paths to linked repositories |\n| `DOCUMENT_PATTERNS` | `**/*.md,**/*.markdown,**/*.yaml,**/*.yml,**/*.txt` | Glob patterns for document files to index alongside code |\n| `OBSERVATION_RETENTION` | `permanent` | How long passive session observations are kept: `permanent`, `session`, or `Nd` (e.g. `30d`) |\n\n---\n\n## Integrations\n\n### Claude Code\n\nRun `pindex` in each project you want to index. The command writes `.mcp.json` automatically:\n\n```bash\ncd /my/project\npindex\n# → .mcp.json written\n# restart Claude Code → pindex-server starts automatically\n```\n\nThe `.mcp.json` format (auto-generated, do not edit by hand):\n\n```json\n{\n  \"mcpServers\": {\n    \"pindex\": {\n      \"command\": \"pindex-server\",\n      \"args\": [],\n      \"env\": {\n        \"PROJECT_ROOT\": \"/absolute/path/to/project\",\n        \"INDEX_PATH\": \"/home/user/.pindex/projects/a3f8b2c1/index.db\",\n        \"MONITORING_PORT\": \"7856\",\n        \"AUTO_REINDEX\": \"true\",\n        \"GENERATE_SUMMARIES\": \"false\",\n        \"MONITORING_AUTO_OPEN\": \"false\",\n        \"BASELINE_MODE\": \"false\",\n        \"TOKEN_PRICE_PER_MILLION\": \"3.00\"\n      }\n    }\n  }\n}\n```\n\nWith federation (`pindex add /other/project`):\n\n```json\n{\n  \"mcpServers\": {\n    \"pindex\": {\n      \"command\": \"pindex-server\",\n      \"args\": [],\n      \"env\": {\n        \"PROJECT_ROOT\": \"/absolute/path/to/project\",\n        \"FEDERATION_REPOS\": \"/absolute/path/to/other/project\",\n        \"...\"\n      }\n    }\n  }\n}\n```\n\n---\n\n### Goose\n\n[Goose](https://block.github.io/goose/) reads extensions from `~/.config/goose/config.yaml`.\n\n**Step 1 — Install PindeX:**\n\n```bash\ngit clone https://github.com/phash/PindeX.git\ncd PindeX \u0026\u0026 npm install \u0026\u0026 npm run build \u0026\u0026 npm install -g .\n```\n\n**Step 2 — Run `pindex` in your project** to get the assigned hash and port:\n\n```bash\ncd /my/project \u0026\u0026 pindex\n```\n\n**Step 3 — Edit `~/.config/goose/config.yaml`:**\n\n```yaml\nextensions:\n  pindex:\n    name: PindeX\n    type: stdio\n    cmd: pindex-server\n    args: []\n    envs:\n      PROJECT_ROOT: /absolute/path/to/project\n      INDEX_PATH: /home/user/.pindex/projects/{hash}/index.db\n      LANGUAGES: typescript,javascript\n      AUTO_REINDEX: \"true\"\n      GENERATE_SUMMARIES: \"false\"\n      MONITORING_PORT: \"{port}\"\n      MONITORING_AUTO_OPEN: \"false\"\n      BASELINE_MODE: \"false\"\n      TOKEN_PRICE_PER_MILLION: \"3.00\"\n    enabled: true\n    timeout: 300\n```\n\nReplace `{hash}` and `{port}` with the values shown by `pindex`. A ready-to-copy template is available in [`goose-extension.yaml`](./goose-extension.yaml).\n\n**Step 4 — Restart Goose:**\n\n```bash\ngoose session start\n```\n\n---\n\n## CLI Reference\n\n```\npindex [command] [options]\n```\n\n| Command | Description |\n|---|---|\n| _(no args)_ / `init` | Set up this project: write `.mcp.json`, inject `CLAUDE.md` section + hooks, register globally |\n| `reinit` | Re-inject PindeX section into `CLAUDE.md` and `.claude/settings.json` (e.g. after an update) |\n| `reinit --force` | Replace the existing section with the current template |\n| `add \u003cpath\u003e` | Link another repo for cross-repo search (federation) |\n| `remove` | Fully unregister project: remove `.mcp.json`, `CLAUDE.md` section, hooks, stop daemon |\n| `remove \u003cpath\u003e` | Remove a federated repo link only |\n| `setup` | One-time global setup (autostart config) |\n| `status` | Show all registered projects and their status |\n| `list` | List all registered projects (compact) |\n| `index [path]` | Manually index a directory (default: current directory) |\n| `index --force` | Force full reindex, bypassing MD5 hash checks |\n| `gui` | Open the aggregated monitoring dashboard in the browser |\n| `stats` | Print a short stats summary |\n| `uninstall` | Stop all daemons (data stays in `~/.pindex`) |\n\n**Examples:**\n\n```bash\n# Set up a new project\ncd /my/project \u0026\u0026 pindex\n\n# Link project-b for cross-repo search\npindex add /my/project-b\n\n# Check all registered projects\npindex status\n\n# Manually force a full reindex\npindex index --force\n\n# Index a Java + Vue project\nLANGUAGES=typescript,javascript,java,vue pindex index --force\n\n# Re-inject CLAUDE.md section (e.g. after updating pindex)\npindex reinit --force\n\n# Fully remove pindex from a project\npindex remove\n\n# Open the dashboard\npindex-gui\n```\n\n---\n\n## Monitoring Dashboard\n\n### Per-project dashboard\n\nEach `pindex-server` instance starts a monitoring server on its assigned port. Open it at:\n\n```\nhttp://localhost:{MONITORING_PORT}\n```\n\nOr let it open automatically on startup:\n\n```bash\nMONITORING_AUTO_OPEN=true node dist/index.js\n```\n\n### Aggregated dashboard (all projects)\n\n```bash\npindex-gui\n```\n\nOpens `http://localhost:7842` — reads **all** registered project databases directly and shows:\n\n- Token savings per project (bar chart)\n- Indexed file and symbol counts\n- Session history\n- Average savings % across all projects\n\nThe GUI refreshes automatically (default 15 seconds) and works even when no `pindex-server` is running. Use the slider in the header to adjust the refresh interval from 1–60 seconds.\n\n**Dashboard features (both dashboards):**\n- Real-time chart (Chart.js) of tokens used vs. estimated cost without index\n- Per-tool breakdown: which tools are used most and how much they save\n- Session comparison: side-by-side indexed vs. baseline A/B data\n- REST API at `/api/sessions` and `/api/sessions/:id` for programmatic access\n\n---\n\n## Development\n\n### Setup\n\n```bash\ngit clone https://github.com/phash/PindeX.git\ncd PindeX\nnpm install\n```\n\n### Build\n\n```bash\nnpm run build        # compile src/ → dist/\nnpm run build:watch  # watch mode\n```\n\n### Tests\n\n```bash\nnpm test               # run full test suite (vitest, pool: forks)\nnpm run test:watch     # watch mode\nnpm run test:coverage  # coverage report — threshold: 80%\n```\n\n\u003e Tests use `pool: 'forks'` — required because `better-sqlite3` uses native bindings that cannot share a process with the vitest worker pool.\n\n### Lint / Type-check\n\n```bash\nnpm run lint   # tsc --noEmit (type errors only, no output files)\n```\n\n### Test structure\n\n```\ntests/\n├── setup.ts              # global mocks (tree-sitter, chokidar, open)\n├── helpers/              # createTestDb(), fixtures, test server\n├── db/                   # schema, migrations, queries\n├── indexer/              # parser, indexer, watcher\n├── tools/                # one file per MCP tool (13 total)\n├── monitoring/           # estimator, token-logger, Express server\n├── cli/                  # project-detector, setup, daemon\n└── integration/\n    ├── mcp-server.test.ts   # MCP server wiring smoke tests\n    └── doc-indexing.test.ts # full document + context memory workflow\n```\n\n---\n\n## Project Structure\n\n```\nsrc/\n├── index.ts                  # Entry point — MCP stdio server + FEDERATION_REPOS\n├── server.ts                 # Tool registration (13 tools, FederatedDb interface)\n├── types.ts                  # Shared TypeScript interfaces\n│\n├── db/\n│   ├── schema.ts             # SQLite schema + FTS5 tables + triggers (v2)\n│   ├── queries.ts            # Typed query helpers\n│   ├── database.ts           # Connection management\n│   └── migrations.ts         # Schema versioning (PRAGMA user_version)\n│\n├── indexer/\n│   ├── index.ts              # Orchestrator — code + document file discovery\n│   ├── parser.ts             # tree-sitter AST → symbols; text → doc chunks\n│   ├── summarizer.ts         # LLM summary stub (not yet active)\n│   └── watcher.ts            # chokidar file watcher → auto-reindex\n│\n├── tools/                    # One file per MCP tool\n│   ├── search_symbols.ts     # FTS5 symbol search — supports federated DBs\n│   ├── get_symbol.ts\n│   ├── get_context.ts\n│   ├── get_file_summary.ts\n│   ├── find_usages.ts\n│   ├── get_dependencies.ts\n│   ├── get_project_overview.ts  # federation-aware stats\n│   ├── reindex.ts\n│   ├── get_token_stats.ts\n│   ├── start_comparison.ts\n│   ├── search_docs.ts        # FTS5 across documents + context entries\n│   ├── get_doc_chunk.ts      # retrieve specific document section(s)\n│   ├── save_context.ts       # persist a fact/decision to context store\n│   └── get_session_memory.ts # query passive session observations\n│\n├── memory/                   # Passive session memory (v1.1+)\n│   ├── ast-diff.ts           # AST diff engine — detects symbol changes\n│   ├── observer.ts           # SessionObserver — hooks tool calls + FileWatcher\n│   └── anti-patterns.ts      # AntiPatternDetector — dead-ends, thrashing, loops\n│\n├── monitoring/\n│   ├── server.ts             # Express + WebSocket (per-project instance)\n│   ├── token-logger.ts       # Per-call token logging\n│   ├── estimator.ts          # \"without index\" heuristic\n│   └── ui/                   # Dashboard HTML / CSS / Chart.js\n│\n├── gui/\n│   ├── index.ts              # pindex-gui entry point\n│   └── server.ts             # Aggregated Express app (reads all project DBs)\n│\n└── cli/\n    ├── index.ts              # CLI router\n    ├── init.ts               # initProject(), writeMcpJson(), addFederatedRepo()\n    ├── setup.ts              # One-time setup (pindex setup)\n    ├── daemon.ts             # Per-project PID-file daemon management\n    └── project-detector.ts   # getPindexHome(), findProjectRoot(), GlobalRegistry\n```\n\n### Key implementation notes\n\n- **ES Modules** — all relative imports use `.js` extensions (TypeScript ESM / NodeNext resolution).\n- **FTS5 sync** — `symbols`, `documents`, and `context_entries` are all kept in sync by SQLite `AFTER INSERT/UPDATE/DELETE` triggers; no application-level bookkeeping needed.\n- **Incremental reindexing** — MD5 hash per file; unchanged files are skipped for both code and document indexing.\n- **Document chunking** — markdown splits at `#`/`##`/`###` heading boundaries; all other text files use fixed 50-line windows. Empty chunks are filtered out before storage.\n- **Context memory** — `save_context` writes to `context_entries` keyed by `session_id`. Entries are never scoped to a single session — `search_docs` always searches the full history, enabling cross-session knowledge retrieval.\n- **Live context** — `get_context` reads from disk at call time so it always returns the current file state, not a stale cache.\n- **Testability** — `createMonitoringApp()` (returns the Express `app`) and `startMonitoringServer()` (binds the HTTP/WebSocket server) are separate functions so tests can mount the app without binding a port.\n- **Per-project ports** — assigned deterministically as `7842 + (parseInt(hash.slice(0,4), 16) % 2000)` and stored in `registry.json` so they never change.\n- **`pindex-gui` reads DBs directly** — no running server required; works as a standalone dashboard even when Claude Code is not open.\n- **Migration** — `getPindexHome()` automatically renames `~/.mcp-indexer` → `~/.pindex` on first call if the old directory exists.\n- **Passive session memory** — `SessionObserver` wires into every MCP tool handler and the `FileWatcher` at startup; no application code in tools needs to know about memory. Observations are linked to symbol names so the staleness engine can cross-reference them with the AST diff output on re-index.\n\n---\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphash%2Fpindex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphash%2Fpindex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphash%2Fpindex/lists"}