codegraphcontext 0.5.2__tar.gz → 0.5.3__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 (146) hide show
  1. {codegraphcontext-0.5.2/src/codegraphcontext.egg-info → codegraphcontext-0.5.3}/PKG-INFO +25 -5
  2. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/README.md +20 -0
  3. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/pyproject.toml +20 -5
  4. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/api/app.py +6 -1
  5. codegraphcontext-0.5.3/src/codegraphcontext/api/auth.py +123 -0
  6. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/api/router.py +9 -5
  7. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/cli/cli_helpers.py +179 -20
  8. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/cli/config_manager.py +56 -14
  9. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/cli/hook_manager.py +26 -4
  10. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/cli/main.py +208 -16
  11. codegraphcontext-0.5.3/src/codegraphcontext/cli/project_config.py +218 -0
  12. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/cli/registry_commands.py +6 -6
  13. codegraphcontext-0.5.3/src/codegraphcontext/cli/simulator.py +343 -0
  14. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/core/bundle_registry.py +45 -6
  15. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/core/cgc_bundle.py +102 -31
  16. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/core/cgcignore.py +29 -11
  17. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/core/database.py +5 -1
  18. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/core/database_embedded_kuzu.py +37 -2
  19. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/core/database_falkordb.py +141 -30
  20. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/core/database_falkordb_remote.py +31 -11
  21. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/core/database_nornic.py +5 -1
  22. codegraphcontext-0.5.3/src/codegraphcontext/core/simulator.py +589 -0
  23. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/core/watcher.py +67 -11
  24. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/prompts.py +52 -2
  25. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/server.py +77 -4
  26. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tool_definitions.py +171 -20
  27. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/code_finder.py +39 -26
  28. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/graph_builder.py +39 -10
  29. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/handlers/analysis_handlers.py +28 -9
  30. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/handlers/management_handlers.py +33 -7
  31. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/handlers/query_handlers.py +10 -4
  32. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/discovery.py +6 -2
  33. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/embeddings.py +8 -0
  34. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/persistence/writer.py +104 -137
  35. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/pipeline.py +65 -17
  36. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/pre_scan.py +14 -2
  37. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/resolution/post_resolution.py +11 -20
  38. codegraphcontext-0.5.3/src/codegraphcontext/tools/indexing/schema.py +156 -0
  39. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/schema_contract.py +1 -0
  40. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/c.py +1 -1
  41. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/cpp.py +1 -1
  42. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/css.py +1 -1
  43. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/dart.py +1 -1
  44. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/elisp.py +1 -1
  45. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/elixir.py +3 -3
  46. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/go.py +3 -3
  47. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/html.py +1 -1
  48. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/javascript.py +32 -27
  49. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/lua.py +1 -1
  50. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/perl.py +1 -1
  51. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/python.py +78 -44
  52. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/ruby.py +2 -2
  53. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/rust.py +1 -1
  54. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/typescript.py +31 -27
  55. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/typescriptjsx.py +3 -3
  56. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/query_tool_languages/cpp_toolkit.py +22 -18
  57. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/query_tool_languages/java_toolkit.py +1 -1
  58. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/report_generator.py +7 -7
  59. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/system.py +13 -16
  60. codegraphcontext-0.5.3/src/codegraphcontext/utils/cypher_ddl.py +80 -0
  61. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/utils/cypher_readonly.py +5 -0
  62. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/viz/server.py +20 -3
  63. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3/src/codegraphcontext.egg-info}/PKG-INFO +25 -5
  64. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext.egg-info/SOURCES.txt +5 -0
  65. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext.egg-info/requires.txt +4 -2
  66. codegraphcontext-0.5.2/src/codegraphcontext/tools/indexing/schema.py +0 -114
  67. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/LICENSE +0 -0
  68. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/MANIFEST.in +0 -0
  69. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/setup.cfg +0 -0
  70. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/__init__.py +0 -0
  71. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/__main__.py +0 -0
  72. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/api/__init__.py +0 -0
  73. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/api/mcp_sse.py +0 -0
  74. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/api/schemas.py +0 -0
  75. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/cli/__init__.py +0 -0
  76. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/cli/setup_macos.py +0 -0
  77. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/cli/setup_wizard.py +0 -0
  78. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/cli/visualizer.py +0 -0
  79. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/core/__init__.py +0 -0
  80. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/core/database_kuzu.py +0 -0
  81. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/core/database_ladybug.py +0 -0
  82. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/core/falkor_worker.py +0 -0
  83. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/core/graph_query.py +0 -0
  84. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/core/jobs.py +0 -0
  85. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/stdlibs.py +0 -0
  86. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/__init__.py +0 -0
  87. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/advanced_language_query_tool.py +0 -0
  88. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/datasources/__init__.py +0 -0
  89. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/datasources/cassandra_ingester.py +0 -0
  90. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/datasources/mysql_ingester.py +0 -0
  91. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/datasources/redis_ingester.py +0 -0
  92. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/handlers/indexing_handlers.py +0 -0
  93. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/handlers/watcher_handlers.py +0 -0
  94. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/__init__.py +0 -0
  95. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/constants.py +0 -0
  96. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/persistence/__init__.py +0 -0
  97. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/persistence/utils.py +0 -0
  98. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/resolution/__init__.py +0 -0
  99. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/resolution/calls.py +0 -0
  100. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/resolution/inheritance.py +0 -0
  101. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/sanitize.py +0 -0
  102. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/scip_pipeline.py +0 -0
  103. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/indexing/vector_resolver.py +0 -0
  104. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/csharp.py +0 -0
  105. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/gradle.py +0 -0
  106. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/haskell.py +0 -0
  107. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/java.py +0 -0
  108. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/kotlin.py +0 -0
  109. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/maven.py +0 -0
  110. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/mybatis.py +0 -0
  111. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/php.py +0 -0
  112. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/scala.py +0 -0
  113. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/languages/swift.py +0 -0
  114. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/package_resolver.py +0 -0
  115. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/query_tool_languages/c_toolkit.py +0 -0
  116. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/query_tool_languages/csharp_toolkit.py +0 -0
  117. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/query_tool_languages/dart_toolkit.py +0 -0
  118. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/query_tool_languages/elisp_toolkit.py +0 -0
  119. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/query_tool_languages/go_toolkit.py +0 -0
  120. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/query_tool_languages/haskell_toolkit.py +0 -0
  121. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/query_tool_languages/javascript_toolkit.py +0 -0
  122. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/query_tool_languages/perl_toolkit.py +0 -0
  123. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/query_tool_languages/python_toolkit.py +0 -0
  124. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/query_tool_languages/ruby_toolkit.py +0 -0
  125. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/query_tool_languages/rust_toolkit.py +0 -0
  126. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/query_tool_languages/scala_toolkit.py +0 -0
  127. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/query_tool_languages/swift_toolkit.py +0 -0
  128. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/query_tool_languages/typescript_toolkit.py +0 -0
  129. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/scip_indexer.py +0 -0
  130. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/scip_pb2.py +0 -0
  131. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/tree_sitter_parser.py +0 -0
  132. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/tools/type_utils.py +0 -0
  133. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/utils/debug_log.py +0 -0
  134. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/utils/gcf_encoder.py +0 -0
  135. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/utils/git_utils.py +0 -0
  136. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/utils/path_ignore.py +0 -0
  137. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/utils/path_sandbox.py +0 -0
  138. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/utils/repo_path.py +0 -0
  139. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/utils/tool_limits.py +0 -0
  140. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/utils/tree_sitter_manager.py +0 -0
  141. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext/utils/visualize_graph.py +0 -0
  142. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext.egg-info/dependency_links.txt +0 -0
  143. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext.egg-info/entry_points.txt +0 -0
  144. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/src/codegraphcontext.egg-info/top_level.txt +0 -0
  145. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/tests/test_issue_806_fix.py +0 -0
  146. {codegraphcontext-0.5.2 → codegraphcontext-0.5.3}/tests/test_mcp_sse.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codegraphcontext
3
- Version: 0.5.2
3
+ Version: 0.5.3
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
@@ -25,8 +25,8 @@ License: MIT License
25
25
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
26
  SOFTWARE.
27
27
 
28
- Project-URL: Homepage, https://github.com/Shashankss1205/CodeGraphContext
29
- Project-URL: Bug Tracker, https://github.com/Shashankss1205/CodeGraphContext/issues
28
+ Project-URL: Homepage, https://github.com/CodeGraphContext/CodeGraphContext
29
+ Project-URL: Bug Tracker, https://github.com/CodeGraphContext/CodeGraphContext/issues
30
30
  Classifier: Programming Language :: Python :: 3
31
31
  Classifier: Programming Language :: Python :: 3.10
32
32
  Classifier: Programming Language :: Python :: 3.11
@@ -60,7 +60,7 @@ Requires-Dist: falkordb<1.6,>=1.0
60
60
  Requires-Dist: falkordblite<0.10,>=0.7; sys_platform != "win32" and python_version >= "3.12"
61
61
  Requires-Dist: requests>=2.28.0
62
62
  Requires-Dist: protobuf<3.21,>=3.20
63
- Requires-Dist: kuzu; sys_platform == "win32" or (sys_platform != "win32" and python_version >= "3.10")
63
+ Requires-Dist: kuzu; python_version < "3.14" or sys_platform == "linux"
64
64
  Requires-Dist: ladybug; sys_platform == "win32" or (sys_platform != "win32" and python_version >= "3.10")
65
65
  Requires-Dist: mcp>=1.0.0
66
66
  Requires-Dist: fastapi>=0.100.0
@@ -77,7 +77,7 @@ Provides-Extra: falkordb-remote
77
77
  Requires-Dist: falkordb<1.6,>=1.0; extra == "falkordb-remote"
78
78
  Requires-Dist: redis<6,>=5; extra == "falkordb-remote"
79
79
  Provides-Extra: kuzu
80
- Requires-Dist: kuzu; (sys_platform == "win32" or (sys_platform != "win32" and python_version >= "3.10")) and extra == "kuzu"
80
+ Requires-Dist: kuzu; (python_version < "3.14" or sys_platform == "linux") and extra == "kuzu"
81
81
  Provides-Extra: ladybug
82
82
  Requires-Dist: ladybug; (sys_platform == "win32" or (sys_platform != "win32" and python_version >= "3.10")) and extra == "ladybug"
83
83
  Provides-Extra: neo4j
@@ -272,6 +272,26 @@ flowchart LR
272
272
 
273
273
 
274
274
  ---
275
+ ## Architecture Overview
276
+
277
+ CodeGraphContext transforms source code into a queryable knowledge graph that can be explored through the CLI or AI assistants via MCP.
278
+
279
+ ```mermaid
280
+ flowchart TD
281
+ A[Code Repository] --> B[Tree-sitter / SCIP Indexing]
282
+ B --> C[Knowledge Graph]
283
+ C --> D[Graph Database]
284
+ D --> E[CLI Toolkit]
285
+ D --> F[MCP Server]
286
+ F --> G[AI Assistant]
287
+ ```
288
+
289
+ ### Workflow
290
+
291
+ 1. Source code is parsed using Tree-sitter or SCIP indexers.
292
+ 2. Relationships between functions, classes, imports, and calls are extracted.
293
+ 3. A knowledge graph is generated and stored in a graph database.
294
+ 4. Users can query the graph through the CLI or AI assistants using MCP.
275
295
 
276
296
  ## 🏗️ Architecture & Workflow
277
297
 
@@ -174,6 +174,26 @@ flowchart LR
174
174
 
175
175
 
176
176
  ---
177
+ ## Architecture Overview
178
+
179
+ CodeGraphContext transforms source code into a queryable knowledge graph that can be explored through the CLI or AI assistants via MCP.
180
+
181
+ ```mermaid
182
+ flowchart TD
183
+ A[Code Repository] --> B[Tree-sitter / SCIP Indexing]
184
+ B --> C[Knowledge Graph]
185
+ C --> D[Graph Database]
186
+ D --> E[CLI Toolkit]
187
+ D --> F[MCP Server]
188
+ F --> G[AI Assistant]
189
+ ```
190
+
191
+ ### Workflow
192
+
193
+ 1. Source code is parsed using Tree-sitter or SCIP indexers.
194
+ 2. Relationships between functions, classes, imports, and calls are extracted.
195
+ 3. A knowledge graph is generated and stored in a graph database.
196
+ 4. Users can query the graph through the CLI or AI assistants using MCP.
177
197
 
178
198
  ## 🏗️ Architecture & Workflow
179
199
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codegraphcontext"
3
- version = "0.5.2"
3
+ version = "0.5.3"
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"
@@ -58,7 +58,20 @@ dependencies = [
58
58
  "falkordblite>=0.7,<0.10; sys_platform != 'win32' and python_version >= '3.12'",
59
59
  "requests>=2.28.0",
60
60
  "protobuf>=3.20,<3.21",
61
- "kuzu; sys_platform == 'win32' or (sys_platform != 'win32' and python_version >= '3.10')",
61
+ # ------------------------------------------------------------------
62
+ # KùzuDB was archived upstream on 2025-10-10; 0.11.3 is the final
63
+ # release and its wheel matrix stops at cp313 for macOS and Windows.
64
+ # Only Linux (manylinux x86_64 / aarch64) got cp314 wheels. Without a
65
+ # marker, `pip install codegraphcontext` on macOS/Windows + Python 3.14
66
+ # falls back to the kuzu sdist and tries a full C++/CMake source build,
67
+ # which fails and takes the whole install down with it.
68
+ #
69
+ # Keep kuzu where a wheel actually exists; elsewhere the backend is
70
+ # simply absent and `database_kuzu` reports its install hint at runtime.
71
+ # LadybugDB (the maintained Kùzu fork, see issue #852) publishes cp314
72
+ # wheels for all three platforms and remains the unconditional default.
73
+ # ------------------------------------------------------------------
74
+ "kuzu; python_version < '3.14' or sys_platform == 'linux'",
62
75
  "ladybug; sys_platform == 'win32' or (sys_platform != 'win32' and python_version >= '3.10')",
63
76
  "mcp>=1.0.0",
64
77
  "fastapi>=0.100.0",
@@ -85,7 +98,9 @@ falkordb-remote = [
85
98
  "redis>=5,<6",
86
99
  ]
87
100
  kuzu = [
88
- "kuzu; sys_platform == 'win32' or (sys_platform != 'win32' and python_version >= '3.10')",
101
+ # Same wheel-availability marker as the core dependency above: no
102
+ # cp314 wheels exist for macOS/Windows and the sdist cannot be built.
103
+ "kuzu; python_version < '3.14' or sys_platform == 'linux'",
89
104
  ]
90
105
  ladybug = [
91
106
  "ladybug; sys_platform == 'win32' or (sys_platform != 'win32' and python_version >= '3.10')",
@@ -112,8 +127,8 @@ datasources = [
112
127
  ]
113
128
 
114
129
  [project.urls]
115
- "Homepage" = "https://github.com/Shashankss1205/CodeGraphContext"
116
- "Bug Tracker" = "https://github.com/Shashankss1205/CodeGraphContext/issues"
130
+ "Homepage" = "https://github.com/CodeGraphContext/CodeGraphContext"
131
+ "Bug Tracker" = "https://github.com/CodeGraphContext/CodeGraphContext/issues"
117
132
 
118
133
  [project.scripts]
119
134
  cgc = "codegraphcontext.cli.main:app"
@@ -4,9 +4,14 @@ from fastapi import FastAPI
4
4
  from fastapi.responses import HTMLResponse
5
5
  from fastapi.middleware.cors import CORSMiddleware
6
6
  from .router import router
7
+ from .auth import log_auth_status
7
8
  from .mcp_sse import handle_sse, handle_messages
8
9
 
9
10
  def create_app() -> FastAPI:
11
+ # Log whether API-key auth is active. Emits a prominent security warning
12
+ # when the gateway is running unauthenticated (CGC_API_KEY unset).
13
+ log_auth_status()
14
+
10
15
  app = FastAPI(
11
16
  title="CodeGraphContext Gateway",
12
17
  description="HTTP API gateway for CodeGraphContext MCP server. Enables integration with ChatGPT Actions, Claude, and web frontends.",
@@ -61,7 +66,7 @@ def create_app() -> FastAPI:
61
66
  <a href="/docs" class="btn">View API Docs</a>
62
67
  <div class="links">
63
68
  <a href="/openapi.json">OpenAPI Spec</a>
64
- <a href="https://github.com/Shashankss1205/CodeGraphContext" target="_blank">GitHub</a>
69
+ <a href="https://github.com/CodeGraphContext/CodeGraphContext" target="_blank">GitHub</a>
65
70
  </div>
66
71
  </div>
67
72
  </body>
@@ -0,0 +1,123 @@
1
+ # src/codegraphcontext/api/auth.py
2
+ """Optional API-key authentication for the CodeGraphContext HTTP API.
3
+
4
+ Backward-compatible and opt-in:
5
+
6
+ * When **no** key is configured, the API behaves exactly as it did before
7
+ (every endpoint is unauthenticated) but a prominent security warning is
8
+ logged at startup so operators know the gateway is wide open.
9
+ * When a key **is** configured (via the ``CGC_API_KEY`` environment variable
10
+ or the standard config mechanism), every protected router endpoint requires
11
+ it, supplied as either ``Authorization: Bearer <key>`` or ``X-API-Key: <key>``.
12
+ Missing/incorrect keys receive an HTTP ``401``.
13
+
14
+ The comparison uses :func:`secrets.compare_digest` to avoid timing side
15
+ channels.
16
+ """
17
+
18
+ import logging
19
+ import os
20
+ import secrets
21
+ from typing import Optional
22
+
23
+ from fastapi import Header, HTTPException
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+ # Config/env key that holds the API key. Reused as the config_manager key so
28
+ # ``cgc config set CGC_API_KEY <value>`` works as well.
29
+ API_KEY_ENV = "CGC_API_KEY"
30
+
31
+
32
+ def get_configured_api_key() -> Optional[str]:
33
+ """Return the configured API key, or ``None`` when auth is disabled.
34
+
35
+ Resolution order (highest priority first):
36
+
37
+ 1. The ``CGC_API_KEY`` environment variable (read directly so auth works
38
+ even when no config file is present).
39
+ 2. The value stored via the existing config mechanism
40
+ (:func:`codegraphcontext.cli.config_manager.get_config_value`).
41
+
42
+ Empty / whitespace-only values are treated as "not configured".
43
+ """
44
+ env_val = os.getenv(API_KEY_ENV)
45
+ if env_val and env_val.strip():
46
+ return env_val.strip()
47
+
48
+ # Fall back to the existing config mechanism (global/local .env, defaults).
49
+ try:
50
+ from codegraphcontext.cli.config_manager import get_config_value
51
+
52
+ cfg_val = get_config_value(API_KEY_ENV)
53
+ if cfg_val and cfg_val.strip():
54
+ return cfg_val.strip()
55
+ except Exception: # pragma: no cover - config lookup is best-effort here
56
+ pass
57
+
58
+ return None
59
+
60
+
61
+ def _extract_provided_key(
62
+ authorization: Optional[str], x_api_key: Optional[str]
63
+ ) -> Optional[str]:
64
+ """Pull the caller-supplied key from the Authorization or X-API-Key header."""
65
+ if authorization:
66
+ value = authorization.strip()
67
+ if value.lower().startswith("bearer "):
68
+ return value[len("bearer ") :].strip()
69
+ # Accept a bare token in the Authorization header as a convenience.
70
+ return value or None
71
+ if x_api_key and x_api_key.strip():
72
+ return x_api_key.strip()
73
+ return None
74
+
75
+
76
+ def _keys_match(provided: str, configured: str) -> bool:
77
+ """Constant-time comparison that never raises on non-ASCII input."""
78
+ try:
79
+ return secrets.compare_digest(
80
+ provided.encode("utf-8"), configured.encode("utf-8")
81
+ )
82
+ except (TypeError, AttributeError):
83
+ return False
84
+
85
+
86
+ async def require_api_key(
87
+ authorization: Optional[str] = Header(default=None),
88
+ x_api_key: Optional[str] = Header(default=None, alias="X-API-Key"),
89
+ ) -> None:
90
+ """FastAPI dependency that enforces the API key when one is configured.
91
+
92
+ No-op (backward compatible) when no key is set; otherwise requires a valid
93
+ key via ``Authorization: Bearer <key>`` or ``X-API-Key: <key>``, returning
94
+ HTTP ``401`` on a missing or incorrect key.
95
+ """
96
+ configured = get_configured_api_key()
97
+ if not configured:
98
+ # Auth disabled -> preserve the pre-existing unauthenticated behavior.
99
+ return
100
+
101
+ provided = _extract_provided_key(authorization, x_api_key)
102
+ if not provided or not _keys_match(provided, configured):
103
+ raise HTTPException(
104
+ status_code=401,
105
+ detail="Invalid or missing API key",
106
+ headers={"WWW-Authenticate": "Bearer"},
107
+ )
108
+
109
+
110
+ def log_auth_status() -> None:
111
+ """Log the authentication status at app startup.
112
+
113
+ Emits a prominent WARNING when the API is unauthenticated so the insecure
114
+ default is impossible to miss in logs.
115
+ """
116
+ if get_configured_api_key():
117
+ logger.info("API key authentication is ENABLED (CGC_API_KEY is set).")
118
+ else:
119
+ logger.warning(
120
+ "⚠️ CodeGraphContext API is running WITHOUT authentication. "
121
+ "Anyone who can reach this server can index code, run Cypher queries "
122
+ "and call tools. Set CGC_API_KEY to require a key."
123
+ )
@@ -5,17 +5,21 @@ from typing import Dict, Any, List
5
5
  from pathlib import Path
6
6
 
7
7
  from .schemas import (
8
- IndexRequest,
9
- QueryRequest,
10
- SearchRequest,
11
- ToolCallRequest,
8
+ IndexRequest,
9
+ QueryRequest,
10
+ SearchRequest,
11
+ ToolCallRequest,
12
12
  ApiResponse
13
13
  )
14
+ from .auth import require_api_key
14
15
  from codegraphcontext.server import MCPServer
15
16
 
16
17
  import socket
17
18
 
18
- router = APIRouter()
19
+ # Optional API-key auth is enforced on every route below via require_api_key.
20
+ # It is a no-op (backward compatible) unless CGC_API_KEY is configured, in
21
+ # which case each request must supply the key. See codegraphcontext.api.auth.
22
+ router = APIRouter(dependencies=[Depends(require_api_key)])
19
23
 
20
24
  # Global server instance (initialized on startup)
21
25
  _server_instance: MCPServer = None
@@ -112,6 +112,9 @@ def _print_index_execution_summary(graph_builder: GraphBuilder) -> None:
112
112
  "Files by extension",
113
113
  _format_extension_counts(summary.get("files_by_extension", {})),
114
114
  )
115
+ failed_files = summary.get("failed_files", 0)
116
+ if failed_files:
117
+ table.add_row("[red]Files failed to parse[/red]", f"[red]{failed_files}[/red]")
115
118
  table.add_row("Function nodes", str(summary.get("function_nodes", 0)))
116
119
  table.add_row("Class nodes", str(summary.get("class_nodes", 0)))
117
120
  table.add_row("CALLS edges", str(summary.get("call_edges", 0)))
@@ -353,7 +356,7 @@ def index_helper(path: str, context: Optional[str] = None):
353
356
  elapsed = time_end - time_start
354
357
  _print_call_resolution_diagnostics(graph_builder)
355
358
  _print_index_execution_summary(graph_builder)
356
- console.print(f"[green]Successfully finished indexing: {path} in {elapsed:.2f} seconds[/green]")
359
+ console.print(f"[green]Successfully finished indexing: {path_obj} in {elapsed:.2f} seconds[/green]")
357
360
 
358
361
  # Check if auto-watch is enabled
359
362
  try:
@@ -454,8 +457,13 @@ def delete_helper(repo_path: str, context: Optional[str] = None):
454
457
  else:
455
458
  console.print(f"[yellow]Repository not found in graph: {repo_path}[/yellow]")
456
459
  console.print("[dim]Tip: Use 'cgc list' to see available repositories.[/dim]")
460
+ raise typer.Exit(code=1)
461
+ except typer.Exit:
462
+ # Control flow, not an error — let it through so the exit code survives.
463
+ raise
457
464
  except Exception as e:
458
465
  console.print(f"[bold red]An error occurred:[/bold red] {e}")
466
+ raise typer.Exit(code=1)
459
467
  finally:
460
468
  db_manager.close_driver()
461
469
 
@@ -519,7 +527,13 @@ def cypher_helper(query: str, context: Optional[str] = None):
519
527
  raise typer.Exit(code=1)
520
528
 
521
529
  backend = getattr(db_manager, "get_backend_type", lambda: "neo4j")()
522
- session_kwargs = {"default_access_mode": "READ"} if backend == "neo4j" else {}
530
+ # Neo4j honours default_access_mode natively; FalkorDB routes READ sessions
531
+ # through GRAPH.RO_QUERY for server-enforced read-only execution.
532
+ session_kwargs = (
533
+ {"default_access_mode": "READ"}
534
+ if backend in ("neo4j", "falkordb", "falkordb-remote")
535
+ else {}
536
+ )
523
537
 
524
538
  try:
525
539
  with db_manager.get_driver().session(**session_kwargs) as session:
@@ -564,6 +578,119 @@ import uvicorn
564
578
  import urllib.parse
565
579
  from ..viz.server import run_server, set_db_manager
566
580
 
581
+ _OFFLINE_VIZ_DEFAULT_QUERY = """
582
+ MATCH (n)-[r]->(m)
583
+ RETURN n, r, m
584
+ LIMIT 300
585
+ """
586
+
587
+
588
+ def _render_offline_visualization(
589
+ db_manager,
590
+ repo_path: Optional[str] = None,
591
+ cypher_query: Optional[str] = None,
592
+ output_path: Optional[str] = None,
593
+ ) -> None:
594
+ """Render the graph with the dependency-free single-file HTML renderer.
595
+
596
+ The React frontend in ``viz/dist`` is not shipped in the wheel, which made
597
+ every visualization entry point a hard failure on a plain ``pip install``.
598
+ ``utils/visualize_graph.py`` is a complete, zero-dependency renderer that
599
+ was sitting in the package with no callers — this wires it up so the
600
+ command degrades to a working (simpler) view instead of exiting 1.
601
+ """
602
+ from ..utils.visualize_graph import open_in_browser, build_graph_data
603
+
604
+ query = cypher_query or _OFFLINE_VIZ_DEFAULT_QUERY
605
+ nodes: Dict[Any, Dict[str, Any]] = {}
606
+ edges: List[Dict[str, Any]] = []
607
+
608
+ def _ident(value) -> Optional[str]:
609
+ return None if value is None else str(value)
610
+
611
+ # Neo4j/Falkor return driver objects carrying .labels / .type; Kùzu and
612
+ # Ladybug return plain dicts carrying _label plus _src/_dst. Check the
613
+ # driver attributes first — a driver object may also be dict-like.
614
+ def _is_relationship(value) -> bool:
615
+ if hasattr(value, "labels"):
616
+ return False
617
+ if hasattr(value, "type"):
618
+ return True
619
+ return isinstance(value, dict) and "_src" in value and "_dst" in value
620
+
621
+ def _is_node(value) -> bool:
622
+ if hasattr(value, "labels"):
623
+ return True
624
+ if hasattr(value, "type"):
625
+ return False
626
+ # Kùzu relationships also carry _label, so _src/_dst is what
627
+ # distinguishes them from nodes.
628
+ return isinstance(value, dict) and "_label" in value and "_src" not in value
629
+
630
+ def _node_payload(value) -> Dict[str, Any]:
631
+ if hasattr(value, "labels"):
632
+ props = dict(value)
633
+ labels = list(getattr(value, "labels", []) or [])
634
+ label = labels[0] if labels else "Node"
635
+ node_id = getattr(value, "element_id", None) or getattr(value, "id", None)
636
+ else:
637
+ props, label = dict(value), value.get("_label", "Node")
638
+ node_id = value.get("_id")
639
+ if node_id is None:
640
+ node_id = props.get("path") or props.get("name")
641
+ return {
642
+ "id": _ident(node_id),
643
+ "label": label,
644
+ "name": props.get("name") or props.get("path") or "",
645
+ "file_path": props.get("path", ""),
646
+ "line_number": props.get("line_number"),
647
+ }
648
+
649
+ def _edge_payload(value) -> Optional[Dict[str, Any]]:
650
+ start = getattr(value, "start_node", None)
651
+ end = getattr(value, "end_node", None)
652
+ if start is not None and end is not None:
653
+ return {
654
+ "source": _ident(getattr(start, "element_id", None) or getattr(start, "id", None)),
655
+ "target": _ident(getattr(end, "element_id", None) or getattr(end, "id", None)),
656
+ "type": getattr(value, "type", "RELATED"),
657
+ }
658
+ if isinstance(value, dict):
659
+ return {
660
+ "source": _ident(value.get("_src")),
661
+ "target": _ident(value.get("_dst")),
662
+ "type": value.get("_label", "RELATED"),
663
+ }
664
+ return None
665
+
666
+ with db_manager.get_driver().session() as session:
667
+ for record in session.run(query):
668
+ values = list(record.values()) if hasattr(record, "values") else list(record)
669
+ for value in values:
670
+ if _is_node(value):
671
+ payload = _node_payload(value)
672
+ if payload["id"] is not None:
673
+ nodes[payload["id"]] = payload
674
+ elif _is_relationship(value):
675
+ edge = _edge_payload(value)
676
+ if edge and edge["source"] and edge["target"]:
677
+ edges.append(edge)
678
+
679
+ if not nodes:
680
+ console.print(
681
+ "[yellow]No graph data returned — index a repository first "
682
+ "with 'cgc index <path>'.[/yellow]"
683
+ )
684
+ raise typer.Exit(code=1)
685
+
686
+ title = f"CGC Code Graph — {Path(repo_path).name}" if repo_path else "CGC Code Graph"
687
+ graph_data = build_graph_data(list(nodes.values()), edges)
688
+ path = open_in_browser(graph_data, title=title, output_path=output_path)
689
+ console.print(
690
+ f"[green]Rendered {len(nodes)} nodes and {len(edges)} edges to[/green] {path}"
691
+ )
692
+
693
+
567
694
  def visualize_helper(
568
695
  repo_path: Optional[str] = None,
569
696
  host: str = "127.0.0.1",
@@ -625,8 +752,15 @@ def visualize_helper(
625
752
  "[dim]then sync[/dim] [cyan]website/dist[/cyan] [dim]→[/dim] "
626
753
  "[cyan]src/codegraphcontext/viz/dist[/cyan][dim].[/dim]"
627
754
  )
628
- db_manager.close_driver()
629
- raise SystemExit(1)
755
+ console.print(
756
+ "\n[yellow]Falling back to the built-in offline renderer.[/yellow]"
757
+ )
758
+ try:
759
+ return _render_offline_visualization(
760
+ db_manager, repo_path=repo_path, cypher_query=cypher_query
761
+ )
762
+ finally:
763
+ db_manager.close_driver()
630
764
 
631
765
  index_html = static_dir / "index.html"
632
766
  if not index_html.is_file():
@@ -815,17 +949,23 @@ def stats_helper(path: str = None, context: Optional[str] = None):
815
949
  return
816
950
 
817
951
  # Get stats
818
- # Get stats using separate queries to handle depth and avoid Cartesian products
952
+ # Get stats using separate queries to handle depth and avoid Cartesian products.
953
+ # `count(x)` counts *rows*, and a variable-length CONTAINS* match
954
+ # yields one row per distinct path to the node: a method is
955
+ # reachable as Repo->..->File->Function and again as
956
+ # Repo->..->File->Class->Function, a nested function three ways.
957
+ # count(DISTINCT x) is required or the totals are inflated —
958
+ # functions were over-reported by ~55% on CGC's own repo.
819
959
  # 1. Files
820
- file_query = "MATCH (r:Repository {path: $path})-[:CONTAINS*]->(f:File) RETURN count(f) as c"
960
+ file_query = "MATCH (r:Repository {path: $path})-[:CONTAINS*]->(f:File) RETURN count(DISTINCT f) as c"
821
961
  file_count = session.run(file_query, path=repo_path_str).single()["c"]
822
-
962
+
823
963
  # 2. Functions (including methods in classes)
824
- func_query = "MATCH (r:Repository {path: $path})-[:CONTAINS*]->(func:Function) RETURN count(func) as c"
964
+ func_query = "MATCH (r:Repository {path: $path})-[:CONTAINS*]->(func:Function) RETURN count(DISTINCT func) as c"
825
965
  func_count = session.run(func_query, path=repo_path_str).single()["c"]
826
-
966
+
827
967
  # 3. Classes
828
- class_query = "MATCH (r:Repository {path: $path})-[:CONTAINS*]->(c:Class) RETURN count(c) as c"
968
+ class_query = "MATCH (r:Repository {path: $path})-[:CONTAINS*]->(c:Class) RETURN count(DISTINCT c) as c"
829
969
  class_count = session.run(class_query, path=repo_path_str).single()["c"]
830
970
 
831
971
  # 4. Modules (imported) - Note: Module nodes are outside the repo structure usually, connected via IMPORTS
@@ -1017,19 +1157,38 @@ def watch_helper(
1017
1157
 
1018
1158
 
1019
1159
  def unwatch_helper(path: str):
1020
- """Stop watching a directory."""
1021
- console.print(f"[yellow]⚠️ Note: 'cgc unwatch' only works when the watcher is running via MCP server.[/yellow]")
1022
- console.print(f"[dim]For CLI watch mode, simply press Ctrl+C in the watch terminal.[/dim]")
1023
- console.print(f"\n[cyan]Path specified:[/cyan] {Path(path).resolve()}")
1160
+ """Report that unwatching is not available from the CLI.
1161
+
1162
+ This command touches no watcher state at all it never has. It used to
1163
+ print a note, echo the requested path back as "Path specified:" (which
1164
+ reads like confirmation that something happened, even for a path that was
1165
+ never watched and does not exist) and exit 0.
1166
+ """
1167
+ console.print(
1168
+ "[bold red]Error:[/bold red] 'cgc unwatch' is not supported from the CLI — "
1169
+ "it cannot reach a watcher started in another process."
1170
+ )
1171
+ console.print("[dim]For CLI watch mode, press Ctrl+C in the terminal running 'cgc watch'.[/dim]")
1172
+ console.print(
1173
+ "[dim]For MCP mode, call the 'unwatch_directory' tool from your IDE.[/dim]"
1174
+ )
1175
+ raise typer.Exit(code=1)
1024
1176
 
1025
1177
 
1026
1178
  def list_watching_helper():
1027
- """List all directories currently being watched."""
1028
- console.print(f"[yellow]⚠️ Note: 'cgc watching' only works when the watcher is running via MCP server.[/yellow]")
1029
- console.print(f"[dim]For CLI watch mode, check the terminal where you ran 'cgc watch'.[/dim]")
1030
- console.print(f"\n[cyan]To see watched directories in MCP mode:[/cyan]")
1031
- console.print(f" 1. Start the MCP server: cgc mcp start")
1032
- console.print(f" 2. Use the 'list_watched_paths' MCP tool from your IDE")
1179
+ """Report that listing watched paths is not available from the CLI.
1180
+
1181
+ Same as unwatch: no watcher state is consulted, so exiting 0 advertised a
1182
+ successful listing of nothing.
1183
+ """
1184
+ console.print(
1185
+ "[bold red]Error:[/bold red] 'cgc watching' is not supported from the CLI — "
1186
+ "it cannot reach a watcher started in another process."
1187
+ )
1188
+ console.print("[dim]For CLI watch mode, check the terminal where you ran 'cgc watch'.[/dim]")
1189
+ console.print("[dim]For MCP mode: start 'cgc mcp start', then call the "
1190
+ "'list_watched_paths' tool from your IDE.[/dim]")
1191
+ raise typer.Exit(code=1)
1033
1192
 
1034
1193
 
1035
1194
  def setup_scip_helper() -> None: