#
tokens: 27285/50000 1/422 files (page 19/22)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 19 of 22. Use http://codebase.md/shashankss1205/codegraphcontext?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .cgcignore
├── .github
│   ├── FUNDING.yml
│   └── workflows
│       ├── e2e-tests.yml
│       ├── post_discord_invite.yml
│       ├── test.yml
│       └── update-contributors.yml
├── .gitignore
├── CLI_Commands.md
├── CONTRIBUTING.md
├── contributors.md
├── docs
│   ├── docs
│   │   ├── architecture.md
│   │   ├── cli.md
│   │   ├── contributing_languages.md
│   │   ├── contributing.md
│   │   ├── cookbook.md
│   │   ├── core.md
│   │   ├── future_work.md
│   │   ├── images
│   │   │   ├── 1.png
│   │   │   ├── 11.png
│   │   │   ├── 12.png
│   │   │   ├── 13.png
│   │   │   ├── 14.png
│   │   │   ├── 16.png
│   │   │   ├── 19.png
│   │   │   ├── 2.png
│   │   │   ├── 20.png
│   │   │   ├── 21.png
│   │   │   ├── 22.png
│   │   │   ├── 23.png
│   │   │   ├── 24.png
│   │   │   ├── 26.png
│   │   │   ├── 28.png
│   │   │   ├── 29.png
│   │   │   ├── 3.png
│   │   │   ├── 30.png
│   │   │   ├── 31.png
│   │   │   ├── 32.png
│   │   │   ├── 33.png
│   │   │   ├── 34.png
│   │   │   ├── 35.png
│   │   │   ├── 36.png
│   │   │   ├── 38.png
│   │   │   ├── 39.png
│   │   │   ├── 4.png
│   │   │   ├── 40.png
│   │   │   ├── 41.png
│   │   │   ├── 42.png
│   │   │   ├── 43.png
│   │   │   ├── 44.png
│   │   │   ├── 5.png
│   │   │   ├── 6.png
│   │   │   ├── 7.png
│   │   │   ├── 8.png
│   │   │   ├── 9.png
│   │   │   ├── Indexing.gif
│   │   │   ├── tool_images
│   │   │   │   ├── 1.png
│   │   │   │   ├── 2.png
│   │   │   │   └── 3.png
│   │   │   └── Usecase.gif
│   │   ├── index.md
│   │   ├── installation.md
│   │   ├── license.md
│   │   ├── server.md
│   │   ├── tools.md
│   │   ├── troubleshooting.md
│   │   ├── use_cases.md
│   │   └── watching.md
│   ├── mkdocs.yml
│   └── site
│       ├── 404.html
│       ├── architecture
│       │   └── index.html
│       ├── assets
│       │   ├── images
│       │   │   └── favicon.png
│       │   ├── javascripts
│       │   │   ├── bundle.79ae519e.min.js
│       │   │   ├── bundle.79ae519e.min.js.map
│       │   │   ├── lunr
│       │   │   │   ├── min
│       │   │   │   │   ├── lunr.ar.min.js
│       │   │   │   │   ├── lunr.da.min.js
│       │   │   │   │   ├── lunr.de.min.js
│       │   │   │   │   ├── lunr.du.min.js
│       │   │   │   │   ├── lunr.el.min.js
│       │   │   │   │   ├── lunr.es.min.js
│       │   │   │   │   ├── lunr.fi.min.js
│       │   │   │   │   ├── lunr.fr.min.js
│       │   │   │   │   ├── lunr.he.min.js
│       │   │   │   │   ├── lunr.hi.min.js
│       │   │   │   │   ├── lunr.hu.min.js
│       │   │   │   │   ├── lunr.hy.min.js
│       │   │   │   │   ├── lunr.it.min.js
│       │   │   │   │   ├── lunr.ja.min.js
│       │   │   │   │   ├── lunr.jp.min.js
│       │   │   │   │   ├── lunr.kn.min.js
│       │   │   │   │   ├── lunr.ko.min.js
│       │   │   │   │   ├── lunr.multi.min.js
│       │   │   │   │   ├── lunr.nl.min.js
│       │   │   │   │   ├── lunr.no.min.js
│       │   │   │   │   ├── lunr.pt.min.js
│       │   │   │   │   ├── lunr.ro.min.js
│       │   │   │   │   ├── lunr.ru.min.js
│       │   │   │   │   ├── lunr.sa.min.js
│       │   │   │   │   ├── lunr.stemmer.support.min.js
│       │   │   │   │   ├── lunr.sv.min.js
│       │   │   │   │   ├── lunr.ta.min.js
│       │   │   │   │   ├── lunr.te.min.js
│       │   │   │   │   ├── lunr.th.min.js
│       │   │   │   │   ├── lunr.tr.min.js
│       │   │   │   │   ├── lunr.vi.min.js
│       │   │   │   │   └── lunr.zh.min.js
│       │   │   │   ├── tinyseg.js
│       │   │   │   └── wordcut.js
│       │   │   └── workers
│       │   │       ├── search.2c215733.min.js
│       │   │       └── search.2c215733.min.js.map
│       │   └── stylesheets
│       │       ├── main.484c7ddc.min.css
│       │       ├── main.484c7ddc.min.css.map
│       │       ├── palette.ab4e12ef.min.css
│       │       └── palette.ab4e12ef.min.css.map
│       ├── cli
│       │   └── index.html
│       ├── contributing
│       │   └── index.html
│       ├── contributing_languages
│       │   └── index.html
│       ├── cookbook
│       │   └── index.html
│       ├── core
│       │   └── index.html
│       ├── future_work
│       │   └── index.html
│       ├── images
│       │   ├── 1.png
│       │   ├── 11.png
│       │   ├── 12.png
│       │   ├── 13.png
│       │   ├── 14.png
│       │   ├── 16.png
│       │   ├── 19.png
│       │   ├── 2.png
│       │   ├── 20.png
│       │   ├── 21.png
│       │   ├── 22.png
│       │   ├── 23.png
│       │   ├── 24.png
│       │   ├── 26.png
│       │   ├── 28.png
│       │   ├── 29.png
│       │   ├── 3.png
│       │   ├── 30.png
│       │   ├── 31.png
│       │   ├── 32.png
│       │   ├── 33.png
│       │   ├── 34.png
│       │   ├── 35.png
│       │   ├── 36.png
│       │   ├── 38.png
│       │   ├── 39.png
│       │   ├── 4.png
│       │   ├── 40.png
│       │   ├── 41.png
│       │   ├── 42.png
│       │   ├── 43.png
│       │   ├── 44.png
│       │   ├── 5.png
│       │   ├── 6.png
│       │   ├── 7.png
│       │   ├── 8.png
│       │   ├── 9.png
│       │   ├── Indexing.gif
│       │   ├── tool_images
│       │   │   ├── 1.png
│       │   │   ├── 2.png
│       │   │   └── 3.png
│       │   └── Usecase.gif
│       ├── index.html
│       ├── installation
│       │   └── index.html
│       ├── license
│       │   └── index.html
│       ├── search
│       │   └── search_index.json
│       ├── server
│       │   └── index.html
│       ├── sitemap.xml
│       ├── sitemap.xml.gz
│       ├── tools
│       │   └── index.html
│       ├── troubleshooting
│       │   └── index.html
│       ├── use_cases
│       │   └── index.html
│       └── watching
│           └── index.html
├── funding.json
├── images
│   ├── 1.png
│   ├── 11.png
│   ├── 12.png
│   ├── 13.png
│   ├── 14.png
│   ├── 16.png
│   ├── 19.png
│   ├── 2.png
│   ├── 20.png
│   ├── 21.png
│   ├── 22.png
│   ├── 23.png
│   ├── 24.png
│   ├── 26.png
│   ├── 28.png
│   ├── 29.png
│   ├── 3.png
│   ├── 30.png
│   ├── 31.png
│   ├── 32.png
│   ├── 33.png
│   ├── 34.png
│   ├── 35.png
│   ├── 36.png
│   ├── 38.png
│   ├── 39.png
│   ├── 4.png
│   ├── 40.png
│   ├── 41.png
│   ├── 42.png
│   ├── 43.png
│   ├── 44.png
│   ├── 5.png
│   ├── 6.png
│   ├── 7.png
│   ├── 8.png
│   ├── 9.png
│   ├── Indexing.gif
│   ├── tool_images
│   │   ├── 1.png
│   │   ├── 2.png
│   │   └── 3.png
│   └── Usecase.gif
├── LICENSE
├── MANIFEST.in
├── organizer
│   ├── CONTRIBUTING_LANGUAGES.md
│   ├── cookbook.md
│   ├── docs.md
│   ├── language_specific_nodes.md
│   ├── Tools_Exploration.md
│   └── troubleshoot.md
├── pyproject.toml
├── README.md
├── scripts
│   ├── generate_lang_contributors.py
│   ├── post_install_fix.sh
│   ├── test_all_parsers.py
│   └── update_language_parsers.py
├── SECURITY.md
├── src
│   └── codegraphcontext
│       ├── __init__.py
│       ├── __main__.py
│       ├── cli
│       │   ├── __init__.py
│       │   ├── cli_helpers.py
│       │   ├── config_manager.py
│       │   ├── main.py
│       │   ├── setup_macos.py
│       │   └── setup_wizard.py
│       ├── core
│       │   ├── __init__.py
│       │   ├── database_falkordb.py
│       │   ├── database.py
│       │   ├── falkor_worker.py
│       │   ├── jobs.py
│       │   └── watcher.py
│       ├── prompts.py
│       ├── server.py
│       ├── tools
│       │   ├── __init__.py
│       │   ├── advanced_language_query_tool.py
│       │   ├── code_finder.py
│       │   ├── graph_builder.py
│       │   ├── languages
│       │   │   ├── c.py
│       │   │   ├── cpp.py
│       │   │   ├── csharp.py
│       │   │   ├── go.py
│       │   │   ├── java.py
│       │   │   ├── javascript.py
│       │   │   ├── kotlin.py
│       │   │   ├── php.py
│       │   │   ├── python.py
│       │   │   ├── ruby.py
│       │   │   ├── rust.py
│       │   │   ├── scala.py
│       │   │   ├── swift.py
│       │   │   ├── typescript.py
│       │   │   └── typescriptjsx.py
│       │   ├── package_resolver.py
│       │   ├── query_tool_languages
│       │   │   ├── c_toolkit.py
│       │   │   ├── cpp_toolkit.py
│       │   │   ├── csharp_toolkit.py
│       │   │   ├── go_toolkit.py
│       │   │   ├── java_toolkit.py
│       │   │   ├── javascript_toolkit.py
│       │   │   ├── python_toolkit.py
│       │   │   ├── ruby_toolkit.py
│       │   │   ├── rust_toolkit.py
│       │   │   ├── scala_toolkit.py
│       │   │   ├── swift_toolkit.py
│       │   │   └── typescript_toolkit.py
│       │   └── system.py
│       └── utils
│           ├── debug_log.py
│           └── tree_sitter_manager.py
├── tests
│   ├── __init__.py
│   ├── conftest.py
│   ├── sample_project
│   │   ├── advanced_calls.py
│   │   ├── advanced_classes.py
│   │   ├── advanced_classes2.py
│   │   ├── advanced_functions.py
│   │   ├── advanced_imports.py
│   │   ├── async_features.py
│   │   ├── callbacks_decorators.py
│   │   ├── circular1.py
│   │   ├── circular2.py
│   │   ├── class_instantiation.py
│   │   ├── cli_and_dunder.py
│   │   ├── complex_classes.py
│   │   ├── comprehensions_generators.py
│   │   ├── context_managers.py
│   │   ├── control_flow.py
│   │   ├── datatypes.py
│   │   ├── dynamic_dispatch.py
│   │   ├── dynamic_imports.py
│   │   ├── edge_cases
│   │   │   ├── comments_only.py
│   │   │   ├── docstring_only.py
│   │   │   ├── empty.py
│   │   │   ├── hardcoded_secrets.py
│   │   │   ├── long_functions.py
│   │   │   └── syntax_error.py
│   │   ├── function_chains.py
│   │   ├── generators.py
│   │   ├── import_reexports.py
│   │   ├── mapping_calls.py
│   │   ├── module_a.py
│   │   ├── module_b.py
│   │   ├── module_c
│   │   │   ├── __init__.py
│   │   │   ├── submodule1.py
│   │   │   └── submodule2.py
│   │   ├── namespace_pkg
│   │   │   └── ns_module.py
│   │   ├── pattern_matching.py
│   │   └── typing_examples.py
│   ├── sample_project_c
│   │   ├── cgc_sample
│   │   ├── include
│   │   │   ├── config.h
│   │   │   ├── math
│   │   │   │   └── vec.h
│   │   │   ├── module.h
│   │   │   ├── platform.h
│   │   │   └── util.h
│   │   ├── Makefile
│   │   ├── README.md
│   │   └── src
│   │       ├── main.c
│   │       ├── math
│   │       │   └── vec.c
│   │       ├── module.c
│   │       └── util.c
│   ├── sample_project_cpp
│   │   ├── class_features.cpp
│   │   ├── classes.cpp
│   │   ├── control_flow.cpp
│   │   ├── edge_cases.cpp
│   │   ├── enum_struct_union.cpp
│   │   ├── exceptions.cpp
│   │   ├── file_io.cpp
│   │   ├── function_chain.cpp
│   │   ├── function_chain.h
│   │   ├── function_types.cpp
│   │   ├── main.cpp
│   │   ├── main.exe
│   │   ├── namespaces.cpp
│   │   ├── raii_example.cpp
│   │   ├── README.md
│   │   ├── sample_project.exe
│   │   ├── stl_usage.cpp
│   │   ├── templates.cpp
│   │   └── types_variable_assignments.cpp
│   ├── sample_project_csharp
│   │   ├── README.md
│   │   └── src
│   │       └── Example.App
│   │           ├── Attributes
│   │           │   └── CustomAttributes.cs
│   │           ├── Example.App.csproj
│   │           ├── Models
│   │           │   ├── Person.cs
│   │           │   ├── Point.cs
│   │           │   ├── Role.cs
│   │           │   └── User.cs
│   │           ├── OuterClass.cs
│   │           ├── Program.cs
│   │           ├── Services
│   │           │   ├── GreetingService.cs
│   │           │   ├── IGreetingService.cs
│   │           │   └── LegacyService.cs
│   │           └── Utils
│   │               ├── CollectionHelper.cs
│   │               └── FileHelper.cs
│   ├── sample_project_go
│   │   ├── advanced_types.go
│   │   ├── basic_functions.go
│   │   ├── embedded_composition.go
│   │   ├── error_handling.go
│   │   ├── generics.go
│   │   ├── go.mod
│   │   ├── goroutines_channels.go
│   │   ├── interfaces.go
│   │   ├── packages_imports.go
│   │   ├── README.md
│   │   ├── structs_methods.go
│   │   └── util
│   │       └── helpers.go
│   ├── sample_project_java
│   │   ├── out
│   │   │   └── com
│   │   │       └── example
│   │   │           └── app
│   │   │               ├── annotations
│   │   │               │   └── Logged.class
│   │   │               ├── Main.class
│   │   │               ├── misc
│   │   │               │   ├── Outer.class
│   │   │               │   └── Outer$Inner.class
│   │   │               ├── model
│   │   │               │   ├── Role.class
│   │   │               │   └── User.class
│   │   │               ├── service
│   │   │               │   ├── AbstractGreeter.class
│   │   │               │   ├── GreetingService.class
│   │   │               │   └── impl
│   │   │               │       └── GreetingServiceImpl.class
│   │   │               └── util
│   │   │                   ├── CollectionUtils.class
│   │   │                   └── IOHelper.class
│   │   ├── README.md
│   │   ├── sources.txt
│   │   └── src
│   │       └── com
│   │           └── example
│   │               └── app
│   │                   ├── annotations
│   │                   │   └── Logged.java
│   │                   ├── Main.java
│   │                   ├── misc
│   │                   │   └── Outer.java
│   │                   ├── model
│   │                   │   ├── Role.java
│   │                   │   └── User.java
│   │                   ├── service
│   │                   │   ├── AbstractGreeter.java
│   │                   │   ├── GreetingService.java
│   │                   │   └── impl
│   │                   │       └── GreetingServiceImpl.java
│   │                   └── util
│   │                       ├── CollectionUtils.java
│   │                       └── IOHelper.java
│   ├── sample_project_javascript
│   │   ├── arrays.js
│   │   ├── asyncAwait.js
│   │   ├── classes.js
│   │   ├── dom.js
│   │   ├── errorHandling.js
│   │   ├── events.js
│   │   ├── exporter.js
│   │   ├── fetchAPI.js
│   │   ├── fixtures
│   │   │   └── js
│   │   │       └── accessors.js
│   │   ├── functions.js
│   │   ├── importer.js
│   │   ├── objects.js
│   │   ├── promises.js
│   │   ├── README.md
│   │   └── variables.js
│   ├── sample_project_kotlin
│   │   ├── AdvancedClasses.kt
│   │   ├── Annotations.kt
│   │   ├── Coroutines.kt
│   │   ├── EdgeCases.kt
│   │   ├── Functions.kt
│   │   ├── Main.kt
│   │   ├── Properties.kt
│   │   └── User.kt
│   ├── sample_project_misc
│   │   ├── index.html
│   │   ├── README.md
│   │   ├── styles.css
│   │   ├── tables.css
│   │   └── tables.html
│   ├── sample_project_php
│   │   ├── classes_objects.php
│   │   ├── database.php
│   │   ├── edgecases.php
│   │   ├── error_handling.php
│   │   ├── file_handling.php
│   │   ├── functions.php
│   │   ├── generators_iterators.php
│   │   ├── globals_superglobals.php
│   │   ├── Inheritance.php
│   │   ├── interface_traits.php
│   │   └── README.md
│   ├── sample_project_ruby
│   │   ├── class_example.rb
│   │   ├── enumerables.rb
│   │   ├── error_handling.rb
│   │   ├── file_io.rb
│   │   ├── inheritance_example.rb
│   │   ├── main.rb
│   │   ├── metaprogramming.rb
│   │   ├── mixins_example.rb
│   │   ├── module_example.rb
│   │   └── tests
│   │       ├── test_mixins.py
│   │       └── test_sample.rb
│   ├── sample_project_rust
│   │   ├── Cargo.toml
│   │   ├── README.md
│   │   └── src
│   │       ├── basic_functions.rs
│   │       ├── concurrency.rs
│   │       ├── error_handling.rs
│   │       ├── generics.rs
│   │       ├── iterators_closures.rs
│   │       ├── lib.rs
│   │       ├── lifetimes_references.rs
│   │       ├── modules.rs
│   │       ├── smart_pointers.rs
│   │       ├── structs_enums.rs
│   │       └── traits.rs
│   ├── sample_project_scala
│   │   ├── Animals.scala
│   │   ├── Complex.scala
│   │   ├── Functional.scala
│   │   ├── Geometry.scala
│   │   ├── Main.scala
│   │   ├── PackageObject.scala
│   │   ├── Script.sc
│   │   ├── Services.scala
│   │   ├── Shapes.scala
│   │   ├── Utils.scala
│   │   └── Variables.scala
│   ├── sample_project_swift
│   │   ├── Generics.swift
│   │   ├── Main.swift
│   │   ├── README.md
│   │   ├── Shapes.swift
│   │   ├── User.swift
│   │   └── Vehicles.swift
│   ├── sample_project_typescript
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── sample_tsx.tsx
│   │   ├── src
│   │   │   ├── advanced-types.ts
│   │   │   ├── async-promises.ts
│   │   │   ├── classes-inheritance.ts
│   │   │   ├── decorators-metadata.ts
│   │   │   ├── error-validation.ts
│   │   │   ├── functions-generics.ts
│   │   │   ├── index.ts
│   │   │   ├── modules-namespaces.ts
│   │   │   ├── types-interfaces.ts
│   │   │   └── utilities-helpers.ts
│   │   └── tsconfig.json
│   ├── test_cpp_parser.py
│   ├── test_database_validation.py
│   ├── test_end_to_end.py
│   ├── test_graph_indexing_js.py
│   ├── test_graph_indexing.py
│   ├── test_kotlin_parser.py
│   ├── test_swift_parser.py
│   ├── test_tree_sitter
│   │   ├── __init__.py
│   │   ├── class_instantiation.py
│   │   ├── complex_classes.py
│   │   └── test_file.py
│   ├── test_tree_sitter_manager.py
│   └── test_typescript_parser.py
├── visualize_graph.py
├── website
│   ├── .example.env
│   ├── .gitignore
│   ├── api
│   │   └── pypi.ts
│   ├── bun.lockb
│   ├── components.json
│   ├── eslint.config.js
│   ├── index.html
│   ├── package-lock.json
│   ├── package.json
│   ├── postcss.config.js
│   ├── public
│   │   ├── favicon.ico
│   │   ├── placeholder.svg
│   │   └── robots.txt
│   ├── README.md
│   ├── src
│   │   ├── App.css
│   │   ├── App.tsx
│   │   ├── assets
│   │   │   ├── function-calls.png
│   │   │   ├── graph-total.png
│   │   │   ├── hero-graph.jpg
│   │   │   └── hierarchy.png
│   │   ├── components
│   │   │   ├── ComparisonTable.tsx
│   │   │   ├── CookbookSection.tsx
│   │   │   ├── DemoSection.tsx
│   │   │   ├── ExamplesSection.tsx
│   │   │   ├── FeaturesSection.tsx
│   │   │   ├── Footer.tsx
│   │   │   ├── HeroSection.tsx
│   │   │   ├── InstallationSection.tsx
│   │   │   ├── MoveToTop.tsx
│   │   │   ├── ShowDownloads.tsx
│   │   │   ├── ShowStarGraph.tsx
│   │   │   ├── SocialMentionsTimeline.tsx
│   │   │   ├── TestimonialSection.tsx
│   │   │   ├── ThemeProvider.tsx
│   │   │   ├── ThemeToggle.tsx
│   │   │   └── ui
│   │   │       ├── accordion.tsx
│   │   │       ├── alert-dialog.tsx
│   │   │       ├── alert.tsx
│   │   │       ├── aspect-ratio.tsx
│   │   │       ├── avatar.tsx
│   │   │       ├── badge.tsx
│   │   │       ├── breadcrumb.tsx
│   │   │       ├── button.tsx
│   │   │       ├── calendar.tsx
│   │   │       ├── card.tsx
│   │   │       ├── carousel.tsx
│   │   │       ├── chart.tsx
│   │   │       ├── checkbox.tsx
│   │   │       ├── collapsible.tsx
│   │   │       ├── command.tsx
│   │   │       ├── context-menu.tsx
│   │   │       ├── dialog.tsx
│   │   │       ├── drawer.tsx
│   │   │       ├── dropdown-menu.tsx
│   │   │       ├── form.tsx
│   │   │       ├── hover-card.tsx
│   │   │       ├── input-otp.tsx
│   │   │       ├── input.tsx
│   │   │       ├── label.tsx
│   │   │       ├── menubar.tsx
│   │   │       ├── navigation-menu.tsx
│   │   │       ├── orbiting-circles.tsx
│   │   │       ├── pagination.tsx
│   │   │       ├── popover.tsx
│   │   │       ├── progress.tsx
│   │   │       ├── radio-group.tsx
│   │   │       ├── resizable.tsx
│   │   │       ├── scroll-area.tsx
│   │   │       ├── select.tsx
│   │   │       ├── separator.tsx
│   │   │       ├── sheet.tsx
│   │   │       ├── sidebar.tsx
│   │   │       ├── skeleton.tsx
│   │   │       ├── slider.tsx
│   │   │       ├── sonner.tsx
│   │   │       ├── switch.tsx
│   │   │       ├── table.tsx
│   │   │       ├── tabs.tsx
│   │   │       ├── textarea.tsx
│   │   │       ├── toast.tsx
│   │   │       ├── toaster.tsx
│   │   │       ├── toggle-group.tsx
│   │   │       ├── toggle.tsx
│   │   │       ├── tooltip.tsx
│   │   │       └── use-toast.ts
│   │   ├── hooks
│   │   │   ├── use-mobile.tsx
│   │   │   └── use-toast.ts
│   │   ├── index.css
│   │   ├── lib
│   │   │   └── utils.ts
│   │   ├── main.tsx
│   │   ├── pages
│   │   │   ├── Index.tsx
│   │   │   └── NotFound.tsx
│   │   └── vite-env.d.ts
│   ├── tailwind.config.ts
│   ├── tsconfig.app.json
│   ├── tsconfig.json
│   ├── tsconfig.node.json
│   ├── vercel.json
│   └── vite.config.ts
└── windows_setup_guide.md
```

# Files

--------------------------------------------------------------------------------
/src/codegraphcontext/cli/main.py:
--------------------------------------------------------------------------------

```python
   1 | # src/codegraphcontext/cli/main.py
   2 | """
   3 | This module defines the command-line interface (CLI) for the CodeGraphContext application.
   4 | It uses the Typer library to create a user-friendly and well-documented CLI.
   5 | 
   6 | Commands:
   7 | - mcp setup: Runs an interactive wizard to configure the MCP client.
   8 | - mcp start: Launches the main MCP server.
   9 | - help: Displays help information.
  10 | - version: Show the installed version.
  11 | """
  12 | import typer
  13 | from rich.console import Console
  14 | from rich.table import Table
  15 | from rich import box
  16 | from typing import Optional
  17 | import asyncio
  18 | import logging
  19 | import json
  20 | import os
  21 | from pathlib import Path
  22 | from dotenv import load_dotenv, find_dotenv, set_key
  23 | from importlib.metadata import version as pkg_version, PackageNotFoundError
  24 | 
  25 | from codegraphcontext.server import MCPServer
  26 | from codegraphcontext.core.database import DatabaseManager
  27 | from .setup_wizard import run_neo4j_setup_wizard, configure_mcp_client
  28 | from . import config_manager
  29 | # Import the new helper functions
  30 | from .cli_helpers import (
  31 |     index_helper,
  32 |     add_package_helper,
  33 |     list_repos_helper,
  34 |     delete_helper,
  35 |     cypher_helper,
  36 |     visualize_helper,
  37 |     reindex_helper,
  38 |     clean_helper,
  39 |     stats_helper,
  40 |     _initialize_services,
  41 |     watch_helper,
  42 |     unwatch_helper,
  43 |     list_watching_helper,
  44 | )
  45 | 
  46 | # Set the log level for the noisy neo4j and asyncio logger to WARNING to keep the output clean.
  47 | logging.getLogger("neo4j").setLevel(logging.WARNING)
  48 | logging.getLogger("asyncio").setLevel(logging.WARNING)
  49 | 
  50 | # Initialize the Typer app and Rich console for formatted output.
  51 | app = typer.Typer(
  52 |     name="cgc",
  53 |     help="CodeGraphContext: An MCP server for AI-powered code analysis.",
  54 |     add_completion=True,
  55 | )
  56 | console = Console(stderr=True)
  57 | 
  58 | # Configure basic logging for the application.
  59 | logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(name)s - %(message)s')
  60 | 
  61 | 
  62 | def get_version() -> str:
  63 |     """
  64 |     Try to read version from the installed package metadata.
  65 |     Fallback to a dev version if not installed.
  66 |     """
  67 |     try:
  68 |         return pkg_version("codegraphcontext")  # must match [project].name in pyproject.toml
  69 |     except PackageNotFoundError:
  70 |         return "0.0.0 (dev)"
  71 | 
  72 | 
  73 | # Create MCP command group
  74 | mcp_app = typer.Typer(help="MCP client configuration commands")
  75 | app.add_typer(mcp_app, name="mcp")
  76 | 
  77 | @mcp_app.command("setup")
  78 | def mcp_setup():
  79 |     """
  80 |     Configure MCP Client (IDE/CLI Integration).
  81 |     
  82 |     Sets up CodeGraphContext integration with your IDE or CLI tool:
  83 |     - VS Code, Cursor, Windsurf
  84 |     - Claude Desktop, Gemini CLI
  85 |     - Cline, RooCode, Amazon Q Developer
  86 |     
  87 |     Works with FalkorDB by default (no database setup needed).
  88 |     """
  89 |     console.print("\n[bold cyan]MCP Client Setup[/bold cyan]")
  90 |     console.print("Configure your IDE or CLI tool to use CodeGraphContext.\n")
  91 |     configure_mcp_client()
  92 | 
  93 | @mcp_app.command("start")
  94 | def mcp_start():
  95 |     """
  96 |     Start the CodeGraphContext MCP server.
  97 |     
  98 |     Starts the server which listens for JSON-RPC requests from stdin.
  99 |     This is used by IDE integrations (VS Code, Cursor, etc.).
 100 |     """
 101 |     console.print("[bold green]Starting CodeGraphContext Server...[/bold green]")
 102 |     _load_credentials()
 103 | 
 104 |     server = None
 105 |     loop = asyncio.new_event_loop()
 106 |     asyncio.set_event_loop(loop)
 107 |     try:
 108 |         # Initialize and run the main server.
 109 |         server = MCPServer(loop=loop)
 110 |         loop.run_until_complete(server.run())
 111 |     except ValueError as e:
 112 |         # This typically happens if credentials are still not found after all checks.
 113 |         console.print(f"[bold red]Configuration Error:[/bold red] {e}")
 114 |         console.print("Please run `cgc neo4j setup` or use FalkorDB (default).")
 115 |     except KeyboardInterrupt:
 116 |         # Handle graceful shutdown on Ctrl+C.
 117 |         console.print("\n[bold yellow]Server stopped by user.[/bold yellow]")
 118 |     finally:
 119 |         # Ensure server and event loop are properly closed.
 120 |         if server:
 121 |             server.shutdown()
 122 |         loop.close()
 123 | 
 124 | @mcp_app.command("tools")
 125 | def mcp_tools():
 126 |     """
 127 |     List all available MCP tools.
 128 |     
 129 |     Shows all tools that can be called by AI assistants through the MCP interface.
 130 |     """
 131 |     _load_credentials()
 132 |     console.print("[bold green]Available MCP Tools:[/bold green]")
 133 |     try:
 134 |         # Instantiate the server to access the tool definitions.
 135 |         server = MCPServer()
 136 |         tools = server.tools.values()
 137 | 
 138 |         table = Table(show_header=True, header_style="bold magenta")
 139 |         table.add_column("Tool Name", style="dim", width=30)
 140 |         table.add_column("Description")
 141 | 
 142 |         for tool in sorted(tools, key=lambda t: t['name']):
 143 |             table.add_row(tool['name'], tool['description'])
 144 | 
 145 |         console.print(table)
 146 | 
 147 |     except ValueError as e:
 148 |         console.print(f"[bold red]Error loading tools:[/bold red] {e}")
 149 |         console.print("Please ensure your database is configured correctly.")
 150 |     except Exception as e:
 151 |         console.print(f"[bold red]An unexpected error occurred:[/bold red] {e}")
 152 | 
 153 | # Abbreviation for mcp setup
 154 | @app.command("m", rich_help_panel="Shortcuts")
 155 | def mcp_setup_alias():
 156 |     """Shortcut for 'cgc mcp setup'"""
 157 |     mcp_setup()
 158 | 
 159 | 
 160 | # Create Neo4j command group
 161 | neo4j_app = typer.Typer(help="Neo4j database configuration commands")
 162 | app.add_typer(neo4j_app, name="neo4j")
 163 | 
 164 | @neo4j_app.command("setup")
 165 | def neo4j_setup():
 166 |     """
 167 |     Configure Neo4j Database Connection.
 168 |     
 169 |     Choose from multiple setup options:
 170 |     - Local (Docker-based, recommended)
 171 |     - Local (Binary installation on Linux)
 172 |     - Hosted (Neo4j AuraDB or remote instance)
 173 |     - Connect to existing Neo4j instance
 174 |     
 175 |     Note: This is optional. CodeGraphContext works with FalkorDB by default.
 176 |     """
 177 |     console.print("\n[bold cyan]Neo4j Database Setup[/bold cyan]")
 178 |     console.print("Configure Neo4j database connection for CodeGraphContext.\n")
 179 |     run_neo4j_setup_wizard()
 180 | 
 181 | # Abbreviation for neo4j setup
 182 | @app.command("n", rich_help_panel="Shortcuts")
 183 | def neo4j_setup_alias():
 184 |     """Shortcut for 'cgc neo4j setup'"""
 185 |     neo4j_setup()
 186 | 
 187 | 
 188 | 
 189 | def _load_credentials():
 190 |     """
 191 |     Loads configuration and credentials from various sources into environment variables.
 192 |     Uses per-variable precedence - each variable is loaded from the highest priority source.
 193 |     Priority order (highest to lowest):
 194 |     1. Local `mcp.json` env vars (highest - explicit MCP server config)
 195 |     2. Local `.env` in project directory (high - project-specific overrides)
 196 |     3. Global `~/.codegraphcontext/.env` (lowest - user defaults)
 197 |     """
 198 |     from dotenv import dotenv_values
 199 |     
 200 |     # Collect all config sources in reverse priority order (lowest to highest)
 201 |     config_sources = []
 202 |     config_source_names = []
 203 |     
 204 |     # 3. Global .env file (lowest priority - user defaults)
 205 |     global_env_path = Path.home() / ".codegraphcontext" / ".env"
 206 |     if global_env_path.exists():
 207 |         try:
 208 |             config_sources.append(dotenv_values(str(global_env_path)))
 209 |             config_source_names.append(str(global_env_path))
 210 |         except Exception as e:
 211 |             console.print(f"[yellow]Warning: Could not load global .env: {e}[/yellow]")
 212 |     
 213 |     # 2. Local project .env (higher priority - project-specific overrides)
 214 |     try:
 215 |         dotenv_path = find_dotenv(usecwd=True, raise_error_if_not_found=False)
 216 |         if dotenv_path:
 217 |             config_sources.append(dotenv_values(dotenv_path))
 218 |             config_source_names.append(str(dotenv_path))
 219 |     except Exception as e:
 220 |         console.print(f"[yellow]Warning: Could not load .env from current directory: {e}[/yellow]")
 221 |     
 222 |     # 1. Local mcp.json (highest priority - explicit MCP server config)
 223 |     mcp_file_path = Path.cwd() / "mcp.json"
 224 |     if mcp_file_path.exists():
 225 |         try:
 226 |             with open(mcp_file_path, "r") as f:
 227 |                 mcp_config = json.load(f)
 228 |             server_env = mcp_config.get("mcpServers", {}).get("CodeGraphContext", {}).get("env", {})
 229 |             if server_env:
 230 |                 config_sources.append(server_env)
 231 |                 config_source_names.append("mcp.json")
 232 |         except Exception as e:
 233 |             console.print(f"[yellow]Warning: Could not load mcp.json: {e}[/yellow]")
 234 |     
 235 |     # Merge all configs with proper precedence (later sources override earlier ones)
 236 |     merged_config = {}
 237 |     for config in config_sources:
 238 |         merged_config.update(config)
 239 |     
 240 |     # Apply merged config to environment
 241 |     for key, value in merged_config.items():
 242 |         if value is not None:  # Only set non-None values
 243 |             os.environ[key] = str(value)
 244 |     
 245 |     # Report what was loaded
 246 |     if config_source_names:
 247 |         if len(config_source_names) == 1:
 248 |             console.print(f"[dim]Loaded configuration from: {config_source_names[-1]}[/dim]")
 249 |         else:
 250 |             console.print(f"[dim]Loaded configuration from: {', '.join(config_source_names)} (highest priority: {config_source_names[-1]})[/dim]")
 251 |     else:
 252 |         console.print("[yellow]No configuration file found. Using defaults.[/yellow]")
 253 |     
 254 |     
 255 |     # Show which database is actually being used
 256 |     # Check for runtime override first (from -db/--database flag)
 257 |     runtime_db = os.environ.get("CGC_RUNTIME_DB_TYPE")
 258 |     if runtime_db:
 259 |         default_db = runtime_db.lower()
 260 |     else:
 261 |         default_db = os.environ.get("DEFAULT_DATABASE", "falkordb").lower()
 262 |     
 263 |     if default_db == "neo4j":
 264 |         has_neo4j_creds = all([
 265 |             os.environ.get("NEO4J_URI"),
 266 |             os.environ.get("NEO4J_USERNAME"),
 267 |             os.environ.get("NEO4J_PASSWORD")
 268 |         ])
 269 |         if has_neo4j_creds:
 270 |             console.print("[cyan]Using database: Neo4j[/cyan]")
 271 |         else:
 272 |             console.print("[yellow]⚠ DEFAULT_DATABASE=neo4j but credentials not found. Falling back to FalkorDB.[/yellow]")
 273 |     else:
 274 |         console.print("[cyan]Using database: FalkorDB[/cyan]")
 275 | 
 276 | 
 277 | 
 278 | # ============================================================================
 279 | # CONFIG COMMAND GROUP
 280 | # ============================================================================
 281 | 
 282 | config_app = typer.Typer(help="Manage configuration settings")
 283 | app.add_typer(config_app, name="config")
 284 | 
 285 | @config_app.command("show")
 286 | def config_show():
 287 |     """
 288 |     Display current configuration settings.
 289 |     
 290 |     Shows all configuration values including database, indexing options,
 291 |     logging settings, and performance tuning parameters.
 292 |     """
 293 |     config_manager.show_config()
 294 | 
 295 | @config_app.command("set")
 296 | def config_set(
 297 |     key: str = typer.Argument(..., help="Configuration key to set"),
 298 |     value: str = typer.Argument(..., help="Value to set")
 299 | ):
 300 |     """
 301 |     Set a configuration value.
 302 |     
 303 |     Examples:
 304 |         cgc config set DEFAULT_DATABASE neo4j
 305 |         cgc config set INDEX_VARIABLES false
 306 |         cgc config set MAX_FILE_SIZE_MB 20
 307 |         cgc config set DEBUG_LOGS true
 308 |     """
 309 |     config_manager.set_config_value(key, value)
 310 | 
 311 | @config_app.command("reset")
 312 | def config_reset():
 313 |     """
 314 |     Reset all configuration to default values.
 315 |     
 316 |     This will restore all settings to their defaults.
 317 |     Your current configuration will be backed up.
 318 |     """
 319 |     if typer.confirm("Are you sure you want to reset all configuration to defaults?", default=False):
 320 |         config_manager.reset_config()
 321 |     else:
 322 |         console.print("[yellow]Reset cancelled[/yellow]")
 323 | 
 324 | @config_app.command("db")
 325 | def config_db(backend: str = typer.Argument(..., help="Database backend: 'neo4j' or 'falkordb'")):
 326 |     """
 327 |     Quickly switch the default database backend.
 328 |     
 329 |     Shortcut for 'cgc config set DEFAULT_DATABASE <backend>'.
 330 |     
 331 |     Examples:
 332 |         cgc config db neo4j
 333 |         cgc config db falkordb
 334 |     """
 335 |     backend = backend.lower()
 336 |     if backend not in ['falkordb', 'neo4j']:
 337 |         console.print(f"[bold red]Invalid backend: {backend}[/bold red]")
 338 |         console.print("Must be 'falkordb' or 'neo4j'")
 339 |         raise typer.Exit(code=1)
 340 |     
 341 |     config_manager.set_config_value("DEFAULT_DATABASE", backend)
 342 |     console.print(f"[green]✔ Default database switched to {backend}[/green]")
 343 | 
 344 | # ============================================================================
 345 | # DOCTOR DIAGNOSTIC COMMAND
 346 | # ============================================================================
 347 | 
 348 | @app.command()
 349 | def doctor():
 350 |     """
 351 |     Run diagnostics to check system health and configuration.
 352 |     
 353 |     Checks:
 354 |     - Configuration validity
 355 |     - Database connectivity
 356 |     - Tree-sitter installation
 357 |     - Required dependencies
 358 |     - File permissions
 359 |     """
 360 |     console.print("[bold cyan]🏥 Running CodeGraphContext Diagnostics...[/bold cyan]\n")
 361 |     
 362 |     all_checks_passed = True
 363 |     
 364 |     # 1. Check configuration
 365 |     console.print("[bold]1. Checking Configuration...[/bold]")
 366 |     try:
 367 |         config = config_manager.load_config()
 368 |         console.print(f"   [green]✓[/green] Configuration loaded from {config_manager.CONFIG_FILE}")
 369 |         
 370 |         # Validate each config value
 371 |         invalid_configs = []
 372 |         for key, value in config.items():
 373 |             is_valid, error_msg = config_manager.validate_config_value(key, value)
 374 |             if not is_valid:
 375 |                 invalid_configs.append(f"{key}: {error_msg}")
 376 |         
 377 |         if invalid_configs:
 378 |             console.print(f"   [red]✗[/red] Invalid configuration values found:")
 379 |             for err in invalid_configs:
 380 |                 console.print(f"     - {err}")
 381 |             all_checks_passed = False
 382 |         else:
 383 |             console.print(f"   [green]✓[/green] All configuration values are valid")
 384 |     except Exception as e:
 385 |         console.print(f"   [red]✗[/red] Configuration error: {e}")
 386 |         all_checks_passed = False
 387 |     
 388 |     # 2. Check database connectivity
 389 |     console.print("\n[bold]2. Checking Database Connection...[/bold]")
 390 |     try:
 391 |         _load_credentials()
 392 |         default_db = config.get("DEFAULT_DATABASE", "falkordb")
 393 |         console.print(f"   Default database: {default_db}")
 394 |         
 395 |         if default_db == "neo4j":
 396 |             uri = os.environ.get("NEO4J_URI")
 397 |             username = os.environ.get("NEO4J_USERNAME")
 398 |             password = os.environ.get("NEO4J_PASSWORD")
 399 |             
 400 |             if uri and username and password:
 401 |                 console.print(f"   [cyan]Testing Neo4j connection to {uri}...[/cyan]")
 402 |                 is_connected, error_msg = DatabaseManager.test_connection(uri, username, password)
 403 |                 if is_connected:
 404 |                     console.print(f"   [green]✓[/green] Neo4j connection successful")
 405 |                 else:
 406 |                     console.print(f"   [red]✗[/red] Neo4j connection failed: {error_msg}")
 407 |                     all_checks_passed = False
 408 |             else:
 409 |                 console.print(f"   [yellow]⚠[/yellow] Neo4j credentials not set. Run 'cgc neo4j setup'")
 410 |         else:
 411 |             # FalkorDB
 412 |             try:
 413 |                 import falkordb
 414 |                 console.print(f"   [green]✓[/green] FalkorDB Lite is installed")
 415 |             except ImportError:
 416 |                 console.print(f"   [yellow]⚠[/yellow] FalkorDB Lite not installed (Python 3.12+ only)")
 417 |                 console.print(f"       Run: pip install falkordblite")
 418 |     except Exception as e:
 419 |         console.print(f"   [red]✗[/red] Database check error: {e}")
 420 |         all_checks_passed = False
 421 |     
 422 |     # 3. Check tree-sitter installation
 423 |     console.print("\n[bold]3. Checking Tree-Sitter Installation...[/bold]")
 424 |     try:
 425 |         from tree_sitter import Language, Parser
 426 |         console.print(f"   [green]✓[/green] tree-sitter is installed")
 427 |         
 428 |         try:
 429 |             from tree_sitter_language_pack import get_language
 430 |             console.print(f"   [green]✓[/green] tree-sitter-language-pack is installed")
 431 |             
 432 |             # Test a few languages
 433 |             test_langs = ["python", "javascript", "typescript"]
 434 |             for lang in test_langs:
 435 |                 try:
 436 |                     get_language(lang)
 437 |                     console.print(f"   [green]✓[/green] {lang} parser available")
 438 |                 except Exception:
 439 |                     console.print(f"   [yellow]⚠[/yellow] {lang} parser not available")
 440 |         except ImportError:
 441 |             console.print(f"   [red]✗[/red] tree-sitter-language-pack not installed")
 442 |             all_checks_passed = False
 443 |     except ImportError as e:
 444 |         console.print(f"   [red]✗[/red] tree-sitter not installed: {e}")
 445 |         all_checks_passed = False
 446 |     
 447 |     # 4. Check file permissions
 448 |     console.print("\n[bold]4. Checking File Permissions...[/bold]")
 449 |     try:
 450 |         config_dir = config_manager.CONFIG_DIR
 451 |         if config_dir.exists():
 452 |             console.print(f"   [green]✓[/green] Config directory exists: {config_dir}")
 453 |             
 454 |             # Check if writable
 455 |             test_file = config_dir / ".test_write"
 456 |             try:
 457 |                 test_file.touch()
 458 |                 test_file.unlink()
 459 |                 console.print(f"   [green]✓[/green] Config directory is writable")
 460 |             except Exception as e:
 461 |                 console.print(f"   [red]✗[/red] Config directory not writable: {e}")
 462 |                 all_checks_passed = False
 463 |         else:
 464 |             console.print(f"   [yellow]⚠[/yellow] Config directory doesn't exist, will be created on first use")
 465 |     except Exception as e:
 466 |         console.print(f"   [red]✗[/red] Permission check error: {e}")
 467 |         all_checks_passed = False
 468 |     
 469 |     # 5. Check cgc command availability
 470 |     console.print("\n[bold]5. Checking CGC Command...[/bold]")
 471 |     import shutil
 472 |     cgc_path = shutil.which("cgc")
 473 |     if cgc_path:
 474 |         console.print(f"   [green]✓[/green] cgc command found at: {cgc_path}")
 475 |     else:
 476 |         console.print(f"   [yellow]⚠[/yellow] cgc command not in PATH (using python -m cgc)")
 477 |     
 478 |     # Final summary
 479 |     console.print("\n" + "=" * 60)
 480 |     if all_checks_passed:
 481 |         console.print("[bold green]✅ All diagnostics passed! System is healthy.[/bold green]")
 482 |     else:
 483 |         console.print("[bold yellow]⚠️  Some issues detected. Please review the output above.[/bold yellow]")
 484 |         console.print("\n[cyan]Common fixes:[/cyan]")
 485 |         console.print("  • For Neo4j issues: Run 'cgc neo4j setup'")
 486 |         console.print("  • For missing packages: pip install codegraphcontext")
 487 |         console.print("  • For config issues: Run 'cgc config reset'")
 488 |     console.print("=" * 60 + "\n")
 489 | 
 490 | 
 491 | 
 492 | 
 493 | @app.command()
 494 | def start():
 495 |     """
 496 |     Start the MCP server.
 497 |     
 498 |     [yellow]⚠️  Deprecated: Use 'cgc mcp start' instead.[/yellow]
 499 |     This command will be removed in a future version.
 500 |     """
 501 |     console.print("[yellow]⚠️  'cgc start' is deprecated. Use 'cgc mcp start' instead.[/yellow]")
 502 |     mcp_start()
 503 | 
 504 | 
 505 | @app.command()
 506 | def index(
 507 |     path: Optional[str] = typer.Argument(None, help="Path to the directory or file to index. Defaults to the current directory."),
 508 |     force: bool = typer.Option(False, "--force", "-f", help="Force re-index (delete existing and rebuild)")
 509 | ):
 510 |     """
 511 |     Indexes a directory or file by adding it to the code graph.
 512 |     If no path is provided, it indexes the current directory.
 513 |     
 514 |     Use --force to delete the existing index and rebuild from scratch.
 515 |     """
 516 |     _load_credentials()
 517 |     if path is None:
 518 |         path = str(Path.cwd())
 519 |     
 520 |     if force:
 521 |         console.print("[yellow]Force re-indexing (--force flag detected)[/yellow]")
 522 |         reindex_helper(path)
 523 |     else:
 524 |         index_helper(path)
 525 | 
 526 | @app.command()
 527 | def clean():
 528 |     """
 529 |     Remove orphaned nodes and relationships from the database.
 530 |     
 531 |     This will clean up nodes that are not connected to any repository,
 532 |     helping to keep your database tidy and performant.
 533 |     """
 534 |     _load_credentials()
 535 |     clean_helper()
 536 | 
 537 | @app.command()
 538 | def stats(path: Optional[str] = typer.Argument(None, help="Path to show stats for. Omit for overall stats.")):
 539 |     """
 540 |     Show indexing statistics.
 541 |     
 542 |     If a path is provided, shows stats for that specific repository.
 543 |     Otherwise, shows overall database statistics.
 544 |     """
 545 |     _load_credentials()
 546 |     if path:
 547 |         path = str(Path(path).resolve())
 548 |     stats_helper(path)
 549 | 
 550 | @app.command()
 551 | def delete(
 552 |     path: Optional[str] = typer.Argument(None, help="Path of the repository to delete from the code graph."),
 553 |     all_repos: bool = typer.Option(False, "--all", help="Delete all indexed repositories")
 554 | ):
 555 |     """
 556 |     Deletes a repository from the code graph.
 557 |     
 558 |     Use --all to delete all repositories at once (requires confirmation).
 559 |     
 560 |     Examples:
 561 |         cgc delete ./my-project       # Delete specific repository
 562 |         cgc delete --all              # Delete all repositories
 563 |     """
 564 |     _load_credentials()
 565 |     
 566 |     if all_repos:
 567 |         # Delete all repositories
 568 |         services = _initialize_services()
 569 |         if not all(services):
 570 |             return
 571 |         db_manager, graph_builder, code_finder = services
 572 |         
 573 |         try:
 574 |             # Get list of repositories
 575 |             repos = code_finder.list_indexed_repositories()
 576 |             
 577 |             if not repos:
 578 |                 console.print("[yellow]No repositories to delete.[/yellow]")
 579 |                 return
 580 |             
 581 |             # Show what will be deleted
 582 |             console.print(f"\n[bold red]⚠️  WARNING: You are about to delete ALL {len(repos)} repositories![/bold red]\n")
 583 |             
 584 |             table = Table(show_header=True, header_style="bold magenta")
 585 |             table.add_column("Name", style="cyan")
 586 |             table.add_column("Path", style="dim")
 587 |             
 588 |             for repo in repos:
 589 |                 table.add_row(repo.get("name", ""), repo.get("path", ""))
 590 |             
 591 |             console.print(table)
 592 |             console.print()
 593 |             
 594 |             # Double confirmation
 595 |             if not typer.confirm("Are you sure you want to delete ALL repositories?", default=False):
 596 |                 console.print("[yellow]Deletion cancelled.[/yellow]")
 597 |                 return
 598 |             
 599 |             console.print("[yellow]Please type 'delete all' to confirm:[/yellow] ", end="")
 600 |             confirmation = input()
 601 |             
 602 |             if confirmation.strip().lower() != "delete all":
 603 |                 console.print("[yellow]Deletion cancelled. Confirmation text did not match.[/yellow]")
 604 |                 return
 605 |             
 606 |             # Delete all repositories
 607 |             console.print("\n[cyan]Deleting all repositories...[/cyan]")
 608 |             deleted_count = 0
 609 |             
 610 |             for repo in repos:
 611 |                 repo_path = repo.get("path", "")
 612 |                 try:
 613 |                     graph_builder.delete_repository_from_graph(repo_path)
 614 |                     console.print(f"[green]✓[/green] Deleted: {repo.get('name', '')}")
 615 |                     deleted_count += 1
 616 |                 except Exception as e:
 617 |                     console.print(f"[red]✗[/red] Failed to delete {repo.get('name', '')}: {e}")
 618 |             
 619 |             console.print(f"\n[bold green]Successfully deleted {deleted_count}/{len(repos)} repositories![/bold green]")
 620 |             
 621 |         finally:
 622 |             db_manager.close_driver()
 623 |     else:
 624 |         # Delete specific repository
 625 |         if not path:
 626 |             console.print("[red]Error: Please provide a path or use --all to delete all repositories[/red]")
 627 |             console.print("Usage: cgc delete <path> or cgc delete --all")
 628 |             raise typer.Exit(code=1)
 629 |         
 630 |         delete_helper(path)
 631 | 
 632 | @app.command()
 633 | def visualize(query: Optional[str] = typer.Argument(None, help="The Cypher query to visualize.")):
 634 |     """
 635 |     Generates a URL to visualize a Cypher query in the Neo4j Browser.
 636 |     If no query is provided, a default query will be used.
 637 |     """
 638 |     if query is None:
 639 |         query = "MATCH p=()-->() RETURN p"
 640 |     _load_credentials()
 641 |     visualize_helper(query)
 642 | 
 643 | @app.command("list")
 644 | def list_repositories():
 645 |     """
 646 |     List all indexed repositories.
 647 |     
 648 |     Shows all projects and packages that have been indexed in the code graph.
 649 |     """
 650 |     _load_credentials()
 651 |     list_repos_helper()
 652 | 
 653 | @app.command(name="add-package")
 654 | def add_package(package_name: str = typer.Argument(..., help="Name of the package to add."), language: str = typer.Argument(..., help="Language of the package." )):
 655 |     """
 656 |     Adds a package to the code graph.
 657 |     """
 658 |     _load_credentials()
 659 |     add_package_helper(package_name, language)
 660 | 
 661 | # ============================================================================
 662 | # WATCH COMMAND GROUP - Live File Monitoring
 663 | # ============================================================================
 664 | 
 665 | @app.command()
 666 | def watch(
 667 |     path: str = typer.Argument(".", help="Path to the directory to watch. Defaults to current directory.")
 668 | ):
 669 |     """
 670 |     Watch a directory for file changes and automatically update the code graph.
 671 |     
 672 |     This command runs in the foreground and monitors the specified directory
 673 |     for any file changes. When changes are detected, the code graph is
 674 |     automatically updated.
 675 |     
 676 |     The watcher will:
 677 |     - Perform an initial scan if the directory is not yet indexed
 678 |     - Monitor for file creation, modification, deletion, and moves
 679 |     - Automatically re-index affected files and update relationships
 680 |     
 681 |     Press Ctrl+C to stop watching.
 682 |     
 683 |     Examples:
 684 |         cgc watch .                    # Watch current directory
 685 |         cgc watch /path/to/project     # Watch specific directory
 686 |         cgc w .                        # Using shortcut alias
 687 |     """
 688 |     _load_credentials()
 689 |     watch_helper(path)
 690 | 
 691 | @app.command()
 692 | def unwatch(
 693 |     path: str = typer.Argument(..., help="Path to stop watching")
 694 | ):
 695 |     """
 696 |     Stop watching a directory for changes.
 697 |     
 698 |     Note: This command is primarily for MCP server mode.
 699 |     For CLI watch mode, simply press Ctrl+C in the watch terminal.
 700 |     
 701 |     Examples:
 702 |         cgc unwatch /path/to/project
 703 |     """
 704 |     _load_credentials()
 705 |     unwatch_helper(path)
 706 | 
 707 | @app.command()
 708 | def watching():
 709 |     """
 710 |     List all directories currently being watched for changes.
 711 |     
 712 |     Note: This command is primarily for MCP server mode.
 713 |     For CLI watch mode, check the terminal where you ran 'cgc watch'.
 714 |     
 715 |     Examples:
 716 |         cgc watching
 717 |     """
 718 |     _load_credentials()
 719 |     list_watching_helper()
 720 | 
 721 | 
 722 | 
 723 | # ============================================================================
 724 | # FIND COMMAND GROUP - Code Search & Discovery
 725 | # ============================================================================
 726 | 
 727 | find_app = typer.Typer(help="Find and search code elements")
 728 | app.add_typer(find_app, name="find")
 729 | 
 730 | @find_app.command("name")
 731 | def find_by_name(
 732 |     name: str = typer.Argument(..., help="Exact name to search for"),
 733 |     type: Optional[str] = typer.Option(None, "--type", "-t", help="Filter by type (function, class, file, module)")
 734 | ):
 735 |     """
 736 |     Find code elements by exact name.
 737 |     
 738 |     Examples:
 739 |         cgc find name MyClass
 740 |         cgc find name calculate --type function
 741 |     """
 742 |     _load_credentials()
 743 |     services = _initialize_services()
 744 |     if not all(services):
 745 |         return
 746 |     db_manager, graph_builder, code_finder = services
 747 |     
 748 |     try:
 749 |         results = []
 750 |         
 751 |         # Search based on type filter
 752 |         if type is None or type.lower() == 'all':
 753 |             funcs = code_finder.find_by_function_name(name, fuzzy_search=False)
 754 |             classes = code_finder.find_by_class_name(name, fuzzy_search=False)
 755 |             variables = code_finder.find_by_variable_name(name)
 756 |             modules = code_finder.find_by_module_name(name)
 757 |             imports = code_finder.find_imports(name)
 758 | 
 759 |             for f in funcs: f['type'] = 'Function'
 760 |             for c in classes: c['type'] = 'Class'
 761 |             for v in variables: v['type'] = 'Variable'
 762 |             for m in modules: m['type'] = 'Module'; m['file_path'] = m.get('name', 'External') # Modules might differ
 763 |             for i in imports: 
 764 |                 i['type'] = 'Import'
 765 |                 i['name'] = i.get('alias') or i.get('imported_name')
 766 |             
 767 |             results.extend(funcs)
 768 |             results.extend(classes)
 769 |             results.extend(variables)
 770 |             results.extend(modules)
 771 |             results.extend(imports)
 772 |         
 773 |         elif type.lower() == 'function':
 774 |             results = code_finder.find_by_function_name(name, fuzzy_search=False)
 775 |             for r in results: r['type'] = 'Function'
 776 |             
 777 |         elif type.lower() == 'class':
 778 |             results = code_finder.find_by_class_name(name, fuzzy_search=False)
 779 |             for r in results: r['type'] = 'Class'
 780 |             
 781 |         elif type.lower() == 'variable':
 782 |             results = code_finder.find_by_variable_name(name)
 783 |             for r in results: r['type'] = 'Variable'
 784 | 
 785 |         elif type.lower() == 'module':
 786 |             results = code_finder.find_by_module_name(name)
 787 |             for r in results: 
 788 |                 r['type'] = 'Module'
 789 |                 r['file_path'] = r.get('name')
 790 |             
 791 |         elif type.lower() == 'file':
 792 |             # Quick query for file
 793 |             with db_manager.get_driver().session() as session:
 794 |                 res = session.run("MATCH (n:File) WHERE n.name = $name RETURN n.name as name, n.path as file_path, n.is_dependency as is_dependency", name=name)
 795 |                 results = [dict(record) for record in res]
 796 |                 for r in results: r['type'] = 'File'
 797 |         
 798 |         if not results:
 799 |             console.print(f"[yellow]No code elements found with name '{name}'[/yellow]")
 800 |             return
 801 |             
 802 |         table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
 803 |         table.add_column("Name", style="cyan")
 804 |         table.add_column("Type", style="bold blue")
 805 |         table.add_column("Location", style="dim", overflow="fold")
 806 |         
 807 |         for res in results:
 808 |             file_path = res.get('file_path', '') or ''
 809 |             line_str = str(res.get('line_number', ''))
 810 |             location_str = f"{file_path}:{line_str}" if line_str else file_path
 811 | 
 812 |             table.add_row(
 813 |                 res.get('name', ''),
 814 |                 res.get('type', 'Unknown'),
 815 |                 location_str
 816 |             )
 817 |             
 818 |         console.print(f"[cyan]Found {len(results)} matches for '{name}':[/cyan]")
 819 |         console.print(table)
 820 |     finally:
 821 |         db_manager.close_driver()
 822 | 
 823 | @find_app.command("pattern")
 824 | def find_by_pattern(
 825 |     pattern: str = typer.Argument(..., help="Substring pattern to search (fuzzy search fallback)"),
 826 |     case_sensitive: bool = typer.Option(False, "--case-sensitive", "-c", help="Case-sensitive search")
 827 | ):
 828 |     """
 829 |     Find code elements using substring matching.
 830 |     
 831 |     Examples:
 832 |         cgc find pattern "Auth"       # Finds Auth, Authentication, Authorize...
 833 |         cgc find pattern "process_"   # Finds process_data, process_request...
 834 |     """
 835 |     _load_credentials()
 836 |     services = _initialize_services()
 837 |     if not all(services):
 838 |         return
 839 |     db_manager, graph_builder, code_finder = services
 840 |     
 841 |     try:
 842 |         with db_manager.get_driver().session() as session:
 843 |             # Search Functions, Classes, and Modules
 844 |             # Note: FalkorDB Lite might not support regex, using CONTAINS
 845 |             
 846 |             if not case_sensitive:
 847 |                 query = """
 848 |                     MATCH (n)
 849 |                     WHERE (n:Function OR n:Class OR n:Module OR n:Variable) AND toLower(n.name) CONTAINS toLower($pattern)
 850 |                     RETURN 
 851 |                         labels(n)[0] as type,
 852 |                         n.name as name,
 853 |                         n.file_path as file_path,
 854 |                         n.line_number as line_number,
 855 |                         n.is_dependency as is_dependency
 856 |                     ORDER BY n.is_dependency ASC, n.name
 857 |                     LIMIT 50
 858 |                 """
 859 |             else:
 860 |                  query = """
 861 |                     MATCH (n)
 862 |                     WHERE (n:Function OR n:Class OR n:Module OR n:Variable) AND n.name CONTAINS $pattern
 863 |                     RETURN 
 864 |                         labels(n)[0] as type,
 865 |                         n.name as name,
 866 |                         n.file_path as file_path,
 867 |                         n.line_number as line_number,
 868 |                         n.is_dependency as is_dependency
 869 |                     ORDER BY n.is_dependency ASC, n.name
 870 |                     LIMIT 50
 871 |                 """
 872 |             
 873 |             result = session.run(query, pattern=pattern)
 874 |             
 875 |             results = [dict(record) for record in result]
 876 |         
 877 |         if not results:
 878 |             console.print(f"[yellow]No matches found for pattern '{pattern}'[/yellow]")
 879 |             return
 880 |             
 881 |         if not case_sensitive and any(c in pattern for c in "*?["):
 882 |              console.print("[yellow]Note: Wildcards/Regex are not fully supported in this mode. Performing substring search.[/yellow]")
 883 | 
 884 |         table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
 885 |         table.add_column("Name", style="cyan")
 886 |         table.add_column("Type", style="blue")
 887 |         table.add_column("Location", style="dim", overflow="fold")
 888 |         table.add_column("Source", style="yellow")
 889 |         
 890 |         for res in results:
 891 |             file_path = res.get('file_path', '') or ''
 892 |             line_str = str(res.get('line_number', '') if res.get('line_number') is not None else '')
 893 |             location_str = f"{file_path}:{line_str}" if line_str else file_path
 894 | 
 895 |             table.add_row(
 896 |                 res.get('name', ''),
 897 |                 res.get('type', 'Unknown'),
 898 |                 location_str,
 899 |                 "📦 Dependency" if res.get('is_dependency') else "📝 Project"
 900 |             )
 901 |             
 902 |         console.print(f"[cyan]Found {len(results)} matches for pattern '{pattern}':[/cyan]")
 903 |         console.print(table)
 904 |     finally:
 905 |         db_manager.close_driver()
 906 | 
 907 | @find_app.command("type")
 908 | def find_by_type(
 909 |     element_type: str = typer.Argument(..., help="Type to search for (function, class, file, module)"),
 910 |     limit: int = typer.Option(50, "--limit", "-l", help="Maximum results to return")
 911 | ):
 912 |     """
 913 |     Find all elements of a specific type.
 914 |     
 915 |     Examples:
 916 |         cgc find type class
 917 |         cgc find type function --limit 100
 918 |     """
 919 |     _load_credentials()
 920 |     services = _initialize_services()
 921 |     if not all(services):
 922 |         return
 923 |     db_manager, graph_builder, code_finder = services
 924 |     
 925 |     try:
 926 |         results = code_finder.find_by_type(element_type, limit)
 927 |         
 928 |         if not results:
 929 |             console.print(f"[yellow]No elements found of type '{element_type}'[/yellow]")
 930 |             return
 931 |             
 932 |         table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
 933 |         table.add_column("Name", style="cyan")
 934 |         table.add_column("Location", style="dim", overflow="fold")
 935 |         table.add_column("Source", style="yellow")
 936 |         
 937 |         for res in results:
 938 |             file_path = res.get('file_path', '') or ''
 939 |             line_str = str(res.get('line_number', ''))
 940 |             location_str = f"{file_path}:{line_str}" if line_str else file_path
 941 |             
 942 |             table.add_row(
 943 |                 res.get('name', ''),
 944 |                 location_str,
 945 |                 "📦 Dependency" if res.get('is_dependency') else "📝 Project"
 946 |             )
 947 |             
 948 |         console.print(f"[cyan]Found {len(results)} {element_type}s:[/cyan]")
 949 |         console.print(table)
 950 |     finally:
 951 |         db_manager.close_driver()
 952 | 
 953 | @find_app.command("variable")
 954 | def find_by_variable(
 955 |     name: str = typer.Argument(..., help="Variable name to search for")
 956 | ):
 957 |     """
 958 |     Find variables by name.
 959 |     
 960 |     Examples:
 961 |         cgc find variable MAX_RETRIES
 962 |         cgc find variable config
 963 |     """
 964 |     _load_credentials()
 965 |     services = _initialize_services()
 966 |     if not all(services):
 967 |         return
 968 |     db_manager, graph_builder, code_finder = services
 969 |     
 970 |     try:
 971 |         results = code_finder.find_by_variable_name(name)
 972 |         
 973 |         if not results:
 974 |             console.print(f"[yellow]No variables found with name '{name}'[/yellow]")
 975 |             return
 976 |             
 977 |         table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
 978 |         table.add_column("Name", style="cyan")
 979 |         table.add_column("Location", style="dim", overflow="fold")
 980 |         table.add_column("Context", style="yellow")
 981 |         
 982 |         for res in results:
 983 |             file_path = res.get('file_path', '') or ''
 984 |             line_str = str(res.get('line_number', ''))
 985 |             location_str = f"{file_path}:{line_str}" if line_str else file_path
 986 | 
 987 |             table.add_row(
 988 |                 res.get('name', ''),
 989 |                 location_str,
 990 |                 res.get('context', '') or 'module'
 991 |             )
 992 |             
 993 |         console.print(f"[cyan]Found {len(results)} variable(s) named '{name}':[/cyan]")
 994 |         console.print(table)
 995 |     finally:
 996 |         db_manager.close_driver()
 997 | 
 998 | @find_app.command("content")
 999 | def find_by_content_search(
1000 |     query: str = typer.Argument(..., help="Text to search for in source code and docstrings")
1001 | ):
1002 |     """
1003 |     Search code content (source and docstrings) using full-text index.
1004 |     
1005 |     Examples:
1006 |         cgc find content "error 503"
1007 |         cgc find content "TODO: refactor"
1008 |     """
1009 |     _load_credentials()
1010 |     services = _initialize_services()
1011 |     if not all(services):
1012 |         return
1013 |     db_manager, graph_builder, code_finder = services
1014 |     
1015 |     try:
1016 |         try:
1017 |             results = code_finder.find_by_content(query)
1018 |         except Exception as e:
1019 |             error_msg = str(e).lower()
1020 |             if 'fulltext' in error_msg or 'db.index.fulltext' in error_msg:
1021 |                 console.print("\n[bold red]❌ Full-text search is not supported on FalkorDB[/bold red]\n")
1022 |                 console.print("[yellow]💡 You have two options:[/yellow]\n")
1023 |                 console.print("  1. [cyan]Switch to Neo4j:[/cyan]")
1024 |                 console.print(f"     [dim]cgc --database neo4j find content \"{query}\"[/dim]\n")
1025 |                 console.print("  2. [cyan]Use pattern search instead:[/cyan]")
1026 |                 console.print(f"     [dim]cgc find pattern \"{query}\"[/dim]")
1027 |                 console.print("     [dim](searches in names only, not source code)[/dim]\n")
1028 |                 return
1029 |             else:
1030 |                 # Re-raise if it's a different error
1031 |                 raise
1032 |         
1033 |         if not results:
1034 |             console.print(f"[yellow]No content matches found for '{query}'[/yellow]")
1035 |             return
1036 |             
1037 |         table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
1038 |         table.add_column("Name", style="cyan")
1039 |         table.add_column("Type", style="blue")
1040 |         table.add_column("Location", style="dim", overflow="fold")
1041 |         
1042 |         for res in results:
1043 |             file_path = res.get('file_path', '') or ''
1044 |             line_str = str(res.get('line_number', ''))
1045 |             location_str = f"{file_path}:{line_str}" if line_str else file_path
1046 | 
1047 |             table.add_row(
1048 |                 res.get('name', ''),
1049 |                 res.get('type', 'Unknown'),
1050 |                 location_str
1051 |             )
1052 |             
1053 |         console.print(f"[cyan]Found {len(results)} content match(es) for '{query}':[/cyan]")
1054 |         console.print(table)
1055 |     finally:
1056 |         db_manager.close_driver()
1057 | 
1058 | @find_app.command("decorator")
1059 | def find_by_decorator_search(
1060 |     decorator: str = typer.Argument(..., help="Decorator name to search for"),
1061 |     file: Optional[str] = typer.Option(None, "--file", "-f", help="Specific file path")
1062 | ):
1063 |     """
1064 |     Find functions with a specific decorator.
1065 |     
1066 |     Examples:
1067 |         cgc find decorator app.route
1068 |         cgc find decorator test --file tests/test_main.py
1069 |     """
1070 |     _load_credentials()
1071 |     services = _initialize_services()
1072 |     if not all(services):
1073 |         return
1074 |     db_manager, graph_builder, code_finder = services
1075 |     
1076 |     try:
1077 |         results = code_finder.find_functions_by_decorator(decorator, file)
1078 |         
1079 |         if not results:
1080 |             console.print(f"[yellow]No functions found with decorator '@{decorator}'[/yellow]")
1081 |             return
1082 |             
1083 |         table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
1084 |         table.add_column("Function", style="cyan")
1085 |         table.add_column("Location", style="dim", overflow="fold")
1086 |         table.add_column("Decorators", style="yellow")
1087 |         
1088 |         for res in results:
1089 |             decorators_str = ", ".join(res.get('decorators', []))
1090 |             file_path = res.get('file_path', '') or ''
1091 |             line_str = str(res.get('line_number', ''))
1092 |             location_str = f"{file_path}:{line_str}" if line_str else file_path
1093 | 
1094 |             table.add_row(
1095 |                 res.get('function_name', ''),
1096 |                 location_str,
1097 |                 decorators_str
1098 |             )
1099 |             
1100 |         console.print(f"[cyan]Found {len(results)} function(s) with decorator '@{decorator}':[/cyan]")
1101 |         console.print(table)
1102 |     finally:
1103 |         db_manager.close_driver()
1104 | 
1105 | @find_app.command("argument")
1106 | def find_by_argument_search(
1107 |     argument: str = typer.Argument(..., help="Argument/parameter name to search for"),
1108 |     file: Optional[str] = typer.Option(None, "--file", "-f", help="Specific file path")
1109 | ):
1110 |     """
1111 |     Find functions that take a specific argument/parameter.
1112 |     
1113 |     Examples:
1114 |         cgc find argument password
1115 |         cgc find argument user_id --file src/auth.py
1116 |     """
1117 |     _load_credentials()
1118 |     services = _initialize_services()
1119 |     if not all(services):
1120 |         return
1121 |     db_manager, graph_builder, code_finder = services
1122 |     
1123 |     try:
1124 |         results = code_finder.find_functions_by_argument(argument, file)
1125 |         
1126 |         if not results:
1127 |             console.print(f"[yellow]No functions found with argument '{argument}'[/yellow]")
1128 |             return
1129 |             
1130 |         table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
1131 |         table.add_column("Function", style="cyan")
1132 |         table.add_column("Location", style="dim", overflow="fold")
1133 |         
1134 |         for res in results:
1135 |             file_path = res.get('file_path', '') or ''
1136 |             line_str = str(res.get('line_number', ''))
1137 |             location_str = f"{file_path}:{line_str}" if line_str else file_path
1138 | 
1139 |             table.add_row(
1140 |                 res.get('function_name', ''),
1141 |                 location_str
1142 |             )
1143 |             
1144 |         console.print(f"[cyan]Found {len(results)} function(s) with argument '{argument}':[/cyan]")
1145 |         console.print(table)
1146 |     finally:
1147 |         db_manager.close_driver()
1148 | 
1149 | 
1150 | # ============================================================================
1151 | # ANALYZE COMMAND GROUP - Code Analysis & Relationships
1152 | # ============================================================================
1153 | 
1154 | analyze_app = typer.Typer(help="Analyze code relationships, dependencies, and quality")
1155 | app.add_typer(analyze_app, name="analyze")
1156 | 
1157 | @analyze_app.command("calls")
1158 | def analyze_calls(
1159 |     function: str = typer.Argument(..., help="Function name to analyze"),
1160 |     file: Optional[str] = typer.Option(None, "--file", "-f", help="Specific file path")
1161 | ):
1162 |     """
1163 |     Show what functions this function calls (callees).
1164 |     
1165 |     Example:
1166 |         cgc analyze calls process_data
1167 |         cgc analyze calls process_data --file src/main.py
1168 |     """
1169 |     _load_credentials()
1170 |     services = _initialize_services()
1171 |     if not all(services):
1172 |         return
1173 |     db_manager, graph_builder, code_finder = services
1174 |     
1175 |     try:
1176 |         results = code_finder.what_does_function_call(function, file)
1177 |         
1178 |         if not results:
1179 |             console.print(f"[yellow]No function calls found for '{function}'[/yellow]")
1180 |             return
1181 |         
1182 |         table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
1183 |         table.add_column("Called Function", style="cyan")
1184 |         table.add_column("Location", style="dim", overflow="fold")
1185 |         table.add_column("Type", style="yellow")
1186 |         
1187 |         for result in results:
1188 |             file_path = result.get("called_file_path", "")
1189 |             line_str = str(result.get("called_line_number", ""))
1190 |             location_str = f"{file_path}:{line_str}" if line_str else file_path
1191 | 
1192 |             table.add_row(
1193 |                 result.get("called_function", ""),
1194 |                 location_str,
1195 |                 "📦 Dependency" if result.get("called_is_dependency") else "📝 Project"
1196 |             )
1197 |         
1198 |         console.print(f"\n[bold cyan]Function '{function}' calls:[/bold cyan]")
1199 |         console.print(table)
1200 |         console.print(f"\n[dim]Total: {len(results)} function(s)[/dim]")
1201 |     finally:
1202 |         db_manager.close_driver()
1203 | 
1204 | @analyze_app.command("callers")
1205 | def analyze_callers(
1206 |     function: str = typer.Argument(..., help="Function name to analyze"),
1207 |     file: Optional[str] = typer.Option(None, "--file", "-f", help="Specific file path")
1208 | ):
1209 |     """
1210 |     Show what functions call this function.
1211 |     
1212 |     Example:
1213 |         cgc analyze callers process_data
1214 |         cgc analyze callers process_data --file src/main.py
1215 |     """
1216 |     _load_credentials()
1217 |     services = _initialize_services()
1218 |     if not all(services):
1219 |         return
1220 |     db_manager, graph_builder, code_finder = services
1221 |     
1222 |     try:
1223 |         results = code_finder.who_calls_function(function, file)
1224 |         
1225 |         if not results:
1226 |             console.print(f"[yellow]No callers found for '{function}'[/yellow]")
1227 |             return
1228 |         
1229 |         table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
1230 |         table.add_column("Caller Function", style="cyan")
1231 |         table.add_column("Location", style="green")
1232 |         table.add_column("Call Type", style="yellow")
1233 | 
1234 |         
1235 |         for result in results:
1236 |             file_path = result.get("caller_file_path", "")
1237 |             line_number = result.get("caller_line_number")
1238 | 
1239 |             location = f"{file_path}:{line_number}" if line_number else file_path
1240 | 
1241 |             table.add_row(
1242 |                 result.get("caller_function", ""),
1243 |                 location,
1244 |                 "📦 Dependency" if result.get("caller_is_dependency") else "📝 Project"
1245 |                 )
1246 |         
1247 |         console.print(f"\n[bold cyan]Functions that call '{function}':[/bold cyan]")
1248 |         console.print(table)
1249 |         console.print(f"\n[dim]Total: {len(results)} caller(s)[/dim]")
1250 |     finally:
1251 |         db_manager.close_driver()
1252 | 
1253 | @analyze_app.command("chain")
1254 | def analyze_chain(
1255 |     from_func: str = typer.Argument(..., help="Starting function"),
1256 |     to_func: str = typer.Argument(..., help="Target function"),
1257 |     max_depth: int = typer.Option(5, "--depth", "-d", help="Maximum call chain depth"),
1258 |     from_file: Optional[str] = typer.Option(None, "--from-file", help="File for starting function"),
1259 |     to_file: Optional[str] = typer.Option(None, "--to-file", help="File for target function")
1260 | ):
1261 |     """
1262 |     Show call chain between two functions.
1263 |     
1264 |     Example:
1265 |         cgc analyze chain main process_data --depth 10
1266 |         cgc analyze chain main process --from-file main.py --to-file utils.py
1267 |     """
1268 |     _load_credentials()
1269 |     services = _initialize_services()
1270 |     if not all(services):
1271 |         return
1272 |     db_manager, graph_builder, code_finder = services
1273 |     
1274 |     try:
1275 |         results = code_finder.find_function_call_chain(from_func, to_func, max_depth, from_file, to_file)
1276 |         
1277 |         if not results:
1278 |             console.print(f"[yellow]No call chain found between '{from_func}' and '{to_func}' within depth {max_depth}[/yellow]")
1279 |             return
1280 |         
1281 |         for idx, chain in enumerate(results, 1):
1282 |             console.print(f"\n[bold cyan]Call Chain #{idx} (length: {chain.get('chain_length', 0)}):[/bold cyan]")
1283 |             
1284 |             functions = chain.get('function_chain', [])
1285 |             call_details = chain.get('call_details', [])
1286 |             
1287 |             for i, func in enumerate(functions):
1288 |                 indent = "  " * i
1289 |                 
1290 |                 # Print function
1291 |                 console.print(f"{indent}[cyan]{func.get('name', 'Unknown')}[/cyan] [dim]({func.get('file_path', '')}:{func.get('line_number', '')})[/dim]")
1292 |                 
1293 |                 # If there is a next step, print the connecting call detail
1294 |                 if i < len(functions) - 1 and i < len(call_details):
1295 |                     detail = call_details[i]
1296 |                     line = detail.get('call_line', '?')
1297 |                     
1298 |                     # Format args for display
1299 |                     args_info = ""
1300 |                     args_val = detail.get('args', [])
1301 |                     if args_val:
1302 |                         if isinstance(args_val, list):
1303 |                             # Filter legacy punctuation just in case
1304 |                             clean_args = [str(a) for a in args_val if str(a) not in ('(', ')', ',')]
1305 |                             args_str = ", ".join(clean_args)
1306 |                         else:
1307 |                             args_str = str(args_val)
1308 |                             
1309 |                         # Truncate if too long
1310 |                         if len(args_str) > 50:
1311 |                             args_str = args_str[:47] + "..."
1312 |                         args_info = f" [dim]({args_str})[/dim]"
1313 |                     
1314 |                     console.print(f"{indent}  ⬇ [dim]calls at line {line}[/dim]{args_info}")
1315 |     finally:
1316 |         db_manager.close_driver()
1317 | 
1318 | @analyze_app.command("deps")
1319 | def analyze_dependencies(
1320 |     target: str = typer.Argument(..., help="Module name"),
1321 |     show_external: bool = typer.Option(True, "--external/--no-external", help="Show external dependencies")
1322 | ):
1323 |     """
1324 |     Show dependencies and imports for a module.
1325 |     
1326 |     Example:
1327 |         cgc analyze deps numpy
1328 |         cgc analyze deps mymodule --no-external
1329 |     """
1330 |     _load_credentials()
1331 |     services = _initialize_services()
1332 |     if not all(services):
1333 |         return
1334 |     db_manager, graph_builder, code_finder = services
1335 |     
1336 |     try:
1337 |         results = code_finder.find_module_dependencies(target)
1338 |         
1339 |         if not results.get('importers') and not results.get('imports'):
1340 |             console.print(f"[yellow]No dependency information found for '{target}'[/yellow]")
1341 |             return
1342 |         
1343 |         # Show who imports this module
1344 |         if results.get('importers'):
1345 |             console.print(f"\n[bold cyan]Files that import '{target}':[/bold cyan]")
1346 |             table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
1347 |             table.add_column("Location", style="cyan", overflow="fold")
1348 |             
1349 |             for imp in results['importers']:
1350 |                 file_path = imp.get('importer_file_path', '')
1351 |                 line_str = str(imp.get('import_line_number', ''))
1352 |                 location_str = f"{file_path}:{line_str}" if line_str else file_path
1353 | 
1354 |                 table.add_row(
1355 |                     location_str
1356 |                 )
1357 |             console.print(table)
1358 |     finally:
1359 |         db_manager.close_driver()
1360 | 
1361 | @analyze_app.command("tree")
1362 | def analyze_inheritance_tree(
1363 |     class_name: str = typer.Argument(..., help="Class name"),
1364 |     file: Optional[str] = typer.Option(None, "--file", "-f", help="Specific file path")
1365 | ):
1366 |     """
1367 |     Show inheritance hierarchy for a class.
1368 |     
1369 |     Example:
1370 |         cgc analyze tree MyClass
1371 |         cgc analyze tree MyClass --file src/models.py
1372 |     """
1373 |     _load_credentials()
1374 |     services = _initialize_services()
1375 |     if not all(services):
1376 |         return
1377 |     db_manager, graph_builder, code_finder = services
1378 |     
1379 |     try:
1380 |         results = code_finder.find_class_hierarchy(class_name, file)
1381 |         
1382 |         console.print(f"\n[bold cyan]Class Hierarchy for '{class_name}':[/bold cyan]\n")
1383 |         
1384 |         # Show parent classes
1385 |         if results.get('parent_classes'):
1386 |             console.print("[bold yellow]Parents (inherits from):[/bold yellow]")
1387 |             for parent in results['parent_classes']:
1388 |                 console.print(f"  ⬆ [cyan]{parent.get('parent_class', '')}[/cyan] [dim]({parent.get('parent_file_path', '')}:{parent.get('parent_line_number', '')})[/dim]")
1389 |         else:
1390 |             console.print("[dim]No parent classes found[/dim]")
1391 |         
1392 |         console.print()
1393 |         
1394 |         # Show child classes
1395 |         if results.get('child_classes'):
1396 |             console.print("[bold yellow]Children (classes that inherit from this):[/bold yellow]")
1397 |             for child in results['child_classes']:
1398 |                 console.print(f"  ⬇ [cyan]{child.get('child_class', '')}[/cyan] [dim]({child.get('child_file_path', '')}:{child.get('child_line_number', '')})[/dim]")
1399 |         else:
1400 |             console.print("[dim]No child classes found[/dim]")
1401 |         
1402 |         console.print()
1403 |         
1404 |         # Show methods
1405 |         if results.get('methods'):
1406 |             console.print(f"[bold yellow]Methods ({len(results['methods'])}):[/bold yellow]")
1407 |             for method in results['methods'][:10]:  # Limit to 10
1408 |                 console.print(f"  • [green]{method.get('method_name', '')}[/green]({method.get('method_args', '')})")
1409 |             if len(results['methods']) > 10:
1410 |                 console.print(f"  [dim]... and {len(results['methods']) - 10} more[/dim]")
1411 |     finally:
1412 |         db_manager.close_driver()
1413 | 
1414 | @analyze_app.command("complexity")
1415 | def analyze_complexity(
1416 |     path: Optional[str] = typer.Argument(None, help="Specific function name to analyze"),
1417 |     threshold: int = typer.Option(10, "--threshold", "-t", help="Complexity threshold for warnings"),
1418 |     limit: int = typer.Option(20, "--limit", "-l", help="Maximum results to show"),
1419 |     file: Optional[str] = typer.Option(None, "--file", "-f", help="Specific file path (only used when function name is provided)")
1420 | ):
1421 |     """
1422 |     Show cyclomatic complexity for functions.
1423 |     
1424 |     Example:
1425 |         cgc analyze complexity                    # Most complex functions
1426 |         cgc analyze complexity --threshold 15     # Functions over threshold
1427 |         cgc analyze complexity my_function        # Specific function
1428 |         cgc analyze complexity my_function -f file.py # Specific function in file
1429 |     """
1430 |     _load_credentials()
1431 |     services = _initialize_services()
1432 |     if not all(services):
1433 |         return
1434 |     db_manager, graph_builder, code_finder = services
1435 |     
1436 |     try:
1437 |         if path:
1438 |             # Specific function
1439 |             result = code_finder.get_cyclomatic_complexity(path, file)
1440 |             if result:
1441 |                 console.print(f"\n[bold cyan]Complexity for '{path}':[/bold cyan]")
1442 |                 console.print(f"  Cyclomatic Complexity: [yellow]{result.get('complexity', 'N/A')}[/yellow]")
1443 |                 console.print(f"  File: [dim]{result.get('file_path', '')}[/dim]")
1444 |                 console.print(f"  Line: [dim]{result.get('line_number', '')}[/dim]")
1445 |             else:
1446 |                 console.print(f"[yellow]Function '{path}' not found or has no complexity data[/yellow]")
1447 |         else:
1448 |             # Most complex functions
1449 |             results = code_finder.find_most_complex_functions(limit)
1450 |             
1451 |             if not results:
1452 |                 console.print("[yellow]No complexity data available[/yellow]")
1453 |                 return
1454 |             
1455 |             table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
1456 |             table.add_column("Function", style="cyan")
1457 |             table.add_column("Complexity", style="yellow", justify="right")
1458 |             table.add_column("Location", style="dim", overflow="fold")
1459 |             
1460 |             for func in results:
1461 |                 complexity = func.get('complexity', 0)
1462 |                 color = "red" if complexity > threshold else "yellow" if complexity > threshold/2 else "green"
1463 |                 file_path = func.get('file_path', '')
1464 |                 line_str = str(func.get('line_number', ''))
1465 |                 location_str = f"{file_path}:{line_str}" if line_str else file_path
1466 | 
1467 |                 table.add_row(
1468 |                     func.get('function_name', ''),
1469 |                     f"[{color}]{complexity}[/{color}]",
1470 |                     location_str
1471 |                 )
1472 |             
1473 |             console.print(f"\n[bold cyan]Most Complex Functions (threshold: {threshold}):[/bold cyan]")
1474 |             console.print(table)
1475 |             console.print(f"\n[dim]{len([f for f in results if f.get('complexity', 0) > threshold])} function(s) exceed threshold[/dim]")
1476 |     finally:
1477 |         db_manager.close_driver()
1478 | 
1479 | @analyze_app.command("dead-code")
1480 | def analyze_dead_code(
1481 |     path: Optional[str] = typer.Argument(None, help="Path to analyze (not yet implemented)"),
1482 |     exclude_decorators: Optional[str] = typer.Option(None, "--exclude", "-e", help="Comma-separated decorators to exclude")
1483 | ):
1484 |     """
1485 |     Find potentially unused functions and classes.
1486 |     
1487 |     Example:
1488 |         cgc analyze dead-code
1489 |         cgc analyze dead-code --exclude route,task,api
1490 |     """
1491 |     _load_credentials()
1492 |     services = _initialize_services()
1493 |     if not all(services):
1494 |         return
1495 |     db_manager, graph_builder, code_finder = services
1496 |     
1497 |     try:
1498 |         exclude_list = exclude_decorators.split(',') if exclude_decorators else []
1499 |         results = code_finder.find_dead_code(exclude_list)
1500 |         
1501 |         unused_funcs = results.get('potentially_unused_functions', [])
1502 |         
1503 |         if not unused_funcs:
1504 |             console.print("[green]✓ No dead code found![/green]")
1505 |             return
1506 |         
1507 |         table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
1508 |         table.add_column("Function", style="cyan")
1509 |         table.add_column("Location", style="dim", overflow="fold")
1510 |         
1511 |         for func in unused_funcs:
1512 |             file_path = func.get('file_path', '')
1513 |             line_str = str(func.get('line_number', ''))
1514 |             location_str = f"{file_path}:{line_str}" if line_str else file_path
1515 | 
1516 |             table.add_row(
1517 |                 func.get('function_name', ''),
1518 |                 location_str
1519 |             )
1520 |         
1521 |         console.print(f"\n[bold yellow]⚠️  Potentially Unused Functions:[/bold yellow]")
1522 |         console.print(table)
1523 |         console.print(f"\n[dim]Total: {len(unused_funcs)} function(s)[/dim]")
1524 |         console.print(f"[dim]Note: {results.get('note', '')}[/dim]")
1525 |     finally:
1526 |         db_manager.close_driver()
1527 | 
1528 | @analyze_app.command("overrides")
1529 | def analyze_overrides(
1530 |     function_name: str = typer.Argument(..., help="Function/method name to find implementations of")
1531 | ):
1532 |     """
1533 |     Find all implementations of a function across different classes.
1534 |     
1535 |     Useful for finding polymorphic implementations and method overrides.
1536 |     
1537 |     Example:
1538 |         cgc analyze overrides area
1539 |         cgc analyze overrides process
1540 |     """
1541 |     _load_credentials()
1542 |     services = _initialize_services()
1543 |     if not all(services):
1544 |         return
1545 |     db_manager, graph_builder, code_finder = services
1546 |     
1547 |     try:
1548 |         results = code_finder.find_function_overrides(function_name)
1549 |         
1550 |         if not results:
1551 |             console.print(f"[yellow]No implementations found for function '{function_name}'[/yellow]")
1552 |             return
1553 |         
1554 |         table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
1555 |         table.add_column("Class", style="cyan")
1556 |         table.add_column("Function", style="green")
1557 |         table.add_column("Location", style="dim", overflow="fold")
1558 |         
1559 |         for res in results:
1560 |             file_path = res.get('class_file_path', '')
1561 |             line_str = str(res.get('function_line_number', ''))
1562 |             location_str = f"{file_path}:{line_str}" if line_str else file_path
1563 | 
1564 |             table.add_row(
1565 |                 res.get('class_name', ''),
1566 |                 res.get('function_name', ''),
1567 |                 location_str
1568 |             )
1569 |         
1570 |         console.print(f"\n[bold cyan]Found {len(results)} implementation(s) of '{function_name}':[/bold cyan]")
1571 |         console.print(table)
1572 |     finally:
1573 |         db_manager.close_driver()
1574 | 
1575 | @analyze_app.command("variable")
1576 | def analyze_variable_usage(
1577 |     variable_name: str = typer.Argument(..., help="Variable name to analyze"),
1578 |     file: Optional[str] = typer.Option(None, "--file", "-f", help="Specific file path")
1579 | ):
1580 |     """
1581 |     Analyze where a variable is defined and used across the codebase.
1582 |     
1583 |     Shows all instances of the variable and their scope (function, class, module).
1584 |     
1585 |     Example:
1586 |         cgc analyze variable MAX_RETRIES
1587 |         cgc analyze variable config
1588 |         cgc analyze variable x --file math_utils.py
1589 |     """
1590 |     _load_credentials()
1591 |     services = _initialize_services()
1592 |     if not all(services):
1593 |         return
1594 |     db_manager, graph_builder, code_finder = services
1595 |     
1596 |     try:
1597 |         # Get variable usage scope
1598 |         scope_results = code_finder.find_variable_usage_scope(variable_name, file)
1599 |         instances = scope_results.get('instances', [])
1600 |         
1601 |         if not instances:
1602 |             console.print(f"[yellow]No instances found for variable '{variable_name}'[/yellow]")
1603 |             return
1604 |         
1605 |         console.print(f"\n[bold cyan]Variable '{variable_name}' Usage Analysis:[/bold cyan]\n")
1606 |         
1607 |         # Group by scope type
1608 |         by_scope = {}
1609 |         for inst in instances:
1610 |             scope_type = inst.get('scope_type', 'unknown')
1611 |             if scope_type not in by_scope:
1612 |                 by_scope[scope_type] = []
1613 |             by_scope[scope_type].append(inst)
1614 |         
1615 |         # Display by scope
1616 |         for scope_type, items in by_scope.items():
1617 |             console.print(f"[bold yellow]{scope_type.upper()} Scope ({len(items)} instance(s)):[/bold yellow]")
1618 |             
1619 |             table = Table(show_header=True, header_style="bold magenta", box=box.ROUNDED)
1620 |             table.add_column("Scope Name", style="cyan")
1621 |             table.add_column("Location", style="dim", overflow="fold")
1622 |             table.add_column("Value", style="yellow")
1623 |             
1624 |             for item in items:
1625 |                 file_path = item.get('file_path', '')
1626 |                 line_str = str(item.get('line_number', ''))
1627 |                 location_str = f"{file_path}:{line_str}" if line_str else file_path
1628 | 
1629 |                 table.add_row(
1630 |                     item.get('scope_name', ''),
1631 |                     location_str,
1632 |                     str(item.get('variable_value', ''))[:50] if item.get('variable_value') else '-'
1633 |                 )
1634 |             
1635 |             console.print(table)
1636 |             console.print()
1637 |         
1638 |         console.print(f"[dim]Total: {len(instances)} instance(s) across {len(by_scope)} scope type(s)[/dim]")
1639 |     finally:
1640 |         db_manager.close_driver()
1641 | 
1642 | 
1643 | # ============================================================================
1644 | # QUERY COMMAND - Raw Cypher Queries
1645 | # ============================================================================
1646 | 
1647 | @app.command("query")
1648 | def query_graph(query: str = typer.Argument(..., help="Cypher query to execute (read-only)")):
1649 |     """
1650 |     Execute a custom Cypher query on the code graph.
1651 |     
1652 |     Examples:
1653 |         cgc query "MATCH (f:Function) RETURN f.name LIMIT 10"
1654 |         cgc query "MATCH (c:Class)-[:CONTAINS]->(m) RETURN c.name, count(m)"
1655 |     """
1656 |     _load_credentials()
1657 |     cypher_helper(query)
1658 | 
1659 | # Keep old 'cypher' as alias for backward compatibility
1660 | @app.command("cypher", hidden=True)
1661 | def cypher_legacy(query: str = typer.Argument(..., help="The read-only Cypher query to execute.")):
1662 |     """[Deprecated] Use 'cgc query' instead."""
1663 |     console.print("[yellow]⚠️  'cgc cypher' is deprecated. Use 'cgc query' instead.[/yellow]")
1664 |     cypher_helper(query)
1665 | 
1666 | 
1667 | 
1668 | # ============================================================================
1669 | # ABBREVIATIONS / SHORTCUTS for common commands
1670 | # ============================================================================
1671 | 
1672 | @app.command("i", rich_help_panel="Shortcuts")
1673 | def index_abbrev(path: Optional[str] = typer.Argument(None, help="Path to index")):
1674 |     """Shortcut for 'cgc index'"""
1675 |     index(path)
1676 | 
1677 | @app.command("ls", rich_help_panel="Shortcuts")
1678 | def list_abbrev():
1679 |     """Shortcut for 'cgc list'"""
1680 |     list_repositories()
1681 | 
1682 | @app.command("rm", rich_help_panel="Shortcuts")
1683 | def delete_abbrev(
1684 |     path: Optional[str] = typer.Argument(None, help="Path to delete"),
1685 |     all_repos: bool = typer.Option(False, "--all", help="Delete all indexed repositories")
1686 | ):
1687 |     """Shortcut for 'cgc delete'"""
1688 |     delete(path, all_repos)
1689 | 
1690 | @app.command("v", rich_help_panel="Shortcuts")
1691 | def visualize_abbrev(query: Optional[str] = typer.Argument(None, help="Cypher query")):
1692 |     """Shortcut for 'cgc visualize'"""
1693 |     visualize(query)
1694 | 
1695 | @app.command("w", rich_help_panel="Shortcuts")
1696 | def watch_abbrev(path: str = typer.Argument(".", help="Path to watch")):
1697 |     """Shortcut for 'cgc watch'"""
1698 |     watch(path)
1699 | 
1700 | 
1701 | # ============================================================================
1702 | 
1703 | 
1704 | 
1705 | @app.command()
1706 | def help(ctx: typer.Context):
1707 |     """Show the main help message and exit."""
1708 |     root_ctx = ctx.parent or ctx
1709 |     typer.echo(root_ctx.get_help())
1710 | 
1711 | 
1712 | @app.command("version")
1713 | def version_cmd():
1714 |     """Show the application version."""
1715 |     console.print(f"CodeGraphContext [bold cyan]{get_version()}[/bold cyan]")
1716 | 
1717 | 
1718 | @app.callback(invoke_without_command=True)
1719 | def main(
1720 |     ctx: typer.Context,
1721 |     database: Optional[str] = typer.Option(
1722 |         None, 
1723 |         "--database", 
1724 |         "-db", 
1725 |         help="[Global] Temporarily override database backend (falkordb or neo4j) for any command"
1726 |     ),
1727 |     version_: bool = typer.Option(
1728 |         None,
1729 |         "--version",
1730 |         "-v",
1731 |         help="[Root-level only] Show version and exit",
1732 |         is_eager=True,
1733 |     ),
1734 |     help_: bool = typer.Option(
1735 |         None,
1736 |         "--help",
1737 |         "-h",
1738 |         help="[Root-level only] Show help and exit",
1739 |         is_eager=True,
1740 |     ), 
1741 | ):
1742 |     """
1743 |     Main entry point for the cgc CLI application.
1744 |     If no subcommand is provided, it displays a welcome message with instructions.
1745 |     """
1746 |     if database:
1747 |         os.environ["CGC_RUNTIME_DB_TYPE"] = database
1748 | 
1749 |     if version_:
1750 |         console.print(f"CodeGraphContext [bold cyan]{get_version()}[/bold cyan]")
1751 |         raise typer.Exit()
1752 | 
1753 |     if ctx.invoked_subcommand is None:
1754 |         console.print("[bold green]👋 Welcome to CodeGraphContext (cgc)![/bold green]\n")
1755 |         console.print("CodeGraphContext is both an [bold cyan]MCP server[/bold cyan] and a [bold cyan]CLI toolkit[/bold cyan] for code analysis.\n")
1756 |         console.print("🤖 [bold]For MCP Server Mode (AI assistants):[/bold]")
1757 |         console.print("   1. Run [cyan]cgc mcp setup[/cyan] (or [cyan]cgc m[/cyan]) to configure your IDE")
1758 |         console.print("   2. Run [cyan]cgc mcp start[/cyan] to launch the server\n")
1759 |         console.print("🛠️  [bold]For CLI Toolkit Mode (direct usage):[/bold]")
1760 |         console.print("   • [cyan]cgc index .[/cyan] - Index your current directory")
1761 |         console.print("   • [cyan]cgc list[/cyan] - List indexed repositories\n")
1762 |         console.print("📊 [bold]Using Neo4j instead of FalkorDB?[/bold]")
1763 |         console.print("     Run [cyan]cgc neo4j setup[/cyan] (or [cyan]cgc n[/cyan]) to configure Neo4j\n")
1764 |         console.print("👉 Run [cyan]cgc help[/cyan] to see all available commands")
1765 |         console.print("👉 Run [cyan]cgc --version[/cyan] to check the version\n")
1766 |         console.print("👉 Running [green]codegraphcontext[/green] works the same as using [green]cgc[/green]")
1767 | 
1768 | 
1769 | if __name__ == "__main__":
1770 |     app()
```
Page 19/22FirstPrevNextLast