scip-cli 1.3.0__tar.gz → 2.0.0__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 (97) hide show
  1. scip_cli-2.0.0/.cursor/rules/agent.mdc +133 -0
  2. scip_cli-2.0.0/.gitignore +53 -0
  3. scip_cli-2.0.0/.pre-commit-config.yaml +15 -0
  4. {scip_cli-1.3.0/scip_cli.egg-info → scip_cli-2.0.0}/PKG-INFO +97 -48
  5. scip_cli-1.3.0/PKG-INFO → scip_cli-2.0.0/README.md +88 -59
  6. scip_cli-2.0.0/pyproject.toml +59 -0
  7. scip_cli-2.0.0/scip_cli/SKILL.md +135 -0
  8. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/__init__.py +2 -1
  9. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/__main__.py +75 -28
  10. scip_cli-2.0.0/scip_cli/analyze/__init__.py +1 -0
  11. scip_cli-2.0.0/scip_cli/analyze/common.py +110 -0
  12. scip_cli-2.0.0/scip_cli/analyze/file.py +354 -0
  13. scip_cli-2.0.0/scip_cli/analyze/project.py +435 -0
  14. scip_cli-2.0.0/scip_cli/analyze/sections.py +77 -0
  15. scip_cli-2.0.0/scip_cli/analyze/symbol.py +184 -0
  16. scip_cli-2.0.0/scip_cli/analyze/targets.py +97 -0
  17. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/cache.py +28 -5
  18. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/cli_args.py +26 -1
  19. scip_cli-2.0.0/scip_cli/commands/analyze.py +142 -0
  20. scip_cli-2.0.0/scip_cli/commands/code.py +123 -0
  21. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/commands/members.py +13 -14
  22. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/commands/rdeps.py +5 -13
  23. scip_cli-2.0.0/scip_cli/commands/refs.py +166 -0
  24. scip_cli-2.0.0/scip_cli/commands/reindex.py +69 -0
  25. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/commands/search.py +98 -57
  26. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/commands/skill.py +7 -3
  27. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/commands/symbols.py +4 -6
  28. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/config.py +3 -3
  29. scip_cli-2.0.0/scip_cli/debug.py +10 -0
  30. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/discover.py +14 -21
  31. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/indexing.py +224 -74
  32. scip_cli-2.0.0/scip_cli/merge.py +108 -0
  33. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/output.py +56 -26
  34. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/paths.py +37 -3
  35. scip_cli-2.0.0/scip_cli/project.py +42 -0
  36. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/queries.py +86 -75
  37. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/scip_tool.py +25 -10
  38. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/scope.py +1 -6
  39. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/session.py +2 -1
  40. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/source.py +12 -3
  41. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/sql.py +7 -4
  42. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/symbols.py +39 -12
  43. scip_cli-2.0.0/scip_cli/targets.py +17 -0
  44. scip_cli-2.0.0/scripts/build.sh +13 -0
  45. scip_cli-2.0.0/scripts/publish.sh +32 -0
  46. scip_cli-2.0.0/scripts/test.sh +9 -0
  47. scip_cli-2.0.0/tests/analyze_db.py +204 -0
  48. scip_cli-2.0.0/tests/conftest.py +25 -0
  49. scip_cli-2.0.0/tests/e2e_harness.py +101 -0
  50. scip_cli-2.0.0/tests/fixture_catalog.py +17 -0
  51. scip_cli-2.0.0/tests/fixtures/sample-project/package.json +5 -0
  52. scip_cli-2.0.0/tests/fixtures/sample-project/src/app/handler.ts +3 -0
  53. scip_cli-2.0.0/tests/fixtures/sample-project/src/config.ts +1 -0
  54. scip_cli-2.0.0/tests/fixtures/sample-project/src/consumer.ts +4 -0
  55. scip_cli-2.0.0/tests/fixtures/sample-project/src/dead.ts +1 -0
  56. scip_cli-2.0.0/tests/fixtures/sample-project/src/helper.ts +7 -0
  57. scip_cli-2.0.0/tests/fixtures/sample-project/src/index.ts +3 -0
  58. scip_cli-2.0.0/tests/fixtures/sample-project/src/user.ts +6 -0
  59. scip_cli-2.0.0/tests/fixtures/sample-project/src/widget.ts +7 -0
  60. scip_cli-2.0.0/tests/fixtures/sample-project/tsconfig.json +8 -0
  61. scip_cli-2.0.0/tests/test_analyze.py +223 -0
  62. {scip_cli-1.3.0 → scip_cli-2.0.0}/tests/test_cache.py +2 -2
  63. {scip_cli-1.3.0 → scip_cli-2.0.0}/tests/test_composability.py +44 -49
  64. {scip_cli-1.3.0 → scip_cli-2.0.0}/tests/test_config.py +1 -0
  65. {scip_cli-1.3.0 → scip_cli-2.0.0}/tests/test_discover.py +1 -0
  66. scip_cli-2.0.0/tests/test_e2e.py +174 -0
  67. scip_cli-2.0.0/tests/test_index_prune.py +122 -0
  68. {scip_cli-1.3.0 → scip_cli-2.0.0}/tests/test_indexer_env.py +2 -1
  69. {scip_cli-1.3.0 → scip_cli-2.0.0}/tests/test_merge.py +40 -21
  70. scip_cli-2.0.0/tests/test_multi_symbol.py +205 -0
  71. {scip_cli-1.3.0 → scip_cli-2.0.0}/tests/test_pure_functions.py +277 -270
  72. scip_cli-2.0.0/tests/test_qualified_symbols.py +100 -0
  73. scip_cli-2.0.0/tests/test_reindex.py +53 -0
  74. {scip_cli-1.3.0 → scip_cli-2.0.0}/tests/test_scip_tool.py +1 -0
  75. {scip_cli-1.3.0 → scip_cli-2.0.0}/tests/test_scope.py +7 -6
  76. scip_cli-2.0.0/tests/test_targets.py +17 -0
  77. {scip_cli-1.3.0 → scip_cli-2.0.0}/tests/test_typescript_projects.py +1 -0
  78. scip_cli-1.3.0/MANIFEST.in +0 -4
  79. scip_cli-1.3.0/README.md +0 -257
  80. scip_cli-1.3.0/pyproject.toml +0 -13
  81. scip_cli-1.3.0/scip_cli/SKILL.md +0 -108
  82. scip_cli-1.3.0/scip_cli/commands/def_cmd.py +0 -57
  83. scip_cli-1.3.0/scip_cli/commands/refs.py +0 -136
  84. scip_cli-1.3.0/scip_cli/commands/reindex.py +0 -55
  85. scip_cli-1.3.0/scip_cli/constants.py +0 -14
  86. scip_cli-1.3.0/scip_cli/lib.py +0 -64
  87. scip_cli-1.3.0/scip_cli/merge.py +0 -175
  88. scip_cli-1.3.0/scip_cli/project.py +0 -29
  89. scip_cli-1.3.0/scip_cli.egg-info/SOURCES.txt +0 -51
  90. scip_cli-1.3.0/scip_cli.egg-info/entry_points.txt +0 -2
  91. scip_cli-1.3.0/scip_cli.egg-info/top_level.txt +0 -1
  92. scip_cli-1.3.0/setup.cfg +0 -4
  93. scip_cli-1.3.0/setup.py +0 -37
  94. scip_cli-1.3.0/tests/test_smoke_cli.py +0 -157
  95. {scip_cli-1.3.0 → scip_cli-2.0.0}/LICENSE +0 -0
  96. {scip_cli-1.3.0 → scip_cli-2.0.0}/scip_cli/commands/__init__.py +0 -0
  97. /scip_cli-1.3.0/scip_cli.egg-info/dependency_links.txt → /scip_cli-2.0.0/tests/__init__.py +0 -0
@@ -0,0 +1,133 @@
1
+ ---
2
+ description: scip-cli dev workflow and TDD with the shared fixture
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # scip-cli agent
7
+
8
+ **Work from repo root.** CLI usage, flags, and user gotchas: `scip-cli skill` (source: `scip_cli/SKILL.md`). Read once per task — do not duplicate SKILL here.
9
+
10
+ Use **`.venv/bin/scip-cli`** / **`.venv/bin/pytest`**. Uncommitted code: `PYTHONPATH=$PWD python -m scip_cli …` if the venv binary is stale.
11
+
12
+ ## Bootstrap
13
+
14
+ ```bash
15
+ python -m venv .venv && source .venv/bin/activate
16
+ pip install -e ".[dev]"
17
+ pre-commit install
18
+ scip-cli skill
19
+ ```
20
+
21
+ Node.js + `npx` required for integration tests (`scip-typescript`). Optional: `SCIP_CLI_DEBUG=1` (SQL to stderr, truncated).
22
+
23
+ ## Lint / test
24
+
25
+ | Task | Command |
26
+ |------|---------|
27
+ | Full suite | `.venv/bin/pytest` |
28
+ | E2e loop | `.venv/bin/pytest tests/test_e2e.py` |
29
+ | Lint / format | `.venv/bin/ruff check .` / `ruff format .` |
30
+
31
+ Pre-commit: ruff + ruff-format + full pytest. E2e before commit on command changes.
32
+
33
+ ## Improving this repo (do this before review subagents)
34
+
35
+ **Dogfood on the repo itself** — faster and more honest than spawning reviewers:
36
+
37
+ ```bash
38
+ .venv/bin/scip-cli reindex
39
+ .venv/bin/scip-cli analyze --limit 25
40
+ .venv/bin/scip-cli analyze --priority high --limit 25 # dead code & cycles only
41
+ .venv/bin/scip-cli analyze scip_cli --limit 15 # directory
42
+ .venv/bin/scip-cli analyze scip_cli/queries.py --limit 20 # file (+ scoped project)
43
+ ```
44
+
45
+ Interpretation: README § *Finding easy wins with analyze*. Target = omit (project), directory, file, or symbol — not `--path` for scope.
46
+
47
+ | Priority | Section | Action |
48
+ |----------|---------|--------|
49
+ | 1 | **Cycles** | Break production file dependency cycles (`cache`↔`scope` was one) |
50
+ | 2 | **Unreferenced / dead exports** | No ref usage / no external refs — verify with `rg`, delete or `_` prefix |
51
+ | 3 | **Same-file only** | Module-private by usage — rename to `_` |
52
+ | 4 | **Stale types** | Low-consumer classes — merge or justify |
53
+
54
+ `analyze` skips test paths by default (`tests/`, `*.test.*`, `*.spec.*`); `--include-tests` to include. Reindex after large edits.
55
+
56
+ Do **not** spawn broad code-review agents until this pass is done (or explain why skipped).
57
+
58
+ ## Analyze feedback loop (mandatory)
59
+
60
+ When you or a review subagent finds a repo issue — bug, dead code, cycle, risky hub, stale type, unused import — **stop and ask first:**
61
+
62
+ > *Could our SQLite index have predicted this, and `analyze` just doesn't surface it yet?*
63
+
64
+ If **yes** (the signal is in `documents`, `mentions`, `global_symbols`, `defn_enclosing_ranges`):
65
+
66
+ 1. **Extend `analyze` first** — new or tuned SQL check in `scip_cli/analyze/`, priority in `sections.py`, tests in `tests/test_analyze.py` + `analyze_db.py`.
67
+ 2. **Dogfood** — `reindex` → confirm the issue appears (or the false positive is filtered).
68
+ 3. **Then** fix the production code (or document a known blind spot).
69
+
70
+ Only skip step 1 when the issue is **outside the index** (runtime, CLI UX, docs drift, git, env, concurrency, test harness).
71
+
72
+ ### Retrospective: caught manually, SQLite already had it
73
+
74
+ | Issue we hit | Index signal | Analyze today | Gap / next check |
75
+ |--------------|--------------|---------------|------------------|
76
+ | `cache` ↔ `scope` import cycle | cross-file `mentions` edges | `[high] Cycles` | **Caught** — keep dogfooding cycles |
77
+ | Cross-file dead export (`get_refs_for_symbols`) | def with no external `mentions` | `[high] Dead exports` | **Caught** |
78
+ | Same-file-only dead code | def, `role=0` only in def file | `[high] Unreferenced` or `[medium] Same-file only` | **Caught** (since extended) |
79
+ | Same-file helper without `_` (`run_with_fallback`) | same-file `role=0` or none | `[medium] Same-file only` / unreferenced | **Caught** — rename to `_` |
80
+ | Typing-only dataclasses (`ProjectSettings`, `IndexScope`) | type `#` symbol, 0 consumer files | `[high] Stale types` + `stale_type_noise` | **Filtered** — index can't see annotations; document or optional `--types` |
81
+ | `analyze/*` section runners “dead” | no external refs | noise filter in `common.py` | **Filtered** — framework pattern |
82
+ | Unused import | `role=2` mention, no in-file use | `[high] Unused imports` (per file) | **Caught** on file target |
83
+ | Hub before editing (`resolve_symbol`, `queries.py`) | fan-in / consumer count | `[medium] Change surface` / `[low] Hotspots` | **Caught** on file target; project hubs are low tier |
84
+ | Symbol only used from tests | consumers all under `tests/` | `[low] Test-only consumers` | **Partial** — Python index often omits same-file `role=0`; verify with `rg` |
85
+ | Indexer omits same-file Python calls | no `role=0` for in-module use | unreferenced / test-only false positives | **Index gap** — not fixable in SQL alone; demoted test-only to low |
86
+ | Duplicate / parallel helpers | — | — | **Not in index** — `rg`, not analyze |
87
+
88
+ Add new rows to `dogfood.md` when you find another gap; implement the SQL check before the next manual review pass.
89
+
90
+ ### Size / complexity checks (assessed — don’t promote to high/medium)
91
+
92
+ SQLite has **line ranges** (`defn_enclosing_ranges`) so LOC is cheap. That does **not** mean “big function” belongs next to dead exports.
93
+
94
+ | Idea | In index? | Verdict |
95
+ |------|-----------|---------|
96
+ | **LOC ≥ N** alone | Yes | **LOW at best** — noisy (`main`, argparse, legitimate parsers). Not a nuke candidate. |
97
+ | **LOC + fan-in** (large hub) | Yes | **Already covered** by `[low] Bottlenecks` (fan-in × fan-out). Add `loc=` to that output if helpful; don’t duplicate as medium. |
98
+ | **LOC + consumers** on file target | Yes | **Change surface** (medium) already sorts by consumers with line ranges — drill there. |
99
+ | **Symbol pressure** | Yes | **Per-symbol** `analyze Foo` shows `loc × fan_in × fan_out`. |
100
+ | **God class / many members** | Yes | Use `members Class` — not analyze. |
101
+ | **File byte size / cyclomatic complexity** | No | Out of scope for SCIP index. |
102
+ | **Fat file (many symbols)** | Yes | Low value; coupling/hotspots approximate module heat. |
103
+
104
+ **Rule:** size-only checks stay **low or file-drill-down**; never high/medium unless paired with a **structural smell** (cycle, dead export, zero production consumers). Prefer enriching existing low-tier lines (e.g. show `loc` on bottlenecks) over a new dashboard section.
105
+
106
+ ## TDD
107
+
108
+ 1. **Red** — `tests/test_e2e.py` + `fixture_catalog` constants.
109
+ 2. **Green** — `scip_cli/commands/*.py`.
110
+ 3. **Refactor** — unit tests for pure helpers only.
111
+
112
+ - **E2e** (`cli` fixture): in-process `main()`, TS project indexed once per session — default for behavior.
113
+ - **Unit**: `:memory:` SQLite, `tests/analyze_db.py`, merge/index prune tests.
114
+ - **No subprocess** for CLI tests; no `reindex` in e2e (mutates `~/.cache/scip-cli`).
115
+ - New symbols: extend `tests/fixtures/sample-project/` + `fixture_catalog.py`.
116
+
117
+ ## Codebase map (contributors)
118
+
119
+ | Area | Path | Notes |
120
+ |------|------|-------|
121
+ | Commands | `scip_cli/commands/` | Thin; SQL in `queries.py` / `analyze/` |
122
+ | Index build | `scip_cli/indexing.py` | `index.db.next` → promote; flock; `>10` tsconfigs log progress |
123
+ | Variable prune | postprocess + `merge.py` | Omit const/let/var on **COPY**, not DELETE — no `variable` kind |
124
+ | Session | `scip_cli/session.py` | `setup()`, `resolve_one_symbol` (limit 2 for ambiguity) |
125
+ | Analyze filters | `scip_cli/analyze/common.py` | `is_test_path`, `analyze_noise` (`_` helpers) |
126
+
127
+ `todo.md` = tracked work; `dogfood.md` = future ideas only. Wishlist/backlog in `docs/` per workspace rules.
128
+
129
+ ## Docs touch points
130
+
131
+ - User install + analyze guide → `README.md`
132
+ - Agent/user CLI reference → `scip_cli/SKILL.md` (must match `__main__.py` flags)
133
+ - After flag changes: update SKILL + README command list; run `scip-cli skill` to verify output
@@ -0,0 +1,53 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+
23
+ # Virtual environments
24
+ venv/
25
+ ENV/
26
+ env/
27
+ .venv
28
+
29
+ # IDE
30
+ .vscode/
31
+ .idea/
32
+ *.swp
33
+ *.swo
34
+ *~
35
+
36
+ # OS
37
+ .DS_Store
38
+ Thumbs.db
39
+
40
+ # Env/secrets
41
+ .env
42
+
43
+ # Pytest
44
+ .pytest_cache/
45
+
46
+ # Project specific
47
+ TODO.md
48
+ todo.md
49
+ dogfood.md
50
+
51
+ # Local-only dev scripts (repo-specific smoke harnesses)
52
+ scripts/deep-smoke.sh
53
+ tmp/
@@ -0,0 +1,15 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.11.0
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
8
+ - repo: local
9
+ hooks:
10
+ - id: pytest
11
+ name: pytest
12
+ entry: pytest
13
+ language: python
14
+ pass_filenames: false
15
+ always_run: true
@@ -1,81 +1,78 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scip-cli
3
- Version: 1.3.0
3
+ Version: 2.0.0
4
4
  Summary: Fast code intelligence via SCIP indexes
5
- Home-page: https://github.com/flesler/scip-cli
5
+ Project-URL: Homepage, https://github.com/flesler/scip-cli
6
6
  Author: Ariel Flesler
7
7
  License: MIT
8
- Classifier: Programming Language :: Python :: 3
8
+ License-File: LICENSE
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
+ Classifier: Programming Language :: Python :: 3
11
12
  Classifier: Topic :: Software Development :: Code Generators
12
13
  Requires-Python: >=3.9
14
+ Provides-Extra: dev
15
+ Requires-Dist: build>=1; extra == 'dev'
16
+ Requires-Dist: pre-commit>=4.0; extra == 'dev'
17
+ Requires-Dist: pytest>=7; extra == 'dev'
18
+ Requires-Dist: ruff>=0.11; extra == 'dev'
13
19
  Description-Content-Type: text/markdown
14
- License-File: LICENSE
15
- Dynamic: author
16
- Dynamic: classifier
17
- Dynamic: description
18
- Dynamic: description-content-type
19
- Dynamic: home-page
20
- Dynamic: license
21
- Dynamic: license-file
22
- Dynamic: requires-python
23
- Dynamic: summary
24
20
 
25
21
  # scip-cli
26
22
 
27
23
  [![PyPI version](https://badge.fury.io/py/scip-cli.svg)](https://badge.fury.io/py/scip-cli)
28
24
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
29
25
 
30
- Fast code intelligence CLI for TypeScript/JavaScript and Python projects. Query SCIP indexes directly via SQLite for instant results.
26
+ Token-efficient code intelligence for AI agents. Precise refs, definitions, and repo health analysis via SCIP indexes TypeScript/JavaScript and Python.
27
+
28
+ ## Why
29
+
30
+ AI agents waste tokens on grep and file scanning. scip-cli gives them precise, type-aware code navigation in milliseconds — and `analyze` surfaces dead code, cycles, and coupling so agents (and humans) can fix real problems fast.
31
31
 
32
32
  ## Features
33
33
 
34
- - **Fast**: Direct SQLite queries, eliminating skippable overhead
35
- - **Simple**: Single binary with subcommands
36
- - **Auto-indexing**: Automatically indexes projects on first query
37
- - **Token-efficient**: Clean, minimal output optimized for AI consumption
34
+ - **Agent-first**: Install as a skill for Claude Code, Cursor, or any AI agent — precise code navigation without burning context
35
+ - **Token-efficient**: One record per line, stderr for warnings, pipe-friendly output
36
+ - **Fast**: Direct SQLite queries 10x to 213x faster than alternatives
37
+ - **`analyze`**: Find dead exports, import cycles, stale types, coupling hotspots — actionable health dashboards at project, file, or symbol scope
38
+ - **Auto-indexing**: Indexes on first query, caches in SQLite, zero config
38
39
 
39
40
  ## For AI Agents
40
41
 
41
- If you're an AI agent, run this to see the quick reference:
42
+ Install as a reusable skill so your agent always knows how to navigate the codebase:
42
43
 
43
44
  ```bash
44
- scip-cli skill
45
+ scip-cli skill ~/.claude/skills/scip-cli/ # Claude Code
46
+ scip-cli skill ~/.cursor/skills/scip-cli/ # Cursor
45
47
  ```
46
48
 
47
- Or install it to your skills folder:
49
+ Or dump the quick reference for one-off use:
48
50
 
49
51
  ```bash
50
- scip-cli skill ~/.claude/skills/scip-cli/SKILL.md
52
+ scip-cli skill
51
53
  ```
52
54
 
53
- This enables commands like `def`, `refs`, `search`, `symbols`, `rdeps`, and `members` - just ask "where is X?" or "find references to X".
54
-
55
55
  ## Installation
56
56
 
57
57
  ### 1. Install scip-cli
58
58
 
59
- **From PyPI:**
59
+ **From PyPI** (end users):
60
60
 
61
61
  ```bash
62
62
  pip install scip-cli
63
63
  ```
64
64
 
65
- **From source (local development):**
65
+ **Local development** (use a project venv — do not rely on global `pip`):
66
66
 
67
67
  ```bash
68
- git clone https://github.com/flesler/scip-cli.git
69
68
  cd scip-cli
70
- pip install .
69
+ python -m venv .venv
70
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
71
+ pip install -e ".[dev]"
72
+ scip-cli --version
71
73
  ```
72
74
 
73
- For editable development (where `pip install -e .` fails due to permissions):
74
-
75
- ```bash
76
- export PYTHONPATH=/path/to/scip-cli:$PYTHONPATH
77
- python -m scip_cli --help
78
- ```
75
+ `pip install -e .` keeps `scip-cli` on your PATH inside the venv while you edit the repo. Run tests with `pytest` from the same venv.
79
76
 
80
77
  ### 2. Install prerequisites (optional)
81
78
 
@@ -125,11 +122,12 @@ scip-cli <command> [arguments]
125
122
  ### Commands
126
123
 
127
124
  - `refs <symbol>` - Find all references to a symbol (`--path` to scope)
128
- - `def <symbol>` - Find symbol definition with source code (`--path`, `--max-lines`)
125
+ - `code <symbol>` - Find symbol definition with source code (`--path`, `--max-lines`, `--full`, `--offset`, `--snippet`, `--line-numbers`)
129
126
  - `search <pattern>` - Search symbols by name pattern (`--path`)
130
127
  - `symbols <file>` - List all symbols in a file (`--path`; bare filename OK)
131
128
  - `rdeps <file>` - Find files that depend on a file (`--path`)
132
129
  - `members <symbol>` - List members of a class/interface (`--path`)
130
+ - `analyze [target]` - SQL health dashboards (`--limit`, `--priority`, `--include-tests`). No target: project-wide; directory or file path; symbol name. See [Finding easy wins with `analyze`](#finding-easy-wins-with-analyze).
133
131
  - `reindex` - Force re-indexing of the current project (`--path` to limit scope; repeatable)
134
132
  - `skill [path]` - Install or dump the SKILL.md
135
133
 
@@ -140,13 +138,13 @@ scip-cli <command> [arguments]
140
138
  scip-cli refs greet
141
139
 
142
140
  # Get definition of greet
143
- scip-cli def greet
141
+ scip-cli code greet
144
142
 
145
143
  # Search for symbols matching "Widget"
146
144
  scip-cli search Widget
147
145
 
148
146
  # Scope to a subdirectory
149
- scip-cli def greet --path packages/api
147
+ scip-cli code greet --path packages/api
150
148
 
151
149
  # List symbols by bare filename
152
150
  scip-cli symbols helper.ts
@@ -157,13 +155,16 @@ scip-cli rdeps src/helper.ts
157
155
  # List members of a class
158
156
  scip-cli members Widget
159
157
 
158
+ # Project health dashboard (or: scip-cli analyze src/foo.ts / scip-cli analyze greet)
159
+ scip-cli analyze
160
+
160
161
  # Install skill file
161
162
  scip-cli skill ~/.claude/skills/scip-cli/SKILL.md
162
163
  ```
163
164
 
164
165
  ### Pipelines
165
166
 
166
- Stdout is one record per line; stderr carries warnings and ambiguity notices. Kinds are lowercase (`function`, `class`, `method`, `property`, `variable`). Pipe-friendly flags: `refs --paths-only`, `search --names-only` / `--paths-only`, `members --names-only`. `rdeps` already prints bare file paths.
167
+ Stdout is one record per line; stderr carries warnings and ambiguity notices. Kinds are lowercase (`function`, `class`, `method`, `property`). Pipe-friendly flags: `refs --paths-only`, `search --names-only` / `--paths-only`, `members --names-only`. `rdeps` already prints bare file paths.
167
168
 
168
169
  ```bash
169
170
  # What do importers of this file export?
@@ -176,7 +177,7 @@ scip-cli refs greet --paths-only
176
177
  scip-cli search Handler --kind class --names-only | xargs -I{} scip-cli members {}
177
178
 
178
179
  # Walk class members to their definitions
179
- scip-cli members Widget --names-only | xargs -I{} scip-cli def Widget.{}
180
+ scip-cli members Widget --names-only | xargs -I{} scip-cli code Widget.{}
180
181
  ```
181
182
 
182
183
  ## How It Works
@@ -206,10 +207,12 @@ Optional `.scip-cli.json` in the project root:
206
207
 
207
208
  `SCIP_CLI_INDEX_WORKERS` controls parallel `scip-typescript` runs during first index (default: up to 8). Merge into one database is always serial.
208
209
 
210
+ Large monorepos (>10 tsconfig projects) log per-project progress to stderr during indexing; smaller repos stay quiet aside from the final `Indexed … (size)` line.
211
+
209
212
  Scoped indexing without editing `.scip-cli.json`:
210
213
 
211
214
  ```bash
212
- scip-cli reindex --path entrypoints/server
215
+ scip-cli reindex --path packages/server
213
216
  scip-cli reindex --path packages/api --path packages/worker
214
217
  ```
215
218
 
@@ -217,20 +220,63 @@ scip-cli reindex --path packages/api --path packages/worker
217
220
 
218
221
  Run `scip-cli reindex` after changing scope, `.scip-cli.json` index settings, or when you want a fresh index.
219
222
 
220
- This is separate from `.scipquery.json`, which belongs to [scip-query](https://github.com/PlunderStruck/scip-query) and configures its analyzers, watch mode, and diff-gate — not read by scip-cli.
223
+ ## Finding easy wins with `analyze`
224
+
225
+ Use `analyze` on the repo itself before broad refactors or agent review — it surfaces cross-file issues from the SCIP index (not Python `vulture`).
226
+
227
+ **Quick pass** (after `scip-cli reindex`):
228
+
229
+ ```bash
230
+ scip-cli analyze --limit 25
231
+ scip-cli analyze --priority high --limit 25 # dead exports & cycles only
232
+ ```
233
+
234
+ Sections are tagged `[high]`, `[medium]`, `[low]` and listed in that order.
235
+
236
+ | Tier | Project sections | Action |
237
+ | ---- | ---------------- | ------ |
238
+ | **high** | Cycles, unreferenced, dead exports, stale types | Nuke or fix cycles; delete unused; `_` prefix |
239
+ | **medium** | Same-file only, change surface (file target) | Module-private by usage |
240
+ | **low** | Test-only consumers, coupling, bottlenecks, hotspots | Noisy on Python (index omits many same-file calls); verify with `rg` |
241
+
242
+ Use `--priority high` for a quick gate; `--priority high,medium` adds context. File drill-down adds change surface and unused imports.
243
+
244
+ **What to look at first**
245
+
246
+ | Section | Easy pickings |
247
+ | ------- | ------------- |
248
+ | **Cycles** | Import/mention cycles between production files — break the edge or extract shared code |
249
+ | **Unreferenced** | No usage in the index at all — delete |
250
+ | **Dead exports** | No external refs — delete or `_` prefix |
251
+ | **Stale types** | Classes/types with ≤1 external consumer — merge, inline, or document why they stay |
252
+ | **Same-file only** | Used only inside defining file — rename to `_` |
253
+ | **Test-only consumers** | Cross-file refs are all from tests — promote to e2e or accept as internal |
254
+
255
+ **Per-file or package drill-down** on hubs or suspects:
256
+
257
+ ```bash
258
+ scip-cli analyze scip_cli/queries.py --limit 20 # file: scoped project + per-file + top symbols
259
+ scip-cli analyze scip_cli --limit 15 # directory: scoped project + each file under it
260
+ ```
261
+
262
+ `Dead exports in file` lists same-module symbols with no *external* refs — module-private `_helpers` are filtered out. Remaining rows are worth a manual `rg` check.
263
+
264
+ **Defaults:** project-wide and directory analyze skip `tests/`, `*.test.*`, `*.spec.*`, `conftest.py`, and `__tests__/`. Pass `--include-tests` to include them. File-target analyze always includes that file.
265
+
266
+ **Limits:** “Dead export” means no cross-file mentions in the index — not unreachable code. Same-file private helpers are expected. Re-run `reindex` after large changes; the index is a snapshot.
221
267
 
222
268
  ## Performance
223
269
 
224
- Inspired by [scip-query](https://github.com/PlunderStruck/scip-query), scip-cli is a lightweight Python reimplementation optimized for speed. Compared to the original bash wrapper scripts:
270
+ Inspired by [scip-query](https://github.com/PlunderStruck/scip-query), scip-cli is a lightweight Python partial reimplementation optimized for speed. Compared to the original:
225
271
 
226
272
  - `refs`: 6.4s → 0.03s (213x faster)
227
- - `def`: 2.8s → 0.05s (56x faster)
273
+ - `code`: 2.8s → 0.05s (56x faster)
228
274
  - `search`: 2.6s → 0.03s (87x faster)
229
275
  - `symbols`: 0.3s → 0.02s (15x faster)
230
276
  - `rdeps`: 0.2s → 0.02s (10x faster)
231
277
  - `members`: 3.1s → 0.03s (103x faster)
232
278
 
233
- The speedup comes from direct SQLite queries instead of shell command chains, eliminating subprocess overhead.
279
+ The speedup comes from using optimized direct SQLite queries and cutting some nice but very slow goodies (like ts-morph).
234
280
 
235
281
  ## Architecture
236
282
 
@@ -243,38 +289,41 @@ scip_cli/
243
289
  ├── discover.py # TypeScript project discovery
244
290
  ├── merge.py # SQLite index merging
245
291
  ├── scip_tool.py # scip binary download
246
- ├── constants.py # Shared constants
247
292
  ├── sql.py # SQLite helpers
248
293
  ├── paths.py # --path scope filtering
249
294
  ├── project.py # Project root + language detection
250
295
  ├── cache.py # Index cache paths
296
+ ├── scope.py # Persisted reindex scope (index-scope.json)
297
+ ├── debug.py # SCIP_CLI_DEBUG stderr helpers
251
298
  ├── indexing.py # SCIP index build + get_db
252
299
  ├── symbols.py # Symbol parsing and kinds
253
300
  ├── queries.py # Symbol/file SQL queries
254
301
  ├── source.py # Filesystem source reads
255
302
  ├── output.py # CLI formatting helpers
256
303
  ├── session.py # setup() and single-match resolution
304
+ ├── targets.py # file-path heuristics (tests; analyze uses analyze/targets.py)
305
+ ├── analyze/ # SQL dashboard queries (project/file/symbol)
257
306
  └── commands/ # Subcommand implementations
258
307
  ```
259
308
 
260
309
  ## Development
261
310
 
262
311
  ```bash
263
- pip install -e .
312
+ pip install -e ".[dev]"
264
313
  pytest tests/ -q
265
314
  pytest tests/ -m integration -q # indexes tests/fixtures/sample-project (needs scip-typescript)
266
315
  ```
267
316
 
268
317
  ### Debug Logging
269
318
 
270
- Set `SCIP_CLI_DEBUG=1` to enable SQL query logging to stderr:
319
+ Set `SCIP_CLI_DEBUG=1` to enable SQL query logging to stderr (statements truncated to 200 chars):
271
320
 
272
321
  ```bash
273
322
  SCIP_CLI_DEBUG=1 scip-cli refs MyFunction
274
323
  # Shows: SQL: SELECT ... | params: (...)
275
324
  ```
276
325
 
277
- This is useful for testing and debugging SQL queries without exposing a `--debug` flag to users.
326
+ This is useful for testing and debugging SQL queries
278
327
 
279
328
  ## License
280
329