symgrep-codesearch 0.6.2__tar.gz → 0.6.3__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.
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/PKG-INFO +1 -1
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/pyproject.toml +4 -1
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/cli.py +60 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/mcp_server.py +29 -1
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep_codesearch.egg-info/PKG-INFO +1 -1
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/LICENSE +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/README.md +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/setup.cfg +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/__init__.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/blocks.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/classfile.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/data_symbols.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/docsymbols.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/enclosing.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/mcp_structured.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/report.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/resolve.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/resolve_js.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/resolve_python.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/ripgrep.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/semantic.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/structural.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep/structure.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep_codesearch.egg-info/SOURCES.txt +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep_codesearch.egg-info/dependency_links.txt +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep_codesearch.egg-info/entry_points.txt +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep_codesearch.egg-info/requires.txt +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep_codesearch.egg-info/top_level.txt +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_blocks_extraction.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_blocks_retrieval.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_bulk_describe.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_classfile.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_data_symbols.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_describe_lane_confinement.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_doc_symbols.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_file_structure.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_freshness.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_honest_recall.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_http_ensure.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_index_reconstruct.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_index_scope.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_index_worker.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_mcp_structured.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_name_uniqueness.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_nudge_runaway.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_report_filters.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_resolve.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_resolve_js.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_resolve_python.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_resolve_r2.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_review_regressions.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_semantic_freshness_signal.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_sites_and_symbols.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_structural.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_symbol_vocabulary.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_ts_fallback_loud.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_ts_symbol_coverage.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_usage.py +0 -0
- {symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_veccore_adoption.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: symgrep-codesearch
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.3
|
|
4
4
|
Summary: Code search with honest recall — structure-aware grep that tells you what it does not know, plus search by meaning
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Repository, https://github.com/ashdamle/symgrep
|
|
@@ -7,6 +7,9 @@ build-backend = "setuptools.build_meta"
|
|
|
7
7
|
# Semgrep team. The IMPORT name is unchanged — `import symgrep` — so consumers (honestreview, spendguard,
|
|
8
8
|
# 7thsense, warden) are unaffected by the distribution rename. The package dir stays src/symgrep.
|
|
9
9
|
name = "symgrep-codesearch"
|
|
10
|
+
# 0.6.3: MCP surface completeness — TOOL_DESCRIPTION now documents structural=/lang= (the last undescribed
|
|
11
|
+
# params), and a new `symgrep install-mcp` subcommand self-registers the server via `claude mcp add`. No API
|
|
12
|
+
# change; keeps PyPI current with the capability descriptions pip-installed MCP clients see.
|
|
10
13
|
# 0.6.2: ripgrep is a system binary and cannot be a normal pip dependency, but the new `[rg]` extra pulls
|
|
11
14
|
# `ripgrep-bin` (a wheel bundling the rg binary) for a self-contained install; rg_binary() now also finds an
|
|
12
15
|
# rg next to the interpreter (venv bin), so the pip-only path works even under `.venv/bin/python -m …`.
|
|
@@ -17,7 +20,7 @@ name = "symgrep-codesearch"
|
|
|
17
20
|
# semantic search. Minor bump (dependency surface changed; no breaking import/CLI/MCP change).
|
|
18
21
|
# 0.5.0: added the public `file_structure` library API (+ its MCP tool and `symgrep structure` CLI), import
|
|
19
22
|
# module-name normalization, and the FileStructure `connects` list (structure schema v2).
|
|
20
|
-
version = "0.6.
|
|
23
|
+
version = "0.6.3"
|
|
21
24
|
description = "Code search with honest recall — structure-aware grep that tells you what it does not know, plus search by meaning"
|
|
22
25
|
readme = "README.md"
|
|
23
26
|
# 3.11+ : the maintained grammar pack (tree-sitter-language-pack, a CORE dep below) ships abi3 wheels for
|
|
@@ -409,10 +409,70 @@ def _cmd_structure(rest) -> int:
|
|
|
409
409
|
return 0
|
|
410
410
|
|
|
411
411
|
|
|
412
|
+
def _resolve_mcp_entrypoint() -> "Optional[str]":
|
|
413
|
+
"""Absolute path to symgrep's MCP stdio entrypoint for THIS install, resolved — never hardcoded. The
|
|
414
|
+
`symgrep-mcp` console script sits next to the interpreter (venv bin) for a pip OR editable install; a bare
|
|
415
|
+
checkout with no install falls back to the repo's bin/symgrep-mcp wrapper. None if neither is found."""
|
|
416
|
+
import shutil
|
|
417
|
+
exe_dir = os.path.dirname(sys.executable or "")
|
|
418
|
+
cand = os.path.join(exe_dir, "symgrep-mcp")
|
|
419
|
+
if os.path.isfile(cand) and os.access(cand, os.X_OK):
|
|
420
|
+
return cand
|
|
421
|
+
on_path = shutil.which("symgrep-mcp")
|
|
422
|
+
if on_path:
|
|
423
|
+
return on_path
|
|
424
|
+
repo_bin = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
|
|
425
|
+
"bin", "symgrep-mcp")
|
|
426
|
+
if os.path.isfile(repo_bin) and os.access(repo_bin, os.X_OK):
|
|
427
|
+
return repo_bin
|
|
428
|
+
return None
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def _cmd_install_mcp(rest) -> int:
|
|
432
|
+
"""`symgrep install-mcp [--scope user|local|project] [--name NAME] [--dry-run]` — register symgrep's own
|
|
433
|
+
MCP server with Claude Code, so a fresh install advertises itself as a tool. It does NOT write
|
|
434
|
+
~/.claude.json itself (one shared file must have ONE writer); it shells to `claude mcp add`, the safe
|
|
435
|
+
single writer that ships with the client — so this command carries no config-mutation logic to drift."""
|
|
436
|
+
import shutil
|
|
437
|
+
import subprocess
|
|
438
|
+
sp = argparse.ArgumentParser(prog="symgrep install-mcp")
|
|
439
|
+
sp.add_argument("--scope", default="user", choices=["local", "user", "project"],
|
|
440
|
+
help="Claude Code config scope to register in (default: user)")
|
|
441
|
+
sp.add_argument("--name", default="symgrep", help="server name to register under (default: symgrep)")
|
|
442
|
+
sp.add_argument("--dry-run", action="store_true", help="print the exact `claude mcp add` command, write nothing")
|
|
443
|
+
a = sp.parse_args(rest)
|
|
444
|
+
claude = shutil.which("claude")
|
|
445
|
+
if not claude:
|
|
446
|
+
print("install-mcp: the `claude` CLI is not on PATH. symgrep delegates registration to it rather than "
|
|
447
|
+
"writing ~/.claude.json itself — install Claude Code, then re-run.", file=sys.stderr)
|
|
448
|
+
return 2
|
|
449
|
+
entry = _resolve_mcp_entrypoint()
|
|
450
|
+
if not entry:
|
|
451
|
+
print("install-mcp: could not locate symgrep's MCP entrypoint (`symgrep-mcp` console script or "
|
|
452
|
+
"bin/symgrep-mcp). Install symgrep in this interpreter (`pip install symgrep-codesearch`) first.",
|
|
453
|
+
file=sys.stderr)
|
|
454
|
+
return 2
|
|
455
|
+
cmd = [claude, "mcp", "add", "--scope", a.scope, a.name, "--", entry]
|
|
456
|
+
if a.dry_run:
|
|
457
|
+
print("DRY RUN — would run:\n " + " ".join(cmd))
|
|
458
|
+
return 0
|
|
459
|
+
print("registering symgrep's MCP server:\n " + " ".join(cmd))
|
|
460
|
+
rc = subprocess.run(cmd).returncode
|
|
461
|
+
if rc == 0:
|
|
462
|
+
# MCP servers are read at client START: a just-registered server is callable in the NEXT session, not
|
|
463
|
+
# this one — say so rather than imply a live pickup this cannot deliver.
|
|
464
|
+
print(f"registered '{a.name}' at scope '{a.scope}'. It becomes callable in the NEXT Claude session "
|
|
465
|
+
"(MCP servers load at client start). `claude mcp add` leaves an existing entry intact, so this "
|
|
466
|
+
"is safe to re-run.")
|
|
467
|
+
return rc
|
|
468
|
+
|
|
469
|
+
|
|
412
470
|
def main(argv=None) -> int:
|
|
413
471
|
_argv = list(sys.argv[1:] if argv is None else argv)
|
|
414
472
|
if _argv and _argv[0] == "structure": # `symgrep structure <path>` — a subcommand over the flag CLI
|
|
415
473
|
return _cmd_structure(_argv[1:])
|
|
474
|
+
if _argv and _argv[0] == "install-mcp": # `symgrep install-mcp` — self-register as an MCP server
|
|
475
|
+
return _cmd_install_mcp(_argv[1:])
|
|
416
476
|
ap = argparse.ArgumentParser(prog="symgrep", description=__doc__)
|
|
417
477
|
ap.add_argument("pattern", nargs="?", default=None,
|
|
418
478
|
help="regex to search (omit with --index: then every positional is a ROOT)")
|
|
@@ -55,7 +55,30 @@ TOOL_DESCRIPTION = (
|
|
|
55
55
|
"nothing is CALLED that, never that nothing DOES it. That gap is how duplicate implementations get "
|
|
56
56
|
"written — measured in one codebase: `share.scrub` beside `share._scrub_text`, `adapters.call_complete` "
|
|
57
57
|
"beside `adapters.call`, `_save_state` in three files. Requires an index (symgrep --index <root>); if "
|
|
58
|
-
"there is none it says so rather than returning an empty result
|
|
58
|
+
"there is none it says so rather than returning an empty result.\n\n"
|
|
59
|
+
"THREE MORE MODES, each a different question:\n"
|
|
60
|
+
" usage=true — is this name DEFINED, REFERENCED, both, or neither? Returns a verdict in\n"
|
|
61
|
+
" {defined_referenced, defined_unused, undefined_referenced, absent}. LEXICAL,\n"
|
|
62
|
+
" by name: 'defined_unused' is a possibly-unused HINT, never proof of dead code.\n"
|
|
63
|
+
" resolve=true — cross-file candidate resolution: {resolved_unique, ambiguous, external, absent}.\n"
|
|
64
|
+
" When >1 definition shares a name it reports AMBIGUOUS with candidates rather\n"
|
|
65
|
+
" than picking a winner. Use this before trusting any single definition of a\n"
|
|
66
|
+
" name that occurs more than once — import order decides it at runtime.\n"
|
|
67
|
+
" structured=true — machine-readable JSON with a mechanical `status` (ok | no_index | unavailable)\n"
|
|
68
|
+
" instead of prose. Use whenever a program, not a human, reads the result.\n\n"
|
|
69
|
+
"unit= sets --semantic GRANULARITY: 'symbol' (default, a whole function) | 'block' (a sub-function\n"
|
|
70
|
+
"AST block — Type-4 clone retrieval, finds copy-pasted fragments whole-function search misses) |\n"
|
|
71
|
+
"'data' (a schema/config/proto/sql definition) | 'both'/'all'. block and data hits need\n"
|
|
72
|
+
"structured=true to read their span. kind= filters within a unit, e.g. 'data_schema', 'sql_table',\n"
|
|
73
|
+
"'proto_message'.\n\n"
|
|
74
|
+
"structural=true SWITCHES FROM REGEX TO AST-PATTERN MATCH — `pattern` becomes a code snippet with\n"
|
|
75
|
+
"metavariables ($NAME matches one node, $$$ is variadic), matched by syntactic SHAPE, so it finds forms a\n"
|
|
76
|
+
"regex cannot express (e.g. `$A == $A` for self-comparisons) without tripping on whitespace or naming. It\n"
|
|
77
|
+
"REQUIRES lang= to pick the grammar the pattern is parsed in (lang= one of the tree-sitter languages:\n"
|
|
78
|
+
"'python' | 'go' | 'javascript' | 'typescript' | 'tsx' | 'rust' | 'java' | 'c' | 'cpp' | 'ruby' | 'php' |\n"
|
|
79
|
+
"'c_sharp' | 'kotlin' | 'scala' | 'bash'); with no usable grammar it reports UNAVAILABLE rather than\n"
|
|
80
|
+
"silently falling back to text. Use it for structural queries a name/regex search cannot express; use\n"
|
|
81
|
+
"plain regex or semantic=true for everything else."
|
|
59
82
|
)
|
|
60
83
|
|
|
61
84
|
|
|
@@ -131,6 +154,11 @@ def _run_fastmcp(http=None) -> bool:
|
|
|
131
154
|
definitions, references, resolution_basis:"candidate-name"}. verdict ∈ resolved_unique | ambiguous |
|
|
132
155
|
external | absent. When >1 definition shares the name it is AMBIGUOUS (candidates, not one winner).
|
|
133
156
|
|
|
157
|
+
structural=True: match by AST SHAPE, not regex — `pattern` is a code snippet with metavariables
|
|
158
|
+
($NAME matches one node, $$$ is variadic). Requires lang= (the tree-sitter grammar the pattern parses
|
|
159
|
+
in, e.g. "python"/"go"/"rust"); reports UNAVAILABLE when no grammar is usable rather than falling back
|
|
160
|
+
to text. lang is used ONLY by structural search.
|
|
161
|
+
|
|
134
162
|
unit: --semantic granularity — "symbol" (default; a whole function/method, the only pre-v6 behaviour,
|
|
135
163
|
byte-stable) | "block" (a sub-function AST block, Type-4 clone retrieval) | "data" (a schema/data/config
|
|
136
164
|
symbol — a data_schema file unit or a proto/sql definition) | "both"/"all". block/data hits need
|
{symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep_codesearch.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: symgrep-codesearch
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.3
|
|
4
4
|
Summary: Code search with honest recall — structure-aware grep that tells you what it does not know, plus search by meaning
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Repository, https://github.com/ashdamle/symgrep
|
|
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
|
{symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep_codesearch.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep_codesearch.egg-info/requires.txt
RENAMED
|
File without changes
|
{symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/src/symgrep_codesearch.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_describe_lane_confinement.py
RENAMED
|
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
|
{symgrep_codesearch-0.6.2 → symgrep_codesearch-0.6.3}/tests/test_semantic_freshness_signal.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|