codebase-index 2.1.0__tar.gz → 2.1.2__tar.gz
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.
- codebase_index-2.1.2/.claude/skills/codebase-index/.skill_version +1 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.claude-plugin/plugin.json +1 -1
- codebase_index-2.1.2/.codex/skills/codebase-index/.skill_version +1 -0
- codebase_index-2.1.2/.opencode/skills/codebase-index/.skill_version +1 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/CHANGELOG.md +37 -1
- {codebase_index-2.1.0 → codebase_index-2.1.2}/PKG-INFO +5 -2
- {codebase_index-2.1.0 → codebase_index-2.1.2}/README.md +4 -1
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/installer.md +1 -1
- codebase_index-2.1.2/hooks/hooks.json +31 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/pyproject.toml +1 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/requirements.lock +1 -1
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/__init__.py +1 -1
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/cli.py +35 -0
- codebase_index-2.1.2/src/codebase_index/hooks.py +272 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/scaffold.py +61 -0
- codebase_index-2.1.2/tests/test_hooks_guard.py +157 -0
- codebase_index-2.1.0/.claude/skills/codebase-index/.skill_version +0 -1
- codebase_index-2.1.0/.codex/skills/codebase-index/.skill_version +0 -1
- codebase_index-2.1.0/.opencode/skills/codebase-index/.skill_version +0 -1
- codebase_index-2.1.0/hooks/hooks.json +0 -14
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.claude/skills/codebase-index/SKILL.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.claude/skills/codebase-index/examples/hooks/settings.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.claude/skills/codebase-index/references/commands.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.claude/skills/codebase-index/references/memory.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.claude/skills/codebase-index/references/response-contract.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.claude/skills/codebase-index/scripts/cbx +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.claude/skills/codebase-index/scripts/cbx.ps1 +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.claude-plugin/marketplace.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.codex/skills/codebase-index/SKILL.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.codex/skills/codebase-index/examples/hooks/settings.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.codex/skills/codebase-index/references/commands.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.codex/skills/codebase-index/references/memory.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.codex/skills/codebase-index/references/response-contract.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.codex/skills/codebase-index/scripts/cbx +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.codex/skills/codebase-index/scripts/cbx.ps1 +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.editorconfig +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.gitattributes +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.github/ISSUE_TEMPLATE/benchmark_report.yml +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.github/ISSUE_TEMPLATE/language_support.yml +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.github/ISSUE_TEMPLATE/skill_listing_request.yml +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.github/SUPPORT.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.github/labels.yml +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.github/workflows/ci.yml +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.github/workflows/release.yml +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.gitignore +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.opencode/agents/codebase-index.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.opencode/commands/codebase-index.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.opencode/skills/codebase-index/SKILL.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.opencode/skills/codebase-index/examples/hooks/settings.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.opencode/skills/codebase-index/references/commands.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.opencode/skills/codebase-index/references/memory.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.opencode/skills/codebase-index/references/response-contract.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.opencode/skills/codebase-index/scripts/cbx +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/.opencode/skills/codebase-index/scripts/cbx.ps1 +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/AGENTS.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/CODE_OF_CONDUCT.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/CONTRIBUTING.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/LICENSE +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/ROADMAP.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/SECURITY.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/adapters/claude.ps1 +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/adapters/claude.sh +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/adapters/codex.ps1 +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/adapters/codex.sh +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/adapters/opencode.ps1 +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/adapters/opencode.sh +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/assets/architecture.svg +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/assets/benchmark.svg +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/assets/demo-terminal.svg +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/assets/mark.png +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/assets/social-preview.png +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/bin/cbx +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/bin/cbx.ps1 +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/bin/codebase-index +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/bin/codebase-index.ps1 +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/ARCHITECTURE.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/BENCHMARKS.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/COMMUNITY_AUDIT.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/COMMUNITY_LAUNCH.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/COMPARISON.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/DATABASE_SCHEMA.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/DEMO.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/DEVELOPMENT.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/FAQ.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/INSTALLATION.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/LANGUAGES.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/MCP.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/MEMORY.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/PRODUCT_UPGRADE_PLAN.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/QUICKSTART.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/RELEASE_CHECKLIST.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/RETRIEVAL.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/RETRIEVAL_PIPELINE.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/ROADMAP.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/SCHEMA.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/SECURITY.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/SECURITY_MODEL.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/SKILL_DESIGN.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/demo.tape +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/plans/2026-05-29-benchmark-index-improvements.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/plans/2026-05-29-generalize-skill-research-discipline.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/plans/2026-05-29-m1-storage-discovery.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/plans/2026-05-29-m2-fts-lexical.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/plans/2026-05-29-m3-treesitter-symbols.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/plans/2026-05-29-m4-hybrid-search.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/plans/2026-05-29-m5-graph-impact.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/plans/2026-05-29-m6-embeddings-vector.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/plans/2026-05-29-m7-5-plugin-one-command-install.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/plans/2026-05-29-m7-skill-packaging.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/plans/2026-05-29-m8-hooks-watch.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/plans/2026-05-29-m9-release.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/plans/2026-05-29-multilang-symbols-make-skill-win.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/plans/2026-06-24-snippet-skeletonization.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/specs/2026-05-29-plugin-one-command-install-design.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/specs/2026-06-14-typed-framework-edges-design.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/specs/2026-06-24-snippet-skeletonization-design.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/docs/superpowers/specs/2026-09-10-evidence-memory-design.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/examples/config.example.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/examples/demo/EXPECTED_OUTPUT.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/examples/demo/README.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/examples/demo/run_demo.ps1 +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/examples/demo/run_demo.sh +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/examples/hooks/settings.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/examples/queries.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/examples/sample-queries.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/examples/sample-retrieval-output.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/install.ps1 +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/install.sh +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/lib/common.ps1 +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/lib/common.sh +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/2.0-audit.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/README.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/__init__.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/architecture.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/build_indexes.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/data/.gitignore +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/diagnose_accretion.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/diagnose_calibration.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/diagnose_slots.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/diagnose_structure.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/experiment_memory.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/experiments.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/fit_gate.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/fit_weights.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/hypotheses.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/novelty.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/nucleus/__init__.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/nucleus/baselines.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/nucleus/evalrun.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/nucleus/memory.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/nucleus/relations.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/nucleus/search.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/related-work.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/selection.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/research/test_nucleus.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/scripts/apply_labels.sh +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/scripts/bootstrap.ps1 +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/scripts/bootstrap.sh +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/scripts/check_links.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/scripts/check_versions.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/scripts/gen_assets.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/scripts/gen_benchmark_chart.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/scripts/gen_terminal_svg.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/scripts/release_notes.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/scripts/release_smoke.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/scripts/sync_skill_copies.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skill/SKILL.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skill/examples/basic-usage.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skill/examples/claude-md-example.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skill/examples/hooks-example.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skill/references/commands.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skill/references/memory.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skill/references/response-contract.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skill/scripts/bootstrap.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skill/scripts/cbx +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skill/scripts/cbx.ps1 +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skill/scripts/doctor.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skill/scripts/install.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skill/scripts/smoke_test.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skills/codebase-index/SKILL.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skills/codebase-index/references/commands.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skills/codebase-index/references/memory.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/skills/codebase-index/references/response-contract.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/__main__.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/config.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/discovery/__init__.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/discovery/classify.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/discovery/gates.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/discovery/ignore.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/discovery/walker.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/doctor.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/embeddings/__init__.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/embeddings/backend.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/embeddings/external.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/embeddings/local.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/embeddings/noop.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/graph/__init__.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/graph/analysis.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/graph/builder.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/graph/expand.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/graph/export.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/graph/modules.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/graph/navigate.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/graph/retrieval.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/indexer/__init__.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/indexer/doc_chunks.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/indexer/freshness.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/indexer/pipeline.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/mcp/__init__.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/mcp/server.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/memory/__init__.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/memory/identity.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/memory/session.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/memory/store.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/memory/validate.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/models.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/output/__init__.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/output/json.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/output/markdown.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/output/redact.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/parsers/__init__.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/parsers/base.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/parsers/languages.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/parsers/line_chunker.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/parsers/symbol_chunks.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/parsers/treesitter.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/retrieval/__init__.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/retrieval/budget.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/retrieval/diversity.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/retrieval/features.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/retrieval/fusion.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/retrieval/fuzzy.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/retrieval/intent.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/retrieval/lexical.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/retrieval/pipeline.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/retrieval/priors.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/retrieval/rerank.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/retrieval/searchers.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/retrieval/skeleton.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/retrieval/tuning.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/retrieval/types.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/service.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/skill_template/SKILL.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/skill_template/examples/hooks/settings.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/skill_template/references/commands.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/skill_template/references/memory.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/skill_template/references/response-contract.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/skill_template/scripts/cbx +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/skill_template/scripts/cbx.ps1 +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/skill_update.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/storage/__init__.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/storage/db.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/storage/repo.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/storage/schema.sql +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/watch/__init__.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/src/codebase_index/watch/watcher.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/__init__.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/benchmark_honest.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/benchmark_honest_RESULTS.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/benchmark_honest_newtowny.txt +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/benchmark_public.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/benchmark_public_RESULTS.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/benchmark_real_repo.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/conftest.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/README.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/__init__.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/baselines.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/gen_queries.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/harness.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/memory_eval.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/metrics.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/queries/self_repo.yml +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/queries/self_repo_git.yml +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/results/1.10.0-perf.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/results/1.10.0-retrieval-8corpus.txt +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/results/2026-09-04-public-baselines.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/results/2026-09-04-public-baselines.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/results/2026-09-14-evidence-memory.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/results/2026-09-14-evidence-memory.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/results/2026-09-24-agent-pilot.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/results/2026-09-24-retrieval-2.1.0.txt +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/results/2026-09-24-terra-nl-queries.yml +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/run_baselines.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/eval/run_eval.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/README.md +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/expected_answers.yml +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/index-1.10.0/index.sqlite +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/multilang/sample.go +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/multilang/sample.java +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/multilang/sample.rs +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/sample_repo/.env +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/sample_repo/.gitignore +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/sample_repo/huge.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/sample_repo/logo.png +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/sample_repo/node_modules/leftpad/index.js +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/sample_repo/secrets.pem +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/sample_repo/src/api/service.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/sample_repo/src/auth/token.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/sample_repo/src/models/user.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/sample_repo/src/schema.generated.ts +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/fixtures/sample_repo/web/app.ts +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/architecture.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/describe_refresh.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/explain_auth.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/impact_user_model.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/mcp_architecture.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/mcp_describe_symbol.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/mcp_explain_code.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/mcp_find_refs.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/mcp_find_symbol.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/mcp_healthcheck.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/mcp_impact_of.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/mcp_impact_of_diff.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/mcp_index_stats.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/mcp_path_between.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/mcp_search_code.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/path_renew_to_token.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/refs_refresh_access_token.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/search_token.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/stats.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden/symbol_user.json +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/golden_utils.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/installer/smoke.ps1 +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/installer/smoke.sh +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_agent_ergonomics.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_analysis.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_benchmark_comparison.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_bootstrap.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_budget.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_chunker.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_classify.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_clean_cli.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_cli.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_cli_golden.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_compact_output.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_config.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_diff_impact.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_discovery.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_diversity.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_doc_chunks.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_doctor.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_embeddings_backend.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_embeddings_external.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_embeddings_local.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_eval_baselines.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_freshness.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_fusion.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_fuzzy.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_gen_queries.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_graph.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_graph_coverage.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_graph_export_cli.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_graph_retrieval.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_hooks_merge.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_hybrid_ranking.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_ignore.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_impact_cli.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_impact_decay.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_index_cli.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_init_cli.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_intent.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_languages.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_lexical.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_mcp_golden.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_mcp_server.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_memory_eval_smoke.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_memory_identity.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_memory_lifecycle.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_memory_session.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_memory_stale_context.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_memory_store.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_memory_surfaces.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_memory_validate.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_migration_1x.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_multilang_symbols.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_navigate.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_output.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_packaging.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_parse_guardrails.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_perf_smoke.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_pipeline.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_pipeline_search.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_pipeline_vectors.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_plugin_manifest.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_plugin_skill_parity.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_plugin_wrappers.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_priors.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_public_benchmark.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_qualified_refs.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_quality_benchmark.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_ranking_features.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_read_cap.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_redact.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_release_scripts.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_repo_search.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_rerank.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_retrieval_types.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_scaffold.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_search_cli.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_searchers.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_seeded_index.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_service.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_skeleton.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_skill_update.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_storage.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_symbol_cli.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_symbol_ranking.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_symbol_refs.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_sync_skill_copies.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_treesitter.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_tuning_contract.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_update.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_update_cli.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_vector_search.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_vectors_storage.py +0 -0
- {codebase_index-2.1.0 → codebase_index-2.1.2}/tests/test_watcher.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.1.2
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "codebase-index",
|
|
4
4
|
"displayName": "Codebase Index",
|
|
5
5
|
"description": "Give Claude a precise local map of your codebase: find implementations, trace behavior, and predict change impact with file-line evidence.",
|
|
6
|
-
"version": "2.1.
|
|
6
|
+
"version": "2.1.2",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "codebase-index contributors"
|
|
9
9
|
},
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.1.2
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.1.2
|
|
@@ -6,6 +6,40 @@ All notable changes to this project are documented here. The format is based on
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [2.1.2] - 2026-09-25
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- The `PreToolUse` guard no longer blocks work it should let through:
|
|
14
|
+
- the first `codebase-index` command of a session turns the guard off even when it
|
|
15
|
+
is the command that builds the index; before, a repository without an index kept
|
|
16
|
+
the guard on for the whole session. Session state now lives in the system temp
|
|
17
|
+
directory (`CBX_HOOK_STATE` overrides it) instead of inside the index;
|
|
18
|
+
- heredoc bodies (`cat > script.ps1 <<'EOF'`, `python - <<EOF`) are file content, not
|
|
19
|
+
commands, and are no longer scanned for `grep`/`Select-String`;
|
|
20
|
+
- a retry is matched by its search term, not by the whole tool call, so a rewritten
|
|
21
|
+
command or a new description for the same search goes through;
|
|
22
|
+
- a quoted alternation such as `grep "a\|b"` is read whole, and a search on its own
|
|
23
|
+
line of a multi-line command is recognised.
|
|
24
|
+
|
|
25
|
+
## [2.1.1] - 2026-09-25
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- `codebase-index install-hooks [--global]` makes Claude Code search through the index
|
|
30
|
+
by default. It merges two hooks into `.claude/settings.json` (or
|
|
31
|
+
`~/.claude/settings.json`), keeping every other hook:
|
|
32
|
+
- `SessionStart`: in an indexed repository, one line of context naming the commands
|
|
33
|
+
that answer code questions;
|
|
34
|
+
- `PreToolUse` on `Grep|Bash`: the first code search of a session, before any
|
|
35
|
+
`codebase-index` command has run, is sent back with the index command to use
|
|
36
|
+
instead. Repeating the same call lets it through, the first index command turns the
|
|
37
|
+
guard off for the session, and searches over docs, logs or config, pipelines such
|
|
38
|
+
as `ps | grep`, and directories without an index are never intercepted.
|
|
39
|
+
`CBX_GUARD=0` disables it; `install-hooks --uninstall` removes both hooks.
|
|
40
|
+
The hooks run as `codebase-index-hook`, a standard-library-only entry point (about
|
|
41
|
+
0.1 s per call). The Claude Code plugin registers the same hooks.
|
|
42
|
+
|
|
9
43
|
## [2.1.0] - 2026-09-24
|
|
10
44
|
|
|
11
45
|
Agent-efficiency release. An agent answering five code questions on a 5.9k-file
|
|
@@ -868,7 +902,9 @@ Pooled over 305 queries (Python, Java, TypeScript), v1.8.0 → 1.9.0:
|
|
|
868
902
|
- Hooks example + `watch` mode for keeping the index fresh without blocking the edit loop (M8).
|
|
869
903
|
- `doctor`, `stats`, `clean` diagnostics/maintenance commands.
|
|
870
904
|
|
|
871
|
-
[Unreleased]: https://github.com/denfry/codebase-index/compare/v2.1.
|
|
905
|
+
[Unreleased]: https://github.com/denfry/codebase-index/compare/v2.1.2...HEAD
|
|
906
|
+
[2.1.2]: https://github.com/denfry/codebase-index/compare/v2.1.1...v2.1.2
|
|
907
|
+
[2.1.1]: https://github.com/denfry/codebase-index/compare/v2.1.0...v2.1.1
|
|
872
908
|
[2.1.0]: https://github.com/denfry/codebase-index/compare/v2.0.0...v2.1.0
|
|
873
909
|
[2.0.0]: https://github.com/denfry/codebase-index/compare/v1.9.0...v2.0.0
|
|
874
910
|
[1.10.0]: https://github.com/denfry/codebase-index/compare/v1.9.0...abb67df
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codebase-index
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.2
|
|
4
4
|
Summary: A precise local codebase map for AI coding agents: find, trace, and predict with file-line evidence.
|
|
5
5
|
Project-URL: Homepage, https://github.com/denfry/codebase-index
|
|
6
6
|
Project-URL: Documentation, https://github.com/denfry/codebase-index/tree/main/docs
|
|
@@ -195,7 +195,10 @@ agent format: `path:start-end symbol` with the matching lines numbered underneat
|
|
|
195
195
|
| **Any MCP client** (Claude Desktop, Cursor, VS Code, Zed, Windsurf, ...) | `pip install "codebase-index[mcp]"` then `codebase-index mcp --root /path/to/repo` | 11 tools (`search_code`, `find_refs`, `impact_of`, `impact_of_diff`, `path_between`, ...) with a versioned JSON envelope |
|
|
196
196
|
| **Anything with a shell** | `codebase-index --json ...` | The same payloads as plain JSON, plus a local SQLite database you can query yourself |
|
|
197
197
|
|
|
198
|
-
`init --target auto` detects which of these are present.
|
|
198
|
+
`init --target auto` detects which of these are present. To make Claude Code reach for
|
|
199
|
+
the index before Grep in every indexed repository, run
|
|
200
|
+
`codebase-index install-hooks --global`: a session-start note plus a guard that sends the
|
|
201
|
+
first code search of a session to the index (repeat the call to run it anyway). See
|
|
199
202
|
[INSTALLATION.md](docs/INSTALLATION.md) and [MCP.md](docs/MCP.md).
|
|
200
203
|
|
|
201
204
|
## Evidence
|
|
@@ -145,7 +145,10 @@ agent format: `path:start-end symbol` with the matching lines numbered underneat
|
|
|
145
145
|
| **Any MCP client** (Claude Desktop, Cursor, VS Code, Zed, Windsurf, ...) | `pip install "codebase-index[mcp]"` then `codebase-index mcp --root /path/to/repo` | 11 tools (`search_code`, `find_refs`, `impact_of`, `impact_of_diff`, `path_between`, ...) with a versioned JSON envelope |
|
|
146
146
|
| **Anything with a shell** | `codebase-index --json ...` | The same payloads as plain JSON, plus a local SQLite database you can query yourself |
|
|
147
147
|
|
|
148
|
-
`init --target auto` detects which of these are present.
|
|
148
|
+
`init --target auto` detects which of these are present. To make Claude Code reach for
|
|
149
|
+
the index before Grep in every indexed repository, run
|
|
150
|
+
`codebase-index install-hooks --global`: a session-start note plus a guard that sends the
|
|
151
|
+
first code search of a session to the index (repeat the call to run it anyway). See
|
|
149
152
|
[INSTALLATION.md](docs/INSTALLATION.md) and [MCP.md](docs/MCP.md).
|
|
150
153
|
|
|
151
154
|
## Evidence
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"SessionStart": [
|
|
4
|
+
{
|
|
5
|
+
"hooks": [
|
|
6
|
+
{
|
|
7
|
+
"type": "command",
|
|
8
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/scripts/bootstrap.sh\""
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"type": "command",
|
|
12
|
+
"command": "codebase-index-hook session-start 2>/dev/null || true",
|
|
13
|
+
"timeout": 5
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"PreToolUse": [
|
|
19
|
+
{
|
|
20
|
+
"matcher": "Grep|Bash",
|
|
21
|
+
"hooks": [
|
|
22
|
+
{
|
|
23
|
+
"type": "command",
|
|
24
|
+
"command": "codebase-index-hook guard 2>/dev/null || true",
|
|
25
|
+
"timeout": 5
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -57,6 +57,7 @@ build = ["build>=1.2", "twine>=5.0"]
|
|
|
57
57
|
codebase-index = "codebase_index.cli:app"
|
|
58
58
|
cbx = "codebase_index.cli:app" # short alias
|
|
59
59
|
codebase-index-mcp = "codebase_index.mcp.server:run" # standalone MCP entry point
|
|
60
|
+
codebase-index-hook = "codebase_index.hooks:main" # Claude Code hooks (stdlib only, fast)
|
|
60
61
|
|
|
61
62
|
[project.urls]
|
|
62
63
|
Homepage = "https://github.com/denfry/codebase-index"
|
|
@@ -1064,6 +1064,41 @@ def watch(
|
|
|
1064
1064
|
raise typer.Exit(code=1)
|
|
1065
1065
|
|
|
1066
1066
|
|
|
1067
|
+
@app.command("install-hooks")
|
|
1068
|
+
def install_hooks(
|
|
1069
|
+
ctx: typer.Context,
|
|
1070
|
+
global_: bool = typer.Option(
|
|
1071
|
+
False, "--global", help="Install into ~/.claude/settings.json (every project)."
|
|
1072
|
+
),
|
|
1073
|
+
uninstall: bool = typer.Option(False, "--uninstall", help="Remove the hooks instead."),
|
|
1074
|
+
) -> None:
|
|
1075
|
+
"""Make Claude Code search through the index by default.
|
|
1076
|
+
|
|
1077
|
+
Adds a SessionStart note and a PreToolUse guard on Grep/Bash: the first code
|
|
1078
|
+
search of a session, before any codebase-index command, is sent back with the
|
|
1079
|
+
index command to run instead; repeating it lets it through. Both do nothing in
|
|
1080
|
+
a directory without an index. Other hooks in the settings file are kept.
|
|
1081
|
+
"""
|
|
1082
|
+
from .config import find_root
|
|
1083
|
+
from . import scaffold
|
|
1084
|
+
|
|
1085
|
+
if global_:
|
|
1086
|
+
path = Path.home() / ".claude" / "settings.json"
|
|
1087
|
+
else:
|
|
1088
|
+
root_opt = ctx.obj.get("root") if ctx.obj else None
|
|
1089
|
+
path = (Path(root_opt).resolve() if root_opt else find_root()) / scaffold.SETTINGS_REL
|
|
1090
|
+
if uninstall:
|
|
1091
|
+
changed = scaffold.uninstall_guard_hooks(path)
|
|
1092
|
+
verb = "removed from"
|
|
1093
|
+
else:
|
|
1094
|
+
changed = scaffold.install_guard_hooks(path)
|
|
1095
|
+
verb = "added to"
|
|
1096
|
+
if changed:
|
|
1097
|
+
typer.echo(f"[install-hooks] {', '.join(changed)} {verb} {path}")
|
|
1098
|
+
else:
|
|
1099
|
+
typer.echo(f"[install-hooks] nothing to change in {path}")
|
|
1100
|
+
|
|
1101
|
+
|
|
1067
1102
|
@app.command("skill-update")
|
|
1068
1103
|
def skill_update(
|
|
1069
1104
|
ctx: typer.Context,
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"""Claude Code hooks that make the index the default way to search code.
|
|
2
|
+
|
|
3
|
+
Two events, both no-ops outside a repository that has an index:
|
|
4
|
+
|
|
5
|
+
- ``session-start`` adds one short note to the session context: this repository
|
|
6
|
+
is indexed, and which commands answer code questions.
|
|
7
|
+
- ``guard`` (PreToolUse on Grep and Bash) intercepts a code search the first time
|
|
8
|
+
in a session, before any ``codebase-index`` command has run, and names the
|
|
9
|
+
index command to use instead. It is a nudge, not a wall: searching for the
|
|
10
|
+
same term again lets it through, the first ``codebase-index`` command in the
|
|
11
|
+
session turns the guard off (even one that has yet to build the index), and
|
|
12
|
+
searches over docs, logs or config, or inside heredoc bodies, are never
|
|
13
|
+
intercepted.
|
|
14
|
+
|
|
15
|
+
Measured on a 5.9k-file monorepo, an agent spent 19% fewer tokens with the index
|
|
16
|
+
than with grep (tests/eval/results/2026-09-24-agent-pilot.md), but agents reach
|
|
17
|
+
for Grep out of habit. The guard runs on every Bash call, so this module imports
|
|
18
|
+
only the standard library and does no index work beyond one small SQLite read.
|
|
19
|
+
|
|
20
|
+
Entry point: ``codebase-index-hook <event>`` reads the hook JSON on stdin and
|
|
21
|
+
prints the hook JSON reply (or nothing). ``CBX_GUARD=0`` disables the guard.
|
|
22
|
+
Per-session state lives in the system temp directory (``CBX_HOOK_STATE``
|
|
23
|
+
overrides it), so it exists before the repository has an index.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
import hashlib
|
|
29
|
+
import json
|
|
30
|
+
import os
|
|
31
|
+
import re
|
|
32
|
+
import sqlite3
|
|
33
|
+
import sys
|
|
34
|
+
import tempfile
|
|
35
|
+
import time
|
|
36
|
+
from pathlib import Path
|
|
37
|
+
from typing import Any, Optional
|
|
38
|
+
|
|
39
|
+
INDEX_REL = Path(".claude") / "cache" / "codebase-index" / "index.sqlite"
|
|
40
|
+
_STATE_DIR = "codebase-index-hooks"
|
|
41
|
+
_STATE_TTL_S = 2 * 24 * 3600
|
|
42
|
+
|
|
43
|
+
# A shell segment that searches file contents: the first command of the segment
|
|
44
|
+
# (after `&&`, `||`, `;`, a newline or the start), so `ps aux | grep x` is not a
|
|
45
|
+
# repo search. Quoted arguments may hold `|`, as in grep "a\|b".
|
|
46
|
+
_SEARCH_CMD = re.compile(
|
|
47
|
+
r"(?:^|&&|\|\||;|\n)[ \t]*(?:cd\s+\S+\s*&&\s*)?"
|
|
48
|
+
r"(?P<cmd>git\s+grep|grep|egrep|fgrep|rg|ag|ack|findstr|Select-String)\b"
|
|
49
|
+
r"""(?P<args>(?:"[^"\n]*"|'[^'\n]*'|[^|;&\n"'])*)""",
|
|
50
|
+
re.IGNORECASE,
|
|
51
|
+
)
|
|
52
|
+
# A heredoc body is file content (a script being written, stdin for python), not
|
|
53
|
+
# commands; an unterminated one runs to the end of the command.
|
|
54
|
+
_HEREDOC = re.compile(
|
|
55
|
+
r"""(?<!<)<<-?(?!<)[ \t]*(['"]?)([A-Za-z_][\w-]*)\1(?P<rest>[^\n]*)\n"""
|
|
56
|
+
r".*?(?:^[ \t]*\2[ \t]*$|\Z)",
|
|
57
|
+
re.DOTALL | re.MULTILINE,
|
|
58
|
+
)
|
|
59
|
+
_INDEX_CMD = re.compile(r"(?:^|[\s;&|/\\\"'])(?:codebase-index|cbx)(?:\.exe|\.ps1)?\s+\w")
|
|
60
|
+
# Searches over prose, logs and config are what grep is for; leave them alone.
|
|
61
|
+
_NON_CODE = re.compile(
|
|
62
|
+
r"\.(?:md|mdx|rst|txt|log|ya?ml|json|toml|ini|cfg|conf|csv|xml|properties|lock|env|html?)\b"
|
|
63
|
+
r"|--include=\*?\.(?:md|txt|log|ya?ml|json|toml)",
|
|
64
|
+
re.IGNORECASE,
|
|
65
|
+
)
|
|
66
|
+
_NON_CODE_TYPES = {"md", "markdown", "txt", "log", "yaml", "yml", "json", "toml", "xml",
|
|
67
|
+
"csv", "ini", "config"}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def main(argv: Optional[list[str]] = None) -> int:
|
|
71
|
+
args = sys.argv[1:] if argv is None else argv
|
|
72
|
+
event = args[0] if args else ""
|
|
73
|
+
try:
|
|
74
|
+
payload = json.loads(sys.stdin.read() or "{}")
|
|
75
|
+
except (ValueError, OSError):
|
|
76
|
+
return 0
|
|
77
|
+
try:
|
|
78
|
+
reply = {"guard": guard, "session-start": session_start}.get(event, _none)(payload)
|
|
79
|
+
except Exception: # a hook must never break the session it runs in
|
|
80
|
+
return 0
|
|
81
|
+
if reply:
|
|
82
|
+
sys.stdout.write(json.dumps(reply))
|
|
83
|
+
return 0
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _none(_payload: dict) -> Optional[dict]:
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def find_index_root(start: Path) -> Optional[Path]:
|
|
91
|
+
"""The nearest directory at or above `start` that holds an index."""
|
|
92
|
+
for path in (start, *start.parents):
|
|
93
|
+
if (path / INDEX_REL).is_file():
|
|
94
|
+
return path
|
|
95
|
+
return None
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _cwd(payload: dict) -> Path:
|
|
99
|
+
raw = str(payload.get("cwd") or os.getcwd())
|
|
100
|
+
# Git Bash hands out MSYS paths (/c/Projects/x); Python on Windows needs C:/.
|
|
101
|
+
msys = re.match(r"^/([a-zA-Z])(/.*)?$", raw)
|
|
102
|
+
if os.name == "nt" and msys:
|
|
103
|
+
raw = f"{msys.group(1)}:{msys.group(2) or '/'}"
|
|
104
|
+
return Path(raw)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
# --- session-start ------------------------------------------------------------------
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def session_start(payload: dict) -> Optional[dict]:
|
|
111
|
+
root = find_index_root(_cwd(payload))
|
|
112
|
+
if root is None:
|
|
113
|
+
return None
|
|
114
|
+
files = _indexed_files(root)
|
|
115
|
+
size = f" ({files} files)" if files else ""
|
|
116
|
+
note = (
|
|
117
|
+
f"This repository has a codebase-index index{size}. For questions about the "
|
|
118
|
+
"code (where something is, how it works, who calls it, what a change breaks) "
|
|
119
|
+
"use the codebase-index skill before Grep or Read: "
|
|
120
|
+
'`codebase-index search "<question>" --compact`, '
|
|
121
|
+
'`codebase-index refs "Owner.member" --compact`, '
|
|
122
|
+
'`codebase-index impact "Owner.member" --compact`. '
|
|
123
|
+
"Output lines are numbered; cite them as file:line."
|
|
124
|
+
)
|
|
125
|
+
return {"hookSpecificOutput": {"hookEventName": "SessionStart", "additionalContext": note}}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _indexed_files(root: Path) -> Optional[int]:
|
|
129
|
+
try:
|
|
130
|
+
conn = sqlite3.connect(f"file:{root / INDEX_REL}?mode=ro", uri=True, timeout=0.5)
|
|
131
|
+
try:
|
|
132
|
+
return int(conn.execute("SELECT COUNT(*) FROM files").fetchone()[0])
|
|
133
|
+
finally:
|
|
134
|
+
conn.close()
|
|
135
|
+
except sqlite3.Error:
|
|
136
|
+
return None
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# --- guard ------------------------------------------------------------------------------
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def guard(payload: dict) -> Optional[dict]:
|
|
143
|
+
if os.environ.get("CBX_GUARD", "").strip() == "0":
|
|
144
|
+
return None
|
|
145
|
+
tool = payload.get("tool_name") or ""
|
|
146
|
+
tool_input = payload.get("tool_input") or {}
|
|
147
|
+
if tool not in ("Grep", "Bash"):
|
|
148
|
+
return None
|
|
149
|
+
state = _State(str(payload.get("session_id") or "default"))
|
|
150
|
+
|
|
151
|
+
if tool == "Bash":
|
|
152
|
+
command = _HEREDOC.sub(lambda m: "<<" + m.group("rest"), str(tool_input.get("command") or ""))
|
|
153
|
+
if _INDEX_CMD.search(command):
|
|
154
|
+
# Checked before the index exists: the first search is what builds it.
|
|
155
|
+
state.mark_used()
|
|
156
|
+
return None
|
|
157
|
+
pattern = _shell_search_pattern(command)
|
|
158
|
+
if pattern is None:
|
|
159
|
+
return None
|
|
160
|
+
else:
|
|
161
|
+
if _grep_targets_non_code(tool_input):
|
|
162
|
+
return None
|
|
163
|
+
pattern = str(tool_input.get("pattern") or "")
|
|
164
|
+
|
|
165
|
+
if state.used or find_index_root(_cwd(payload)) is None:
|
|
166
|
+
return None
|
|
167
|
+
# Keyed by the search term, not the whole call: a retry rarely repeats the
|
|
168
|
+
# command byte for byte (a new description, another pipe, a regenerated script).
|
|
169
|
+
fingerprint = hashlib.sha1(_term(pattern).lower().encode("utf-8")).hexdigest()
|
|
170
|
+
if state.was_denied(fingerprint):
|
|
171
|
+
return None # the retry after a nudge: the agent decided grep is right
|
|
172
|
+
state.deny(fingerprint)
|
|
173
|
+
return {
|
|
174
|
+
"hookSpecificOutput": {
|
|
175
|
+
"hookEventName": "PreToolUse",
|
|
176
|
+
"permissionDecision": "deny",
|
|
177
|
+
"permissionDecisionReason": _reason(pattern),
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def _shell_search_pattern(command: str) -> Optional[str]:
|
|
183
|
+
"""The search term of a content search in `command`, or None if there is none."""
|
|
184
|
+
for match in _SEARCH_CMD.finditer(command):
|
|
185
|
+
args = match.group("args")
|
|
186
|
+
if _NON_CODE.search(args):
|
|
187
|
+
continue
|
|
188
|
+
quoted = re.search(r"""(['"])(.+?)\1""", args)
|
|
189
|
+
if quoted:
|
|
190
|
+
return quoted.group(2)
|
|
191
|
+
words = [w for w in args.split() if not w.startswith("-")]
|
|
192
|
+
return words[0] if words else ""
|
|
193
|
+
return None
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def _grep_targets_non_code(tool_input: dict) -> bool:
|
|
197
|
+
kind = str(tool_input.get("type") or "").lower()
|
|
198
|
+
if kind in _NON_CODE_TYPES:
|
|
199
|
+
return True
|
|
200
|
+
target = f"{tool_input.get('glob') or ''} {tool_input.get('path') or ''}"
|
|
201
|
+
return bool(_NON_CODE.search(target))
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _term(pattern: str) -> str:
|
|
205
|
+
"""A regex search pattern as plain query words."""
|
|
206
|
+
return " ".join(re.sub(r"""[\\^$()\[\]{}|*+?"']""", " ", pattern).split())[:80]
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def _reason(pattern: str) -> str:
|
|
210
|
+
term = _term(pattern) or "<what you are looking for>"
|
|
211
|
+
return (
|
|
212
|
+
"codebase-index: this repository is indexed, and the index answers code "
|
|
213
|
+
"searches with ranked, numbered lines in fewer tokens than grep. Run it first:\n"
|
|
214
|
+
f' codebase-index search "{term}" --compact # where / how\n'
|
|
215
|
+
' codebase-index refs "Owner.member" --compact # every call site, with callers\n'
|
|
216
|
+
' codebase-index symbol "Name" # a definition\n'
|
|
217
|
+
"If the index does not answer, search for the same term again and it will run. "
|
|
218
|
+
"Once any codebase-index command has run in this session, searches are not "
|
|
219
|
+
"intercepted."
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
class _State:
|
|
224
|
+
"""Per-session guard state: whether the index was used, which calls were nudged."""
|
|
225
|
+
|
|
226
|
+
def __init__(self, session: str) -> None:
|
|
227
|
+
safe = re.sub(r"[^A-Za-z0-9_.-]", "_", session)[:80] or "default"
|
|
228
|
+
self.dir = Path(os.environ.get("CBX_HOOK_STATE") or Path(tempfile.gettempdir()) / _STATE_DIR)
|
|
229
|
+
self.path = self.dir / f"{safe}.json"
|
|
230
|
+
self.data: dict[str, Any] = {"used": False, "denied": []}
|
|
231
|
+
try:
|
|
232
|
+
self.data.update(json.loads(self.path.read_text(encoding="utf-8")))
|
|
233
|
+
except (OSError, ValueError):
|
|
234
|
+
pass
|
|
235
|
+
|
|
236
|
+
@property
|
|
237
|
+
def used(self) -> bool:
|
|
238
|
+
return bool(self.data.get("used"))
|
|
239
|
+
|
|
240
|
+
def was_denied(self, fingerprint: str) -> bool:
|
|
241
|
+
return fingerprint in self.data.get("denied", [])
|
|
242
|
+
|
|
243
|
+
def mark_used(self) -> None:
|
|
244
|
+
if not self.used:
|
|
245
|
+
self.data["used"] = True
|
|
246
|
+
self._save()
|
|
247
|
+
|
|
248
|
+
def deny(self, fingerprint: str) -> None:
|
|
249
|
+
self.data.setdefault("denied", []).append(fingerprint)
|
|
250
|
+
self._save()
|
|
251
|
+
|
|
252
|
+
def _save(self) -> None:
|
|
253
|
+
try:
|
|
254
|
+
self.dir.mkdir(parents=True, exist_ok=True)
|
|
255
|
+
self.path.write_text(json.dumps(self.data), encoding="utf-8")
|
|
256
|
+
_prune(self.dir)
|
|
257
|
+
except OSError:
|
|
258
|
+
pass
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def _prune(directory: Path) -> None:
|
|
262
|
+
cutoff = time.time() - _STATE_TTL_S
|
|
263
|
+
for item in directory.glob("*.json"):
|
|
264
|
+
try:
|
|
265
|
+
if item.stat().st_mtime < cutoff:
|
|
266
|
+
item.unlink()
|
|
267
|
+
except OSError:
|
|
268
|
+
pass
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
if __name__ == "__main__":
|
|
272
|
+
raise SystemExit(main())
|
|
@@ -283,6 +283,67 @@ def merge_hook_settings(root: Path) -> bool:
|
|
|
283
283
|
return True
|
|
284
284
|
|
|
285
285
|
|
|
286
|
+
# Index-first hooks (hooks.py): a SessionStart note and a PreToolUse guard that
|
|
287
|
+
# steers the first code search of a session to the index.
|
|
288
|
+
_GUARD_MARKER = "codebase-index-hook"
|
|
289
|
+
GUARD_HOOKS: dict[str, dict] = {
|
|
290
|
+
"SessionStart": {
|
|
291
|
+
"hooks": [{"type": "command", "command": "codebase-index-hook session-start",
|
|
292
|
+
"timeout": 5}],
|
|
293
|
+
},
|
|
294
|
+
"PreToolUse": {
|
|
295
|
+
"matcher": "Grep|Bash",
|
|
296
|
+
"hooks": [{"type": "command", "command": "codebase-index-hook guard", "timeout": 5}],
|
|
297
|
+
},
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def _is_guard_entry(entry: dict) -> bool:
|
|
302
|
+
return any(_GUARD_MARKER in str(h.get("command", "")) for h in entry.get("hooks", []))
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def install_guard_hooks(settings_path: Path) -> list[str]:
|
|
306
|
+
"""Merge the index-first hooks into a Claude Code settings file.
|
|
307
|
+
|
|
308
|
+
Idempotent, and leaves every other hook in place. Returns the events added.
|
|
309
|
+
"""
|
|
310
|
+
settings: dict = {}
|
|
311
|
+
if settings_path.exists():
|
|
312
|
+
settings = json.loads(settings_path.read_text(encoding="utf-8") or "{}")
|
|
313
|
+
hooks = settings.setdefault("hooks", {})
|
|
314
|
+
added = []
|
|
315
|
+
for event, entry in GUARD_HOOKS.items():
|
|
316
|
+
entries = hooks.setdefault(event, [])
|
|
317
|
+
if not any(_is_guard_entry(e) for e in entries):
|
|
318
|
+
entries.append(json.loads(json.dumps(entry)))
|
|
319
|
+
added.append(event)
|
|
320
|
+
if added:
|
|
321
|
+
settings_path.parent.mkdir(parents=True, exist_ok=True)
|
|
322
|
+
settings_path.write_text(json.dumps(settings, indent=2) + "\n", encoding="utf-8")
|
|
323
|
+
return added
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def uninstall_guard_hooks(settings_path: Path) -> list[str]:
|
|
327
|
+
"""Remove the index-first hooks; other hooks are kept. Returns the events changed."""
|
|
328
|
+
if not settings_path.exists():
|
|
329
|
+
return []
|
|
330
|
+
settings = json.loads(settings_path.read_text(encoding="utf-8") or "{}")
|
|
331
|
+
hooks = settings.get("hooks", {})
|
|
332
|
+
removed = []
|
|
333
|
+
for event in GUARD_HOOKS:
|
|
334
|
+
entries = hooks.get(event, [])
|
|
335
|
+
kept = [e for e in entries if not _is_guard_entry(e)]
|
|
336
|
+
if len(kept) != len(entries):
|
|
337
|
+
removed.append(event)
|
|
338
|
+
if kept:
|
|
339
|
+
hooks[event] = kept
|
|
340
|
+
else:
|
|
341
|
+
hooks.pop(event, None)
|
|
342
|
+
if removed:
|
|
343
|
+
settings_path.write_text(json.dumps(settings, indent=2) + "\n", encoding="utf-8")
|
|
344
|
+
return removed
|
|
345
|
+
|
|
346
|
+
|
|
286
347
|
# ── MCP client config helpers ──────────────────────────────────────────────────────────────────
|
|
287
348
|
|
|
288
349
|
_MCP_SERVER_NAME = "codebase-index"
|