codemesh 0.1.3__tar.gz → 0.1.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. {codemesh-0.1.3 → codemesh-0.1.4}/PKG-INFO +1 -1
  2. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/__init__.py +1 -1
  3. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/cli/install_cmd.py +138 -0
  4. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/cli/main.py +75 -0
  5. {codemesh-0.1.3 → codemesh-0.1.4}/pyproject.toml +1 -1
  6. {codemesh-0.1.3 → codemesh-0.1.4}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  7. {codemesh-0.1.3 → codemesh-0.1.4}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  8. {codemesh-0.1.3 → codemesh-0.1.4}/.github/workflows/ci.yml +0 -0
  9. {codemesh-0.1.3 → codemesh-0.1.4}/.github/workflows/publish.yml +0 -0
  10. {codemesh-0.1.3 → codemesh-0.1.4}/.gitignore +0 -0
  11. {codemesh-0.1.3 → codemesh-0.1.4}/CHANGELOG.md +0 -0
  12. {codemesh-0.1.3 → codemesh-0.1.4}/CONTRIBUTING.md +0 -0
  13. {codemesh-0.1.3 → codemesh-0.1.4}/LICENSE +0 -0
  14. {codemesh-0.1.3 → codemesh-0.1.4}/Makefile +0 -0
  15. {codemesh-0.1.3 → codemesh-0.1.4}/README.md +0 -0
  16. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/__main__.py +0 -0
  17. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/cli/__init__.py +0 -0
  18. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/cli/init.py +0 -0
  19. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/context/__init__.py +0 -0
  20. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/context/builder.py +0 -0
  21. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/db/__init__.py +0 -0
  22. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/db/connection.py +0 -0
  23. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/db/queries.py +0 -0
  24. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/db/schema.py +0 -0
  25. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/embedding/__init__.py +0 -0
  26. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/__init__.py +0 -0
  27. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/languages/__init__.py +0 -0
  28. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/languages/c_family.py +0 -0
  29. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/languages/go.py +0 -0
  30. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/languages/java.py +0 -0
  31. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/languages/python.py +0 -0
  32. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/languages/rust.py +0 -0
  33. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/languages/swift.py +0 -0
  34. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/languages/typescript.py +0 -0
  35. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/orchestrator.py +0 -0
  36. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/graph/__init__.py +0 -0
  37. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/graph/query_manager.py +0 -0
  38. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/graph/traverser.py +0 -0
  39. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/indexer.py +0 -0
  40. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/mcp/__init__.py +0 -0
  41. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/mcp/server.py +0 -0
  42. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/mcp/tools.py +0 -0
  43. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/querier.py +0 -0
  44. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/resolution/__init__.py +0 -0
  45. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/resolution/frameworks/__init__.py +0 -0
  46. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/resolution/frameworks/django.py +0 -0
  47. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/resolution/frameworks/fastapi.py +0 -0
  48. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/resolution/import_resolver.py +0 -0
  49. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/resolution/name_matcher.py +0 -0
  50. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/resolution/resolver.py +0 -0
  51. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/retrieval/__init__.py +0 -0
  52. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/search/__init__.py +0 -0
  53. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/sync/__init__.py +0 -0
  54. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/sync/watcher.py +0 -0
  55. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/types.py +0 -0
  56. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/viz/__init__.py +0 -0
  57. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/viz/graph_builder.py +0 -0
  58. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/viz/server.py +0 -0
  59. {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/viz/templates/index.html +0 -0
  60. {codemesh-0.1.3 → codemesh-0.1.4}/tests/__init__.py +0 -0
  61. {codemesh-0.1.3 → codemesh-0.1.4}/tests/conftest.py +0 -0
  62. {codemesh-0.1.3 → codemesh-0.1.4}/tests/fixtures/__init__.py +0 -0
  63. {codemesh-0.1.3 → codemesh-0.1.4}/tests/test_adversarial.py +0 -0
  64. {codemesh-0.1.3 → codemesh-0.1.4}/tests/test_benchmark_repoqa.py +0 -0
  65. {codemesh-0.1.3 → codemesh-0.1.4}/tests/test_embedding_e2e.py +0 -0
  66. {codemesh-0.1.3 → codemesh-0.1.4}/tests/test_extraction.py +0 -0
  67. {codemesh-0.1.3 → codemesh-0.1.4}/tests/test_integration.py +0 -0
  68. {codemesh-0.1.3 → codemesh-0.1.4}/tests/test_llm_judge.py +0 -0
  69. {codemesh-0.1.3 → codemesh-0.1.4}/tests/test_performance.py +0 -0
  70. {codemesh-0.1.3 → codemesh-0.1.4}/tests/test_viz.py +0 -0
  71. {codemesh-0.1.3 → codemesh-0.1.4}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codemesh
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Summary: BM25 keyword search and graph walk for code intelligence
5
5
  Project-URL: Homepage, https://github.com/gkatte/codemesh
6
6
  Project-URL: Repository, https://github.com/gkatte/codemesh
@@ -2,4 +2,4 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- __version__ = "0.1.3"
5
+ __version__ = "0.1.4"
@@ -7,6 +7,8 @@ import json
7
7
  import logging
8
8
  from pathlib import Path
9
9
 
10
+ import typer
11
+
10
12
  logger = logging.getLogger(__name__)
11
13
 
12
14
  _CLAUDE_MCP_CONFIG = {
@@ -185,6 +187,114 @@ def install_codex(root: Path) -> dict:
185
187
  return result
186
188
 
187
189
 
190
+ def uninstall_claude(root: Path, global_config: bool = True) -> dict:
191
+ """Remove CodeMesh MCP server configuration from Claude Code.
192
+
193
+ Args:
194
+ root: Project root (for project-local config).
195
+ global_config: If True, modify ~/.claude.json (global).
196
+ If False, modify .claude.json in project root.
197
+ """
198
+ result = {"claude_json": None, "claude_settings": None}
199
+
200
+ if global_config:
201
+ claude_dir = _find_claude_json_dir()
202
+ if claude_dir is None:
203
+ return result
204
+ claude_json = claude_dir / "claude.json"
205
+ claude_settings = claude_dir / "settings.json"
206
+ else:
207
+ claude_json = root / ".claude.json"
208
+ claude_settings = root / ".claude_settings.json"
209
+
210
+ # Remove codemesh from claude.json
211
+ if claude_json.exists():
212
+ try:
213
+ data = json.loads(claude_json.read_text())
214
+ except (json.JSONDecodeError, OSError):
215
+ data = {}
216
+ if "codemesh" in data.get("mcpServers", {}):
217
+ del data["mcpServers"]["codemesh"]
218
+ if not data["mcpServers"]:
219
+ del data["mcpServers"]
220
+ claude_json.write_text(json.dumps(data, indent=2))
221
+ result["claude_json"] = str(claude_json)
222
+ else:
223
+ result["claude_json"] = "not configured"
224
+
225
+ # Remove codemesh permissions from settings.json
226
+ if claude_settings.exists():
227
+ try:
228
+ settings = json.loads(claude_settings.read_text())
229
+ except (json.JSONDecodeError, OSError):
230
+ settings = {}
231
+ perms = settings.get("permissions", {}).get("allow", [])
232
+ codemesh_perms = [p for p in perms if p.startswith("mcp__codemesh__")]
233
+ if codemesh_perms:
234
+ settings.setdefault("permissions", {})["allow"] = [
235
+ p for p in perms if not p.startswith("mcp__codemesh__")
236
+ ]
237
+ claude_settings.write_text(json.dumps(settings, indent=2))
238
+ result["claude_settings"] = str(claude_settings)
239
+ else:
240
+ result["claude_settings"] = "not configured"
241
+
242
+ return result
243
+
244
+
245
+ def uninstall_cursor(root: Path) -> dict:
246
+ """Remove CodeMesh MCP server configuration from Cursor."""
247
+ result = {"cursor_mcp": None}
248
+
249
+ mcp_json = root / ".cursor" / "mcp.json"
250
+ if not mcp_json.exists():
251
+ result["cursor_mcp"] = "not configured"
252
+ return result
253
+
254
+ try:
255
+ config = json.loads(mcp_json.read_text())
256
+ except (json.JSONDecodeError, OSError):
257
+ return result
258
+
259
+ if "codemesh" in config.get("mcpServers", {}):
260
+ del config["mcpServers"]["codemesh"]
261
+ if not config["mcpServers"]:
262
+ del config["mcpServers"]
263
+ mcp_json.write_text(json.dumps(config, indent=2))
264
+ result["cursor_mcp"] = str(mcp_json)
265
+ else:
266
+ result["cursor_mcp"] = "not configured"
267
+
268
+ return result
269
+
270
+
271
+ def uninstall_codex(root: Path) -> dict:
272
+ """Remove CodeMesh MCP server configuration from Codex CLI."""
273
+ result = {"codex_config": None}
274
+
275
+ codex_dir = Path.home() / ".codex"
276
+ config_file = codex_dir / "config.json"
277
+ if not config_file.exists():
278
+ result["codex_config"] = "not configured"
279
+ return result
280
+
281
+ try:
282
+ config = json.loads(config_file.read_text())
283
+ except (json.JSONDecodeError, OSError):
284
+ return result
285
+
286
+ if "codemesh" in config.get("mcpServers", {}):
287
+ del config["mcpServers"]["codemesh"]
288
+ if not config["mcpServers"]:
289
+ del config["mcpServers"]
290
+ config_file.write_text(json.dumps(config, indent=2))
291
+ result["codex_config"] = str(config_file)
292
+ else:
293
+ result["codex_config"] = "not configured"
294
+
295
+ return result
296
+
297
+
188
298
  def detect_agents() -> list[str]:
189
299
  """Detect which AI coding agents are installed."""
190
300
  agents = []
@@ -206,3 +316,31 @@ def detect_agents() -> list[str]:
206
316
  agents.append("codex")
207
317
 
208
318
  return agents
319
+
320
+
321
+ def clean_project(root: Path, force: bool = False) -> dict:
322
+ """Remove CodeMesh project artifacts (.codemesh/, CLAUDE.md, AGENTS.md, .cursor/rules/).
323
+
324
+ Returns a dict with paths removed.
325
+ """
326
+ removed = []
327
+
328
+ # Clean .codemesh/ directory
329
+ codemesh_dir = root / ".codemesh"
330
+ if codemesh_dir.exists():
331
+ import shutil as _shutil
332
+ _shutil.rmtree(codemesh_dir)
333
+ removed.append(str(codemesh_dir))
334
+
335
+ # Clean agent instruction files written by init
336
+ for label, path in [
337
+ ("CLAUDE.md", root / "CLAUDE.md"),
338
+ ("AGENTS.md", root / "AGENTS.md"),
339
+ (".cursor/rules/codemesh.mdc", root / ".cursor" / "rules" / "codemesh.mdc"),
340
+ ]:
341
+ if path.exists():
342
+ if force or typer.confirm(f"Remove {label}?", default=False):
343
+ path.unlink()
344
+ removed.append(str(path))
345
+
346
+ return {"removed": removed}
@@ -126,6 +126,81 @@ def install(
126
126
  typer.echo("\nRestart your agent(s) for the MCP server to load.")
127
127
 
128
128
 
129
+ @app.command()
130
+ def uninstall(
131
+ target: str = typer.Option(
132
+ "auto",
133
+ "--target",
134
+ "-t",
135
+ help="Agent(s) to uninstall: auto, all, claude, cursor, codex, or comma-separated list",
136
+ ),
137
+ global_config: bool = typer.Option(
138
+ True, "--global/--local", help="Remove global config (default) or project-local"
139
+ ),
140
+ yes: bool = typer.Option(False, "--yes", "-y", help="Non-interactive mode"),
141
+ path: str = typer.Option(".", "--path", "-p", help="Project path for local config"),
142
+ clean: bool = typer.Option(False, "--clean", help="Also remove .codemesh/ and rule files"),
143
+ ) -> None:
144
+ """Uninstall CodeMesh MCP server configuration from AI coding agents.
145
+
146
+ Removes MCP server entries and permissions from agent config files.
147
+ Optionally cleans up project artifacts (.codemesh/, CLAUDE.md, AGENTS.md).
148
+ """
149
+ from codemesh.cli.install_cmd import (
150
+ detect_agents,
151
+ uninstall_claude,
152
+ uninstall_codex,
153
+ uninstall_cursor,
154
+ clean_project,
155
+ )
156
+
157
+ root = Path(path).resolve()
158
+ targets = target.lower().split(",") if target not in ("auto", "all") else [target]
159
+
160
+ if "auto" in targets:
161
+ detected = detect_agents()
162
+ if not detected:
163
+ typer.echo("No AI coding agents detected. Use --target to specify manually.")
164
+ raise typer.Exit(1)
165
+ targets = detected
166
+ if not yes:
167
+ typer.echo(f"Detected agents: {', '.join(targets)}")
168
+ typer.confirm("Uninstall from these agents?", abort=True)
169
+
170
+ if "all" in targets:
171
+ targets = ["claude", "cursor", "codex"]
172
+
173
+ results = {}
174
+ for agent in targets:
175
+ agent = agent.strip()
176
+ if agent == "claude":
177
+ r = uninstall_claude(root, global_config=global_config)
178
+ results["claude"] = r
179
+ elif agent == "cursor":
180
+ r = uninstall_cursor(root)
181
+ results["cursor"] = r
182
+ elif agent == "codex":
183
+ r = uninstall_codex(root)
184
+ results["codex"] = r
185
+ else:
186
+ typer.echo(f"Unknown agent: {agent}", err=True)
187
+
188
+ typer.echo("CodeMesh MCP server removed:")
189
+ for agent, r in results.items():
190
+ for key, val in r.items():
191
+ if val:
192
+ typer.echo(f" {agent}/{key}: {val}")
193
+
194
+ if clean:
195
+ removed = clean_project(root, force=yes)
196
+ if removed["removed"]:
197
+ typer.echo("\nProject artifacts removed:")
198
+ for p in removed["removed"]:
199
+ typer.echo(f" {p}")
200
+ else:
201
+ typer.echo("\nNo project artifacts found.")
202
+
203
+
129
204
  @app.command()
130
205
  def index(
131
206
  path: str = typer.Argument(".", help="Path to the codebase to index"),
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "codemesh"
7
- version = "0.1.3"
7
+ version = "0.1.4"
8
8
  description = "BM25 keyword search and graph walk for code intelligence"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes