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.
- {codemesh-0.1.3 → codemesh-0.1.4}/PKG-INFO +1 -1
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/__init__.py +1 -1
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/cli/install_cmd.py +138 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/cli/main.py +75 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/pyproject.toml +1 -1
- {codemesh-0.1.3 → codemesh-0.1.4}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/.github/workflows/ci.yml +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/.github/workflows/publish.yml +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/.gitignore +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/CHANGELOG.md +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/CONTRIBUTING.md +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/LICENSE +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/Makefile +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/README.md +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/__main__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/cli/__init__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/cli/init.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/context/__init__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/context/builder.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/db/__init__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/db/connection.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/db/queries.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/db/schema.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/embedding/__init__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/__init__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/languages/__init__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/languages/c_family.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/languages/go.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/languages/java.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/languages/python.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/languages/rust.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/languages/swift.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/languages/typescript.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/extraction/orchestrator.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/graph/__init__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/graph/query_manager.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/graph/traverser.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/indexer.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/mcp/__init__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/mcp/server.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/mcp/tools.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/querier.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/resolution/__init__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/resolution/frameworks/__init__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/resolution/frameworks/django.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/resolution/frameworks/fastapi.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/resolution/import_resolver.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/resolution/name_matcher.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/resolution/resolver.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/retrieval/__init__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/search/__init__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/sync/__init__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/sync/watcher.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/types.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/viz/__init__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/viz/graph_builder.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/viz/server.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/codemesh/viz/templates/index.html +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/tests/__init__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/tests/conftest.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/tests/fixtures/__init__.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/tests/test_adversarial.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/tests/test_benchmark_repoqa.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/tests/test_embedding_e2e.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/tests/test_extraction.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/tests/test_integration.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/tests/test_llm_judge.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/tests/test_performance.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/tests/test_viz.py +0 -0
- {codemesh-0.1.3 → codemesh-0.1.4}/uv.lock +0 -0
|
@@ -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"),
|
|
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
|
|
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
|
|
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
|
|
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
|