Fast code intelligence via SCIP indexes
Project description
scip-cli
Token-efficient code intelligence for AI agents. Precise refs, definitions, and repo health analysis via SCIP indexes — TypeScript/JavaScript and Python.
Why
AI agents waste tokens on grep and file scanning. scip-cli gives them precise, type-aware code navigation in milliseconds — and analyze surfaces dead code, cycles, and coupling so agents (and humans) can fix real problems fast.
Features
- Agent-first: Install as a skill for Claude Code, Cursor, or any AI agent — precise code navigation without burning context
- Token-efficient: One record per line, stderr for warnings, pipe-friendly output
- Fast: Direct SQLite queries — 10x to 213x faster than alternatives
analyze: Find dead exports, import cycles, stale types, coupling hotspots — actionable health dashboards at project, file, or symbol scope- Auto-indexing: Indexes on first query, caches in SQLite, zero config
For AI Agents
Install as a reusable skill so your agent always knows how to navigate the codebase:
scip-cli skill ~/.claude/skills/scip-cli/ # Claude Code
scip-cli skill ~/.cursor/skills/scip-cli/ # Cursor
Or dump the quick reference for one-off use:
scip-cli skill
Installation
1. Install scip-cli
From PyPI (end users):
pip install scip-cli
Local development — almost always keep bare scip-cli mapped to this checkout via editable install. You edit the repo; the CLI you run is live code, not a frozen PyPI copy.
cd scip-cli
pip install -e ".[dev]"
scip-cli --version
All docs and examples use scip-cli (never .venv/bin/scip-cli or python -m scip_cli). After publishing, briefly pip install scip-cli to smoke-test PyPI, then pip install -e ".[dev]" again.
Optional venv for isolation — activate it, run the same editable install, still invoke scip-cli on PATH:
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
Tests and lint: pytest, ruff check . from the same environment.
2. Install prerequisites (optional)
On first index, scip-cli runs language indexers and builds a SQLite cache. You can let it fetch tools on demand, or install them globally ahead of time so the first run does not download via npx:
Option A: Zero extra setup (recommended)
Install scip-cli and run it. On first index, scip-cli will:
- Download
scip-typescript/scip-pythonvianpxwhen not already on PATH - Download the
scipconverter binary from GitHub releases into~/.cache/scip-cli/bin/when not already on PATH - Walk the repo for
tsconfig*.jsonproject roots (TypeScript monorepos), runscip-typescriptper project (parallel by default), convert each partial index, then merge into oneindex.db
No .scip-cli.json required for discovery. Subsequent queries read the cached database only.
Option B: Install indexers globally ahead of time
Same indexing steps as Option A; this only avoids npx download on the first run:
# TypeScript/JavaScript indexer (also handles plain JS via --infer-tsconfig)
npm install -g @sourcegraph/scip-typescript
# Python indexer
npm install -g @sourcegraph/scip-python
# SCIP CLI for index conversion (GitHub release — not on npm)
# https://github.com/scip-code/scip/releases (v0.8.1+ recommended)
Verify installation:
scip-cli --help
scip-typescript --version # Only if you chose Option B
scip --version # Install from GitHub releases; v0.8.1+ recommended
Usage
All commands are subcommands of scip-cli:
scip-cli <command> [arguments]
Commands
refs <symbol>- Find all references to a symbol (--pathto scope)code <symbol>- Find symbol definition with source code (--path,--max-lines,--full,--offset,--snippet,--line-numbers)search <pattern>- Search symbols by name pattern (--path)symbols <file>- List all symbols in a file (--path; bare filename OK)rdeps <file>- Find files that depend on a file (--path)members <symbol>- List members of a class/interface (--path)analyze [target]- SQL health dashboards (--limit,--priority,--include-tests). No target: project-wide; directory or file path; symbol name. See Finding easy wins withanalyze.reindex- Force re-indexing of the current project (--pathto limit scope; repeatable)skill [path]- Install or dump the SKILL.md
Examples
# Find where greet is used
scip-cli refs greet
# Get definition of greet
scip-cli code greet
# Search for symbols matching "Widget"
scip-cli search Widget
# Scope to a subdirectory
scip-cli code greet --path packages/api
# List symbols by bare filename
scip-cli symbols helper.ts
# Find files that import from a module
scip-cli rdeps src/helper.ts
# List members of a class
scip-cli members Widget
# Project health dashboard (or: scip-cli analyze src/foo.ts / scip-cli analyze greet)
scip-cli analyze
# Install skill file
scip-cli skill ~/.claude/skills/scip-cli/SKILL.md
Pipelines
Stdout is one record per line; stderr carries warnings and ambiguity notices. Kinds are lowercase (function, class, method, property). Pipe-friendly flags: refs --paths-only, search --names-only / --paths-only, members --names-only. rdeps already prints bare file paths.
# What do importers of this file export?
scip-cli rdeps src/helper.ts | xargs -I{} scip-cli symbols {}
# Which files reference a symbol?
scip-cli refs greet --paths-only
# Classes matching a name → list their members
scip-cli search Handler --kind class --names-only | xargs -I{} scip-cli members {}
# Walk class members to their definitions
scip-cli members Widget --names-only | xargs -I{} scip-cli code Widget.{}
How It Works
- On first query, automatically detects project language from
package.json(TS/JS) orpyproject.toml/setup.py(Python) - For TypeScript monorepos, walks the repository for
tsconfig*.jsonproject roots (nested ancestors deduped; root included only when itsincludeis broad) - Runs
scip-typescriptper project (in parallel when there are multiple projects; setSCIP_CLI_INDEX_WORKERS=1to force serial), orscip-pythonfor Python - Converts each SCIP output to SQLite with
scip expt-convert, then merges partial databases when needed - Caches the result in
~/.cache/scip-cli/projects/<dirname>-<hash>/index.db(e.g.my-monorepo-1a3f7a) - Subsequent queries are SQLite lookups against that cache (not re-indexing)
Configuration
Optional .scip-cli.json in the project root:
{
"maxHeapMb": 8192,
"indexRoots": ["packages/core", "apps/worker"],
"onlyIndexRoots": false
}
maxHeapMb— Node heap forscip-typescript/scip-python(default 8192 MB when omitted). Overridden bySCIP_CLI_MAX_HEAP_MB. This is the V8 heap cap, not total RAM usage.indexRoots— extra TypeScript project directories to include on first index, merged with auto-discovered projects.onlyIndexRoots— skip auto-discovery and index onlyindexRoots(smaller initial index when you only care about part of a monorepo).
SCIP_CLI_INDEX_WORKERS controls parallel scip-typescript runs during first index (default: up to 8). Merge into one database is always serial.
Large monorepos (>10 tsconfig projects) log per-project progress to stderr during indexing; smaller repos stay quiet aside from the final Indexed … (size) line.
Scoped indexing without editing .scip-cli.json:
scip-cli reindex --path packages/server
scip-cli reindex --path packages/api --path packages/worker
--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.
Run scip-cli reindex after changing scope, .scip-cli.json index settings, or when you want a fresh index.
Finding easy wins with analyze
Use analyze on the repo itself before broad refactors or agent review — it surfaces cross-file issues from the SCIP index (not Python vulture).
Quick pass (after scip-cli reindex):
scip-cli analyze --limit 25
scip-cli analyze --priority high --limit 25 # dead exports & cycles only
Sections are tagged [high], [medium], [low] and listed in that order.
| Tier | Project sections | Action |
|---|---|---|
| high | Cycles, unreferenced, dead exports, stale types | Nuke or fix cycles; delete unused; _ prefix |
| medium | Same-file only, change surface (file target) | Module-private by usage |
| low | Test-only consumers, coupling, bottlenecks, hotspots | Noisy on Python (index omits many same-file calls); verify with rg |
Use --priority high for a quick gate; --priority high,medium adds context. File drill-down adds change surface and unused imports.
What to look at first
| Section | Easy pickings |
|---|---|
| Cycles | Import/mention cycles between production files — break the edge or extract shared code |
| Unreferenced | No usage in the index at all — delete |
| Dead exports | No external refs — delete or _ prefix |
| Stale types | Classes/types with ≤1 external consumer — merge, inline, or document why they stay |
| Same-file only | Used only inside defining file — rename to _ |
| Test-only consumers | Cross-file refs are all from tests — promote to e2e or accept as internal |
Per-file or package drill-down on hubs or suspects:
scip-cli analyze scip_cli/queries.py --limit 20 # file: scoped project + per-file + top symbols
scip-cli analyze scip_cli --limit 15 # directory: scoped project + each file under it
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.
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.
Limits: “Dead export” means no cross-file mentions in the index — not unreachable code. Same-file private helpers are expected. Re-run reindex after large changes; the index is a snapshot.
Performance
Inspired by scip-query, scip-cli is a lightweight Python partial reimplementation optimized for speed. Compared to the original:
refs: 6.4s → 0.03s (213x faster)code: 2.8s → 0.05s (56x faster)search: 2.6s → 0.03s (87x faster)symbols: 0.3s → 0.02s (15x faster)rdeps: 0.2s → 0.02s (10x faster)members: 3.1s → 0.03s (103x faster)
The speedup comes from using optimized direct SQLite queries and cutting some nice but very slow goodies (like ts-morph).
Architecture
scip_cli/
├── __init__.py
├── __main__.py # CLI entry point
├── cli_args.py # Shared argparse helpers
├── config.py # .scip-cli.json loader
├── discover.py # TypeScript project discovery
├── merge.py # SQLite index merging
├── scip_tool.py # scip binary download
├── sql.py # SQLite helpers
├── paths.py # --path scope filtering
├── project.py # Project root + language detection
├── cache.py # Index cache paths
├── scope.py # Persisted reindex scope (index-scope.json)
├── debug.py # SCIP_CLI_DEBUG stderr helpers
├── indexing.py # SCIP index build + get_db
├── symbols.py # Symbol parsing and kinds
├── queries.py # Symbol/file SQL queries
├── source.py # Filesystem source reads
├── output.py # CLI formatting helpers
├── session.py # setup() and single-match resolution
├── targets.py # file-path heuristics (tests; analyze uses analyze/targets.py)
├── analyze/ # SQL dashboard queries (project/file/symbol)
└── commands/ # Subcommand implementations
Development
pip install -e ".[dev]"
pytest tests/ -q
pytest tests/ -m integration -q # indexes tests/fixtures/sample-project (needs scip-typescript)
Debug Logging
Set SCIP_CLI_DEBUG=1 to enable SQL query logging to stderr (statements truncated to 200 chars):
SCIP_CLI_DEBUG=1 scip-cli refs MyFunction
# Shows: SQL: SELECT ... | params: (...)
This is useful for testing and debugging SQL queries
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file scip_cli-2.1.0.tar.gz.
File metadata
- Download URL: scip_cli-2.1.0.tar.gz
- Upload date:
- Size: 71.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b80b42e4b82672ec783f9323741f0a4207d5cbea570f76831c8726e5c3ac8b0
|
|
| MD5 |
8bb8009bdcfce0d92b2fc959d15b32c5
|
|
| BLAKE2b-256 |
2b780cad236ed8a69932a7a63a8a3e072f6ae8280a7a8a849ff022895144e1ef
|
File details
Details for the file scip_cli-2.1.0-py3-none-any.whl.
File metadata
- Download URL: scip_cli-2.1.0-py3-none-any.whl
- Upload date:
- Size: 63.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e73ac831c8f946bbd15e07914955a0c0ec33758a9fd6cfa3abc5e8fcd44f05e7
|
|
| MD5 |
ee0714ffc57e9f44ca9283adc7a9dc3a
|
|
| BLAKE2b-256 |
538fe239c05419e23090bba428e2d5bda7530739ea871a92841dec955c02fe15
|