codegraphcontext 0.1.28__tar.gz → 0.1.31__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 (72) hide show
  1. {codegraphcontext-0.1.28/src/codegraphcontext.egg-info → codegraphcontext-0.1.31}/PKG-INFO +4 -3
  2. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/README.md +3 -2
  3. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/pyproject.toml +1 -1
  4. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/cli/cli_helpers.py +41 -4
  5. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/cli/config_manager.py +86 -23
  6. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/cli/main.py +47 -13
  7. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/cli/setup_wizard.py +49 -8
  8. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/core/database_falkordb.py +21 -3
  9. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/graph_builder.py +7 -0
  10. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/languages/python.py +9 -0
  11. codegraphcontext-0.1.31/src/codegraphcontext/tools/languages/swift.py +479 -0
  12. codegraphcontext-0.1.31/src/codegraphcontext/tools/query_tool_languages/swift_toolkit.py +5 -0
  13. codegraphcontext-0.1.31/src/codegraphcontext/utils/debug_log.py +90 -0
  14. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/utils/tree_sitter_manager.py +2 -0
  15. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31/src/codegraphcontext.egg-info}/PKG-INFO +4 -3
  16. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext.egg-info/SOURCES.txt +3 -0
  17. codegraphcontext-0.1.31/tests/test_swift_parser.py +157 -0
  18. codegraphcontext-0.1.28/src/codegraphcontext/utils/debug_log.py +0 -39
  19. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/LICENSE +0 -0
  20. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/MANIFEST.in +0 -0
  21. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/setup.cfg +0 -0
  22. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/__init__.py +0 -0
  23. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/__main__.py +0 -0
  24. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/cli/__init__.py +0 -0
  25. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/cli/setup_macos.py +0 -0
  26. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/core/__init__.py +0 -0
  27. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/core/database.py +0 -0
  28. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/core/falkor_worker.py +0 -0
  29. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/core/jobs.py +0 -0
  30. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/core/watcher.py +0 -0
  31. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/prompts.py +0 -0
  32. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/server.py +0 -0
  33. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/__init__.py +0 -0
  34. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/advanced_language_query_tool.py +0 -0
  35. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/code_finder.py +0 -0
  36. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/languages/c.py +0 -0
  37. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/languages/cpp.py +0 -0
  38. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/languages/csharp.py +0 -0
  39. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/languages/go.py +0 -0
  40. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/languages/java.py +0 -0
  41. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/languages/javascript.py +0 -0
  42. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/languages/kotlin.py +0 -0
  43. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/languages/php.py +0 -0
  44. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/languages/ruby.py +0 -0
  45. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/languages/rust.py +0 -0
  46. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/languages/scala.py +0 -0
  47. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/languages/typescript.py +0 -0
  48. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/package_resolver.py +0 -0
  49. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/query_tool_languages/c_toolkit.py +0 -0
  50. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/query_tool_languages/cpp_toolkit.py +0 -0
  51. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/query_tool_languages/csharp_toolkit.py +0 -0
  52. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/query_tool_languages/go_toolkit.py +0 -0
  53. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/query_tool_languages/java_toolkit.py +0 -0
  54. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/query_tool_languages/javascript_toolkit.py +0 -0
  55. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/query_tool_languages/python_toolkit.py +0 -0
  56. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/query_tool_languages/ruby_toolkit.py +0 -0
  57. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/query_tool_languages/rust_toolkit.py +0 -0
  58. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/query_tool_languages/scala_toolkit.py +0 -0
  59. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/query_tool_languages/typescript_toolkit.py +0 -0
  60. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext/tools/system.py +0 -0
  61. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext.egg-info/dependency_links.txt +0 -0
  62. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext.egg-info/entry_points.txt +0 -0
  63. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext.egg-info/requires.txt +0 -0
  64. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/src/codegraphcontext.egg-info/top_level.txt +0 -0
  65. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/tests/test_cpp_parser.py +0 -0
  66. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/tests/test_database_validation.py +0 -0
  67. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/tests/test_end_to_end.py +0 -0
  68. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/tests/test_graph_indexing.py +0 -0
  69. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/tests/test_graph_indexing_js.py +0 -0
  70. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/tests/test_kotlin_parser.py +0 -0
  71. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/tests/test_tree_sitter_manager.py +0 -0
  72. {codegraphcontext-0.1.28 → codegraphcontext-0.1.31}/tests/test_typescript_parser.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codegraphcontext
3
- Version: 0.1.28
3
+ Version: 0.1.31
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
@@ -91,7 +91,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
91
91
  ![Using the MCP server](https://github.com/Shashankss1205/CodeGraphContext/blob/main/images/Usecase.gif)
92
92
 
93
93
  ## Project Details
94
- - **Version:** 0.1.28
94
+ - **Version:** 0.1.31
95
95
  - **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
96
96
  - **License:** MIT License (See [LICENSE](LICENSE) for details)
97
97
  - **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
@@ -106,7 +106,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
106
106
  - **Live File Watching:** Watch directories for changes and automatically update the graph in real-time (`cgc watch`).
107
107
  - **Interactive Setup:** A user-friendly command-line wizard for easy setup.
108
108
  - **Dual Mode:** Works as a standalone **CLI toolkit** for developers and as an **MCP server** for AI agents.
109
- - **Multi-Language Support:** Full support for 11 programming languages.
109
+ - **Multi-Language Support:** Full support for 12 programming languages.
110
110
  - **Flexible Database Backend:** FalkorDB Lite (default, inbuilt for Unix and through WSL for Windows) or Neo4j (all platforms via Docker/native).
111
111
 
112
112
 
@@ -126,6 +126,7 @@ CodeGraphContext provides comprehensive parsing and analysis for the following l
126
126
  - **Ruby** (`.rb`)
127
127
  - **PHP** (`.php`)
128
128
  - **Kotlin** (`.kt`) - Full support for classes, objects, companions, functions, and coroutines
129
+ - **Swift** (`.swift`) - Full support for classes, structs, protocols, enums, and generics
129
130
 
130
131
  Each language parser extracts functions, classes, methods, parameters, inheritance relationships, function calls, and imports to build a comprehensive code graph.
131
132
 
@@ -29,7 +29,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
29
29
  ![Using the MCP server](https://github.com/Shashankss1205/CodeGraphContext/blob/main/images/Usecase.gif)
30
30
 
31
31
  ## Project Details
32
- - **Version:** 0.1.28
32
+ - **Version:** 0.1.31
33
33
  - **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
34
34
  - **License:** MIT License (See [LICENSE](LICENSE) for details)
35
35
  - **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
@@ -44,7 +44,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
44
44
  - **Live File Watching:** Watch directories for changes and automatically update the graph in real-time (`cgc watch`).
45
45
  - **Interactive Setup:** A user-friendly command-line wizard for easy setup.
46
46
  - **Dual Mode:** Works as a standalone **CLI toolkit** for developers and as an **MCP server** for AI agents.
47
- - **Multi-Language Support:** Full support for 11 programming languages.
47
+ - **Multi-Language Support:** Full support for 12 programming languages.
48
48
  - **Flexible Database Backend:** FalkorDB Lite (default, inbuilt for Unix and through WSL for Windows) or Neo4j (all platforms via Docker/native).
49
49
 
50
50
 
@@ -64,6 +64,7 @@ CodeGraphContext provides comprehensive parsing and analysis for the following l
64
64
  - **Ruby** (`.rb`)
65
65
  - **PHP** (`.php`)
66
66
  - **Kotlin** (`.kt`) - Full support for classes, objects, companions, functions, and coroutines
67
+ - **Swift** (`.swift`) - Full support for classes, structs, protocols, enums, and generics
67
68
 
68
69
  Each language parser extracts functions, classes, methods, parameters, inheritance relationships, function calls, and imports to build a comprehensive code graph.
69
70
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codegraphcontext"
3
- version = "0.1.28"
3
+ version = "0.1.31"
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"
@@ -61,10 +61,28 @@ def index_helper(path: str):
61
61
  return
62
62
 
63
63
  indexed_repos = code_finder.list_indexed_repositories()
64
- if any(Path(repo["path"]).resolve() == path_obj for repo in indexed_repos):
65
- console.print(f"[yellow]Repository '{path}' is already indexed. Skipping.[/yellow]")
66
- db_manager.close_driver()
67
- return
64
+ repo_exists = any(Path(repo["path"]).resolve() == path_obj for repo in indexed_repos)
65
+
66
+ if repo_exists:
67
+ # Check if the repository actually has files (not just an empty node from interrupted indexing)
68
+ try:
69
+ with db_manager.get_driver().session() as session:
70
+ result = session.run(
71
+ "MATCH (r:Repository {path: $path})-[:CONTAINS]->(f:File) RETURN count(f) as file_count",
72
+ path=str(path_obj)
73
+ )
74
+ record = result.single()
75
+ file_count = record["file_count"] if record else 0
76
+
77
+ if file_count > 0:
78
+ console.print(f"[yellow]Repository '{path}' is already indexed with {file_count} files. Skipping.[/yellow]")
79
+ console.print("[dim]💡 Tip: Use 'cgc index --force' to re-index[/dim]")
80
+ db_manager.close_driver()
81
+ return
82
+ else:
83
+ console.print(f"[yellow]Repository '{path}' exists but has no files (likely interrupted). Re-indexing...[/yellow]")
84
+ except Exception as e:
85
+ console.print(f"[yellow]Warning: Could not check file count: {e}. Proceeding with indexing...[/yellow]")
68
86
 
69
87
  console.print(f"Starting indexing for: {path_obj}")
70
88
  console.print("[yellow]This may take a few minutes for large repositories...[/yellow]")
@@ -77,6 +95,19 @@ def index_helper(path: str):
77
95
  time_end = time.time()
78
96
  elapsed = time_end - time_start
79
97
  console.print(f"[green]Successfully finished indexing: {path} in {elapsed:.2f} seconds[/green]")
98
+
99
+ # Check if auto-watch is enabled
100
+ try:
101
+ from codegraphcontext.cli.config_manager import get_config_value
102
+ auto_watch = get_config_value('ENABLE_AUTO_WATCH')
103
+ if auto_watch and str(auto_watch).lower() == 'true':
104
+ console.print("\n[cyan]🔍 ENABLE_AUTO_WATCH is enabled. Starting watcher...[/cyan]")
105
+ db_manager.close_driver() # Close before starting watcher
106
+ watch_helper(path) # This will block the terminal
107
+ return # watch_helper handles its own cleanup
108
+ except Exception as e:
109
+ console.print(f"[yellow]Warning: Could not check ENABLE_AUTO_WATCH: {e}[/yellow]")
110
+
80
111
  except Exception as e:
81
112
  console.print(f"[bold red]An error occurred during indexing:[/bold red] {e}")
82
113
  finally:
@@ -519,8 +550,14 @@ def stats_helper(path: str = None):
519
550
 
520
551
  def watch_helper(path: str):
521
552
  """Watch a directory for changes and auto-update the graph (blocking mode)."""
553
+ import logging
522
554
  from ..core.watcher import CodeWatcher
523
555
 
556
+ # Suppress verbose watchdog DEBUG logs
557
+ logging.getLogger('watchdog').setLevel(logging.WARNING)
558
+ logging.getLogger('watchdog.observers').setLevel(logging.WARNING)
559
+ logging.getLogger('watchdog.observers.inotify_buffer').setLevel(logging.WARNING)
560
+
524
561
  services = _initialize_services()
525
562
  if not all(services):
526
563
  return
@@ -21,9 +21,13 @@ DATABASE_CREDENTIAL_KEYS = {"NEO4J_URI", "NEO4J_USERNAME", "NEO4J_PASSWORD"}
21
21
  # Default configuration values
22
22
  DEFAULT_CONFIG = {
23
23
  "DEFAULT_DATABASE": "falkordb",
24
+ "FALKORDB_PATH": str(CONFIG_DIR / "falkordb.db"),
25
+ "FALKORDB_SOCKET_PATH": str(CONFIG_DIR / "falkordb.sock"),
24
26
  "INDEX_VARIABLES": "true",
25
27
  "ALLOW_DB_DELETION": "false",
26
28
  "DEBUG_LOGS": "false",
29
+ "DEBUG_LOG_PATH": str(Path.home() / "mcp_debug.log"),
30
+ "ENABLE_APP_LOGS": "CRITICAL",
27
31
  "LOG_FILE_PATH": str(CONFIG_DIR / "logs" / "cgc.log"),
28
32
  "MAX_FILE_SIZE_MB": "10",
29
33
  "IGNORE_TEST_FILES": "false",
@@ -39,10 +43,14 @@ DEFAULT_CONFIG = {
39
43
  # Configuration key descriptions
40
44
  CONFIG_DESCRIPTIONS = {
41
45
  "DEFAULT_DATABASE": "Default database backend (neo4j|falkordb)",
46
+ "FALKORDB_PATH": "Path to FalkorDB database file",
47
+ "FALKORDB_SOCKET_PATH": "Path to FalkorDB Unix socket",
42
48
  "INDEX_VARIABLES": "Index variable nodes in the graph (lighter graph if false)",
43
49
  "ALLOW_DB_DELETION": "Allow full database deletion commands",
44
- "DEBUG_LOGS": "Enable debug logging",
45
- "LOG_FILE_PATH": "Path to save log files",
50
+ "DEBUG_LOGS": "Enable debug logging (for development/troubleshooting)",
51
+ "DEBUG_LOG_PATH": "Path to debug log file",
52
+ "ENABLE_APP_LOGS": "Application log level (DEBUG|INFO|WARNING|ERROR|CRITICAL|DISABLED)",
53
+ "LOG_FILE_PATH": "Path to application log file",
46
54
  "MAX_FILE_SIZE_MB": "Maximum file size to index (in MB)",
47
55
  "IGNORE_TEST_FILES": "Skip test files during indexing",
48
56
  "IGNORE_HIDDEN_FILES": "Skip hidden files/directories",
@@ -60,6 +68,7 @@ CONFIG_VALIDATORS = {
60
68
  "INDEX_VARIABLES": ["true", "false"],
61
69
  "ALLOW_DB_DELETION": ["true", "false"],
62
70
  "DEBUG_LOGS": ["true", "false"],
71
+ "ENABLE_APP_LOGS": ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "DISABLED"],
63
72
  "IGNORE_TEST_FILES": ["true", "false"],
64
73
  "IGNORE_HIDDEN_FILES": ["true", "false"],
65
74
  "ENABLE_AUTO_WATCH": ["true", "false"],
@@ -74,34 +83,76 @@ def ensure_config_dir():
74
83
 
75
84
 
76
85
  def load_config() -> Dict[str, str]:
77
- """Load configuration from file, creating with defaults if not exists."""
86
+ """
87
+ Load configuration with priority support.
88
+ Priority order (highest to lowest):
89
+ 1. Environment variables
90
+ 2. Local .env file (in current or parent directories)
91
+ 3. Global ~/.codegraphcontext/.env
92
+ """
78
93
  ensure_config_dir()
79
94
 
80
- if not CONFIG_FILE.exists():
81
- # Create with defaults
82
- save_config(DEFAULT_CONFIG)
83
- return DEFAULT_CONFIG.copy()
95
+ # Start with defaults
96
+ config = DEFAULT_CONFIG.copy()
84
97
 
85
- config = {}
86
- try:
87
- with open(CONFIG_FILE, "r") as f:
88
- for line in f:
89
- line = line.strip()
90
- if line and not line.startswith("#") and "=" in line:
91
- key, value = line.split("=", 1)
92
- config[key.strip()] = value.strip()
93
- except Exception as e:
94
- console.print(f"[red]Error loading config: {e}[/red]")
95
- return DEFAULT_CONFIG.copy()
98
+ # Load global config
99
+ if CONFIG_FILE.exists():
100
+ try:
101
+ with open(CONFIG_FILE, "r") as f:
102
+ for line in f:
103
+ line = line.strip()
104
+ if line and not line.startswith("#") and "=" in line:
105
+ key, value = line.split("=", 1)
106
+ config[key.strip()] = value.strip()
107
+ except Exception as e:
108
+ console.print(f"[red]Error loading global config: {e}[/red]")
96
109
 
97
- # Merge with defaults for any missing keys
98
- for key, default_value in DEFAULT_CONFIG.items():
99
- if key not in config:
100
- config[key] = default_value
110
+ # Load local .env file if it exists (overrides global)
111
+ local_env = find_local_env()
112
+ if local_env and local_env.exists():
113
+ try:
114
+ with open(local_env, "r") as f:
115
+ for line in f:
116
+ line = line.strip()
117
+ if line and not line.startswith("#") and "=" in line:
118
+ key, value = line.split("=", 1)
119
+ key = key.strip()
120
+ # Only override if it's a config key (not database credentials in local file)
121
+ if key in DEFAULT_CONFIG or key in DATABASE_CREDENTIAL_KEYS:
122
+ config[key] = value.strip()
123
+ except Exception as e:
124
+ console.print(f"[yellow]Warning: Error loading local .env: {e}[/yellow]")
125
+
126
+ # Environment variables have highest priority
127
+ for key in DEFAULT_CONFIG.keys():
128
+ env_value = os.getenv(key)
129
+ if env_value is not None:
130
+ config[key] = env_value
101
131
 
102
132
  return config
103
133
 
104
134
 
135
+ def find_local_env() -> Optional[Path]:
136
+ """
137
+ Find a local .env file by searching current directory and parents.
138
+ Returns the first .env file found, or None.
139
+ """
140
+ current = Path.cwd()
141
+
142
+ # Search up to 5 levels up
143
+ for _ in range(5):
144
+ env_file = current / ".env"
145
+ if env_file.exists() and env_file != CONFIG_FILE:
146
+ return env_file
147
+
148
+ # Stop at root
149
+ if current.parent == current:
150
+ break
151
+ current = current.parent
152
+
153
+ return None
154
+
155
+
105
156
  def save_config(config: Dict[str, str], preserve_db_credentials: bool = True):
106
157
  """
107
158
  Save configuration to file.
@@ -211,7 +262,7 @@ def validate_config_value(key: str, value: str) -> tuple[bool, Optional[str]]:
211
262
  except ValueError:
212
263
  return False, "MAX_DEPTH must be 'unlimited' or a number"
213
264
 
214
- if key == "LOG_FILE_PATH":
265
+ if key in ("LOG_FILE_PATH", "DEBUG_LOG_PATH"):
215
266
  # Validate path is writable
216
267
  log_path = Path(value)
217
268
  try:
@@ -219,6 +270,18 @@ def validate_config_value(key: str, value: str) -> tuple[bool, Optional[str]]:
219
270
  except Exception as e:
220
271
  return False, f"Cannot create log directory: {e}"
221
272
 
273
+ if key in ("FALKORDB_PATH", "FALKORDB_SOCKET_PATH"):
274
+ # Validate path is writable
275
+ db_path = Path(value)
276
+ try:
277
+ db_path.parent.mkdir(parents=True, exist_ok=True)
278
+ except Exception as e:
279
+ return False, f"Cannot create directory for {key}: {e}"
280
+
281
+ # Check if parent directory is writable
282
+ if not os.access(db_path.parent, os.W_OK):
283
+ return False, f"Directory {db_path.parent} is not writable"
284
+
222
285
  return True, None
223
286
 
224
287
 
@@ -188,13 +188,13 @@ def neo4j_setup_alias():
188
188
 
189
189
  def _load_credentials():
190
190
  """
191
- Loads Neo4j credentials from various sources into environment variables.
191
+ Loads configuration and credentials from various sources into environment variables.
192
192
  Priority order:
193
193
  1. Local `mcp.json`
194
194
  2. Global `~/.codegraphcontext/.env`
195
195
  3. Any `.env` file found in the directory tree.
196
196
  """
197
- # 1. Prefer loading from mcp.json
197
+ # 1. Prefer loading from mcp.json (always uses Neo4j when present)
198
198
  mcp_file_path = Path.cwd() / "mcp.json"
199
199
  if mcp_file_path.exists():
200
200
  try:
@@ -203,7 +203,8 @@ def _load_credentials():
203
203
  server_env = mcp_config.get("mcpServers", {}).get("CodeGraphContext", {}).get("env", {})
204
204
  for key, value in server_env.items():
205
205
  os.environ[key] = value
206
- console.print("[green]Loaded Neo4j credentials from local mcp.json.[/green]")
206
+ console.print("[dim]Loaded configuration from local mcp.json[/dim]")
207
+ console.print("[cyan]Using database: Neo4j[/cyan]")
207
208
  return
208
209
  except Exception as e:
209
210
  console.print(f"[bold red]Error loading mcp.json:[/bold red] {e}")
@@ -213,7 +214,22 @@ def _load_credentials():
213
214
  if global_env_path.exists():
214
215
  try:
215
216
  load_dotenv(dotenv_path=global_env_path)
216
- console.print(f"[green]Loaded Neo4j credentials from global .env file: {global_env_path}[/green]")
217
+ console.print(f"[dim]Loaded configuration from: {global_env_path}[/dim]")
218
+
219
+ # Show which database is actually being used
220
+ default_db = os.environ.get("DEFAULT_DATABASE", "falkordb").lower()
221
+ if default_db == "neo4j":
222
+ has_neo4j_creds = all([
223
+ os.environ.get("NEO4J_URI"),
224
+ os.environ.get("NEO4J_USERNAME"),
225
+ os.environ.get("NEO4J_PASSWORD")
226
+ ])
227
+ if has_neo4j_creds:
228
+ console.print("[cyan]Using database: Neo4j[/cyan]")
229
+ else:
230
+ console.print("[yellow]⚠ DEFAULT_DATABASE=neo4j but credentials not found. Falling back to FalkorDB.[/yellow]")
231
+ else:
232
+ console.print("[cyan]Using database: FalkorDB[/cyan]")
217
233
  return
218
234
  except Exception as e:
219
235
  console.print(f"[bold red]Error loading global .env file from {global_env_path}:[/bold red] {e}")
@@ -223,9 +239,25 @@ def _load_credentials():
223
239
  dotenv_path = find_dotenv(usecwd=True, raise_error_if_not_found=False)
224
240
  if dotenv_path:
225
241
  load_dotenv(dotenv_path)
226
- console.print(f"[green]Loaded Neo4j credentials from discovered .env file: {dotenv_path}[/green]")
242
+ console.print(f"[dim]Loaded configuration from: {dotenv_path}[/dim]")
243
+
244
+ # Show which database is actually being used
245
+ default_db = os.environ.get("DEFAULT_DATABASE", "falkordb").lower()
246
+ if default_db == "neo4j":
247
+ has_neo4j_creds = all([
248
+ os.environ.get("NEO4J_URI"),
249
+ os.environ.get("NEO4J_USERNAME"),
250
+ os.environ.get("NEO4J_PASSWORD")
251
+ ])
252
+ if has_neo4j_creds:
253
+ console.print("[cyan]Using database: Neo4j[/cyan]")
254
+ else:
255
+ console.print("[yellow]⚠ DEFAULT_DATABASE=neo4j but credentials not found. Falling back to FalkorDB.[/yellow]")
256
+ else:
257
+ console.print("[cyan]Using database: FalkorDB[/cyan]")
227
258
  else:
228
- console.print("[yellow]No local mcp.json or .env file found. Credentials may not be set.[/yellow]")
259
+ console.print("[yellow]No configuration file found. Using defaults.[/yellow]")
260
+ console.print("[cyan]Using database: FalkorDB (default)[/cyan]")
229
261
  except Exception as e:
230
262
  console.print(f"[bold red]Error loading .env file:[/bold red] {e}")
231
263
 
@@ -1648,16 +1680,18 @@ def main(
1648
1680
 
1649
1681
  if ctx.invoked_subcommand is None:
1650
1682
  console.print("[bold green]👋 Welcome to CodeGraphContext (cgc)![/bold green]\n")
1651
- console.print(" [bold]Quick Start (with FalkorDB):[/bold]")
1683
+ console.print("CodeGraphContext is both an [bold cyan]MCP server[/bold cyan] and a [bold cyan]CLI toolkit[/bold cyan] for code analysis.\n")
1684
+ console.print("🤖 [bold]For MCP Server Mode (AI assistants):[/bold]")
1652
1685
  console.print(" 1. Run [cyan]cgc mcp setup[/cyan] (or [cyan]cgc m[/cyan]) to configure your IDE")
1653
- console.print(" 2. Run [cyan]cgc start[/cyan] to launch the server\n")
1654
- console.print("📊 [bold]Using Neo4j instead?[/bold]")
1655
- console.print(" 1. Run [cyan]cgc neo4j setup[/cyan] (or [cyan]cgc n[/cyan]) to configure Neo4j")
1656
- console.print(" 2. Run [cyan]cgc mcp setup[/cyan] to configure your IDE")
1657
- console.print(" 3. Run [cyan]cgc start[/cyan] to launch the server\n")
1686
+ console.print(" 2. Run [cyan]cgc mcp start[/cyan] to launch the server\n")
1687
+ console.print("🛠️ [bold]For CLI Toolkit Mode (direct usage):[/bold]")
1688
+ console.print(" [cyan]cgc index .[/cyan] - Index your current directory")
1689
+ console.print(" [cyan]cgc list[/cyan] - List indexed repositories\n")
1690
+ console.print("📊 [bold]Using Neo4j instead of FalkorDB?[/bold]")
1691
+ console.print(" Run [cyan]cgc neo4j setup[/cyan] (or [cyan]cgc n[/cyan]) to configure Neo4j\n")
1658
1692
  console.print("👉 Run [cyan]cgc help[/cyan] to see all available commands")
1659
1693
  console.print("👉 Run [cyan]cgc --version[/cyan] to check the version\n")
1660
- console.print("👉 Running [green]codegraphcontext [white]works the same as using [green]cgc[/white]")
1694
+ console.print("👉 Running [green]codegraphcontext[/green] works the same as using [green]cgc[/green]")
1661
1695
 
1662
1696
 
1663
1697
  if __name__ == "__main__":
@@ -313,30 +313,71 @@ def run_neo4j_setup_wizard():
313
313
  def configure_mcp_client():
314
314
  """
315
315
  Configure MCP client (IDE/CLI) integration.
316
- This function sets up the MCP server configuration for the user's IDE without requiring Neo4j credentials.
317
- Works with FalkorDB by default.
316
+ This function sets up the MCP server configuration for the user's IDE.
317
+ Includes all current configuration values in the env section.
318
318
  """
319
319
  console.print("[bold cyan]MCP Client Configuration[/bold cyan]\n")
320
320
  console.print("This will configure CodeGraphContext integration with your IDE or CLI tool.")
321
321
  console.print("CodeGraphContext works with FalkorDB by default (no database setup needed).\n")
322
322
 
323
- # Generate MCP configuration without Neo4j credentials (for FalkorDB use)
323
+ # Load current configuration (includes project-local .env if present)
324
+ try:
325
+ from codegraphcontext.cli.config_manager import load_config
326
+ config = load_config()
327
+ except Exception as e:
328
+ console.print(f"[yellow]Warning: Could not load configuration: {e}[/yellow]")
329
+ config = {}
330
+
331
+ # Build env section with all configuration values
332
+ env_vars = {}
333
+
334
+ # Add database credentials if they exist
335
+ env_file = Path.home() / ".codegraphcontext" / ".env"
336
+ if env_file.exists():
337
+ try:
338
+ with open(env_file, "r") as f:
339
+ for line in f:
340
+ line = line.strip()
341
+ if line and not line.startswith("#") and "=" in line:
342
+ key, value = line.split("=", 1)
343
+ key = key.strip()
344
+ if key in ["NEO4J_URI", "NEO4J_USERNAME", "NEO4J_PASSWORD"]:
345
+ env_vars[key] = value.strip()
346
+ except Exception:
347
+ pass
348
+
349
+ # Add all configuration values, converting relative paths to absolute
350
+ for key, value in config.items():
351
+ # Skip database credentials (already added above)
352
+ if key in ["NEO4J_URI", "NEO4J_USERNAME", "NEO4J_PASSWORD"]:
353
+ continue
354
+
355
+ # Convert relative paths to absolute for path-related configs
356
+ if "PATH" in key and value:
357
+ path_obj = Path(value)
358
+ if not path_obj.is_absolute():
359
+ value = str(path_obj.resolve())
360
+
361
+ env_vars[key] = value
362
+
363
+ # Generate MCP configuration
324
364
  cgc_path = shutil.which("cgc") or sys.executable
325
365
 
326
366
  if "python" in Path(cgc_path).name:
327
367
  # fallback to running as module if no cgc binary is found
328
368
  command = cgc_path
329
- args = ["-m", "cgc", "start"]
369
+ args = ["-m", "cgc", "mcp", "start"]
330
370
  else:
331
371
  command = cgc_path
332
- args = ["start"]
372
+ args = ["mcp", "start"]
333
373
 
334
- # Create MCP config without Neo4j env vars (uses FalkorDB by default)
374
+ # Create MCP config with complete env section
335
375
  mcp_config = {
336
376
  "mcpServers": {
337
377
  "CodeGraphContext": {
338
378
  "command": command,
339
379
  "args": args,
380
+ "env": env_vars,
340
381
  "tools": {
341
382
  "alwaysAllow": [
342
383
  "add_code_to_graph", "add_package_to_graph",
@@ -369,8 +410,8 @@ def configure_mcp_client():
369
410
  _configure_ide(mcp_config)
370
411
 
371
412
  console.print("\n[bold green]✅ MCP Client configuration complete![/bold green]")
372
- console.print("[cyan]You can now run 'cgc start' to launch the server with FalkorDB.[/cyan]")
373
- console.print("[yellow]Note: If you want to use Neo4j instead, run 'cgc neo4j setup' first.[/yellow]\n")
413
+ console.print("[cyan]You can now run 'cgc mcp start' to launch the server.[/cyan]")
414
+ console.print("[yellow]💡 Tip: To update MCP config after changing settings, re-run 'cgc mcp setup'[/yellow]\n")
374
415
 
375
416
 
376
417
  def find_latest_neo4j_creds_file():
@@ -42,15 +42,33 @@ class FalkorDBManager:
42
42
  if hasattr(self, '_initialized'):
43
43
  return
44
44
 
45
- # Default database path in user's home directory
45
+ # Configuration priority:
46
+ # 1. Environment variable (highest priority)
47
+ # 2. Config manager (supports project-local .env)
48
+ # 3. Default path (lowest priority)
49
+
50
+ # Try to load from config manager
51
+ try:
52
+ from codegraphcontext.cli.config_manager import get_config_value
53
+ config_db_path = get_config_value('FALKORDB_PATH')
54
+ config_socket_path = get_config_value('FALKORDB_SOCKET_PATH')
55
+ except Exception:
56
+ # Config manager not available or error loading
57
+ config_db_path = None
58
+ config_socket_path = None
59
+
60
+ # Database path with fallback chain
46
61
  self.db_path = os.getenv(
47
62
  'FALKORDB_PATH',
48
- str(Path.home() / '.codegraphcontext' / 'falkordb.db')
63
+ config_db_path or str(Path.home() / '.codegraphcontext' / 'falkordb.db')
49
64
  )
65
+
66
+ # Socket path with fallback chain
50
67
  self.socket_path = os.getenv(
51
68
  'FALKORDB_SOCKET_PATH',
52
- str(Path.home() / '.codegraphcontext' / 'falkordb.sock')
69
+ config_socket_path or str(Path.home() / '.codegraphcontext' / 'falkordb.sock')
53
70
  )
71
+
54
72
  self.graph_name = os.getenv('FALKORDB_GRAPH_NAME', 'codegraph')
55
73
  self._initialized = True
56
74
 
@@ -67,6 +67,9 @@ class TreeSitterParser:
67
67
  elif self.language_name == 'scala':
68
68
  from .languages.scala import ScalaTreeSitterParser
69
69
  self.language_specific_parser = ScalaTreeSitterParser(self)
70
+ elif self.language_name == 'swift':
71
+ from .languages.swift import SwiftTreeSitterParser
72
+ self.language_specific_parser = SwiftTreeSitterParser(self)
70
73
 
71
74
 
72
75
 
@@ -110,6 +113,7 @@ class GraphBuilder:
110
113
  '.kt': TreeSitterParser('kotlin'),
111
114
  '.scala': TreeSitterParser('scala'),
112
115
  '.sc': TreeSitterParser('scala'),
116
+ '.swift': TreeSitterParser('swift'),
113
117
  }
114
118
  self.create_schema()
115
119
 
@@ -224,6 +228,9 @@ class GraphBuilder:
224
228
  if '.sc' in files_by_lang:
225
229
  from .languages import scala as scala_lang_module
226
230
  imports_map.update(scala_lang_module.pre_scan_scala(files_by_lang['.sc'], self.parsers['.sc']))
231
+ if '.swift' in files_by_lang:
232
+ from .languages import swift as swift_lang_module
233
+ imports_map.update(swift_lang_module.pre_scan_swift(files_by_lang['.swift'], self.parsers['.swift']))
227
234
 
228
235
  return imports_map
229
236
 
@@ -5,9 +5,18 @@ from nbconvert import PythonExporter
5
5
  from pathlib import Path
6
6
  from typing import Any, Dict, Optional, Tuple
7
7
  import ast
8
+ import logging
9
+ import warnings
8
10
  from codegraphcontext.utils.debug_log import debug_log, info_logger, error_logger, warning_logger, debug_logger
9
11
  from codegraphcontext.utils.tree_sitter_manager import execute_query
10
12
 
13
+ # Suppress verbose traitlets/nbconvert DEBUG logs
14
+ logging.getLogger('traitlets').setLevel(logging.WARNING)
15
+ logging.getLogger('nbconvert').setLevel(logging.WARNING)
16
+
17
+ # Suppress IPython UserWarning from nbconvert
18
+ warnings.filterwarnings('ignore', message='.*IPython is needed to transform IPython syntax.*')
19
+
11
20
 
12
21
  PY_QUERIES = {
13
22
  "imports": """