scip-cli 2.3.0__tar.gz → 2.5.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.
- {scip_cli-2.3.0 → scip_cli-2.5.0}/.cursor/rules/agent.mdc +22 -1
- scip_cli-2.5.0/.github/workflows/ci.yml +22 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/.pre-commit-config.yaml +5 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/PKG-INFO +42 -23
- {scip_cli-2.3.0 → scip_cli-2.5.0}/README.md +40 -22
- {scip_cli-2.3.0 → scip_cli-2.5.0}/pyproject.toml +18 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/SKILL.md +4 -4
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/__init__.py +1 -1
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/__main__.py +6 -3
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/analyze/common.py +1 -1
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/analyze/file.py +1 -1
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/analyze/live.py +16 -1
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/analyze/project.py +17 -3
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/analyze/sections.py +9 -7
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/analyze/symbol.py +2 -2
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/cache.py +4 -2
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/commands/analyze.py +12 -10
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/commands/deps.py +1 -1
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/commands/members.py +1 -1
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/commands/reindex.py +14 -6
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/commands/search.py +5 -3
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/discover.py +58 -2
- scip_cli-2.5.0/scip_cli/indexing/__init__.py +29 -0
- scip_cli-2.5.0/scip_cli/indexing/constants.py +13 -0
- scip_cli-2.5.0/scip_cli/indexing/convert.py +94 -0
- scip_cli-2.5.0/scip_cli/indexing/core.py +210 -0
- scip_cli-2.5.0/scip_cli/indexing/languages.py +85 -0
- scip_cli-2.5.0/scip_cli/indexing/orchestrate.py +158 -0
- scip_cli-2.5.0/scip_cli/indexing/postprocess.py +114 -0
- scip_cli-2.5.0/scip_cli/indexing/runners.py +116 -0
- scip_cli-2.5.0/scip_cli/indexing/typescript.py +165 -0
- scip_cli-2.5.0/scip_cli/merge.py +168 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/output.py +4 -2
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/paths.py +5 -4
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/project.py +6 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/queries.py +25 -9
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/scip_tool.py +8 -7
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/source.py +20 -5
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/sql.py +18 -3
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/symbols.py +11 -9
- scip_cli-2.5.0/scripts/bench_postprocess.py +236 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scripts/publish.sh +6 -0
- scip_cli-2.5.0/scripts/test.sh +29 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_analyze.py +2 -1
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_analyze_perf.py +5 -3
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_discover.py +77 -0
- scip_cli-2.5.0/tests/test_index_batching.py +59 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_index_prune.py +40 -3
- scip_cli-2.5.0/tests/test_indexer_fallback.py +315 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_merge.py +36 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_pure_functions.py +2 -0
- scip_cli-2.5.0/tests/test_python_index_integration.py +88 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_reindex.py +15 -1
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_scope.py +3 -2
- scip_cli-2.3.0/scip_cli/indexing.py +0 -520
- scip_cli-2.3.0/scip_cli/merge.py +0 -108
- scip_cli-2.3.0/scripts/test.sh +0 -9
- {scip_cli-2.3.0 → scip_cli-2.5.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/.github/pull_request_template.md +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/.gitignore +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/CODE_OF_CONDUCT.md +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/CONTRIBUTING.md +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/LICENSE +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/SECURITY.md +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/analyze/__init__.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/analyze/graph.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/analyze/targets.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/cli_args.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/commands/__init__.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/commands/code.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/commands/rdeps.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/commands/refs.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/commands/skill.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/commands/symbols.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/config.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/debug.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/scope.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/session.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scip_cli/targets.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/scripts/build.sh +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/__init__.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/analyze_db.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/conftest.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/e2e_harness.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixture_catalog.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/package.json +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/app/handler.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/config.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/consumer.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/dead.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/domain/i18n/en.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/domain/i18n/index.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/domain/i18n/useLocale.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/domain/labels/index.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/events/streamTypes.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/gateway/index.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/helper.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/hooks/useHookA.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/hooks/useHookB.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/hooks/useItems.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/index.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/integrations/inferenceClient.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/loaders/useInference.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/pages/panelPage.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/rules/applyRule.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/types/a.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/types/b.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/ui/Button.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/ui/LazyPanel.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/ui/buttonConsumer.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/ui/menuModule.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/user.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/widget.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/src/widgets/OrphanWidget.ts +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/fixtures/sample-project/tsconfig.json +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/perf_util.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_analyze_graph.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_cache.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_composability.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_config.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_e2e.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_e2e_analyze_patterns.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_e2e_perf.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_indexer_env.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_multi_symbol.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_qualified_symbols.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_scip_tool.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_targets.py +0 -0
- {scip_cli-2.3.0 → scip_cli-2.5.0}/tests/test_typescript_projects.py +0 -0
|
@@ -30,11 +30,15 @@ Node.js + `npx` required for integration tests (`scip-typescript`). Optional: `S
|
|
|
30
30
|
|
|
31
31
|
| Task | Command |
|
|
32
32
|
|------|---------|
|
|
33
|
+
| **All checks** | `scripts/test.sh` (lint + format + types + tests) |
|
|
33
34
|
| Full suite | `pytest` |
|
|
34
35
|
| E2e loop | `pytest tests/test_e2e.py tests/test_e2e_analyze_patterns.py` |
|
|
35
36
|
| Lint / format | `ruff check .` / `ruff format .` |
|
|
37
|
+
| Typecheck | `basedpyright scip_cli/` |
|
|
36
38
|
|
|
37
|
-
Pre-commit: ruff + ruff-format + full pytest. E2e before commit on command changes.
|
|
39
|
+
Pre-commit: ruff + ruff-format + basedpyright + full pytest. E2e before commit on command changes.
|
|
40
|
+
|
|
41
|
+
**Use `scripts/test.sh`** before committing to catch all issues (lint, format, types, tests). This matches what pre-commit runs.
|
|
38
42
|
|
|
39
43
|
## Improving this repo (do this before review subagents)
|
|
40
44
|
|
|
@@ -186,3 +190,20 @@ If both layers help during development, **keep both until e2e passes**, then del
|
|
|
186
190
|
- User install + analyze guide → `README.md`
|
|
187
191
|
- Agent/user CLI reference → `scip_cli/SKILL.md` (must match `__main__.py` flags)
|
|
188
192
|
- After flag changes: update SKILL + README command list; run `scip-cli skill` to verify output
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
## Dogfood Notes
|
|
196
|
+
|
|
197
|
+
Future improvements from using the CLI on real projects.
|
|
198
|
+
|
|
199
|
+
### Workflow
|
|
200
|
+
|
|
201
|
+
Requires bare `scip-cli` mapped to local (`pip install -e ".[dev]"` from repo root).
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
scip-cli reindex
|
|
205
|
+
scip-cli analyze --limit 25
|
|
206
|
+
scip-cli analyze scip_cli/queries.py --limit 20 # drill into hubs
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Project-wide analyze skips test paths by default; `--include-tests` to include. See README **Finding easy wins with analyze**.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: ${{ matrix.python-version }}
|
|
19
|
+
- name: Install dependencies
|
|
20
|
+
run: pip install -e ".[dev]"
|
|
21
|
+
- name: Run publish gate
|
|
22
|
+
run: ./scripts/test.sh
|
|
@@ -5,11 +5,16 @@ repos:
|
|
|
5
5
|
- id: ruff
|
|
6
6
|
args: [--fix]
|
|
7
7
|
- id: ruff-format
|
|
8
|
+
- repo: https://github.com/DetachHead/basedpyright-pre-commit-mirror
|
|
9
|
+
rev: 1.39.9
|
|
10
|
+
hooks:
|
|
11
|
+
- id: basedpyright
|
|
8
12
|
- repo: local
|
|
9
13
|
hooks:
|
|
10
14
|
- id: pytest
|
|
11
15
|
name: pytest
|
|
12
16
|
entry: pytest
|
|
13
17
|
language: python
|
|
18
|
+
additional_dependencies: [pytest>=7]
|
|
14
19
|
pass_filenames: false
|
|
15
20
|
always_run: true
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scip-cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.0
|
|
4
4
|
Summary: Fast code intelligence via SCIP indexes
|
|
5
5
|
Project-URL: Homepage, https://github.com/flesler/scip-cli
|
|
6
6
|
Author: Ariel Flesler
|
|
@@ -12,6 +12,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Classifier: Topic :: Software Development :: Code Generators
|
|
13
13
|
Requires-Python: >=3.9
|
|
14
14
|
Provides-Extra: dev
|
|
15
|
+
Requires-Dist: basedpyright>=1.39.9; extra == 'dev'
|
|
15
16
|
Requires-Dist: build>=1; extra == 'dev'
|
|
16
17
|
Requires-Dist: pre-commit>=4.0; extra == 'dev'
|
|
17
18
|
Requires-Dist: pytest>=7; extra == 'dev'
|
|
@@ -23,7 +24,7 @@ Description-Content-Type: text/markdown
|
|
|
23
24
|
[](https://badge.fury.io/py/scip-cli)
|
|
24
25
|
[](https://opensource.org/licenses/MIT)
|
|
25
26
|
|
|
26
|
-
Token-efficient code intelligence for AI agents. Precise refs, definitions, and repo health analysis via SCIP indexes — TypeScript/JavaScript and
|
|
27
|
+
Token-efficient code intelligence for AI agents. Precise refs, definitions, and repo health analysis via SCIP indexes — TypeScript/JavaScript, Python, Go, and Rust.
|
|
27
28
|
|
|
28
29
|
## Why
|
|
29
30
|
|
|
@@ -79,7 +80,7 @@ python -m venv .venv && source .venv/bin/activate
|
|
|
79
80
|
pip install -e ".[dev]"
|
|
80
81
|
```
|
|
81
82
|
|
|
82
|
-
Tests and lint: `pytest`, `ruff check
|
|
83
|
+
Tests and lint: `pytest`, `ruff check .`, `basedpyright scip_cli/` from the same environment (or `scripts/test.sh` for the publish gate).
|
|
83
84
|
|
|
84
85
|
### 2. Install prerequisites (optional)
|
|
85
86
|
|
|
@@ -89,7 +90,7 @@ On **first index**, scip-cli runs language indexers and builds a SQLite cache. Y
|
|
|
89
90
|
|
|
90
91
|
Install `scip-cli` and run it. On first index, scip-cli will:
|
|
91
92
|
|
|
92
|
-
- Download `scip-typescript` / `scip-python` via `npx` when not already on PATH
|
|
93
|
+
- Download `scip-typescript` / `scip-python` via `npx`, `scip-go` via `go install`, or `rust-analyzer` via `rustup` when not already on PATH
|
|
93
94
|
- Download the `scip` converter binary from [GitHub releases](https://github.com/scip-code/scip/releases) into `~/.cache/scip-cli/bin/` when not already on PATH
|
|
94
95
|
- Walk the repo for `tsconfig*.json` project roots (TypeScript monorepos), run `scip-typescript` per project (parallel by default), convert each partial index, then merge into one `index.db`
|
|
95
96
|
|
|
@@ -106,6 +107,12 @@ npm install -g @sourcegraph/scip-typescript
|
|
|
106
107
|
# Python indexer
|
|
107
108
|
npm install -g @sourcegraph/scip-python
|
|
108
109
|
|
|
110
|
+
# Go indexer
|
|
111
|
+
go install github.com/scip-code/scip-go/cmd/scip-go@latest
|
|
112
|
+
|
|
113
|
+
# Rust indexer (rust-analyzer with SCIP support)
|
|
114
|
+
rustup component add rust-analyzer
|
|
115
|
+
|
|
109
116
|
# SCIP CLI for index conversion (GitHub release — not on npm)
|
|
110
117
|
# https://github.com/scip-code/scip/releases (v0.8.1+ recommended)
|
|
111
118
|
```
|
|
@@ -199,9 +206,9 @@ scip-cli deps greet --paths-only | sort -u
|
|
|
199
206
|
|
|
200
207
|
## How It Works
|
|
201
208
|
|
|
202
|
-
1. On first query, automatically detects project language from `package.json` (TS/JS)
|
|
209
|
+
1. On first query, automatically detects project language from `package.json` (TS/JS), `pyproject.toml`/`setup.py` (Python), `go.mod` (Go), or `Cargo.toml` (Rust)
|
|
203
210
|
2. For TypeScript monorepos, walks the repository for `tsconfig*.json` project roots (nested ancestors deduped; root included only when its `include` is broad)
|
|
204
|
-
3. Runs `scip-typescript` per project (in parallel when there are multiple projects; set `SCIP_CLI_INDEX_WORKERS=1` to force serial),
|
|
211
|
+
3. Runs `scip-typescript` per project (in parallel when there are multiple projects; set `SCIP_CLI_INDEX_WORKERS=1` to force serial), `scip-python` for Python, `scip-go` for Go, or `rust-analyzer scip` for Rust
|
|
205
212
|
4. Converts each SCIP output to SQLite with `scip expt-convert`, then merges partial databases when needed
|
|
206
213
|
5. Caches the result in `~/.cache/scip-cli/projects/<dirname>-<hash>/index.db` (e.g. `my-monorepo-1a3f7a`)
|
|
207
214
|
6. Subsequent queries are SQLite lookups against that cache (not re-indexing)
|
|
@@ -218,11 +225,23 @@ Optional `.scip-cli.json` in the project root:
|
|
|
218
225
|
}
|
|
219
226
|
```
|
|
220
227
|
|
|
221
|
-
- `maxHeapMb` — Node heap for `scip-typescript` / `scip-python` (default **8192 MB** when omitted). Overridden by `SCIP_CLI_MAX_HEAP_MB`. This is the V8 heap cap, not total RAM usage.
|
|
228
|
+
- `maxHeapMb` — Node heap for `scip-typescript` / `scip-python` (default **8192 MB** when omitted). Overridden by `SCIP_CLI_MAX_HEAP_MB`. This is the V8 heap cap, not total RAM usage. Does not affect `scip-go`.
|
|
222
229
|
- `indexRoots` — extra TypeScript project directories to include on **first index**, merged with auto-discovered projects.
|
|
223
230
|
- `onlyIndexRoots` — skip auto-discovery and index **only** `indexRoots` (smaller initial index when you only care about part of a monorepo).
|
|
224
231
|
|
|
225
|
-
`SCIP_CLI_INDEX_WORKERS` controls parallel
|
|
232
|
+
`SCIP_CLI_INDEX_WORKERS` controls parallel indexer runs during first index (default: up to 8). Merge into one database is always serial.
|
|
233
|
+
|
|
234
|
+
Other environment variables:
|
|
235
|
+
|
|
236
|
+
| Variable | Purpose |
|
|
237
|
+
| ------------------------------ | --------------------------------------------------------------------------------------------- |
|
|
238
|
+
| `SCIP_CLI_MAX_HEAP_MB` | Node heap for `scip-typescript` / `scip-python` (overrides `maxHeapMb` in config) |
|
|
239
|
+
| `SCIP_CLI_TS_INDEX_BATCH_SIZE` | Split large TS repos into multiple `scip-typescript` runs (default: all tsconfigs in one run) |
|
|
240
|
+
| `SCIP_CLI_MERGE_BATCH_SIZE` | SQLite ATTACH batch size when merging part DBs (max 9) |
|
|
241
|
+
| `SCIP_CLI_MAX_DEF_LINES` | Max definition lines in `code` output |
|
|
242
|
+
| `SCIP_CLI_DEBUG` | Log SQL queries to stderr |
|
|
243
|
+
|
|
244
|
+
**Version policy:** only the `scip` converter (`expt-convert`) is pinned to the 0.8.x release line because it defines the SQLite schema. Language indexers (`scip-typescript`, `scip-python` via `npx`; `scip-go` via `go install @latest`) install at latest on first use. `rust-analyzer` installs via `rustup component add`.
|
|
226
245
|
|
|
227
246
|
Large monorepos (>10 tsconfig projects) log per-project progress to stderr during indexing; smaller repos stay quiet aside from the final `Indexed … (size)` line.
|
|
228
247
|
|
|
@@ -233,7 +252,7 @@ scip-cli reindex --path packages/server
|
|
|
233
252
|
scip-cli reindex --path packages/api --path packages/worker
|
|
234
253
|
```
|
|
235
254
|
|
|
236
|
-
`--path` limits which discovered tsconfig projects are indexed (prefix match, same idea as query `--path`). The scope is saved as `index-scope.json` next to `index.db` and reused until you run a full `scip-cli reindex` with no `--path`.
|
|
255
|
+
`--path` limits which discovered tsconfig projects are indexed (prefix match, same idea as query `--path`). **TypeScript only** — other languages reject `reindex --path`. The scope is saved as `index-scope.json` next to `index.db` and reused until you run a full `scip-cli reindex` with no `--path`.
|
|
237
256
|
|
|
238
257
|
Run `scip-cli reindex` after changing scope, `.scip-cli.json` index settings, or when you want a fresh index.
|
|
239
258
|
|
|
@@ -250,24 +269,24 @@ scip-cli analyze --priority high --limit 25 # dead exports & cycles only
|
|
|
250
269
|
|
|
251
270
|
Sections are tagged `[high]`, `[medium]`, `[low]` and listed in that order.
|
|
252
271
|
|
|
253
|
-
| Tier
|
|
254
|
-
|
|
|
255
|
-
| **high**
|
|
256
|
-
| **medium** | Same-file only, change surface (file target)
|
|
257
|
-
| **low**
|
|
272
|
+
| Tier | Project sections | Action |
|
|
273
|
+
| ---------- | ---------------------------------------------------- | -------------------------------------------------------------------- |
|
|
274
|
+
| **high** | Cycles, unreferenced, dead exports, stale types | Nuke or fix cycles; delete unused; `_` prefix |
|
|
275
|
+
| **medium** | Same-file only, change surface (file target) | Module-private by usage |
|
|
276
|
+
| **low** | Test-only consumers, coupling, bottlenecks, hotspots | Noisy on Python (index omits many same-file calls); verify with `rg` |
|
|
258
277
|
|
|
259
278
|
Use `--priority high` for a quick gate; `--priority high,medium` adds context. File drill-down adds change surface and unused imports.
|
|
260
279
|
|
|
261
280
|
**What to look at first**
|
|
262
281
|
|
|
263
|
-
| Section
|
|
264
|
-
|
|
|
265
|
-
| **Cycles**
|
|
266
|
-
| **Unreferenced**
|
|
267
|
-
| **Dead exports**
|
|
268
|
-
| **Stale types**
|
|
269
|
-
| **Same-file only**
|
|
270
|
-
| **Test-only consumers** | Cross-file refs are all from tests — promote to e2e or accept as internal
|
|
282
|
+
| Section | Easy pickings |
|
|
283
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
284
|
+
| **Cycles** | Import/mention cycles between production files — break the edge or extract shared code |
|
|
285
|
+
| **Unreferenced** | No usage in the index at all — delete |
|
|
286
|
+
| **Dead exports** | No external refs — delete or `_` prefix |
|
|
287
|
+
| **Stale types** | Classes/types with no external consumer in the index — verify in-file or type-only use before removing |
|
|
288
|
+
| **Same-file only** | Used only inside defining file — rename to `_` |
|
|
289
|
+
| **Test-only consumers** | Cross-file refs are all from tests — promote to e2e or accept as internal |
|
|
271
290
|
|
|
272
291
|
**Per-file or package drill-down** on hubs or suspects:
|
|
273
292
|
|
|
@@ -276,7 +295,7 @@ scip-cli analyze scip_cli/queries.py --limit 20 # file: scoped project + per-f
|
|
|
276
295
|
scip-cli analyze scip_cli --limit 15 # directory: scoped project + each file under it
|
|
277
296
|
```
|
|
278
297
|
|
|
279
|
-
`Dead exports in file` lists same-module symbols with no
|
|
298
|
+
`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.
|
|
280
299
|
|
|
281
300
|
**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.
|
|
282
301
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://badge.fury.io/py/scip-cli)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
|
|
6
|
-
Token-efficient code intelligence for AI agents. Precise refs, definitions, and repo health analysis via SCIP indexes — TypeScript/JavaScript and
|
|
6
|
+
Token-efficient code intelligence for AI agents. Precise refs, definitions, and repo health analysis via SCIP indexes — TypeScript/JavaScript, Python, Go, and Rust.
|
|
7
7
|
|
|
8
8
|
## Why
|
|
9
9
|
|
|
@@ -59,7 +59,7 @@ python -m venv .venv && source .venv/bin/activate
|
|
|
59
59
|
pip install -e ".[dev]"
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
Tests and lint: `pytest`, `ruff check
|
|
62
|
+
Tests and lint: `pytest`, `ruff check .`, `basedpyright scip_cli/` from the same environment (or `scripts/test.sh` for the publish gate).
|
|
63
63
|
|
|
64
64
|
### 2. Install prerequisites (optional)
|
|
65
65
|
|
|
@@ -69,7 +69,7 @@ On **first index**, scip-cli runs language indexers and builds a SQLite cache. Y
|
|
|
69
69
|
|
|
70
70
|
Install `scip-cli` and run it. On first index, scip-cli will:
|
|
71
71
|
|
|
72
|
-
- Download `scip-typescript` / `scip-python` via `npx` when not already on PATH
|
|
72
|
+
- Download `scip-typescript` / `scip-python` via `npx`, `scip-go` via `go install`, or `rust-analyzer` via `rustup` when not already on PATH
|
|
73
73
|
- Download the `scip` converter binary from [GitHub releases](https://github.com/scip-code/scip/releases) into `~/.cache/scip-cli/bin/` when not already on PATH
|
|
74
74
|
- Walk the repo for `tsconfig*.json` project roots (TypeScript monorepos), run `scip-typescript` per project (parallel by default), convert each partial index, then merge into one `index.db`
|
|
75
75
|
|
|
@@ -86,6 +86,12 @@ npm install -g @sourcegraph/scip-typescript
|
|
|
86
86
|
# Python indexer
|
|
87
87
|
npm install -g @sourcegraph/scip-python
|
|
88
88
|
|
|
89
|
+
# Go indexer
|
|
90
|
+
go install github.com/scip-code/scip-go/cmd/scip-go@latest
|
|
91
|
+
|
|
92
|
+
# Rust indexer (rust-analyzer with SCIP support)
|
|
93
|
+
rustup component add rust-analyzer
|
|
94
|
+
|
|
89
95
|
# SCIP CLI for index conversion (GitHub release — not on npm)
|
|
90
96
|
# https://github.com/scip-code/scip/releases (v0.8.1+ recommended)
|
|
91
97
|
```
|
|
@@ -179,9 +185,9 @@ scip-cli deps greet --paths-only | sort -u
|
|
|
179
185
|
|
|
180
186
|
## How It Works
|
|
181
187
|
|
|
182
|
-
1. On first query, automatically detects project language from `package.json` (TS/JS)
|
|
188
|
+
1. On first query, automatically detects project language from `package.json` (TS/JS), `pyproject.toml`/`setup.py` (Python), `go.mod` (Go), or `Cargo.toml` (Rust)
|
|
183
189
|
2. For TypeScript monorepos, walks the repository for `tsconfig*.json` project roots (nested ancestors deduped; root included only when its `include` is broad)
|
|
184
|
-
3. Runs `scip-typescript` per project (in parallel when there are multiple projects; set `SCIP_CLI_INDEX_WORKERS=1` to force serial),
|
|
190
|
+
3. Runs `scip-typescript` per project (in parallel when there are multiple projects; set `SCIP_CLI_INDEX_WORKERS=1` to force serial), `scip-python` for Python, `scip-go` for Go, or `rust-analyzer scip` for Rust
|
|
185
191
|
4. Converts each SCIP output to SQLite with `scip expt-convert`, then merges partial databases when needed
|
|
186
192
|
5. Caches the result in `~/.cache/scip-cli/projects/<dirname>-<hash>/index.db` (e.g. `my-monorepo-1a3f7a`)
|
|
187
193
|
6. Subsequent queries are SQLite lookups against that cache (not re-indexing)
|
|
@@ -198,11 +204,23 @@ Optional `.scip-cli.json` in the project root:
|
|
|
198
204
|
}
|
|
199
205
|
```
|
|
200
206
|
|
|
201
|
-
- `maxHeapMb` — Node heap for `scip-typescript` / `scip-python` (default **8192 MB** when omitted). Overridden by `SCIP_CLI_MAX_HEAP_MB`. This is the V8 heap cap, not total RAM usage.
|
|
207
|
+
- `maxHeapMb` — Node heap for `scip-typescript` / `scip-python` (default **8192 MB** when omitted). Overridden by `SCIP_CLI_MAX_HEAP_MB`. This is the V8 heap cap, not total RAM usage. Does not affect `scip-go`.
|
|
202
208
|
- `indexRoots` — extra TypeScript project directories to include on **first index**, merged with auto-discovered projects.
|
|
203
209
|
- `onlyIndexRoots` — skip auto-discovery and index **only** `indexRoots` (smaller initial index when you only care about part of a monorepo).
|
|
204
210
|
|
|
205
|
-
`SCIP_CLI_INDEX_WORKERS` controls parallel
|
|
211
|
+
`SCIP_CLI_INDEX_WORKERS` controls parallel indexer runs during first index (default: up to 8). Merge into one database is always serial.
|
|
212
|
+
|
|
213
|
+
Other environment variables:
|
|
214
|
+
|
|
215
|
+
| Variable | Purpose |
|
|
216
|
+
| ------------------------------ | --------------------------------------------------------------------------------------------- |
|
|
217
|
+
| `SCIP_CLI_MAX_HEAP_MB` | Node heap for `scip-typescript` / `scip-python` (overrides `maxHeapMb` in config) |
|
|
218
|
+
| `SCIP_CLI_TS_INDEX_BATCH_SIZE` | Split large TS repos into multiple `scip-typescript` runs (default: all tsconfigs in one run) |
|
|
219
|
+
| `SCIP_CLI_MERGE_BATCH_SIZE` | SQLite ATTACH batch size when merging part DBs (max 9) |
|
|
220
|
+
| `SCIP_CLI_MAX_DEF_LINES` | Max definition lines in `code` output |
|
|
221
|
+
| `SCIP_CLI_DEBUG` | Log SQL queries to stderr |
|
|
222
|
+
|
|
223
|
+
**Version policy:** only the `scip` converter (`expt-convert`) is pinned to the 0.8.x release line because it defines the SQLite schema. Language indexers (`scip-typescript`, `scip-python` via `npx`; `scip-go` via `go install @latest`) install at latest on first use. `rust-analyzer` installs via `rustup component add`.
|
|
206
224
|
|
|
207
225
|
Large monorepos (>10 tsconfig projects) log per-project progress to stderr during indexing; smaller repos stay quiet aside from the final `Indexed … (size)` line.
|
|
208
226
|
|
|
@@ -213,7 +231,7 @@ scip-cli reindex --path packages/server
|
|
|
213
231
|
scip-cli reindex --path packages/api --path packages/worker
|
|
214
232
|
```
|
|
215
233
|
|
|
216
|
-
`--path` limits which discovered tsconfig projects are indexed (prefix match, same idea as query `--path`). The scope is saved as `index-scope.json` next to `index.db` and reused until you run a full `scip-cli reindex` with no `--path`.
|
|
234
|
+
`--path` limits which discovered tsconfig projects are indexed (prefix match, same idea as query `--path`). **TypeScript only** — other languages reject `reindex --path`. The scope is saved as `index-scope.json` next to `index.db` and reused until you run a full `scip-cli reindex` with no `--path`.
|
|
217
235
|
|
|
218
236
|
Run `scip-cli reindex` after changing scope, `.scip-cli.json` index settings, or when you want a fresh index.
|
|
219
237
|
|
|
@@ -230,24 +248,24 @@ scip-cli analyze --priority high --limit 25 # dead exports & cycles only
|
|
|
230
248
|
|
|
231
249
|
Sections are tagged `[high]`, `[medium]`, `[low]` and listed in that order.
|
|
232
250
|
|
|
233
|
-
| Tier
|
|
234
|
-
|
|
|
235
|
-
| **high**
|
|
236
|
-
| **medium** | Same-file only, change surface (file target)
|
|
237
|
-
| **low**
|
|
251
|
+
| Tier | Project sections | Action |
|
|
252
|
+
| ---------- | ---------------------------------------------------- | -------------------------------------------------------------------- |
|
|
253
|
+
| **high** | Cycles, unreferenced, dead exports, stale types | Nuke or fix cycles; delete unused; `_` prefix |
|
|
254
|
+
| **medium** | Same-file only, change surface (file target) | Module-private by usage |
|
|
255
|
+
| **low** | Test-only consumers, coupling, bottlenecks, hotspots | Noisy on Python (index omits many same-file calls); verify with `rg` |
|
|
238
256
|
|
|
239
257
|
Use `--priority high` for a quick gate; `--priority high,medium` adds context. File drill-down adds change surface and unused imports.
|
|
240
258
|
|
|
241
259
|
**What to look at first**
|
|
242
260
|
|
|
243
|
-
| Section
|
|
244
|
-
|
|
|
245
|
-
| **Cycles**
|
|
246
|
-
| **Unreferenced**
|
|
247
|
-
| **Dead exports**
|
|
248
|
-
| **Stale types**
|
|
249
|
-
| **Same-file only**
|
|
250
|
-
| **Test-only consumers** | Cross-file refs are all from tests — promote to e2e or accept as internal
|
|
261
|
+
| Section | Easy pickings |
|
|
262
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
263
|
+
| **Cycles** | Import/mention cycles between production files — break the edge or extract shared code |
|
|
264
|
+
| **Unreferenced** | No usage in the index at all — delete |
|
|
265
|
+
| **Dead exports** | No external refs — delete or `_` prefix |
|
|
266
|
+
| **Stale types** | Classes/types with no external consumer in the index — verify in-file or type-only use before removing |
|
|
267
|
+
| **Same-file only** | Used only inside defining file — rename to `_` |
|
|
268
|
+
| **Test-only consumers** | Cross-file refs are all from tests — promote to e2e or accept as internal |
|
|
251
269
|
|
|
252
270
|
**Per-file or package drill-down** on hubs or suspects:
|
|
253
271
|
|
|
@@ -256,7 +274,7 @@ scip-cli analyze scip_cli/queries.py --limit 20 # file: scoped project + per-f
|
|
|
256
274
|
scip-cli analyze scip_cli --limit 15 # directory: scoped project + each file under it
|
|
257
275
|
```
|
|
258
276
|
|
|
259
|
-
`Dead exports in file` lists same-module symbols with no
|
|
277
|
+
`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.
|
|
260
278
|
|
|
261
279
|
**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.
|
|
262
280
|
|
|
@@ -32,6 +32,7 @@ packages = ["scip_cli"]
|
|
|
32
32
|
[project.optional-dependencies]
|
|
33
33
|
dev = [
|
|
34
34
|
"ruff>=0.11",
|
|
35
|
+
"basedpyright>=1.39.9",
|
|
35
36
|
"pytest>=7",
|
|
36
37
|
"pre-commit>=4.0",
|
|
37
38
|
"build>=1",
|
|
@@ -57,3 +58,20 @@ addopts = "-q --tb=line --no-header"
|
|
|
57
58
|
markers = [
|
|
58
59
|
"integration: uses the shared indexed TS fixture (requires npx / scip-typescript)",
|
|
59
60
|
]
|
|
61
|
+
|
|
62
|
+
[tool.basedpyright]
|
|
63
|
+
pythonVersion = "3.10"
|
|
64
|
+
venvPath = "."
|
|
65
|
+
venv = ".venv"
|
|
66
|
+
include = ["scip_cli"]
|
|
67
|
+
exclude = ["tests"]
|
|
68
|
+
|
|
69
|
+
# Gradual typing: basedpyright's unknown* rules fire hundreds of times on CLI/SQL glue
|
|
70
|
+
# pythonVersion=3.10 matches union syntax in annotations; package still supports 3.9 via __future__ annotations
|
|
71
|
+
reportAny = "none"
|
|
72
|
+
reportUnknownParameterType = "none"
|
|
73
|
+
reportUnknownArgumentType = "none"
|
|
74
|
+
reportUnknownVariableType = "none"
|
|
75
|
+
reportUnknownMemberType = "none"
|
|
76
|
+
reportMissingParameterType = "none"
|
|
77
|
+
reportUnusedCallResult = "none"
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: scip-cli
|
|
3
|
-
description: Read when needing symbols, definitions, refs, members, or SQL health dashboards in TS/JS or
|
|
3
|
+
description: Read when needing symbols, definitions, refs, members, or SQL health dashboards in TS/JS, Python, Go, or Rust
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
TypeScript/JavaScript (.ts, .tsx, .js, .jsx)
|
|
6
|
+
TypeScript/JavaScript (.ts, .tsx, .js, .jsx), Python (.py), Go (.go), and Rust (.rs) — not GraphQL, CSS, or other files.
|
|
7
7
|
|
|
8
8
|
All commands are sub-commands of `scip-cli`. Run from the project root.
|
|
9
9
|
|
|
@@ -27,10 +27,10 @@ All commands are sub-commands of `scip-cli`. Run from the project root.
|
|
|
27
27
|
- **Bare names** resolve functions, types (aliases + interfaces), and classes. Use dotted qualifiers to disambiguate members: `code Widget.run`, `refs Foo.setBar`, `search MyClass.myMethod`, `members pkg.MyClass`. Type/object fields use the same form: `search Options.verbose`, `code Options.verbose`. Consts/let/var are not kept in the index (too many rows, single-line defs) — use `rg` or read the file. Class methods need `members ClassName`, not bare `code methodName`.
|
|
28
28
|
- **Ambiguous types** (e.g. `Opts` in multiple hooks) — `code`/`refs` return all matches up to `--limit`; `members` and `analyze` pick the first match with a stderr warning. Use dotted qualifiers or `--path` to narrow.
|
|
29
29
|
- **Stale index** — the cache is a snapshot; run `scip-cli reindex` after substantive code changes (no automatic invalidation).
|
|
30
|
-
- **Query `--path` vs `reindex --path`** — query `--path` filters results only. `reindex --path` persists scope and **replaces** the cached index with only those tsconfig projects; run full `reindex` (no `--path`) to restore.
|
|
30
|
+
- **Query `--path` vs `reindex --path`** — query `--path` filters results only. `reindex --path` is **TypeScript-only**: persists scope and **replaces** the cached index with only those tsconfig projects; run full `reindex` (no `--path`) to restore.
|
|
31
31
|
- **First run** in a project may auto-index (one-time wait; large monorepos with many `tsconfig.json` files take longer). Projects index in parallel by default (`SCIP_CLI_INDEX_WORKERS`; merge is serial). Repos with more than 10 tsconfig projects log per-project progress to stderr. JS-only projects (no `tsconfig.json`) are supported automatically.
|
|
32
32
|
- **Monorepos** are indexed by walking for `tsconfig*.json` under the repo (skips `node_modules`, `.git`, etc.). Nested parent/child projects are deduped. Add extra roots or limit indexing with `.scip-cli.json` (see README). Use query `--path packages/api` to scope lookups.
|
|
33
|
-
- **Prerequisites**: Node.js (for `npx`
|
|
33
|
+
- **Prerequisites**: Node.js (for TypeScript/Python via `npx`), Go toolchain (for Go via `go install`), or Rust toolchain (for Rust via `rustup`). The `scip` converter auto-downloads on first use if missing; `scip-typescript` / `scip-python` download via `npx`; `scip-go` downloads via `go install` to `~/go/bin`; `rust-analyzer` installs via `rustup component add`. Optional `.scip-cli.json` for extra index roots or heap tuning. `brew install scip` installs an unrelated optimization solver — scip-cli ignores it and downloads the real binary.
|
|
34
34
|
|
|
35
35
|
## Details
|
|
36
36
|
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
"""CLI entry point for scip-cli."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
import argparse
|
|
4
6
|
import logging
|
|
5
7
|
import os
|
|
6
8
|
import shutil
|
|
7
9
|
import sqlite3
|
|
8
10
|
import sys
|
|
11
|
+
from collections.abc import Callable
|
|
9
12
|
|
|
10
13
|
from . import __version__
|
|
11
14
|
from .cli_args import add_limit_argument, add_names_only_argument, add_path_argument, add_paths_only_argument
|
|
@@ -19,7 +22,7 @@ else:
|
|
|
19
22
|
logging.disable(logging.DEBUG)
|
|
20
23
|
|
|
21
24
|
|
|
22
|
-
def main():
|
|
25
|
+
def main() -> None:
|
|
23
26
|
parser = argparse.ArgumentParser(
|
|
24
27
|
prog="scip-cli",
|
|
25
28
|
description="Fast code intelligence via SCIP indexes",
|
|
@@ -45,7 +48,7 @@ def main():
|
|
|
45
48
|
type=int,
|
|
46
49
|
default=None,
|
|
47
50
|
metavar="N",
|
|
48
|
-
help=
|
|
51
|
+
help="Max source lines per definition body (default: 80, env SCIP_CLI_MAX_DEF_LINES). Use 0 for unlimited.",
|
|
49
52
|
)
|
|
50
53
|
code_parser.add_argument(
|
|
51
54
|
"--full",
|
|
@@ -151,7 +154,7 @@ def main():
|
|
|
151
154
|
return
|
|
152
155
|
|
|
153
156
|
# Dispatch to command handlers
|
|
154
|
-
dispatch = {
|
|
157
|
+
dispatch: dict[str, Callable[..., None]] = {
|
|
155
158
|
"refs": refs.main,
|
|
156
159
|
"code": code.main,
|
|
157
160
|
"search": search.main,
|
|
@@ -298,7 +298,7 @@ def top_symbol_pressure(db, relative_path: str, limit: int = DEFAULT_LIMIT) -> l
|
|
|
298
298
|
|
|
299
299
|
|
|
300
300
|
def _bind_path(fn, relative_path: str):
|
|
301
|
-
def run(db, limit: int, **
|
|
301
|
+
def run(db, limit: int, **_kwargs):
|
|
302
302
|
return fn(db, relative_path, limit)
|
|
303
303
|
|
|
304
304
|
return run
|
|
@@ -15,7 +15,7 @@ _EXTERNAL_MENTION = """
|
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
def _fetch_all(db, sql: str, params=())
|
|
18
|
+
def _fetch_all(db, sql: str, params=()):
|
|
19
19
|
return debug_execute(db, sql, params).fetchall()
|
|
20
20
|
|
|
21
21
|
|
|
@@ -155,6 +155,21 @@ def has_same_file_reference_usage(db, symbol_id: int, def_doc_id: int) -> bool:
|
|
|
155
155
|
return row is not None
|
|
156
156
|
|
|
157
157
|
|
|
158
|
+
def has_same_file_usage_mention(db, symbol_id: int, def_doc_id: int) -> bool:
|
|
159
|
+
"""Non-definition mention in the defining file (in-file callers)."""
|
|
160
|
+
row = _fetch_one(
|
|
161
|
+
db,
|
|
162
|
+
"""
|
|
163
|
+
SELECT 1 FROM mentions m
|
|
164
|
+
JOIN chunks c ON m.chunk_id = c.id
|
|
165
|
+
WHERE m.symbol_id = ? AND c.document_id = ? AND m.role != 1
|
|
166
|
+
LIMIT 1
|
|
167
|
+
""",
|
|
168
|
+
(symbol_id, def_doc_id),
|
|
169
|
+
)
|
|
170
|
+
return row is not None
|
|
171
|
+
|
|
172
|
+
|
|
158
173
|
def file_has_scip_importers(db, relative_path: str, *, live: LiveIndex, def_doc_id: int) -> bool:
|
|
159
174
|
"""True when the index shows another file importing this module or its symbols."""
|
|
160
175
|
if def_doc_id in live.live_module_docs:
|
|
@@ -18,7 +18,12 @@ from .common import (
|
|
|
18
18
|
stale_type_noise,
|
|
19
19
|
)
|
|
20
20
|
from .graph import FILE_EDGES_SQL, fetch_file_edges, find_longer_cycles
|
|
21
|
-
from .live import
|
|
21
|
+
from .live import (
|
|
22
|
+
LiveIndex,
|
|
23
|
+
file_has_scip_importers,
|
|
24
|
+
has_same_file_reference_usage,
|
|
25
|
+
has_same_file_usage_mention,
|
|
26
|
+
)
|
|
22
27
|
from .sections import Check, Priority, run_checks
|
|
23
28
|
|
|
24
29
|
|
|
@@ -165,6 +170,8 @@ def _format_dead_export_rows(
|
|
|
165
170
|
continue
|
|
166
171
|
if has_same_file_reference_usage(db, symbol_id, def_doc_id):
|
|
167
172
|
continue
|
|
173
|
+
if has_same_file_usage_mention(db, symbol_id, def_doc_id):
|
|
174
|
+
continue
|
|
168
175
|
if live.dead_export_noise(symbol, def_doc_id):
|
|
169
176
|
continue
|
|
170
177
|
lines.append(f"{short_name(symbol)} loc={loc} ({path})")
|
|
@@ -416,7 +423,6 @@ def run_all(
|
|
|
416
423
|
budget=None,
|
|
417
424
|
) -> list[tuple[str, list[str], str | None]]:
|
|
418
425
|
suffix = _scope_suffix(scope)
|
|
419
|
-
opts = {"include_tests": include_tests, "scope": scope, "budget": budget}
|
|
420
426
|
checks = [
|
|
421
427
|
Check("cycles", Priority.HIGH, f"Cycles (file dependencies){suffix}", cycles),
|
|
422
428
|
Check("unreferenced", Priority.HIGH, f"Unreferenced symbols (no refs){suffix}", unreferenced_symbols),
|
|
@@ -438,4 +444,12 @@ def run_all(
|
|
|
438
444
|
Check("bottlenecks", Priority.LOW, f"Bottlenecks (fan-in x fan-out){suffix}", bottlenecks),
|
|
439
445
|
Check("hotspots", Priority.LOW, f"Hotspots (most referenced){suffix}", hotspots),
|
|
440
446
|
]
|
|
441
|
-
return run_checks(
|
|
447
|
+
return run_checks(
|
|
448
|
+
checks,
|
|
449
|
+
db,
|
|
450
|
+
limit,
|
|
451
|
+
priorities,
|
|
452
|
+
include_tests=include_tests,
|
|
453
|
+
scope=scope,
|
|
454
|
+
budget=budget,
|
|
455
|
+
)
|
|
@@ -5,7 +5,6 @@ from __future__ import annotations
|
|
|
5
5
|
from collections.abc import Callable
|
|
6
6
|
from dataclasses import dataclass
|
|
7
7
|
from enum import Enum
|
|
8
|
-
from typing import Any
|
|
9
8
|
|
|
10
9
|
from .common import section
|
|
11
10
|
|
|
@@ -101,20 +100,23 @@ def run_checks(
|
|
|
101
100
|
db,
|
|
102
101
|
limit: int,
|
|
103
102
|
priorities: set[Priority] | None,
|
|
104
|
-
|
|
103
|
+
*,
|
|
104
|
+
include_tests: bool = False,
|
|
105
|
+
scope: str | None = None,
|
|
106
|
+
budget: RowBudget | None = None,
|
|
105
107
|
) -> list[tuple[str, list[str], str | None]]:
|
|
106
108
|
"""Run checks in priority order (high → low), optionally filtered."""
|
|
107
109
|
selected = [check for check in checks if priorities is None or check.priority in priorities]
|
|
108
110
|
selected.sort(key=lambda check: (_ORDER.index(check.priority), check.key))
|
|
109
|
-
|
|
111
|
+
budget_obj: RowBudget = budget or RowBudget(remaining=limit)
|
|
110
112
|
sections: list[tuple[str, list[str], str | None]] = []
|
|
111
113
|
for check in selected:
|
|
112
|
-
if
|
|
114
|
+
if budget_obj.exhausted():
|
|
113
115
|
break
|
|
114
|
-
lines = check.run(db,
|
|
116
|
+
lines = check.run(db, budget_obj.remaining, include_tests=include_tests, scope=scope)
|
|
115
117
|
if lines != ["(none)"]:
|
|
116
|
-
lines = lines[:
|
|
117
|
-
|
|
118
|
+
lines = lines[: budget_obj.remaining]
|
|
119
|
+
budget_obj.remaining -= len(lines)
|
|
118
120
|
preface = check.false_positive_preface if check.false_positive_preface else _preface_for(check.key)
|
|
119
121
|
sections.append(section(check.labeled_title(), lines, preface=preface))
|
|
120
122
|
return sections
|
|
@@ -8,14 +8,14 @@ from .sections import Check, Priority, run_checks
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def _bind_symbol(fn, symbol_id: int):
|
|
11
|
-
def run(db, limit: int, **
|
|
11
|
+
def run(db, limit: int, **_kwargs):
|
|
12
12
|
return fn(db, symbol_id, limit)
|
|
13
13
|
|
|
14
14
|
return run
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def _bind_symbol0(fn, symbol_id: int):
|
|
18
|
-
def run(db,
|
|
18
|
+
def run(db, _limit: int, **_kwargs):
|
|
19
19
|
return fn(db, symbol_id)
|
|
20
20
|
|
|
21
21
|
return run
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Index cache path resolution."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
import contextlib
|
|
4
6
|
import fcntl
|
|
5
7
|
import hashlib
|
|
@@ -78,13 +80,13 @@ def project_cache_slug(project_root: Path) -> str:
|
|
|
78
80
|
return f"{slug}-{digest}"
|
|
79
81
|
|
|
80
82
|
|
|
81
|
-
def get_cache_dir(project_root):
|
|
83
|
+
def get_cache_dir(project_root: Path | str) -> Path:
|
|
82
84
|
"""Get the cache directory for a project (one dir per repo root)."""
|
|
83
85
|
root = Path(project_root).resolve()
|
|
84
86
|
return Path.home() / ".cache" / "scip-cli" / "projects" / project_cache_slug(root)
|
|
85
87
|
|
|
86
88
|
|
|
87
|
-
def find_db(project_root=None):
|
|
89
|
+
def find_db(project_root: Path | str | None = None) -> Path | None:
|
|
88
90
|
"""Find the index.db for the given project (or cwd)."""
|
|
89
91
|
root = project_root or find_project_root()
|
|
90
92
|
if not root:
|