scip-cli 2.5.0__tar.gz → 2.7.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 (152) hide show
  1. scip_cli-2.7.0/.agents/commands/migration-problems.md +82 -0
  2. {scip_cli-2.5.0/.cursor → scip_cli-2.7.0/.agents}/rules/agent.mdc +93 -71
  3. scip_cli-2.7.0/.github/workflows/ci.yml +45 -0
  4. {scip_cli-2.5.0 → scip_cli-2.7.0}/.gitignore +2 -2
  5. scip_cli-2.7.0/AGENTS.md +1 -0
  6. {scip_cli-2.5.0 → scip_cli-2.7.0}/CODE_OF_CONDUCT.md +1 -1
  7. {scip_cli-2.5.0 → scip_cli-2.7.0}/PKG-INFO +27 -10
  8. {scip_cli-2.5.0 → scip_cli-2.7.0}/README.md +26 -9
  9. {scip_cli-2.5.0 → scip_cli-2.7.0}/SECURITY.md +5 -5
  10. scip_cli-2.7.0/docs/port.md +80 -0
  11. scip_cli-2.7.0/docs/ports/conclusions.md +424 -0
  12. scip_cli-2.7.0/docs/ports/experiment-summary.md +257 -0
  13. scip_cli-2.7.0/docs/ports/go-experiment.md +252 -0
  14. scip_cli-2.7.0/docs/ports/go.md +203 -0
  15. scip_cli-2.7.0/docs/ports/plan.md +161 -0
  16. scip_cli-2.7.0/docs/ports/rust-experiment.md +324 -0
  17. scip_cli-2.7.0/docs/ports/rust.md +264 -0
  18. scip_cli-2.7.0/docs/ports/summary.md +118 -0
  19. scip_cli-2.7.0/docs/ports/zig-experiment.md +333 -0
  20. scip_cli-2.7.0/docs/ports/zig.md +283 -0
  21. {scip_cli-2.5.0 → scip_cli-2.7.0}/pyproject.toml +1 -3
  22. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/SKILL.md +38 -27
  23. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/__init__.py +1 -1
  24. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/__main__.py +27 -0
  25. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/analyze/file.py +8 -12
  26. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/analyze/graph.py +34 -24
  27. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/analyze/project.py +42 -0
  28. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/analyze/sections.py +72 -7
  29. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/analyze/symbol.py +2 -1
  30. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/commands/analyze.py +24 -5
  31. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/commands/deps.py +6 -5
  32. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/commands/reindex.py +32 -4
  33. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/commands/search.py +78 -72
  34. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/commands/symbols.py +30 -0
  35. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/discover.py +6 -12
  36. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/indexing/__init__.py +2 -1
  37. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/indexing/orchestrate.py +16 -0
  38. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/indexing/postprocess.py +44 -6
  39. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/indexing/typescript.py +36 -4
  40. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/merge.py +1 -1
  41. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/scip_tool.py +5 -1
  42. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/scope.py +1 -1
  43. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/source.py +1 -1
  44. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/sql.py +4 -6
  45. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/targets.py +1 -1
  46. scip_cli-2.7.0/scip_cli/tsconfig.py +226 -0
  47. scip_cli-2.7.0/scripts/bench.sh +60 -0
  48. {scip_cli-2.5.0 → scip_cli-2.7.0}/scripts/bench_postprocess.py +3 -1
  49. {scip_cli-2.5.0 → scip_cli-2.7.0}/scripts/publish.sh +26 -2
  50. {scip_cli-2.5.0 → scip_cli-2.7.0}/scripts/test.sh +2 -2
  51. scip_cli-2.7.0/tests/bench_db.py +261 -0
  52. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/conftest.py +1 -1
  53. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/e2e_harness.py +1 -1
  54. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/fixture_catalog.py +5 -1
  55. scip_cli-2.7.0/tests/fixtures/typescript-project/src/helper.ts +23 -0
  56. scip_cli-2.7.0/tests/fixtures/typescript-project/src/lib/handler.ts +3 -0
  57. scip_cli-2.7.0/tests/fixtures/typescript-project/src/models/MutationAggregate.ts +32 -0
  58. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_analyze.py +61 -3
  59. scip_cli-2.7.0/tests/test_bench_queries.py +124 -0
  60. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_e2e.py +107 -0
  61. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_e2e_analyze_patterns.py +1 -1
  62. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_index_batching.py +16 -0
  63. scip_cli-2.7.0/tests/test_reindex.py +128 -0
  64. scip_cli-2.7.0/tests/test_symbols_freq.py +107 -0
  65. scip_cli-2.7.0/tests/test_tsconfig.py +137 -0
  66. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_typescript_projects.py +10 -0
  67. scip_cli-2.5.0/.github/workflows/ci.yml +0 -22
  68. scip_cli-2.5.0/tests/fixtures/sample-project/src/helper.ts +0 -7
  69. scip_cli-2.5.0/tests/test_reindex.py +0 -67
  70. {scip_cli-2.5.0 → scip_cli-2.7.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  71. {scip_cli-2.5.0 → scip_cli-2.7.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  72. {scip_cli-2.5.0 → scip_cli-2.7.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
  73. {scip_cli-2.5.0 → scip_cli-2.7.0}/.github/pull_request_template.md +0 -0
  74. {scip_cli-2.5.0 → scip_cli-2.7.0}/.pre-commit-config.yaml +0 -0
  75. {scip_cli-2.5.0 → scip_cli-2.7.0}/CONTRIBUTING.md +0 -0
  76. {scip_cli-2.5.0 → scip_cli-2.7.0}/LICENSE +0 -0
  77. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/analyze/__init__.py +0 -0
  78. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/analyze/common.py +0 -0
  79. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/analyze/live.py +0 -0
  80. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/analyze/targets.py +0 -0
  81. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/cache.py +0 -0
  82. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/cli_args.py +0 -0
  83. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/commands/__init__.py +0 -0
  84. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/commands/code.py +0 -0
  85. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/commands/members.py +0 -0
  86. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/commands/rdeps.py +0 -0
  87. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/commands/refs.py +0 -0
  88. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/commands/skill.py +0 -0
  89. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/config.py +0 -0
  90. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/debug.py +0 -0
  91. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/indexing/constants.py +0 -0
  92. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/indexing/convert.py +0 -0
  93. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/indexing/core.py +0 -0
  94. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/indexing/languages.py +0 -0
  95. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/indexing/runners.py +0 -0
  96. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/output.py +0 -0
  97. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/paths.py +0 -0
  98. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/project.py +0 -0
  99. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/queries.py +0 -0
  100. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/session.py +0 -0
  101. {scip_cli-2.5.0 → scip_cli-2.7.0}/scip_cli/symbols.py +0 -0
  102. {scip_cli-2.5.0 → scip_cli-2.7.0}/scripts/build.sh +0 -0
  103. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/__init__.py +0 -0
  104. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/analyze_db.py +0 -0
  105. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/package.json +0 -0
  106. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/app/handler.ts +0 -0
  107. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/config.ts +0 -0
  108. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/consumer.ts +0 -0
  109. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/dead.ts +0 -0
  110. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/domain/i18n/en.ts +0 -0
  111. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/domain/i18n/index.ts +0 -0
  112. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/domain/i18n/useLocale.ts +0 -0
  113. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/domain/labels/index.ts +0 -0
  114. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/events/streamTypes.ts +0 -0
  115. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/gateway/index.ts +0 -0
  116. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/hooks/useHookA.ts +0 -0
  117. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/hooks/useHookB.ts +0 -0
  118. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/hooks/useItems.ts +0 -0
  119. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/index.ts +0 -0
  120. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/integrations/inferenceClient.ts +0 -0
  121. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/loaders/useInference.ts +0 -0
  122. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/pages/panelPage.ts +0 -0
  123. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/rules/applyRule.ts +0 -0
  124. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/types/a.ts +0 -0
  125. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/types/b.ts +0 -0
  126. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/ui/Button.ts +0 -0
  127. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/ui/LazyPanel.ts +0 -0
  128. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/ui/buttonConsumer.ts +0 -0
  129. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/ui/menuModule.ts +0 -0
  130. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/user.ts +0 -0
  131. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/widget.ts +0 -0
  132. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/src/widgets/OrphanWidget.ts +0 -0
  133. {scip_cli-2.5.0/tests/fixtures/sample-project → scip_cli-2.7.0/tests/fixtures/typescript-project}/tsconfig.json +0 -0
  134. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/perf_util.py +0 -0
  135. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_analyze_graph.py +0 -0
  136. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_analyze_perf.py +0 -0
  137. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_cache.py +0 -0
  138. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_composability.py +0 -0
  139. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_config.py +0 -0
  140. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_discover.py +0 -0
  141. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_e2e_perf.py +0 -0
  142. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_index_prune.py +0 -0
  143. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_indexer_env.py +0 -0
  144. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_indexer_fallback.py +0 -0
  145. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_merge.py +0 -0
  146. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_multi_symbol.py +0 -0
  147. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_pure_functions.py +0 -0
  148. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_python_index_integration.py +0 -0
  149. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_qualified_symbols.py +0 -0
  150. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_scip_tool.py +0 -0
  151. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_scope.py +0 -0
  152. {scip_cli-2.5.0 → scip_cli-2.7.0}/tests/test_targets.py +0 -0
@@ -0,0 +1,82 @@
1
+ # Document migration problems
2
+
3
+ Review this session (and any ports you just touched) and append **only** language / tooling walls to `migration-problems.md`.
4
+
5
+ ## Where to write
6
+
7
+ | Repo | File |
8
+ |------|------|
9
+ | `scip-cli-go` | `migration-problems.md` |
10
+ | `scip-cli-rust` | `migration-problems.md` |
11
+ | `scip-cli-zig` | `migration-problems.md` |
12
+ | `scip-cli` (Python) | Usually **none** — Python is the reference, not a port. Only add a note if the user asks. |
13
+
14
+ If the workspace is one of the ports, edit that repo’s file. If several ports were touched, update each relevant file. Match existing numbering and section style in that file.
15
+
16
+ Do **not** invent entries from first principles — only document walls you (or a subagent) actually hit in this work.
17
+
18
+ ---
19
+
20
+ ## Why this file exists
21
+
22
+ These repos are an experiment: **which language is better for AI to code in?**
23
+
24
+ `migration-problems.md` is evidence for that question. A reader should learn something about the **language, compiler, stdlib, or ecosystem tooling** — not about scip-cli product bugs or “we forgot a branch.”
25
+
26
+ Ask before writing:
27
+
28
+ > *If we ported a different CLI tomorrow, would this entry still teach something about coding in this language with an AI?*
29
+
30
+ If **no** → do not add it.
31
+
32
+ ---
33
+
34
+ ## What TO put (include)
35
+
36
+ Fundamental friction that slows or confuses an AI agent because of the **language or its tools**:
37
+
38
+ | Category | Examples |
39
+ |----------|----------|
40
+ | **Compiler / type system** | Borrow checker traps; Zig shadowing rules; Go’s `module/v2` path rules; errors that force many tiny fix loops |
41
+ | **Stdlib / API drift** | Zig 0.17 removed `std.fs.cwd`; training data assumes older APIs; crate APIs that don’t match Python intuition (`regex` no lookbehind) |
42
+ | **Tooling loop cost** | Full `zig build -Doptimize=ReleaseFast` ~25s+ → fewer AI iterations; `gofmt`/`cargo fmt` rewrite every commit; clippy/rustc so strict the agent flails for N cycles |
43
+ | **Ecosystem surprises** | CGO vs pure-Go SQLite; `anyhow::bail!` prefixes user errors; package name vs import path traps |
44
+ | **Agent × language interaction** | Persistent shell + language-specific env scripts hanging; test runners with no skip → vacuously green |
45
+
46
+ Entry shape (adapt to the file’s existing voice):
47
+
48
+ - **Symptom** — what the agent saw (compile error, hang, parity fail)
49
+ - **Cause** — language/tooling root cause (not “we missed a line of business logic”)
50
+ - **Lesson** — what an AI (or human) should remember next time in this language
51
+ - Optional: time sink / iteration count if it was large
52
+
53
+ Prefer **one sharp entry** over a dump of every compile error.
54
+
55
+ ---
56
+
57
+ ## What NOT to put (exclude)
58
+
59
+ | Do not document | Why |
60
+ |-----------------|-----|
61
+ | Product / logic bugs (“search printed duplicates”, “forgot DER fallback”) | Same bug in any language; says nothing about Go vs Rust vs Zig |
62
+ | “We forgot to port X” / incomplete ports | Process failure, not language |
63
+ | TODOs, wishlists, backlog | Wrong file (`todo.md` / docs) |
64
+ | One-off typos, wrong SQL, missed edge cases in *our* code | Not language-fundamental |
65
+ | Parity mismatches that are just divergent implementations | Unless caused by a real language constraint |
66
+ | Generic “AI made a mistake” | Only if the language *systematically* induces that mistake (e.g. trained on old Zig stdlib) |
67
+
68
+ **Litmus test:** Removing scip-cli from the story — does the entry still make sense?
69
+ - ✅ “Zig ReleaseFast builds dominate the edit–compile loop”
70
+ - ❌ “Search must dedupe Prisma typeLiterals by file:line”
71
+
72
+ ---
73
+
74
+ ## How to run this command
75
+
76
+ 1. Skim the conversation / diffs for walls that burned time.
77
+ 2. Open the target `migration-problems.md`; read the last few entries so style and numbers match.
78
+ 3. For each candidate, apply the litmus test. Drop application-logic noise.
79
+ 4. Append new entries (or fix an existing entry if you previously wrote the wrong *kind* of note).
80
+ 5. Do **not** commit unless the user asks. Briefly tell the user what you added (or that nothing qualified).
81
+
82
+ If nothing in the session qualifies, say so — **empty is better than polluting the experiment.**
@@ -28,13 +28,13 @@ Node.js + `npx` required for integration tests (`scip-typescript`). Optional: `S
28
28
 
29
29
  ## Lint / test
30
30
 
31
- | Task | Command |
32
- |------|---------|
33
- | **All checks** | `scripts/test.sh` (lint + format + types + tests) |
34
- | Full suite | `pytest` |
35
- | E2e loop | `pytest tests/test_e2e.py tests/test_e2e_analyze_patterns.py` |
36
- | Lint / format | `ruff check .` / `ruff format .` |
37
- | Typecheck | `basedpyright scip_cli/` |
31
+ |Task|Command|
32
+ |---|---|
33
+ |**All checks**|`scripts/test.sh` (lint + format + types + tests)|
34
+ |Full suite|`pytest`|
35
+ |E2e loop|`pytest tests/test_e2e.py tests/test_e2e_analyze_patterns.py`|
36
+ |Lint / format|`ruff check .` / `ruff format .`|
37
+ |Typecheck|`basedpyright scip_cli/`|
38
38
 
39
39
  Pre-commit: ruff + ruff-format + basedpyright + full pytest. E2e before commit on command changes.
40
40
 
@@ -54,12 +54,12 @@ scip-cli analyze scip_cli/queries.py --limit 20 # file (+ scoped project)
54
54
 
55
55
  Interpretation: README § *Finding easy wins with analyze*. Target = omit (project), directory, file, or symbol — not `--path` for scope.
56
56
 
57
- | Priority | Section | Action |
58
- |----------|---------|--------|
59
- | 1 | **Cycles** | Break production file dependency cycles (`cache`↔`scope` was one) |
60
- | 2 | **Unreferenced / dead exports** | No ref usage / no external refs — verify with `rg`, delete or `_` prefix |
61
- | 3 | **Same-file only** | Module-private by usage — rename to `_` |
62
- | 4 | **Stale types** | Low-consumer classes — merge or justify |
57
+ |Priority|Section|Action|
58
+ |---|---|---|
59
+ |1|**Cycles**|Break production file dependency cycles (`cache`↔`scope` was one)|
60
+ |2|**Unreferenced / dead exports**|No ref usage / no external refs — verify with `rg`, delete or `_` prefix|
61
+ |3|**Same-file only**|Module-private by usage — rename to `_`|
62
+ |4|**Stale types**|Low-consumer classes — merge or justify|
63
63
 
64
64
  `analyze` skips test paths by default (`tests/`, `*.test.*`, `*.spec.*`); `--include-tests` to include. Reindex after large edits.
65
65
 
@@ -82,19 +82,19 @@ Only skip step 1 when the issue is **outside the index** (runtime, CLI UX, docs
82
82
 
83
83
  ### Retrospective: caught manually, SQLite already had it
84
84
 
85
- | Issue we hit | Index signal | Analyze today | Gap / next check |
86
- |--------------|--------------|---------------|------------------|
87
- | `cache` ↔ `scope` import cycle | cross-file `mentions` edges | `[high] Cycles` | **Caught** — keep dogfooding cycles |
88
- | Cross-file dead export (`get_refs_for_symbols`) | def with no external `mentions` | `[high] Dead exports` | **Caught** |
89
- | Same-file-only dead code | def, `role=0` only in def file | `[high] Unreferenced` or `[medium] Same-file only` | **Caught** (since extended) |
90
- | Same-file helper without `_` (`run_with_fallback`) | same-file `role=0` or none | `[medium] Same-file only` / unreferenced | **Caught** — rename to `_` |
91
- | 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` |
92
- | `analyze/*` section runners “dead” | no external refs | noise filter in `common.py` | **Filtered** — framework pattern |
93
- | Unused import | `role=2` mention, no in-file use | `[high] Unused imports` (per file) | **Caught** on file target |
94
- | 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 |
95
- | 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` |
96
- | 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 |
97
- | Duplicate / parallel helpers | — | — | **Not in index** — `rg`, not analyze |
85
+ |Issue we hit|Index signal|Analyze today|Gap / next check|
86
+ |---|---|---|---|
87
+ |`cache` ↔ `scope` import cycle|cross-file `mentions` edges|`[high] Cycles`|**Caught** — keep dogfooding cycles|
88
+ |Cross-file dead export (`get_refs_for_symbols`)|def with no external `mentions`|`[high] Dead exports`|**Caught**|
89
+ |Same-file-only dead code|def, `role=0` only in def file|`[high] Unreferenced` or `[medium] Same-file only`|**Caught** (since extended)|
90
+ |Same-file helper without `_` (`run_with_fallback`)|same-file `role=0` or none|`[medium] Same-file only` / unreferenced|**Caught** — rename to `_`|
91
+ |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`|
92
+ |`analyze/*` section runners “dead”|no external refs|noise filter in `common.py`|**Filtered** — framework pattern|
93
+ |Unused import|`role=2` mention, no in-file use|`[high] Unused imports` (per file)|**Caught** on file target|
94
+ |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|
95
+ |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`|
96
+ |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|
97
+ |Duplicate / parallel helpers|—|—|**Not in index** — `rg`, not analyze|
98
98
 
99
99
  Add new rows to `dogfood.md` when you find another gap; implement the SQL check before the next manual review pass.
100
100
 
@@ -102,15 +102,15 @@ Add new rows to `dogfood.md` when you find another gap; implement the SQL check
102
102
 
103
103
  SQLite has **line ranges** (`defn_enclosing_ranges`) so LOC is cheap. That does **not** mean “big function” belongs next to dead exports.
104
104
 
105
- | Idea | In index? | Verdict |
106
- |------|-----------|---------|
107
- | **LOC ≥ N** alone | Yes | **LOW at best** — noisy (`main`, argparse, legitimate parsers). Not a nuke candidate. |
108
- | **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. |
109
- | **LOC + consumers** on file target | Yes | **Change surface** (medium) already sorts by consumers with line ranges — drill there. |
110
- | **Symbol pressure** | Yes | **Per-symbol** `analyze Foo` shows `loc × fan_in × fan_out`. |
111
- | **God class / many members** | Yes | Use `members Class` — not analyze. |
112
- | **File byte size / cyclomatic complexity** | No | Out of scope for SCIP index. |
113
- | **Fat file (many symbols)** | Yes | Low value; coupling/hotspots approximate module heat. |
105
+ |Idea|In index?|Verdict|
106
+ |---|---|---|
107
+ |**LOC ≥ N** alone|Yes|**LOW at best** — noisy (`main`, argparse, legitimate parsers). Not a nuke candidate.|
108
+ |**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.|
109
+ |**LOC + consumers** on file target|Yes|**Change surface** (medium) already sorts by consumers with line ranges — drill there.|
110
+ |**Symbol pressure**|Yes|**Per-symbol** `analyze Foo` shows `loc × fan_in × fan_out`.|
111
+ |**God class / many members**|Yes|Use `members Class` — not analyze.|
112
+ |**File byte size / cyclomatic complexity**|No|Out of scope for SCIP index.|
113
+ |**Fat file (many symbols)**|Yes|Low value; coupling/hotspots approximate module heat.|
114
114
 
115
115
  **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.
116
116
 
@@ -118,33 +118,55 @@ SQLite has **line ranges** (`defn_enclosing_ranges`) so LOC is cheap. That does
118
118
 
119
119
  The e2e fixture and this repo's own index are **small** — every query looks fast here. That hides blowups on real projects (40MB+ indexes, dense graphs).
120
120
 
121
- **Before merging new or heavily changed SQL** (`queries.py`, `analyze/*`):
122
-
123
- 1. Time it against **1–2 existing checks** on a **large cached index** you already have (not the fixture):
124
- ```bash
125
- python3 -u -c "
126
- import sqlite3, time, sys
127
- from pathlib import Path
128
- sys.path.insert(0, '.')
129
- from scip_cli.analyze import project as p
130
- from scip_cli.sql import configure_read_connection
131
- db_path = Path.home() / '.cache/scip-cli/projects/<project-slug>/index.db'
132
- db = sqlite3.connect(f'file:{db_path}?mode=ro', uri=True)
133
- configure_read_connection(db)
134
- for name, fn in [('hotspots', p.hotspots), ('cycles', p.cycles), ('dead_exports', p.dead_exports)]:
135
- t = time.perf_counter(); fn(db, limit=25); print(f'{name}: {(time.perf_counter()-t)*1000:.0f}ms')
136
- "
137
- ```
138
- 2. Flag anything **notably slower** than peers — orders of magnitude or multi-second, not a few ms drift.
139
- 3. Swap in your new/changed check for one of the rows; keep a fast peer (e.g. `hotspots`) and a heavy peer (e.g. `dead_exports`).
140
-
141
- **In CI:** `tests/test_e2e_perf.py` (whole commands) and `tests/test_analyze_perf.py` (per-check on mini DB) catch gross regressions on the tiny fixture only — they **will not** catch large-repo OOMs. Use the manual benchmark above for that.
121
+ ### Scaled :memory: benchmark (primary)
122
+
123
+ `tests/bench_db.py` generates a deterministic 1000-file / ~15K-symbol / ~100K-mention DB in `:memory:`. `tests/test_bench_queries.py` times all key queries on it.
124
+
125
+ **Before/after comparison flow:**
126
+
127
+ ```bash
128
+ # 1. Before changes — save baseline
129
+ scripts/bench.sh --baseline
130
+
131
+ # 2. Make your SQL/query changes
132
+
133
+ # 3. Compare — runs current, diffs against baseline
134
+ scripts/bench.sh --compare
135
+
136
+ # Or just run current without comparison
137
+ scripts/bench.sh
138
+ ```
139
+
140
+ Output per query: `BENCH:<name>:<elapsed_ms>`. The compare table shows ratio (>1.0 = regression, <1.0 = improvement).
141
+
142
+ **When to use:** Any change to `queries.py`, `analyze/*`, `symbols.py` SQL clauses, or `sql.py` pragmas. Run `scripts/bench.sh --compare` before committing.
143
+
144
+ ### Large cached index benchmark (secondary)
145
+
146
+ For queries that behave differently on real 40MB+ indexes vs the synthetic DB:
147
+
148
+ ```bash
149
+ python3 -u -c "
150
+ import sqlite3, time, sys
151
+ from pathlib import Path
152
+ sys.path.insert(0, '.')
153
+ from scip_cli.analyze import project as p
154
+ from scip_cli.sql import configure_read_connection
155
+ db_path = Path.home() / '.cache/scip-cli/projects/<project-slug>/index.db'
156
+ db = sqlite3.connect(f'file:{db_path}?mode=ro', uri=True)
157
+ configure_read_connection(db)
158
+ for name, fn in [('hotspots', p.hotspots), ('cycles', p.cycles), ('dead_exports', p.dead_exports)]:
159
+ t = time.perf_counter(); fn(db, limit=25); print(f'{name}: {(time.perf_counter()-t)*1000:.0f}ms')
160
+ "
161
+ ```
162
+
163
+ **In CI:** `tests/test_e2e_perf.py` (whole commands) and `tests/test_analyze_perf.py` (per-check on mini DB) catch gross regressions on the tiny fixture only — they **will not** catch large-repo OOMs. Use `scripts/bench.sh --compare` for that.
142
164
 
143
165
  ## TDD
144
166
 
145
167
  ### Default: extend the shared fixture
146
168
 
147
- **One indexed TS project** — `tests/fixtures/sample-project/` — indexed once per session via `indexed_fixture` (`conftest.py`). Stable names live in `tests/fixture_catalog.py`.
169
+ **One indexed TS project** — `tests/fixtures/typescript-project/` — indexed once per session via `indexed_fixture` (`conftest.py`). Stable names live in `tests/fixture_catalog.py`.
148
170
 
149
171
  1. **Red** — add a **minimal** `.ts` file (or tweak an existing one) that reproduces the SCIP shape; assert in `tests/test_e2e.py` or `tests/test_e2e_analyze_patterns.py` using `cli` / `open_index_db` + analyze helpers.
150
172
  2. **Green** — fix `scip_cli/` (commands, `analyze/*`, `queries.py`, …).
@@ -159,29 +181,29 @@ The e2e fixture and this repo's own index are **small** — every query looks fa
159
181
  When dogfooding **another repo** surfaces a bug or false positive (analyze noise, dead-export mistake, cycle, stale type, refs mismatch):
160
182
 
161
183
  1. **Capture the pattern, not the project** — note the SCIP shape (module `/`, export alias `foo0:`, lazy import, `Props#`, barrel cycle, …). Do **not** copy real repo names, paths, or filenames into tests or docs.
162
- 2. **Red on the fixture** — smallest TS repro under `tests/fixtures/sample-project/` with generic names (`LazyPanel`, `evictItem`, `OrphanWidget`, …). E2e test proves the bug against **real `scip-typescript`** output.
184
+ 2. **Red on the fixture** — smallest TS repro under `tests/fixtures/typescript-project/` with generic names (`LazyPanel`, `evictItem`, `OrphanWidget`, …). E2e test proves the bug against **real `scip-typescript`** output.
163
185
  3. **Green** — fix analyze heuristics / SQL / CLI; dogfood on this repo if applicable.
164
186
  4. **Verify** — `pytest tests/test_e2e_analyze_patterns.py` (or full `pytest`); only then trim redundant tests.
165
187
 
166
188
  **Prefer fixture e2e over fake SQLite graphs.** `tests/analyze_db.py` (`AnalyzeDbBuilder`, `:memory:`) is for SQL/dashboard **plumbing** and graph primitives (`test_analyze_graph.py`, `mini_codebase_db`) — not for reproducing production SCIP symbol shapes. Hand-built symbols often diverge from scip-typescript (path format, `0:` aliases, module rows) and can pass while production still breaks.
167
189
 
168
- | Use fixture e2e | Use `analyze_db` unit |
169
- |-----------------|----------------------|
170
- | False positives / analyze checks from real projects | Tarjan, edge-type SQL, `run_all` section wiring |
171
- | Any behavior that depends on indexer symbol strings | Noise filters with one or two synthetic rows |
172
- | CLI commands (`refs`, `search`, `analyze` output) | Merge/index prune tests |
190
+ |Use fixture e2e|Use `analyze_db` unit|
191
+ |---|---|
192
+ |False positives / analyze checks from real projects|Tarjan, edge-type SQL, `run_all` section wiring|
193
+ |Any behavior that depends on indexer symbol strings|Noise filters with one or two synthetic rows|
194
+ |CLI commands (`refs`, `search`, `analyze` output)|Merge/index prune tests|
173
195
 
174
196
  If both layers help during development, **keep both until e2e passes**, then delete duplicate in-memory repros — fixture is the source of truth.
175
197
 
176
198
  ## Codebase map (contributors)
177
199
 
178
- | Area | Path | Notes |
179
- |------|------|-------|
180
- | Commands | `scip_cli/commands/` | Thin; SQL in `queries.py` / `analyze/` |
181
- | Index build | `scip_cli/indexing.py` | `index.db.next` → promote; flock; `>10` tsconfigs log progress |
182
- | Variable prune | postprocess + `merge.py` | Omit const/let/var on **COPY**, not DELETE — no `variable` kind |
183
- | Session | `scip_cli/session.py` | `setup()`, `resolve_one_symbol` (limit 2 for ambiguity) |
184
- | Analyze filters | `scip_cli/analyze/common.py` | `is_test_path`, `analyze_noise` (`_` helpers) |
200
+ |Area|Path|Notes|
201
+ |---|---|---|
202
+ |Commands|`scip_cli/commands/`|Thin; SQL in `queries.py` / `analyze/`|
203
+ |Index build|`scip_cli/indexing.py`|`index.db.next` → promote; flock; `>10` tsconfigs log progress|
204
+ |Variable prune|postprocess + `merge.py`|Omit const/let/var on **COPY**, not DELETE — no `variable` kind|
205
+ |Session|`scip_cli/session.py`|`setup()`, `resolve_one_symbol` (limit 2 for ambiguity)|
206
+ |Analyze filters|`scip_cli/analyze/common.py`|`is_test_path`, `analyze_noise` (`_` helpers)|
185
207
 
186
208
  `todo.md` = tracked work; `dogfood.md` = future ideas only. Wishlist/backlog in `docs/` per workspace rules.
187
209
 
@@ -206,4 +228,4 @@ scip-cli analyze --limit 25
206
228
  scip-cli analyze scip_cli/queries.py --limit 20 # drill into hubs
207
229
  ```
208
230
 
209
- Project-wide analyze skips test paths by default; `--include-tests` to include. See README **Finding easy wins with analyze**.
231
+ Project-wide analyze skips test paths by default; `--include-tests` to include. See README **Finding easy wins with analyze**.
@@ -0,0 +1,45 @@
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
+ id: setup_python
18
+ with:
19
+ python-version: ${{ matrix.python-version }}
20
+
21
+ - name: Restore cached virtualenv
22
+ uses: actions/cache/restore@v4
23
+ with:
24
+ key: venv-${{ runner.os }}-${{ steps.setup_python.outputs.python-version }}-${{ hashFiles('pyproject.toml') }}
25
+ path: .venv
26
+
27
+ - name: Create venv and install dependencies
28
+ run: |
29
+ python -m venv .venv
30
+ source .venv/bin/activate
31
+ pip install -e ".[dev]"
32
+ npm install -g @sourcegraph/scip-typescript
33
+ mkdir -p ~/.local/bin
34
+ curl -sL https://github.com/scip-code/scip/releases/download/v0.9.0/scip-linux-amd64.tar.gz | tar xz -C ~/.local/bin
35
+ echo "$VIRTUAL_ENV/bin" >> $GITHUB_PATH
36
+ echo "VIRTUAL_ENV=$VIRTUAL_ENV" >> $GITHUB_ENV
37
+
38
+ - name: Save cached virtualenv
39
+ uses: actions/cache/save@v4
40
+ with:
41
+ key: venv-${{ runner.os }}-${{ steps.setup_python.outputs.python-version }}-${{ hashFiles('pyproject.toml') }}
42
+ path: .venv
43
+
44
+ - name: Run publish gate
45
+ run: ./scripts/test.sh
@@ -10,8 +10,6 @@ dist/
10
10
  downloads/
11
11
  eggs/
12
12
  .eggs/
13
- lib/
14
- lib64/
15
13
  parts/
16
14
  sdist/
17
15
  var/
@@ -19,6 +17,7 @@ wheels/
19
17
  *.egg-info/
20
18
  .installed.cfg
21
19
  *.egg
20
+ .ruff_cache/
22
21
 
23
22
  # Virtual environments
24
23
  venv/
@@ -51,3 +50,4 @@ dogfood.md
51
50
  # Local-only dev scripts (repo-specific smoke harnesses)
52
51
  scripts/deep-smoke.sh
53
52
  tmp/
53
+ *.db
@@ -0,0 +1 @@
1
+ .cursor/rules/agent.mdc
@@ -60,7 +60,7 @@ representative at an online or offline event.
60
60
 
61
61
  Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
62
  reported to the community leaders responsible for enforcement at
63
- ariel.flesler@gmail.com.
63
+ aflesler@gmail.com.
64
64
  All complaints will be reviewed and investigated promptly and fairly.
65
65
 
66
66
  All community leaders are obligated to respect the privacy and security of the
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scip-cli
3
- Version: 2.5.0
3
+ Version: 2.7.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
@@ -24,7 +24,7 @@ Description-Content-Type: text/markdown
24
24
  [![PyPI version](https://badge.fury.io/py/scip-cli.svg)](https://badge.fury.io/py/scip-cli)
25
25
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
26
26
 
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
+ Python CLI for AI agents. Queries SCIP indexes for precise refs, definitions, and repo health analysis — TypeScript/JavaScript, Python, Go, Rust.
28
28
 
29
29
  ## Why
30
30
 
@@ -38,6 +38,17 @@ AI agents waste tokens on grep and file scanning. scip-cli gives them precise, t
38
38
  - **`analyze`**: Find dead exports, import cycles, stale types, coupling hotspots — actionable health dashboards at project, file, or symbol scope
39
39
  - **Auto-indexing**: Indexes on first query, caches in SQLite, zero config
40
40
 
41
+ ## Ports
42
+
43
+ CLI/output parity ports of this project (Python is the reference):
44
+
45
+ | Language | Repository |
46
+ | ------------------ | ----------------------------------------------------------------- |
47
+ | Python (reference) | [flesler/scip-cli](https://github.com/flesler/scip-cli) |
48
+ | Go | [flesler/scip-cli-go](https://github.com/flesler/scip-cli-go) |
49
+ | Rust | [flesler/scip-cli-rust](https://github.com/flesler/scip-cli-rust) |
50
+ | Zig | [flesler/scip-cli-zig](https://github.com/flesler/scip-cli-zig) |
51
+
41
52
  ## For AI Agents
42
53
 
43
54
  Install as a reusable skill so your agent always knows how to navigate the codebase:
@@ -142,7 +153,7 @@ scip-cli <command> [arguments]
142
153
  - `rdeps <file>` - Find files that depend on a file (`--path`)
143
154
  - `deps <symbol|file>` - Find outbound dependencies (what a symbol or file calls) (`--path`, `--paths-only`)
144
155
  - `members <symbol>` - List members of a class/interface (`--path`)
145
- - `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).
156
+ - `analyze [target]` - SQL health dashboards (`--limit`, `--priority`, `--check`, `--include-tests`). No target: project-wide; directory or file path; symbol name. See [Finding easy wins with `analyze`](#finding-easy-wins-with-analyze).
146
157
  - `reindex` - Force re-indexing of the current project (`--path` to limit scope; repeatable)
147
158
  - `skill [path]` - Install or dump the SKILL.md
148
159
 
@@ -250,9 +261,13 @@ Scoped indexing without editing `.scip-cli.json`:
250
261
  ```bash
251
262
  scip-cli reindex --path packages/server
252
263
  scip-cli reindex --path packages/api --path packages/worker
264
+ scip-cli reindex --tsconfig 'apps/api/tsconfig.*.json'
265
+ scip-cli reindex --tsconfig tsconfig.app.json --tsconfig tsconfig.spec.json
253
266
  ```
254
267
 
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`.
268
+ `--path` limits which discovered tsconfig **directories** are indexed (prefix match, same idea as query `--path`). `--tsconfig` skips discovery and indexes those `tsconfig*.json` **files** (repeatable; globs are expanded inside the tool). File-based runs default to one `scip-typescript` process per file so each gets its own heap (`SCIP_CLI_TS_INDEX_BATCH_SIZE` still overrides). Cannot combine `--path` and `--tsconfig`. **TypeScript only.** 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`/`--tsconfig`.
269
+
270
+ When a tsconfig (after `extends`) has `allowJs: true`, matching `.js`/`.jsx` files under that config's `include`/`files` are indexed too (same roots as `.ts`/`.tsx`). `allowJs: false` or unset leaves JavaScript out. JS-only repos with no `tsconfig.json` still use `--infer-tsconfig`.
256
271
 
257
272
  Run `scip-cli reindex` after changing scope, `.scip-cli.json` index settings, or when you want a fresh index.
258
273
 
@@ -265,15 +280,17 @@ Use `analyze` on the repo itself before broad refactors or agent review — it s
265
280
  ```bash
266
281
  scip-cli analyze --limit 25
267
282
  scip-cli analyze --priority high --limit 25 # dead exports & cycles only
283
+ scip-cli analyze --check cycles --limit 25 # one named section
284
+ scip-cli analyze --check dead_files --limit 25
268
285
  ```
269
286
 
270
287
  Sections are tagged `[high]`, `[medium]`, `[low]` and listed in that order.
271
288
 
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` |
289
+ | Tier | Project sections | Action |
290
+ | ---------- | ----------------------------------------------------------- | -------------------------------------------------------------------- |
291
+ | **high** | Cycles, unreferenced, dead exports, dead files, stale types | Nuke or fix cycles; delete unused; `_` prefix |
292
+ | **medium** | Same-file only, change surface (file target) | Module-private by usage |
293
+ | **low** | Test-only consumers, coupling, bottlenecks, hotspots | Noisy on Python (index omits many same-file calls); verify with `rg` |
277
294
 
278
295
  Use `--priority high` for a quick gate; `--priority high,medium` adds context. File drill-down adds change surface and unused imports.
279
296
 
@@ -347,7 +364,7 @@ scip_cli/
347
364
  ```bash
348
365
  pip install -e ".[dev]"
349
366
  pytest tests/ -q
350
- pytest tests/ -m integration -q # indexes tests/fixtures/sample-project (needs scip-typescript)
367
+ pytest tests/ -m integration -q # indexes tests/fixtures/typescript-project (needs scip-typescript)
351
368
  ```
352
369
 
353
370
  ### Debug Logging
@@ -3,7 +3,7 @@
3
3
  [![PyPI version](https://badge.fury.io/py/scip-cli.svg)](https://badge.fury.io/py/scip-cli)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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, Python, Go, and Rust.
6
+ Python CLI for AI agents. Queries SCIP indexes for precise refs, definitions, and repo health analysis — TypeScript/JavaScript, Python, Go, Rust.
7
7
 
8
8
  ## Why
9
9
 
@@ -17,6 +17,17 @@ AI agents waste tokens on grep and file scanning. scip-cli gives them precise, t
17
17
  - **`analyze`**: Find dead exports, import cycles, stale types, coupling hotspots — actionable health dashboards at project, file, or symbol scope
18
18
  - **Auto-indexing**: Indexes on first query, caches in SQLite, zero config
19
19
 
20
+ ## Ports
21
+
22
+ CLI/output parity ports of this project (Python is the reference):
23
+
24
+ | Language | Repository |
25
+ | ------------------ | ----------------------------------------------------------------- |
26
+ | Python (reference) | [flesler/scip-cli](https://github.com/flesler/scip-cli) |
27
+ | Go | [flesler/scip-cli-go](https://github.com/flesler/scip-cli-go) |
28
+ | Rust | [flesler/scip-cli-rust](https://github.com/flesler/scip-cli-rust) |
29
+ | Zig | [flesler/scip-cli-zig](https://github.com/flesler/scip-cli-zig) |
30
+
20
31
  ## For AI Agents
21
32
 
22
33
  Install as a reusable skill so your agent always knows how to navigate the codebase:
@@ -121,7 +132,7 @@ scip-cli <command> [arguments]
121
132
  - `rdeps <file>` - Find files that depend on a file (`--path`)
122
133
  - `deps <symbol|file>` - Find outbound dependencies (what a symbol or file calls) (`--path`, `--paths-only`)
123
134
  - `members <symbol>` - List members of a class/interface (`--path`)
124
- - `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).
135
+ - `analyze [target]` - SQL health dashboards (`--limit`, `--priority`, `--check`, `--include-tests`). No target: project-wide; directory or file path; symbol name. See [Finding easy wins with `analyze`](#finding-easy-wins-with-analyze).
125
136
  - `reindex` - Force re-indexing of the current project (`--path` to limit scope; repeatable)
126
137
  - `skill [path]` - Install or dump the SKILL.md
127
138
 
@@ -229,9 +240,13 @@ Scoped indexing without editing `.scip-cli.json`:
229
240
  ```bash
230
241
  scip-cli reindex --path packages/server
231
242
  scip-cli reindex --path packages/api --path packages/worker
243
+ scip-cli reindex --tsconfig 'apps/api/tsconfig.*.json'
244
+ scip-cli reindex --tsconfig tsconfig.app.json --tsconfig tsconfig.spec.json
232
245
  ```
233
246
 
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`.
247
+ `--path` limits which discovered tsconfig **directories** are indexed (prefix match, same idea as query `--path`). `--tsconfig` skips discovery and indexes those `tsconfig*.json` **files** (repeatable; globs are expanded inside the tool). File-based runs default to one `scip-typescript` process per file so each gets its own heap (`SCIP_CLI_TS_INDEX_BATCH_SIZE` still overrides). Cannot combine `--path` and `--tsconfig`. **TypeScript only.** 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`/`--tsconfig`.
248
+
249
+ When a tsconfig (after `extends`) has `allowJs: true`, matching `.js`/`.jsx` files under that config's `include`/`files` are indexed too (same roots as `.ts`/`.tsx`). `allowJs: false` or unset leaves JavaScript out. JS-only repos with no `tsconfig.json` still use `--infer-tsconfig`.
235
250
 
236
251
  Run `scip-cli reindex` after changing scope, `.scip-cli.json` index settings, or when you want a fresh index.
237
252
 
@@ -244,15 +259,17 @@ Use `analyze` on the repo itself before broad refactors or agent review — it s
244
259
  ```bash
245
260
  scip-cli analyze --limit 25
246
261
  scip-cli analyze --priority high --limit 25 # dead exports & cycles only
262
+ scip-cli analyze --check cycles --limit 25 # one named section
263
+ scip-cli analyze --check dead_files --limit 25
247
264
  ```
248
265
 
249
266
  Sections are tagged `[high]`, `[medium]`, `[low]` and listed in that order.
250
267
 
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` |
268
+ | Tier | Project sections | Action |
269
+ | ---------- | ----------------------------------------------------------- | -------------------------------------------------------------------- |
270
+ | **high** | Cycles, unreferenced, dead exports, dead files, stale types | Nuke or fix cycles; delete unused; `_` prefix |
271
+ | **medium** | Same-file only, change surface (file target) | Module-private by usage |
272
+ | **low** | Test-only consumers, coupling, bottlenecks, hotspots | Noisy on Python (index omits many same-file calls); verify with `rg` |
256
273
 
257
274
  Use `--priority high` for a quick gate; `--priority high,medium` adds context. File drill-down adds change surface and unused imports.
258
275
 
@@ -326,7 +343,7 @@ scip_cli/
326
343
  ```bash
327
344
  pip install -e ".[dev]"
328
345
  pytest tests/ -q
329
- pytest tests/ -m integration -q # indexes tests/fixtures/sample-project (needs scip-typescript)
346
+ pytest tests/ -m integration -q # indexes tests/fixtures/typescript-project (needs scip-typescript)
330
347
  ```
331
348
 
332
349
  ### Debug Logging
@@ -2,16 +2,16 @@
2
2
 
3
3
  ## Supported Versions
4
4
 
5
- | Version | Supported |
6
- | ------- | ------------------ |
7
- | latest | :white_check_mark: |
8
- | < latest| :x: |
5
+ |Version|Supported|
6
+ |---|---|
7
+ |latest|:white_check_mark:|
8
+ |< latest|:x:|
9
9
 
10
10
  ## Reporting a Vulnerability
11
11
 
12
12
  **Do not open public issues for security vulnerabilities.**
13
13
 
14
- If you discover a security vulnerability, please email **ariel.flesler@gmail.com** with:
14
+ If you discover a security vulnerability, please email **aflesler@gmail.com** with:
15
15
 
16
16
  - Description of the vulnerability
17
17
  - Steps to reproduce or proof of concept