codegraphcontext 0.4.17__tar.gz → 0.4.18__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.
Files changed (173) hide show
  1. {codegraphcontext-0.4.17/src/codegraphcontext.egg-info → codegraphcontext-0.4.18}/PKG-INFO +5 -5
  2. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/README.md +4 -4
  3. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/pyproject.toml +1 -1
  4. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/api/app.py +5 -0
  5. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/cli/cli_helpers.py +52 -4
  6. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/cli/config_manager.py +33 -8
  7. codegraphcontext-0.4.18/src/codegraphcontext/cli/hook_manager.py +220 -0
  8. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/cli/main.py +121 -15
  9. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/cli/setup_wizard.py +96 -10
  10. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/core/cgc_bundle.py +14 -4
  11. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/core/database_kuzu.py +10 -0
  12. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/core/watcher.py +48 -5
  13. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/code_finder.py +1 -1
  14. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/graph_builder.py +38 -178
  15. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/handlers/management_handlers.py +6 -2
  16. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/handlers/watcher_handlers.py +7 -2
  17. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/discovery.py +1 -2
  18. codegraphcontext-0.4.18/src/codegraphcontext/tools/indexing/persistence/utils.py +46 -0
  19. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/persistence/writer.py +264 -93
  20. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/pipeline.py +27 -13
  21. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/resolution/calls.py +21 -10
  22. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/resolution/post_resolution.py +18 -6
  23. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/scip_pipeline.py +38 -3
  24. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/python.py +10 -11
  25. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/report_generator.py +11 -11
  26. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/utils/path_sandbox.py +2 -1
  27. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18/src/codegraphcontext.egg-info}/PKG-INFO +5 -5
  28. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext.egg-info/SOURCES.txt +2 -0
  29. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/LICENSE +0 -0
  30. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/MANIFEST.in +0 -0
  31. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/setup.cfg +0 -0
  32. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/__init__.py +0 -0
  33. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/__main__.py +0 -0
  34. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/api/__init__.py +0 -0
  35. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/api/mcp_sse.py +0 -0
  36. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/api/router.py +0 -0
  37. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/api/schemas.py +0 -0
  38. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/cli/__init__.py +0 -0
  39. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/cli/registry_commands.py +0 -0
  40. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/cli/setup_macos.py +0 -0
  41. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/cli/visualizer.py +0 -0
  42. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/core/__init__.py +0 -0
  43. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/core/bundle_registry.py +0 -0
  44. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/core/cgcignore.py +0 -0
  45. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/core/database.py +0 -0
  46. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/core/database_falkordb.py +0 -0
  47. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/core/database_falkordb_remote.py +0 -0
  48. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/core/database_ladybug.py +0 -0
  49. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/core/database_nornic.py +0 -0
  50. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/core/falkor_worker.py +0 -0
  51. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/core/jobs.py +0 -0
  52. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/prompts.py +0 -0
  53. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/server.py +0 -0
  54. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tool_definitions.py +0 -0
  55. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/__init__.py +0 -0
  56. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/advanced_language_query_tool.py +0 -0
  57. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/datasources/__init__.py +0 -0
  58. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/datasources/cassandra_ingester.py +0 -0
  59. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/datasources/mysql_ingester.py +0 -0
  60. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/datasources/redis_ingester.py +0 -0
  61. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/handlers/analysis_handlers.py +0 -0
  62. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/handlers/indexing_handlers.py +0 -0
  63. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/handlers/query_handlers.py +0 -0
  64. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/__init__.py +0 -0
  65. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/constants.py +0 -0
  66. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/embeddings.py +0 -0
  67. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/persistence/__init__.py +0 -0
  68. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/pre_scan.py +0 -0
  69. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/resolution/__init__.py +0 -0
  70. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/resolution/inheritance.py +0 -0
  71. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/sanitize.py +0 -0
  72. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/schema.py +0 -0
  73. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/schema_contract.py +0 -0
  74. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/indexing/vector_resolver.py +0 -0
  75. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/c.py +0 -0
  76. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/cpp.py +0 -0
  77. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/csharp.py +0 -0
  78. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/css.py +0 -0
  79. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/dart.py +0 -0
  80. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/elisp.py +0 -0
  81. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/elixir.py +0 -0
  82. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/go.py +0 -0
  83. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/gradle.py +0 -0
  84. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/haskell.py +0 -0
  85. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/html.py +0 -0
  86. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/java.py +0 -0
  87. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/javascript.py +0 -0
  88. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/kotlin.py +0 -0
  89. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/lua.py +0 -0
  90. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/maven.py +0 -0
  91. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/mybatis.py +0 -0
  92. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/perl.py +0 -0
  93. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/php.py +0 -0
  94. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/ruby.py +0 -0
  95. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/rust.py +0 -0
  96. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/scala.py +0 -0
  97. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/swift.py +0 -0
  98. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/typescript.py +0 -0
  99. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/languages/typescriptjsx.py +0 -0
  100. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/package_resolver.py +0 -0
  101. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/query_tool_languages/c_toolkit.py +0 -0
  102. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/query_tool_languages/cpp_toolkit.py +0 -0
  103. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/query_tool_languages/csharp_toolkit.py +0 -0
  104. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/query_tool_languages/dart_toolkit.py +0 -0
  105. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/query_tool_languages/elisp_toolkit.py +0 -0
  106. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/query_tool_languages/go_toolkit.py +0 -0
  107. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/query_tool_languages/haskell_toolkit.py +0 -0
  108. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/query_tool_languages/java_toolkit.py +0 -0
  109. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/query_tool_languages/javascript_toolkit.py +0 -0
  110. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/query_tool_languages/perl_toolkit.py +0 -0
  111. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/query_tool_languages/python_toolkit.py +0 -0
  112. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/query_tool_languages/ruby_toolkit.py +0 -0
  113. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/query_tool_languages/rust_toolkit.py +0 -0
  114. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/query_tool_languages/scala_toolkit.py +0 -0
  115. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/query_tool_languages/swift_toolkit.py +0 -0
  116. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/query_tool_languages/typescript_toolkit.py +0 -0
  117. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/scip_indexer.py +0 -0
  118. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/scip_pb2.py +0 -0
  119. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/system.py +0 -0
  120. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/tree_sitter_parser.py +0 -0
  121. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/tools/type_utils.py +0 -0
  122. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/utils/cypher_readonly.py +0 -0
  123. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/utils/debug_log.py +0 -0
  124. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/utils/git_utils.py +0 -0
  125. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/utils/path_ignore.py +0 -0
  126. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/utils/repo_path.py +0 -0
  127. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/utils/tool_limits.py +0 -0
  128. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/utils/tree_sitter_manager.py +0 -0
  129. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/utils/visualize_graph.py +0 -0
  130. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/assets/__vite-browser-external-9wXp6ZBx.js +0 -0
  131. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/assets/function-calls-BtRHrqa2.png +0 -0
  132. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/assets/graph-total-D1fBAugo.png +0 -0
  133. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/assets/hero-graph-2voMJp2a.jpg +0 -0
  134. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/assets/hierarchy-DGADo0YT.png +0 -0
  135. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/assets/index-C-187lf0.js +0 -0
  136. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/assets/index-fNAa6jgv.css +0 -0
  137. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/assets/parser-pyodide.worker-BgsDfaad.js +0 -0
  138. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/assets/parser.worker-_nvrecvj.js +0 -0
  139. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/assets/tree-sitter-qKYAACSa.wasm +0 -0
  140. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/cgcIcon.png +0 -0
  141. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/favicon.ico +0 -0
  142. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/index.html +0 -0
  143. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/logo-icon.svg +0 -0
  144. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/logo.svg +0 -0
  145. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/placeholder.svg +0 -0
  146. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/preview-image.png +0 -0
  147. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/robots.txt +0 -0
  148. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-c.wasm +0 -0
  149. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-c_sharp.wasm +0 -0
  150. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-core.js +0 -0
  151. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-cpp.wasm +0 -0
  152. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-dart.wasm +0 -0
  153. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-go.wasm +0 -0
  154. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-java.wasm +0 -0
  155. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-javascript.wasm +0 -0
  156. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-kotlin.wasm +0 -0
  157. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-perl.wasm +0 -0
  158. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-php.wasm +0 -0
  159. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-python.wasm +0 -0
  160. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-ruby.wasm +0 -0
  161. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-rust.wasm +0 -0
  162. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-swift.wasm +0 -0
  163. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-tsx.wasm +0 -0
  164. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter-typescript.wasm +0 -0
  165. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/tree-sitter.wasm +0 -0
  166. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/web-tree-sitter.js +0 -0
  167. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/dist/wasm/web-tree-sitter.wasm +0 -0
  168. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext/viz/server.py +0 -0
  169. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext.egg-info/dependency_links.txt +0 -0
  170. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext.egg-info/entry_points.txt +0 -0
  171. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext.egg-info/requires.txt +0 -0
  172. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/src/codegraphcontext.egg-info/top_level.txt +0 -0
  173. {codegraphcontext-0.4.17 → codegraphcontext-0.4.18}/tests/test_issue_806_fix.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codegraphcontext
3
- Version: 0.4.17
3
+ Version: 0.4.18
4
4
  Summary: An MCP server that indexes local code into a graph database to provide context to AI assistants.
5
5
  Author-email: Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
6
6
  License: MIT License
@@ -96,7 +96,7 @@ Dynamic: license-file
96
96
  - 🇯🇵 [日本語](docs/translations/README.ja.md)
97
97
  - 🇪🇸 Español (Soon)
98
98
 
99
- 🌍 **Help translate CodeGraphContext to your language by raising an issue & PR on https://github.com/Shashankss1205/CodeGraphContext/issues!**
99
+ 🌍 **Help translate CodeGraphContext to your language by raising an issue & PR on [GitHub Issues](https://github.com/Shashankss1205/CodeGraphContext/issues)!**
100
100
 
101
101
  <p align="center">
102
102
  <br>
@@ -185,7 +185,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
185
185
  ---
186
186
 
187
187
  ## Project Details
188
- - **Version:** 0.4.17
188
+ - **Version:** 0.4.18
189
189
  - **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
190
190
  - **License:** MIT License (See [LICENSE](LICENSE) for details)
191
191
  - **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
@@ -214,7 +214,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
214
214
  - **Code Indexing:** Analyzes code and builds a knowledge graph of its components.
215
215
  - **Relationship Analysis:** Query for callers, callees, class hierarchies, call chains and more.
216
216
  - **Pre-indexed Bundles:** Load famous repositories instantly with `.cgc` bundles - no indexing required! ([Learn more](docs/BUNDLES.md))
217
- - **Live File Watching:** Watch directories for changes and automatically update the graph in real-time (`codegraphcontext watch`).
217
+ - **Live File Watching:** Watch directories for changes and automatically update the graph in real-time (`cgc watch`).
218
218
  - **Interactive Setup:** A user-friendly command-line wizard for easy setup.
219
219
  - **Dual Mode:** Works as a standalone **CLI toolkit** for developers and as an **MCP server** for AI agents.
220
220
  - **Multi-Language Support:** Full support for 22 programming languages.
@@ -248,7 +248,7 @@ CodeGraphContext supports multiple graph database backends to suit your environm
248
248
 
249
249
  | Feature | KuzuDB | LadybugDB | FalkorDB Lite | Neo4j / Nornic DB |
250
250
  | :--- | :--- | :--- | :--- | :--- |
251
- | **Typical default** | **Standard Default** (embedded, powered by KuzuDB) | **Specialized Embedded** (similar to Kuzu) | **Unix** (Python 3.12+, when `falkordblite` works) | When explicitly configured |
251
+ | **Typical default** | Cross-platform fallback when FalkorDB Lite is unavailable | Optional embedded backend | **Default on Unix** (Python 3.12+, when `falkordblite` is installed) | When explicitly configured via `cgc config db` |
252
252
  | **Setup** | Zero-config / Embedded | Zero-config / Embedded | Zero-config / In-process | Docker / External |
253
253
  | **Platform** | **All (Windows Native, macOS, Linux)** | **All (Windows Native, macOS, Linux)** | Unix-only (Linux/macOS/WSL) | All Platforms |
254
254
  | **Use Case** | Desktop, IDE, Local development | Custom research projects | Specialized Unix development | Enterprise, Massive graphs |
@@ -11,7 +11,7 @@
11
11
  - 🇯🇵 [日本語](docs/translations/README.ja.md)
12
12
  - 🇪🇸 Español (Soon)
13
13
 
14
- 🌍 **Help translate CodeGraphContext to your language by raising an issue & PR on https://github.com/Shashankss1205/CodeGraphContext/issues!**
14
+ 🌍 **Help translate CodeGraphContext to your language by raising an issue & PR on [GitHub Issues](https://github.com/Shashankss1205/CodeGraphContext/issues)!**
15
15
 
16
16
  <p align="center">
17
17
  <br>
@@ -100,7 +100,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
100
100
  ---
101
101
 
102
102
  ## Project Details
103
- - **Version:** 0.4.17
103
+ - **Version:** 0.4.18
104
104
  - **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
105
105
  - **License:** MIT License (See [LICENSE](LICENSE) for details)
106
106
  - **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
@@ -129,7 +129,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
129
129
  - **Code Indexing:** Analyzes code and builds a knowledge graph of its components.
130
130
  - **Relationship Analysis:** Query for callers, callees, class hierarchies, call chains and more.
131
131
  - **Pre-indexed Bundles:** Load famous repositories instantly with `.cgc` bundles - no indexing required! ([Learn more](docs/BUNDLES.md))
132
- - **Live File Watching:** Watch directories for changes and automatically update the graph in real-time (`codegraphcontext watch`).
132
+ - **Live File Watching:** Watch directories for changes and automatically update the graph in real-time (`cgc watch`).
133
133
  - **Interactive Setup:** A user-friendly command-line wizard for easy setup.
134
134
  - **Dual Mode:** Works as a standalone **CLI toolkit** for developers and as an **MCP server** for AI agents.
135
135
  - **Multi-Language Support:** Full support for 22 programming languages.
@@ -163,7 +163,7 @@ CodeGraphContext supports multiple graph database backends to suit your environm
163
163
 
164
164
  | Feature | KuzuDB | LadybugDB | FalkorDB Lite | Neo4j / Nornic DB |
165
165
  | :--- | :--- | :--- | :--- | :--- |
166
- | **Typical default** | **Standard Default** (embedded, powered by KuzuDB) | **Specialized Embedded** (similar to Kuzu) | **Unix** (Python 3.12+, when `falkordblite` works) | When explicitly configured |
166
+ | **Typical default** | Cross-platform fallback when FalkorDB Lite is unavailable | Optional embedded backend | **Default on Unix** (Python 3.12+, when `falkordblite` is installed) | When explicitly configured via `cgc config db` |
167
167
  | **Setup** | Zero-config / Embedded | Zero-config / Embedded | Zero-config / In-process | Docker / External |
168
168
  | **Platform** | **All (Windows Native, macOS, Linux)** | **All (Windows Native, macOS, Linux)** | Unix-only (Linux/macOS/WSL) | All Platforms |
169
169
  | **Use Case** | Desktop, IDE, Local development | Custom research projects | Specialized Unix development | Enterprise, Massive graphs |
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codegraphcontext"
3
- version = "0.4.17"
3
+ version = "0.4.18"
4
4
  description = "An MCP server that indexes local code into a graph database to provide context to AI assistants."
5
5
  authors = [{ name = "Shashank Shekhar Singh", email = "shashankshekharsingh1205@gmail.com" }]
6
6
  readme = "README.md"
@@ -24,6 +24,11 @@ def create_app() -> FastAPI:
24
24
 
25
25
  app.include_router(router, prefix="/api/v1")
26
26
 
27
+ @app.get("/health")
28
+ async def health():
29
+ """Liveness probe for load balancers and k8s."""
30
+ return {"status": "ok"}
31
+
27
32
  # MCP-over-SSE Endpoints
28
33
  app.add_api_route("/api/v1/mcp/sse", handle_sse, methods=["GET"])
29
34
  app.add_api_route("/api/v1/mcp/messages", handle_messages, methods=["POST"])
@@ -260,6 +260,10 @@ def index_helper(path: str, context: Optional[str] = None):
260
260
  """Synchronously indexes a repository in a given context."""
261
261
  time_start = time.time()
262
262
  path_obj = Path(path).resolve()
263
+ # Normalize to forward slashes for cross-platform DB consistency.
264
+ # The graph DB always stores paths via Path.resolve().as_posix(),
265
+ # so Cypher queries must also use forward slashes on Windows.
266
+ repo_path_str = path_obj.as_posix()
263
267
  index_cwd = path_obj if path_obj.is_dir() else path_obj.parent
264
268
  services = _initialize_services(context, cwd=index_cwd)
265
269
  if not all(services[:3]):
@@ -283,7 +287,7 @@ def index_helper(path: str, context: Optional[str] = None):
283
287
  with db_manager.get_driver().session() as session:
284
288
  result = session.run(
285
289
  "MATCH (r:Repository {path: $path})-[:CONTAINS*]->(f:File) RETURN count(DISTINCT f) as file_count",
286
- path=str(path_obj)
290
+ path=repo_path_str
287
291
  )
288
292
  record = result.single()
289
293
  file_count = record["file_count"] if record else 0
@@ -415,6 +419,49 @@ def delete_helper(repo_path: str, context: Optional[str] = None):
415
419
  finally:
416
420
  db_manager.close_driver()
417
421
 
422
+ def _print_query_exception(e: Exception, query: str) -> None:
423
+ """
424
+ Pretty-print a database query exception, surfacing the raw driver
425
+ error message so Cypher syntax problems are clearly visible.
426
+ """
427
+ import traceback
428
+
429
+ error_type = type(e).__name__
430
+ error_module = type(e).__module__ or ""
431
+
432
+ # Neo4j: CypherSyntaxError and other ClientError subclasses carry
433
+ # a .message and .code attribute with the full server-side detail.
434
+ if "neo4j" in error_module:
435
+ code = getattr(e, "code", None)
436
+ msg = getattr(e, "message", None) or str(e)
437
+ console.print(f"[bold red]Query Error ({error_type}):[/bold red]")
438
+ if code:
439
+ console.print(f" [yellow]Code:[/yellow] {code}")
440
+ console.print(f" [yellow]Message:[/yellow] {msg}")
441
+
442
+ # FalkorDB: ResponseError / exceptions in falkordb or redis packages
443
+ elif "falkordb" in error_module or "redis" in error_module:
444
+ console.print(f"[bold red]Query Error ({error_type}):[/bold red]")
445
+ console.print(f" [yellow]Database message:[/yellow] {e}")
446
+
447
+ # KuzuDB: RuntimeError from the kuzu extension
448
+ # KuzuDB: RuntimeError from the kuzu extension or database_kuzu wrapper
449
+ elif "kuzu" in error_module or (
450
+ error_type == "RuntimeError" and "Parser exception" in str(e)
451
+ ):
452
+ console.print(f"[bold red]Query Error ({error_type}):[/bold red]")
453
+ console.print(f" [yellow]Database message:[/yellow] {e}")
454
+
455
+ else:
456
+ # Fallback: unknown backend — print type + message + traceback
457
+ console.print(f"[bold red]An error occurred while executing query ({error_type}):[/bold red]")
458
+ console.print(f" [yellow]Message:[/yellow] {e}")
459
+ console.print("[dim]--- Traceback ---[/dim]")
460
+ console.print(f"[dim]{traceback.format_exc()}[/dim]")
461
+
462
+ console.print(f"\n[dim]Failed query:[/dim]")
463
+ console.print(f"[dim] {query}[/dim]")
464
+
418
465
 
419
466
  def cypher_helper(query: str, context: Optional[str] = None):
420
467
  """Executes a read-only Cypher query."""
@@ -440,7 +487,7 @@ def cypher_helper(query: str, context: Optional[str] = None):
440
487
  records = [record.data() for record in result]
441
488
  console.print(json.dumps(records, indent=2))
442
489
  except Exception as e:
443
- console.print(f"[bold red]An error occurred while executing query:[/bold red] {e}")
490
+ _print_query_exception(e, query)
444
491
  db_manager.close_driver()
445
492
  raise typer.Exit(code=1)
446
493
  finally:
@@ -466,7 +513,7 @@ def cypher_helper_visual(query: str, context: Optional[str] = None):
466
513
  try:
467
514
  visualize_cypher_results(query)
468
515
  except Exception as e:
469
- console.print(f"[bold red]An error occurred while executing query:[/bold red] {e}")
516
+ _print_query_exception(e, query)
470
517
  db_manager.close_driver()
471
518
  raise typer.Exit(code=1)
472
519
  finally:
@@ -844,10 +891,11 @@ def watch_helper(path: str, context: Optional[str] = None, use_polling: Optional
844
891
 
845
892
  # Add the directory to watch
846
893
  if is_indexed:
847
- console.print("[green]✓[/green] Already indexed (no initial scan needed)")
894
+ console.print("[green]✓[/green] Already indexed. Synchronizing current files...")
848
895
  watcher.watch_directory(
849
896
  str(path_obj),
850
897
  perform_initial_scan=False,
898
+ sync_on_start=True,
851
899
  cgcignore_path=ctx.cgcignore_path,
852
900
  )
853
901
  else:
@@ -160,6 +160,14 @@ CONFIG_VALIDATORS = {
160
160
  "CGC_EMBEDDING_MODEL": ["local", "openai"],
161
161
  "FUZZY_SEARCH": ["true", "false"],
162
162
  }
163
+
164
+ SUPPORTED_DATABASES: List[str] = CONFIG_VALIDATORS["DEFAULT_DATABASE"]
165
+ DATABASE_CLI_HELP = (
166
+ "Database backend ("
167
+ + "|".join(SUPPORTED_DATABASES)
168
+ + "). Defaults to DEFAULT_DATABASE from config."
169
+ )
170
+
163
171
  DEFAULT_CGCIGNORE_PATTERNS = """\
164
172
  # Default .cgcignore patterns
165
173
  # Lines starting with # are comments; blank lines are ignored.
@@ -279,18 +287,25 @@ def load_config() -> Dict[str, str]:
279
287
  def should_apply_project_dotenv() -> bool:
280
288
  """True when cwd-local ``.codegraphcontext/.env`` should merge with global config.
281
289
 
282
- Skips project env when ``HOME`` is isolated (e.g. E2E) but ``cwd`` is an unrelated
283
- checkout, unless ``CGC_LOAD_PROJECT_ENV=1``. Set ``CGC_IGNORE_PROJECT_ENV=1`` to force skip.
290
+ Project env is loaded only in **per-repo** context mode (or when
291
+ ``CGC_LOAD_PROJECT_ENV=1``). In **global** / **named** mode, ``~/.codegraphcontext/.env``
292
+ wins so clones with a checked-in ``.codegraphcontext/.env`` do not hijack config.
293
+
294
+ Set ``CGC_IGNORE_PROJECT_ENV=1`` to force skip; ``CGC_LOAD_PROJECT_ENV=1`` to force load.
284
295
  """
285
296
  if os.getenv("CGC_IGNORE_PROJECT_ENV", "").strip().lower() in ("1", "true", "yes"):
286
297
  return False
287
298
  if os.getenv("CGC_LOAD_PROJECT_ENV", "").strip().lower() in ("1", "true", "yes"):
288
299
  return True
300
+ cfg = load_context_config()
301
+ if cfg.mode != "per-repo":
302
+ return False
289
303
  try:
290
304
  Path.cwd().resolve().relative_to(Path.home().resolve())
291
305
  return True
292
306
  except ValueError:
293
- return False
307
+ # Per-repo indexing from /tmp with an isolated HOME (common in E2E/CI).
308
+ return True
294
309
 
295
310
 
296
311
  def find_local_env() -> Optional[Path]:
@@ -869,23 +884,33 @@ def resolve_context(
869
884
  local_cgc = cwd / ".codegraphcontext"
870
885
  local_cgc.mkdir(parents=True, exist_ok=True)
871
886
  (local_cgc / "db").mkdir(exist_ok=True)
872
-
887
+
888
+ inherited_db = load_config().get("DEFAULT_DATABASE", "falkordb")
889
+
873
890
  # Copy global .env into local context for easy per-repo tweaking
874
891
  import shutil
875
892
  if CONFIG_FILE.exists():
876
893
  shutil.copy2(CONFIG_FILE, local_cgc / ".env")
877
-
878
- console.print(f"[dim]Auto-initialized per-repo context at {local_cgc}[/dim]")
894
+
895
+ local_yaml = local_cgc / "config.yaml"
896
+ if not local_yaml.exists():
897
+ with open(local_yaml, "w", encoding="utf-8") as f:
898
+ yaml.safe_dump({"database": inherited_db}, f)
899
+
900
+ console.print(
901
+ f"[dim]Auto-initialized per-repo context at {local_cgc} "
902
+ f"(Database: {inherited_db})[/dim]"
903
+ )
879
904
 
880
905
  if local_cgc is not None:
881
906
  # Read local config.yaml if present
882
907
  local_yaml = local_cgc / "config.yaml"
883
- local_db = "falkordb"
908
+ local_db = load_config().get("DEFAULT_DATABASE", "falkordb")
884
909
  if local_yaml.exists():
885
910
  try:
886
911
  with open(local_yaml, encoding="utf-8") as f:
887
912
  local_raw = yaml.safe_load(f) or {}
888
- local_db = local_raw.get("database", "falkordb")
913
+ local_db = local_raw.get("database", local_db)
889
914
  except Exception:
890
915
  pass
891
916
  db_path = str(local_cgc / "db" / local_db)
@@ -0,0 +1,220 @@
1
+ """Git hook management for keeping CGC indexes in sync."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from pathlib import Path
7
+ import stat
8
+ import subprocess
9
+
10
+
11
+ MANAGED_MARKER = "# CGC_MANAGED_HOOK"
12
+ HOOK_NAMES = ("post-commit", "post-checkout")
13
+ GITATTRIBUTES_ENTRY = "*.cgc merge=cgc-bundle"
14
+
15
+
16
+ class HookError(RuntimeError):
17
+ """Raised when hook installation cannot proceed safely."""
18
+
19
+
20
+ @dataclass(frozen=True)
21
+ class GitRepository:
22
+ root: Path
23
+ git_dir: Path
24
+
25
+
26
+ @dataclass(frozen=True)
27
+ class HookStatus:
28
+ repo_root: Path
29
+ git_dir: Path
30
+ installed_hooks: tuple[str, ...]
31
+ unmanaged_hooks: tuple[str, ...]
32
+ has_merge_driver: bool
33
+ has_gitattributes_entry: bool
34
+
35
+ @property
36
+ def installed(self) -> bool:
37
+ return (
38
+ bool(self.installed_hooks)
39
+ and self.has_merge_driver
40
+ and self.has_gitattributes_entry
41
+ )
42
+
43
+
44
+ def find_git_repository(start: Path | str | None = None) -> GitRepository:
45
+ """Find the nearest Git repository root and git directory."""
46
+ current = Path(start or Path.cwd()).resolve()
47
+ if current.is_file():
48
+ current = current.parent
49
+
50
+ for candidate in (current, *current.parents):
51
+ git_path = candidate / ".git"
52
+ if git_path.is_dir():
53
+ return GitRepository(root=candidate, git_dir=git_path)
54
+ if git_path.is_file():
55
+ target = _read_worktree_gitdir(git_path)
56
+ return GitRepository(root=candidate, git_dir=target)
57
+
58
+ raise HookError("No Git repository found from the current directory.")
59
+
60
+
61
+ def install_hooks(start: Path | str | None = None, *, force: bool = False) -> HookStatus:
62
+ repo = find_git_repository(start)
63
+ hooks_dir = repo.git_dir / "hooks"
64
+ hooks_dir.mkdir(parents=True, exist_ok=True)
65
+
66
+ script = _hook_script(repo.root)
67
+ for hook_name in HOOK_NAMES:
68
+ hook_path = hooks_dir / hook_name
69
+ if hook_path.exists() and not _is_managed_hook(hook_path) and not force:
70
+ raise HookError(
71
+ f"{hook_name} already exists and is not managed by CGC. "
72
+ "Re-run with --force to replace it."
73
+ )
74
+ hook_path.write_text(script, encoding="utf-8")
75
+ mode = hook_path.stat().st_mode
76
+ hook_path.chmod(mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
77
+
78
+ _ensure_gitattributes(repo.root)
79
+ _configure_merge_driver(repo.root)
80
+ return get_hook_status(repo.root)
81
+
82
+
83
+ def uninstall_hooks(start: Path | str | None = None) -> HookStatus:
84
+ repo = find_git_repository(start)
85
+ hooks_dir = repo.git_dir / "hooks"
86
+
87
+ for hook_name in HOOK_NAMES:
88
+ hook_path = hooks_dir / hook_name
89
+ if hook_path.exists() and _is_managed_hook(hook_path):
90
+ hook_path.unlink()
91
+
92
+ _remove_gitattributes_entry(repo.root)
93
+ _unset_git_config(repo.root, "merge.cgc-bundle.name")
94
+ _unset_git_config(repo.root, "merge.cgc-bundle.driver")
95
+ return get_hook_status(repo.root)
96
+
97
+
98
+ def get_hook_status(start: Path | str | None = None) -> HookStatus:
99
+ repo = find_git_repository(start)
100
+ hooks_dir = repo.git_dir / "hooks"
101
+ installed_hooks: list[str] = []
102
+ unmanaged_hooks: list[str] = []
103
+
104
+ for hook_name in HOOK_NAMES:
105
+ hook_path = hooks_dir / hook_name
106
+ if not hook_path.exists():
107
+ continue
108
+ if _is_managed_hook(hook_path):
109
+ installed_hooks.append(hook_name)
110
+ else:
111
+ unmanaged_hooks.append(hook_name)
112
+
113
+ return HookStatus(
114
+ repo_root=repo.root,
115
+ git_dir=repo.git_dir,
116
+ installed_hooks=tuple(installed_hooks),
117
+ unmanaged_hooks=tuple(unmanaged_hooks),
118
+ has_merge_driver=_has_git_config(repo.root, "merge.cgc-bundle.driver"),
119
+ has_gitattributes_entry=_has_gitattributes_entry(repo.root),
120
+ )
121
+
122
+
123
+ def _read_worktree_gitdir(git_file: Path) -> Path:
124
+ content = git_file.read_text(encoding="utf-8").strip()
125
+ prefix = "gitdir:"
126
+ if not content.lower().startswith(prefix):
127
+ raise HookError(f"Unsupported .git file format at {git_file}")
128
+
129
+ raw_path = content[len(prefix):].strip()
130
+ git_dir = Path(raw_path)
131
+ if not git_dir.is_absolute():
132
+ git_dir = (git_file.parent / git_dir).resolve()
133
+ return git_dir
134
+
135
+
136
+ def _hook_script(repo_root: Path) -> str:
137
+ repo_root_value = _sh_quote(str(repo_root))
138
+ return (
139
+ "#!/bin/sh\n"
140
+ f"{MANAGED_MARKER}: CodeGraphContext auto-update hook\n"
141
+ f"CGC_REPO_ROOT={repo_root_value}\n"
142
+ "if command -v cgc >/dev/null 2>&1; then\n"
143
+ ' cgc update "$CGC_REPO_ROOT" --quiet\n'
144
+ "else\n"
145
+ ' python -m codegraphcontext update "$CGC_REPO_ROOT" --quiet\n'
146
+ "fi\n"
147
+ )
148
+
149
+
150
+ def _sh_quote(value: str) -> str:
151
+ return "'" + value.replace("'", "'\"'\"'") + "'"
152
+
153
+
154
+ def _is_managed_hook(path: Path) -> bool:
155
+ try:
156
+ return MANAGED_MARKER in path.read_text(encoding="utf-8", errors="ignore")
157
+ except OSError:
158
+ return False
159
+
160
+
161
+ def _ensure_gitattributes(repo_root: Path) -> None:
162
+ path = repo_root / ".gitattributes"
163
+ existing = path.read_text(encoding="utf-8") if path.exists() else ""
164
+ lines = existing.splitlines()
165
+ if any(line.strip() == GITATTRIBUTES_ENTRY for line in lines):
166
+ return
167
+
168
+ prefix = existing
169
+ if prefix and not prefix.endswith("\n"):
170
+ prefix += "\n"
171
+ path.write_text(f"{prefix}{GITATTRIBUTES_ENTRY}\n", encoding="utf-8")
172
+
173
+
174
+ def _remove_gitattributes_entry(repo_root: Path) -> None:
175
+ path = repo_root / ".gitattributes"
176
+ if not path.exists():
177
+ return
178
+
179
+ lines = [
180
+ line
181
+ for line in path.read_text(encoding="utf-8").splitlines()
182
+ if line.strip() != GITATTRIBUTES_ENTRY
183
+ ]
184
+ if lines:
185
+ path.write_text("\n".join(lines) + "\n", encoding="utf-8")
186
+ else:
187
+ path.unlink()
188
+
189
+
190
+ def _has_gitattributes_entry(repo_root: Path) -> bool:
191
+ path = repo_root / ".gitattributes"
192
+ if not path.exists():
193
+ return False
194
+ return any(
195
+ line.strip() == GITATTRIBUTES_ENTRY
196
+ for line in path.read_text(encoding="utf-8").splitlines()
197
+ )
198
+
199
+
200
+ def _configure_merge_driver(repo_root: Path) -> None:
201
+ _git_config(repo_root, "merge.cgc-bundle.name", "CodeGraphContext bundle merge driver")
202
+ _git_config(repo_root, "merge.cgc-bundle.driver", "cgc bundle merge %O %A %B")
203
+
204
+
205
+ def _git_config(repo_root: Path, key: str, value: str) -> None:
206
+ subprocess.run(["git", "-C", str(repo_root), "config", key, value], check=True)
207
+
208
+
209
+ def _unset_git_config(repo_root: Path, key: str) -> None:
210
+ subprocess.run(["git", "-C", str(repo_root), "config", "--unset-all", key], check=False)
211
+
212
+
213
+ def _has_git_config(repo_root: Path, key: str) -> bool:
214
+ result = subprocess.run(
215
+ ["git", "-C", str(repo_root), "config", "--get", key],
216
+ check=False,
217
+ stdout=subprocess.DEVNULL,
218
+ stderr=subprocess.DEVNULL,
219
+ )
220
+ return result.returncode == 0