code-context-control 2.29.0__tar.gz → 2.32.1__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 (196) hide show
  1. {code_context_control-2.29.0 → code_context_control-2.32.1}/PKG-INFO +38 -9
  2. {code_context_control-2.29.0 → code_context_control-2.32.1}/README.md +36 -8
  3. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/c3.py +229 -3
  4. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/commands/parser.py +60 -0
  5. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/docs.html +37 -1
  6. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/hook_ghost_files.py +17 -1
  7. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/mcp_server.py +109 -0
  8. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/server.py +365 -0
  9. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/tools/_helpers.py +17 -3
  10. code_context_control-2.32.1/cli/tools/bitbucket.py +654 -0
  11. code_context_control-2.32.1/cli/tools/project.py +287 -0
  12. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/ui/app.js +4 -0
  13. code_context_control-2.32.1/cli/ui/components/bitbucket.js +297 -0
  14. {code_context_control-2.29.0 → code_context_control-2.32.1}/code_context_control.egg-info/PKG-INFO +38 -9
  15. {code_context_control-2.29.0 → code_context_control-2.32.1}/code_context_control.egg-info/SOURCES.txt +19 -0
  16. {code_context_control-2.29.0 → code_context_control-2.32.1}/code_context_control.egg-info/requires.txt +1 -0
  17. {code_context_control-2.29.0 → code_context_control-2.32.1}/core/config.py +29 -0
  18. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/config.py +7 -0
  19. code_context_control-2.32.1/oracle/mcp_oracle.py +146 -0
  20. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/oracle.html +130 -2
  21. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/oracle_server.py +210 -3
  22. code_context_control-2.32.1/oracle/services/api_auth.py +120 -0
  23. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/services/chat_engine.py +9 -0
  24. code_context_control-2.32.1/oracle/services/tool_executor.py +30 -0
  25. code_context_control-2.32.1/oracle/services/tool_registry.py +412 -0
  26. {code_context_control-2.29.0 → code_context_control-2.32.1}/pyproject.toml +2 -1
  27. code_context_control-2.32.1/services/bitbucket_client.py +485 -0
  28. code_context_control-2.32.1/services/bitbucket_credentials.py +215 -0
  29. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/claude_md.py +2 -0
  30. code_context_control-2.32.1/services/project_runtime.py +291 -0
  31. code_context_control-2.32.1/tests/test_bitbucket_cli_smoke.py +59 -0
  32. code_context_control-2.32.1/tests/test_bitbucket_client.py +203 -0
  33. code_context_control-2.32.1/tests/test_bitbucket_credentials.py +124 -0
  34. code_context_control-2.32.1/tests/test_bitbucket_tool.py +179 -0
  35. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_ghost_files.py +22 -1
  36. code_context_control-2.32.1/tests/test_oracle_api_auth.py +94 -0
  37. code_context_control-2.32.1/tests/test_oracle_apikey_api.py +101 -0
  38. code_context_control-2.32.1/tests/test_oracle_discovery_api.py +100 -0
  39. code_context_control-2.32.1/tests/test_project_tool.py +287 -0
  40. code_context_control-2.32.1/tests/test_tool_registry.py +91 -0
  41. {code_context_control-2.29.0 → code_context_control-2.32.1}/LICENSE +0 -0
  42. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/__init__.py +0 -0
  43. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/_hook_utils.py +0 -0
  44. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/commands/__init__.py +0 -0
  45. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/commands/common.py +0 -0
  46. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/edits.html +0 -0
  47. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/hook_auto_snapshot.py +0 -0
  48. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/hook_c3_signal.py +0 -0
  49. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/hook_c3read.py +0 -0
  50. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/hook_edit_ledger.py +0 -0
  51. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/hook_edit_unlock.py +0 -0
  52. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/hook_filter.py +0 -0
  53. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/hook_pretool_enforce.py +0 -0
  54. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/hook_read.py +0 -0
  55. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/hook_session_stats.py +0 -0
  56. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/hook_terse_advisor.py +0 -0
  57. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/hub.html +0 -0
  58. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/hub_server.py +0 -0
  59. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/mcp_proxy.py +0 -0
  60. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/tools/__init__.py +0 -0
  61. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/tools/agent.py +0 -0
  62. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/tools/compress.py +0 -0
  63. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/tools/delegate.py +0 -0
  64. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/tools/edit.py +0 -0
  65. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/tools/edits.py +0 -0
  66. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/tools/filter.py +0 -0
  67. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/tools/impact.py +0 -0
  68. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/tools/memory.py +0 -0
  69. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/tools/read.py +0 -0
  70. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/tools/search.py +0 -0
  71. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/tools/session.py +0 -0
  72. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/tools/shell.py +0 -0
  73. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/tools/status.py +0 -0
  74. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/tools/validate.py +0 -0
  75. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/ui/api.js +0 -0
  76. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/ui/components/chat.js +0 -0
  77. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/ui/components/dashboard.js +0 -0
  78. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/ui/components/edits.js +0 -0
  79. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/ui/components/instructions.js +0 -0
  80. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/ui/components/memory.js +0 -0
  81. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/ui/components/sessions.js +0 -0
  82. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/ui/components/settings.js +0 -0
  83. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/ui/components/sidebar.js +0 -0
  84. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/ui/icons.js +0 -0
  85. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/ui/shared.js +0 -0
  86. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/ui/theme.js +0 -0
  87. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/ui.html +0 -0
  88. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/ui_legacy.html +0 -0
  89. {code_context_control-2.29.0 → code_context_control-2.32.1}/cli/ui_nano.html +0 -0
  90. {code_context_control-2.29.0 → code_context_control-2.32.1}/code_context_control.egg-info/dependency_links.txt +0 -0
  91. {code_context_control-2.29.0 → code_context_control-2.32.1}/code_context_control.egg-info/entry_points.txt +0 -0
  92. {code_context_control-2.29.0 → code_context_control-2.32.1}/code_context_control.egg-info/top_level.txt +0 -0
  93. {code_context_control-2.29.0 → code_context_control-2.32.1}/core/__init__.py +0 -0
  94. {code_context_control-2.29.0 → code_context_control-2.32.1}/core/ide.py +0 -0
  95. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/__init__.py +0 -0
  96. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/services/__init__.py +0 -0
  97. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/services/c3_bridge.py +0 -0
  98. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/services/chat_store.py +0 -0
  99. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/services/cross_memory.py +0 -0
  100. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/services/federated_graph.py +0 -0
  101. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/services/health_checker.py +0 -0
  102. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/services/insight_engine.py +0 -0
  103. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/services/memory_reader.py +0 -0
  104. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/services/memory_writer.py +0 -0
  105. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/services/ollama_bridge.py +0 -0
  106. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/services/project_scanner.py +0 -0
  107. {code_context_control-2.29.0 → code_context_control-2.32.1}/oracle/services/review_agent.py +0 -0
  108. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/__init__.py +0 -0
  109. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/activity_log.py +0 -0
  110. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/agent_base.py +0 -0
  111. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/agents.py +0 -0
  112. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/auto_memory.py +0 -0
  113. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/bench/__init__.py +0 -0
  114. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/bench/external/__init__.py +0 -0
  115. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/bench/external/aider_polyglot.py +0 -0
  116. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/bench/external/swe_bench.py +0 -0
  117. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/benchmark_dashboard.py +0 -0
  118. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/compressor.py +0 -0
  119. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/context_snapshot.py +0 -0
  120. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/conversation_store.py +0 -0
  121. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/doc_index.py +0 -0
  122. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/e2e_benchmark.py +0 -0
  123. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/e2e_evaluator.py +0 -0
  124. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/e2e_tasks.py +0 -0
  125. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/edit_ledger.py +0 -0
  126. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/embedding_index.py +0 -0
  127. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/error_reporting.py +0 -0
  128. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/file_memory.py +0 -0
  129. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/hub_service.py +0 -0
  130. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/indexer.py +0 -0
  131. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/memory.py +0 -0
  132. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/memory_consolidator.py +0 -0
  133. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/memory_graph.py +0 -0
  134. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/memory_grounder.py +0 -0
  135. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/memory_scorer.py +0 -0
  136. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/metrics.py +0 -0
  137. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/notifications.py +0 -0
  138. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/ollama_client.py +0 -0
  139. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/output_filter.py +0 -0
  140. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/parser.py +0 -0
  141. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/project_manager.py +0 -0
  142. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/protocol.py +0 -0
  143. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/proxy_state.py +0 -0
  144. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/retrieval_broker.py +0 -0
  145. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/router.py +0 -0
  146. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/runtime.py +0 -0
  147. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/session_benchmark.py +0 -0
  148. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/session_manager.py +0 -0
  149. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/session_preloader.py +0 -0
  150. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/text_index.py +0 -0
  151. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/tool_classifier.py +0 -0
  152. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/transcript_index.py +0 -0
  153. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/validation_cache.py +0 -0
  154. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/vector_store.py +0 -0
  155. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/version_tracker.py +0 -0
  156. {code_context_control-2.29.0 → code_context_control-2.32.1}/services/watcher.py +0 -0
  157. {code_context_control-2.29.0 → code_context_control-2.32.1}/setup.cfg +0 -0
  158. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_aider_polyglot.py +0 -0
  159. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_c3_shell.py +0 -0
  160. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_cli_smoke.py +0 -0
  161. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_e2e_benchmark.py +0 -0
  162. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_edit_normalization.py +0 -0
  163. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_enforcement_flip.py +0 -0
  164. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_federated_graph.py +0 -0
  165. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_hub_server_smoke.py +0 -0
  166. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_mcp_server_smoke.py +0 -0
  167. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_memory_graph_api.py +0 -0
  168. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_memory_system.py +0 -0
  169. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_notification_discipline.py +0 -0
  170. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_output_filter.py +0 -0
  171. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_permissions.py +0 -0
  172. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_project_manager.py +0 -0
  173. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_project_manager_merge.py +0 -0
  174. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_session_benchmark.py +0 -0
  175. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_session_budget.py +0 -0
  176. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_swe_bench.py +0 -0
  177. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_validate.py +0 -0
  178. {code_context_control-2.29.0 → code_context_control-2.32.1}/tests/test_windows_reliability.py +0 -0
  179. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/__init__.py +0 -0
  180. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/backend.py +0 -0
  181. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/main.py +0 -0
  182. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/screens/__init__.py +0 -0
  183. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/screens/benchmark_view.py +0 -0
  184. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/screens/claudemd_view.py +0 -0
  185. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/screens/compress_view.py +0 -0
  186. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/screens/index_view.py +0 -0
  187. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/screens/init_view.py +0 -0
  188. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/screens/mcp_view.py +0 -0
  189. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/screens/optimize_view.py +0 -0
  190. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/screens/pipe_view.py +0 -0
  191. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/screens/projects_view.py +0 -0
  192. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/screens/search_view.py +0 -0
  193. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/screens/session_view.py +0 -0
  194. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/screens/stats.py +0 -0
  195. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/screens/ui_view.py +0 -0
  196. {code_context_control-2.29.0 → code_context_control-2.32.1}/tui/theme.tcss +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-control
3
- Version: 2.29.0
3
+ Version: 2.32.1
4
4
  Summary: Local code-intelligence layer for AI coding tools (Claude Code, Codex, Gemini, Copilot). Retrieve less, read less, edit safer.
5
5
  Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -41,6 +41,7 @@ Requires-Dist: flask>=3.0.0
41
41
  Requires-Dist: rich>=13.0.0
42
42
  Requires-Dist: click>=8.0.0
43
43
  Requires-Dist: pyyaml>=6.0.0
44
+ Requires-Dist: keyring>=24.0
44
45
  Provides-Extra: vector
45
46
  Requires-Dist: scikit-learn>=1.3.0; extra == "vector"
46
47
  Requires-Dist: numpy>=1.24.0; extra == "vector"
@@ -147,13 +148,9 @@ C3 ships with two web UIs (no electron, no install — pure Flask + vanilla JS):
147
148
  <img src="https://raw.githubusercontent.com/drknowhow/code-context-control/main/docs/screenshots/hub_projects.png" alt="C3 Project Hub - all projects" width="900">
148
149
  </p>
149
150
 
150
- Every C3-initialized project on your machine appears here. Group them by tag, filter by active/idle, see which IDE each project uses, jump straight into your IDE with one click, and monitor session activity at a glance. Each project card shows live status, version, MCP wiring mode, port, and last activity.
151
+ Every C3-initialized project on your machine appears here automatically — `c3 init` registers the project with the hub on first run, no extra step. Group them by tag, filter by active/idle, see which IDE each project uses, jump straight into your IDE with one click, and monitor session activity at a glance. Each project card shows live status, version, MCP wiring mode, port, and last activity.
151
152
 
152
- Same data, grid layout:
153
-
154
- <p align="center">
155
- <img src="https://raw.githubusercontent.com/drknowhow/code-context-control/main/docs/screenshots/hub_projects_grid.png" alt="C3 Project Hub - grid view" width="900">
156
- </p>
153
+ Per-card actions cover the full lifecycle: launch the IDE, open the per-project UI, edit name / tags / notes, transfer the registration to a new path, **merge** another project's memory + conversation history + edit ledger into this one (with optional source cleanup), or remove it from the registry.
157
154
 
158
155
  **Open in your IDE of choice** — C3 auto-detects which CLIs you have installed and gives you one-click launchers:
159
156
 
@@ -231,7 +228,7 @@ Per-project knobs for everything: budget thresholds, feature flag mode, edit led
231
228
 
232
229
  ## The MCP tool suite
233
230
 
234
- C3 exposes 14 tools as a native MCP server. Your IDE calls them directly:
231
+ C3 exposes 16 tools as a native MCP server. Your IDE calls them directly:
235
232
 
236
233
  | Tool | What it does |
237
234
  |---|---|
@@ -249,8 +246,40 @@ C3 exposes 14 tools as a native MCP server. Your IDE calls them directly:
249
246
  | `c3_delegate` | Offload heavy work to local Ollama / Codex / Gemini / etc. |
250
247
  | `c3_agent` | Multi-step agentic workflows (review, investigate, refactor) |
251
248
  | `c3_edits` | Edit-ledger queries + version diffs + restore points |
249
+ | `c3_bitbucket` | Bitbucket Data Center integration — PRs, branches, builds, repo admin (v2.30.0) |
250
+ | `c3_project` | Cross-project — discover & operate on other c3-installed projects; guarded writes (v2.31.0) |
251
+
252
+ Every tool is **read-only safe in plan mode** (except `c3_edit`, `c3_shell`, and write actions on `c3_bitbucket` / `c3_project`).
253
+
254
+ ### Bitbucket Data Center / Server (v2.30.0)
255
+
256
+ `c3_bitbucket` connects to self-hosted enterprise Bitbucket via REST + Personal
257
+ Access Token. Tokens live in the **OS keyring** (Windows Credential Manager,
258
+ macOS Keychain, Linux Secret Service) — never in `.c3/config.json`.
259
+
260
+ ```bash
261
+ # One-time login per server
262
+ c3 bitbucket login --url https://bitbucket.example.com
263
+ # → prompts for username + PAT (masked)
264
+
265
+ # Pin defaults so subsequent calls don't need project/repo
266
+ c3 bitbucket set-default --project PROJ --repo my-service
267
+
268
+ # Inspect status
269
+ c3 bitbucket status
270
+ ```
252
271
 
253
- Every tool is **read-only safe in plan mode** (except `c3_edit` and `c3_shell`).
272
+ The MCP tool dispatches by `action`. Read-only actions: `status`, `whoami`,
273
+ `list_projects`, `list_repos`, `get_repo`, `list_prs`, `get_pr`, `get_pr_diff`,
274
+ `get_pr_activities`, `list_branches`, `list_commits`, `list_activity`,
275
+ `build_status`, `repo_settings`, `list_webhooks`, `list_permissions`. Write
276
+ actions: `create_pr`, `comment_pr`, `approve_pr`, `unapprove_pr`, `decline_pr`,
277
+ `merge_pr`, `create_branch`, `delete_branch`, `update_repo_settings`,
278
+ `create_webhook`, `delete_webhook`. PR merges and branch deletes are recorded
279
+ to the C3 edit ledger so the audit trail covers platform-side changes too.
280
+
281
+ The **Hub UI** (per-project) gains a "Bitbucket" tab with sub-views for
282
+ Overview / Pull Requests / Branches / Activity / Admin.
254
283
 
255
284
  ---
256
285
 
@@ -86,13 +86,9 @@ C3 ships with two web UIs (no electron, no install — pure Flask + vanilla JS):
86
86
  <img src="https://raw.githubusercontent.com/drknowhow/code-context-control/main/docs/screenshots/hub_projects.png" alt="C3 Project Hub - all projects" width="900">
87
87
  </p>
88
88
 
89
- Every C3-initialized project on your machine appears here. Group them by tag, filter by active/idle, see which IDE each project uses, jump straight into your IDE with one click, and monitor session activity at a glance. Each project card shows live status, version, MCP wiring mode, port, and last activity.
89
+ Every C3-initialized project on your machine appears here automatically — `c3 init` registers the project with the hub on first run, no extra step. Group them by tag, filter by active/idle, see which IDE each project uses, jump straight into your IDE with one click, and monitor session activity at a glance. Each project card shows live status, version, MCP wiring mode, port, and last activity.
90
90
 
91
- Same data, grid layout:
92
-
93
- <p align="center">
94
- <img src="https://raw.githubusercontent.com/drknowhow/code-context-control/main/docs/screenshots/hub_projects_grid.png" alt="C3 Project Hub - grid view" width="900">
95
- </p>
91
+ Per-card actions cover the full lifecycle: launch the IDE, open the per-project UI, edit name / tags / notes, transfer the registration to a new path, **merge** another project's memory + conversation history + edit ledger into this one (with optional source cleanup), or remove it from the registry.
96
92
 
97
93
  **Open in your IDE of choice** — C3 auto-detects which CLIs you have installed and gives you one-click launchers:
98
94
 
@@ -170,7 +166,7 @@ Per-project knobs for everything: budget thresholds, feature flag mode, edit led
170
166
 
171
167
  ## The MCP tool suite
172
168
 
173
- C3 exposes 14 tools as a native MCP server. Your IDE calls them directly:
169
+ C3 exposes 16 tools as a native MCP server. Your IDE calls them directly:
174
170
 
175
171
  | Tool | What it does |
176
172
  |---|---|
@@ -188,8 +184,40 @@ C3 exposes 14 tools as a native MCP server. Your IDE calls them directly:
188
184
  | `c3_delegate` | Offload heavy work to local Ollama / Codex / Gemini / etc. |
189
185
  | `c3_agent` | Multi-step agentic workflows (review, investigate, refactor) |
190
186
  | `c3_edits` | Edit-ledger queries + version diffs + restore points |
187
+ | `c3_bitbucket` | Bitbucket Data Center integration — PRs, branches, builds, repo admin (v2.30.0) |
188
+ | `c3_project` | Cross-project — discover & operate on other c3-installed projects; guarded writes (v2.31.0) |
189
+
190
+ Every tool is **read-only safe in plan mode** (except `c3_edit`, `c3_shell`, and write actions on `c3_bitbucket` / `c3_project`).
191
+
192
+ ### Bitbucket Data Center / Server (v2.30.0)
193
+
194
+ `c3_bitbucket` connects to self-hosted enterprise Bitbucket via REST + Personal
195
+ Access Token. Tokens live in the **OS keyring** (Windows Credential Manager,
196
+ macOS Keychain, Linux Secret Service) — never in `.c3/config.json`.
197
+
198
+ ```bash
199
+ # One-time login per server
200
+ c3 bitbucket login --url https://bitbucket.example.com
201
+ # → prompts for username + PAT (masked)
202
+
203
+ # Pin defaults so subsequent calls don't need project/repo
204
+ c3 bitbucket set-default --project PROJ --repo my-service
205
+
206
+ # Inspect status
207
+ c3 bitbucket status
208
+ ```
191
209
 
192
- Every tool is **read-only safe in plan mode** (except `c3_edit` and `c3_shell`).
210
+ The MCP tool dispatches by `action`. Read-only actions: `status`, `whoami`,
211
+ `list_projects`, `list_repos`, `get_repo`, `list_prs`, `get_pr`, `get_pr_diff`,
212
+ `get_pr_activities`, `list_branches`, `list_commits`, `list_activity`,
213
+ `build_status`, `repo_settings`, `list_webhooks`, `list_permissions`. Write
214
+ actions: `create_pr`, `comment_pr`, `approve_pr`, `unapprove_pr`, `decline_pr`,
215
+ `merge_pr`, `create_branch`, `delete_branch`, `update_repo_settings`,
216
+ `create_webhook`, `delete_webhook`. PR merges and branch deletes are recorded
217
+ to the C3 edit ledger so the audit trail covers platform-side changes too.
218
+
219
+ The **Hub UI** (per-project) gains a "Bitbucket" tab with sub-views for
220
+ Overview / Pull Requests / Branches / Activity / Admin.
193
221
 
194
222
  ---
195
223
 
@@ -60,7 +60,7 @@ from cli.commands.common import cmd_stats as common_cmd_stats
60
60
  from cli.commands.common import cmd_ui as common_cmd_ui
61
61
  from cli.commands.parser import build_parser
62
62
  from core import count_tokens, format_token_count
63
- from core.config import AGENT_DEFAULTS, DELEGATE_DEFAULTS, PROXY_DEFAULTS, load_delegate_config
63
+ from core.config import AGENT_DEFAULTS, BITBUCKET_DEFAULTS, DELEGATE_DEFAULTS, PROXY_DEFAULTS, load_delegate_config
64
64
  from core.config import DEFAULTS as HYBRID_DEFAULTS
65
65
  from core.ide import PROFILES, detect_ide, get_profile, load_ide_config, normalize_ide_name
66
66
  from services.compressor import CodeCompressor
@@ -85,7 +85,7 @@ console = Console() if HAS_RICH else None
85
85
  # Config
86
86
  CONFIG_DIR = ".c3"
87
87
  CONFIG_FILE = ".c3/config.json"
88
- __version__ = "2.28.3"
88
+ __version__ = "2.32.1"
89
89
 
90
90
 
91
91
  def _command_deps() -> CommandDeps:
@@ -164,6 +164,7 @@ def _build_init_config(project_path: str) -> dict:
164
164
  "proxy": deepcopy(PROXY_DEFAULTS),
165
165
  "delegate": deepcopy(DELEGATE_DEFAULTS),
166
166
  "agents": deepcopy(AGENT_DEFAULTS),
167
+ "bitbucket": deepcopy(BITBUCKET_DEFAULTS),
167
168
  }
168
169
  merged = _deep_merge_dict(defaults, existing if isinstance(existing, dict) else {})
169
170
  # Always persist current path/version on init/update.
@@ -237,7 +238,8 @@ _C3_MCP_ALLOW = [
237
238
  "mcp__c3__c3_session", "mcp__c3__c3_status", "mcp__c3__c3_filter",
238
239
  "mcp__c3__c3_memory", "mcp__c3__c3_validate", "mcp__c3__c3_edit",
239
240
  "mcp__c3__c3_agent", "mcp__c3__c3_delegate", "mcp__c3__c3_edits",
240
- "mcp__c3__c3_impact", "mcp__c3__c3_shell",
241
+ "mcp__c3__c3_impact", "mcp__c3__c3_shell", "mcp__c3__c3_bitbucket",
242
+ "mcp__c3__c3_project",
241
243
  ]
242
244
 
243
245
  # Obsolete MCP tool names from earlier C3 versions. `c3 permissions clean`
@@ -563,6 +565,25 @@ def _check_c3_health(project_path: str) -> dict:
563
565
  facts_dir = c3_dir / "facts"
564
566
  info["facts"] = len(list(facts_dir.glob("*.json"))) if facts_dir.exists() else 0
565
567
 
568
+ # Bitbucket integration (v2.30.0+) — informational
569
+ bb_section = config.get("bitbucket") if isinstance(config, dict) else None
570
+ if isinstance(bb_section, dict):
571
+ active = bb_section.get("active") or {}
572
+ accounts = bb_section.get("accounts") or []
573
+ info["bitbucket_accounts"] = len(accounts) if isinstance(accounts, list) else 0
574
+ info["bitbucket_active_account"] = (
575
+ f"{active.get('username', '')}@{active.get('base_url', '')}"
576
+ if active.get("base_url") and active.get("username") else ""
577
+ )
578
+ info["bitbucket_default_repo"] = (
579
+ f"{bb_section.get('default_project', '')}/{bb_section.get('default_repo', '')}"
580
+ if bb_section.get("default_project") and bb_section.get("default_repo") else ""
581
+ )
582
+ else:
583
+ info["bitbucket_accounts"] = 0
584
+ info["bitbucket_active_account"] = ""
585
+ info["bitbucket_default_repo"] = ""
586
+
566
587
  info["issues"] = issues
567
588
  info["healthy"] = len(issues) == 0
568
589
  return info
@@ -946,6 +967,15 @@ def cmd_init(args):
946
967
  except Exception:
947
968
  print(" Gemini: unknown")
948
969
 
970
+ # Bitbucket integration (v2.30.0+)
971
+ bb_n = int(health.get("bitbucket_accounts") or 0)
972
+ if bb_n:
973
+ active = health.get("bitbucket_active_account") or "(no active)"
974
+ repo = health.get("bitbucket_default_repo") or "(no default repo)"
975
+ print(f" Bitbkt: {bb_n} account(s), active={active}, repo={repo}")
976
+ else:
977
+ print(" Bitbkt: not configured (run 'c3 bitbucket login --url <URL>')")
978
+
949
979
  if health["healthy"]:
950
980
  print("\n Status: healthy — no issues detected.")
951
981
  else:
@@ -4462,6 +4492,8 @@ back to native tools as the task progresses.
4462
4492
  - **Shell**: `c3_shell(cmd, timeout=60)` — structured shell exec (tests/git/build). Auto-filters output, logs git mutations to the ledger. Native Bash for interactive/TTY only
4463
4493
  - **Memory**: `c3_memory(action='recall')` — full recall. `index` + `fetch` for token-efficient two-step retrieval
4464
4494
  - **Delegate**: `c3_delegate(task, backend='ollama|codex|gemini|claude|auto')` — offload to other models
4495
+ - **Bitbucket** (v2.30.0+, when `c3 bitbucket login` has run): `c3_bitbucket(action='list_prs|get_pr|merge_pr|...')` — self-hosted Bitbucket Data Center / Server. Token in OS keyring; mutating actions auto-log to the edit ledger.
4496
+ - **Cross-project** (v2.31.0+): `c3_project(action='list|scan|search|read|edit|...', project='<name|path>')` — discover and operate on OTHER c3-installed projects. Reads run freely; writes (edit/shell/memory) need `allow_write=true`.
4465
4497
 
4466
4498
  ## Self-Check
4467
4499
  If you haven't called a c3_* tool in several turns during active development, re-engage
@@ -5388,6 +5420,198 @@ def cmd_hub(args):
5388
5420
  run_hub(port=port, open_browser=open_browser, silent=silent, quiet=quiet)
5389
5421
 
5390
5422
 
5423
+ def cmd_bitbucket(args):
5424
+ """Bitbucket Data Center / Server credential + workspace management."""
5425
+ sub = getattr(args, "bitbucket_cmd", None)
5426
+ if not sub:
5427
+ print("Usage: c3 bitbucket {login,logout,status,use,set-default} [args]")
5428
+ return
5429
+
5430
+ project_path = getattr(args, "project_path", ".") or "."
5431
+
5432
+ if sub == "login":
5433
+ _bb_cmd_login(args, project_path)
5434
+ elif sub == "logout":
5435
+ _bb_cmd_logout(args, project_path)
5436
+ elif sub == "status":
5437
+ _bb_cmd_status(args, project_path)
5438
+ elif sub == "use":
5439
+ _bb_cmd_use(args, project_path)
5440
+ elif sub == "set-default":
5441
+ _bb_cmd_set_default(args, project_path)
5442
+ else:
5443
+ print(f"Unknown bitbucket subcommand: {sub}")
5444
+
5445
+
5446
+ def _bb_cmd_login(args, project_path: str) -> None:
5447
+ import getpass
5448
+
5449
+ from services import bitbucket_credentials as bb_creds
5450
+ from services.bitbucket_client import BitbucketDataCenterClient, BitbucketError
5451
+
5452
+ base_url = (args.url or "").rstrip("/")
5453
+ username = args.username or input(f"Username for {base_url}: ").strip()
5454
+ if not username:
5455
+ print("Login cancelled — username required.")
5456
+ return
5457
+ token = args.token or getpass.getpass(f"Personal Access Token for {username}: ").strip()
5458
+ if not token:
5459
+ print("Login cancelled — token required.")
5460
+ return
5461
+
5462
+ try:
5463
+ bb_creds.save_credentials(
5464
+ base_url, username, token,
5465
+ project_path=project_path,
5466
+ set_active=not getattr(args, "no_set_active", False),
5467
+ )
5468
+ except bb_creds.BitbucketCredentialError as exc:
5469
+ print(f"[error] {exc}")
5470
+ return
5471
+
5472
+ if getattr(args, "insecure", False):
5473
+ bb_creds.set_verify_tls(False, project_path=project_path)
5474
+
5475
+ print(f"[OK] Stored credentials for {username}@{base_url}")
5476
+
5477
+ # Connection probe — non-fatal if it fails (token might be valid but
5478
+ # network blocked at this moment).
5479
+ try:
5480
+ client = BitbucketDataCenterClient(
5481
+ base_url=base_url, token=token,
5482
+ verify_tls=not getattr(args, "insecure", False),
5483
+ )
5484
+ props = client.application_properties()
5485
+ version = props.get("version", "?")
5486
+ user = client.whoami()
5487
+ print(f" Server: {version} ({base_url})")
5488
+ print(f" Auth as: {user.get('displayName', username)} <{user.get('emailAddress', '?')}>")
5489
+ except BitbucketError as exc:
5490
+ print(f"[warn] Connection probe failed: {exc}")
5491
+ print(" Token saved anyway — re-test with `c3 bitbucket status`.")
5492
+
5493
+
5494
+ def _bb_cmd_logout(args, project_path: str) -> None:
5495
+ from services import bitbucket_credentials as bb_creds
5496
+
5497
+ base_url = (getattr(args, "url", "") or "").rstrip("/")
5498
+ username = getattr(args, "username", "") or ""
5499
+ if not base_url or not username:
5500
+ active = bb_creds.get_active_account(project_path)
5501
+ base_url = base_url or active.get("base_url", "")
5502
+ username = username or active.get("username", "")
5503
+ if not base_url or not username:
5504
+ print("[error] No account specified and no active account configured.")
5505
+ return
5506
+ removed = bb_creds.delete_credentials(base_url, username, project_path=project_path)
5507
+ if removed:
5508
+ print(f"[OK] Removed {username}@{base_url}")
5509
+ else:
5510
+ print(f"[warn] Nothing to remove for {username}@{base_url}")
5511
+
5512
+
5513
+ def _bb_cmd_status(args, project_path: str) -> None:
5514
+ from core.config import load_bitbucket_config
5515
+ from services import bitbucket_credentials as bb_creds
5516
+ from services.bitbucket_client import BitbucketDataCenterClient, BitbucketError
5517
+
5518
+ cfg = load_bitbucket_config(project_path)
5519
+ active = cfg.get("active") or {}
5520
+ accounts = cfg.get("accounts") or []
5521
+
5522
+ print("[bitbucket:status]")
5523
+ print(f" Active : {active.get('username') or '-'}@{active.get('base_url') or '-'}")
5524
+ print(f" Defaults: project={cfg.get('default_project') or '-'} repo={cfg.get('default_repo') or '-'}")
5525
+ print(f" Verify TLS: {cfg.get('verify_tls', True)}")
5526
+ print(f" Accounts ({len(accounts)}):")
5527
+ for a in accounts:
5528
+ marker = "*" if a == active else " "
5529
+ print(f" {marker} {a.get('username','?')}@{a.get('base_url','?')}")
5530
+
5531
+ if not active.get("base_url") or not active.get("username"):
5532
+ print(" Connection: (no active account)")
5533
+ return
5534
+ token = bb_creds.load_token(active["base_url"], active["username"])
5535
+ if not token:
5536
+ print(" Connection: FAIL — no token in keyring")
5537
+ return
5538
+ try:
5539
+ client = BitbucketDataCenterClient(
5540
+ base_url=active["base_url"], token=token,
5541
+ verify_tls=bool(cfg.get("verify_tls", True)),
5542
+ )
5543
+ props = client.application_properties()
5544
+ print(f" Connection: OK (version {props.get('version','?')})")
5545
+ except BitbucketError as exc:
5546
+ print(f" Connection: FAIL — {exc}")
5547
+
5548
+
5549
+ def _bb_cmd_use(args, project_path: str) -> None:
5550
+ from services import bitbucket_credentials as bb_creds
5551
+ bb_creds.set_active_account(args.url, args.username, project_path=project_path)
5552
+ print(f"[OK] Active account: {args.username}@{args.url.rstrip('/')}")
5553
+
5554
+
5555
+ def _bb_cmd_set_default(args, project_path: str) -> None:
5556
+ from services import bitbucket_credentials as bb_creds
5557
+ bb_creds.set_default_repo(args.project, args.repo, project_path=project_path)
5558
+ print(f"[OK] Default repo: {args.project}/{args.repo}")
5559
+
5560
+
5561
+ def cmd_oracle(args):
5562
+ """Oracle Discovery API key + connection management."""
5563
+ sub = getattr(args, "oracle_cmd", None)
5564
+ if sub != "api":
5565
+ print("Usage: c3 oracle api {info,key,rotate,clear}")
5566
+ return
5567
+
5568
+ from oracle.config import load_config
5569
+ from oracle.mcp_oracle import mcp_url
5570
+ from oracle.services import api_auth
5571
+
5572
+ action = getattr(args, "action", "info") or "info"
5573
+
5574
+ if action == "rotate":
5575
+ print("Rotated. New Discovery API key:")
5576
+ print(f" {api_auth.rotate()}")
5577
+ return
5578
+ if action == "clear":
5579
+ removed = api_auth.clear()
5580
+ print("Discovery API key cleared." if removed else "No stored Discovery API key to clear.")
5581
+ return
5582
+
5583
+ key = api_auth.get_or_create_key()
5584
+ if action == "key":
5585
+ print(key)
5586
+ return
5587
+
5588
+ cfg = load_config()
5589
+ host = cfg.get("bind_host", "127.0.0.1")
5590
+ disp_host = "127.0.0.1" if host in ("0.0.0.0", "") else host
5591
+ rest_port = getattr(args, "port", None) or cfg.get("port", 3331)
5592
+ mcp_port = getattr(args, "mcp_port", None) or cfg.get("mcp_port", 3332)
5593
+ rest_base = f"http://{disp_host}:{rest_port}/api/discovery"
5594
+ url = mcp_url(host, mcp_port)
5595
+
5596
+ print("[oracle:api]")
5597
+ print(f" REST base : {rest_base}")
5598
+ print(f" OpenAPI : {rest_base}/openapi.json")
5599
+ print(f" MCP URL : {url}")
5600
+ print(f" Auth : Bearer {key}")
5601
+ print()
5602
+ print(" Claude .mcp.json entry:")
5603
+ snippet = {
5604
+ "mcpServers": {
5605
+ "c3-oracle": {
5606
+ "type": "http",
5607
+ "url": url,
5608
+ "headers": {"Authorization": f"Bearer {key}"},
5609
+ }
5610
+ }
5611
+ }
5612
+ print(json.dumps(snippet, indent=2))
5613
+
5614
+
5391
5615
  def cmd_projects(args):
5392
5616
  """Manage the global C3 project registry."""
5393
5617
  from services.project_manager import ProjectManager
@@ -6139,6 +6363,8 @@ def main():
6139
6363
  "ui": cmd_ui,
6140
6364
  "projects": cmd_projects,
6141
6365
  "hub": cmd_hub,
6366
+ "bitbucket": cmd_bitbucket,
6367
+ "oracle": cmd_oracle,
6142
6368
  }
6143
6369
 
6144
6370
  cmd_func = commands.get(args.command)
@@ -283,4 +283,64 @@ def build_parser(version: str, parse_cli_ide_arg):
283
283
  p_bext.add_argument("--dry-run", action="store_true",
284
284
  help="Validate setup (CLIs, datasets) without running the agent")
285
285
 
286
+ # ── Bitbucket Data Center / Server (v2.30.0) ─────────────────────────
287
+ p_bitbucket = subparsers.add_parser(
288
+ "bitbucket",
289
+ help="Bitbucket Data Center / Server credential + workspace management",
290
+ )
291
+ bb_subs = p_bitbucket.add_subparsers(dest="bitbucket_cmd")
292
+
293
+ bb_login = bb_subs.add_parser(
294
+ "login",
295
+ help="Authenticate with a Bitbucket Data Center server (interactive PAT prompt)",
296
+ )
297
+ bb_login.add_argument("--url", required=True, help="Bitbucket server base URL (e.g. https://bitbucket.example.com)")
298
+ bb_login.add_argument("--username", help="Bitbucket username (prompted if omitted)")
299
+ bb_login.add_argument("--token", help="Personal Access Token (prompted via getpass if omitted — preferred)")
300
+ bb_login.add_argument("--no-set-active", action="store_true", help="Do not switch the active account to this one")
301
+ bb_login.add_argument("--insecure", action="store_true", help="Disable TLS verification (self-signed certs)")
302
+ bb_login.add_argument("project_path", nargs="?", default=".")
303
+
304
+ bb_logout = bb_subs.add_parser("logout", help="Remove a Bitbucket account from keyring + config")
305
+ bb_logout.add_argument("--url", help="Bitbucket server base URL (defaults to active account)")
306
+ bb_logout.add_argument("--username", help="Username to log out (defaults to active account)")
307
+ bb_logout.add_argument("project_path", nargs="?", default=".")
308
+
309
+ bb_status = bb_subs.add_parser("status", help="Show configured Bitbucket accounts and connectivity")
310
+ bb_status.add_argument("project_path", nargs="?", default=".")
311
+
312
+ bb_use = bb_subs.add_parser("use", help="Switch the active Bitbucket account")
313
+ bb_use.add_argument("--url", required=True)
314
+ bb_use.add_argument("--username", required=True)
315
+ bb_use.add_argument("project_path", nargs="?", default=".")
316
+
317
+ bb_default = bb_subs.add_parser(
318
+ "set-default",
319
+ help="Set the default project key + repo slug for this C3 project",
320
+ )
321
+ bb_default.add_argument("--project", required=True, help="Bitbucket project key (e.g. PROJ)")
322
+ bb_default.add_argument("--repo", required=True, help="Repository slug")
323
+ bb_default.add_argument("project_path", nargs="?", default=".")
324
+
325
+ # ── Oracle Discovery API (v2.32.0) ──────────────────────────────────
326
+ p_oracle = subparsers.add_parser(
327
+ "oracle",
328
+ help="Oracle Discovery API key + connection management",
329
+ )
330
+ or_subs = p_oracle.add_subparsers(dest="oracle_cmd")
331
+ or_api = or_subs.add_parser(
332
+ "api",
333
+ help="Show connection info / manage the Discovery API key",
334
+ )
335
+ or_api.add_argument(
336
+ "action",
337
+ nargs="?",
338
+ default="info",
339
+ choices=["info", "key", "rotate", "clear"],
340
+ help="info (default): print REST+MCP URLs and a .mcp.json snippet; "
341
+ "key: print the token; rotate: replace it; clear: delete it",
342
+ )
343
+ or_api.add_argument("--port", type=int, default=None, help="Override REST port in printed info")
344
+ or_api.add_argument("--mcp-port", type=int, default=None, help="Override MCP port in printed info")
345
+
286
346
  return parser
@@ -751,6 +751,7 @@
751
751
 
752
752
  <div class="sidebar-section">MCP Server</div>
753
753
  <a href="#mcp-tools">MCP Tools</a>
754
+ <a href="#bitbucket-tool">Bitbucket Integration</a>
754
755
  <a href="#context-tools">Context Manager</a>
755
756
  <a href="#claudemd-tools">Instructions Tools</a>
756
757
  <a href="#agent-tools">Background Agents</a>
@@ -1147,7 +1148,7 @@ python cli/c3.py install-mcp . gemini</code></pre>
1147
1148
 
1148
1149
  <!-- ─── MCP Tools ───────────────────── -->
1149
1150
  <h2 id="mcp-tools">MCP Tools Reference</h2>
1150
- <p>C3 exposes 9 MCP tools. All core tools work without Ollama; delegate requires it.</p>
1151
+ <p>C3 exposes 16 MCP tools. All core tools work without Ollama; delegate requires it. The Bitbucket integration is optional and activated via <code>c3 bitbucket login</code>.</p>
1151
1152
 
1152
1153
  <h3>Discovery &amp; Compression</h3>
1153
1154
  <table>
@@ -1298,6 +1299,41 @@ python cli/c3.py install-mcp . gemini</code></pre>
1298
1299
  View the full timeline at <code>/edits</code>.
1299
1300
  </div>
1300
1301
 
1302
+ <!-- Bitbucket Integration (v2.30.0) -->
1303
+ <h2 id="bitbucket-tool">Bitbucket Data Center / Server</h2>
1304
+ <p>C3 v2.30.0 ships a dedicated <code>c3_bitbucket</code> tool for self-hosted enterprise Bitbucket. It supports read browsing (PRs, branches, builds, activity), PR write actions (create / comment / approve / decline / merge), branch writes, and repository administration (settings, webhooks, permissions). PATs are stored in the OS keyring — never in <code>.c3/config.json</code>.</p>
1305
+
1306
+ <table>
1307
+ <tr><th>Surface</th><th>What it provides</th></tr>
1308
+ <tr><td><code>c3_bitbucket</code> MCP tool</td><td>Action-dispatched Bitbucket calls from Claude Code (27 actions across read / PR-write / branch / admin)</td></tr>
1309
+ <tr><td><code>c3 bitbucket {login,logout,status,use,set-default}</code></td><td>CLI for credential and default-repo management. Login uses <code>getpass</code> for masked PAT entry.</td></tr>
1310
+ <tr><td>Hub UI Bitbucket tab</td><td>Per-project visual browser: Overview, Pull Requests, Branches, Activity, Admin</td></tr>
1311
+ <tr><td><code>/api/bitbucket/*</code> REST endpoints</td><td>Project session-server endpoints proxying to <code>BitbucketDataCenterClient</code></td></tr>
1312
+ </table>
1313
+
1314
+ <div class="tip">
1315
+ <div class="tip-title">Where the token lives</div>
1316
+ Tokens are stored exclusively in the <strong>OS keyring</strong> (Windows Credential Manager / macOS Keychain / Linux Secret Service) under service <code>c3-bitbucket</code>. Only a non-secret index of <code>(base_url, username)</code> pairs and the active-account pointer is written to <code>.c3/config.json</code>. <code>.c3/</code> is gitignored.
1317
+ </div>
1318
+
1319
+ <p><strong>Quick start</strong></p>
1320
+ <pre><code>c3 bitbucket login --url https://bitbucket.example.com
1321
+ c3 bitbucket set-default --project PROJ --repo my-service
1322
+ c3 bitbucket status</code></pre>
1323
+
1324
+ <p>From Claude Code:</p>
1325
+ <pre><code>c3_bitbucket(action='list_prs', state='OPEN')
1326
+ c3_bitbucket(action='get_pr', pr_id=42)
1327
+ c3_bitbucket(action='approve_pr', pr_id=42)
1328
+ c3_bitbucket(action='merge_pr', pr_id=42) # version auto-fetched</code></pre>
1329
+
1330
+ <div class="tip">
1331
+ <div class="tip-title">Audit trail</div>
1332
+ PR merges, branch deletes, webhook writes, and other mutating actions are appended to the C3 edit ledger under the virtual path <code>bitbucket://&lt;project&gt;/&lt;repo&gt;</code> so the local audit trail covers platform-side state changes too. Token text is stripped from logged kwargs before persisting.
1333
+ </div>
1334
+
1335
+ <p>Full reference (action tables, security model, configuration shape, examples, troubleshooting): <a href="/guide/bitbucket.html">Bitbucket integration guide</a>. Currently <strong>Bitbucket Cloud</strong> (<code>bitbucket.org</code>) is not supported — only Data Center / Server.</p>
1336
+
1301
1337
  <h3 id="agent-tools">Background Agents</h3>
1302
1338
  <p>C3 runs 9 autonomous daemon threads that perform periodic analysis and surface findings via a notification
1303
1339
  queue. Notifications are automatically prepended to the next MCP tool response so Claude sees them naturally.
@@ -35,6 +35,16 @@ _PYTHON_TYPE_NAMES = {
35
35
  "Awaitable", "Coroutine", "AsyncIterator", "AsyncGenerator",
36
36
  }
37
37
 
38
+ # Common heredoc / here-string end-markers that leak as filenames when
39
+ # Bash or PowerShell misparses a `<<EOF` / `@'...'@` block. Match is
40
+ # size-agnostic: a non-empty `EOF` file is still a ghost.
41
+ _HEREDOC_MARKERS = {
42
+ "EOF", "EOM", "EOL", "END", "STOP", "DONE",
43
+ "MARK", "MARKER", "DELIM", "DELIMITER",
44
+ "INPUT", "OUTPUT", "DATA", "BLOCK", "HEREDOC",
45
+ "'@", "@'", # PowerShell here-string fragments
46
+ }
47
+
38
48
  # Max file size to consider a ghost (bytes). Genuine files are usually larger.
39
49
  _MAX_GHOST_SIZE = 4096
40
50
 
@@ -108,6 +118,10 @@ def _is_ghost_file(path: Path) -> bool:
108
118
  if name in _PYTHON_TYPE_NAMES:
109
119
  return True
110
120
 
121
+ # HEREDOC end-marker leaked as filename (e.g., "EOF", "'@", "END")
122
+ if name in _HEREDOC_MARKERS and not real_suffix:
123
+ return True
124
+
111
125
  # Partial type annotation (e.g., "tuple[float", "dict[str")
112
126
  if "[" in name and not real_suffix:
113
127
  return True
@@ -154,7 +168,9 @@ def scan_ghost_files(project_root: Path) -> list[dict]:
154
168
  name = entry.name
155
169
 
156
170
  # Determine reason
157
- if name in _PYTHON_TYPE_NAMES:
171
+ if name in _HEREDOC_MARKERS:
172
+ reason = "heredoc end-marker leak"
173
+ elif name in _PYTHON_TYPE_NAMES:
158
174
  reason = "Python type name"
159
175
  elif "[" in name:
160
176
  reason = "partial type annotation"