sampler-cli 0.2.0__tar.gz → 0.2.1__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.
- sampler_cli-0.2.1/PKG-INFO +182 -0
- sampler_cli-0.2.1/README.md +145 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/pyproject.toml +1 -1
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/__init__.py +1 -1
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/cli/main.py +87 -5
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/db.py +30 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/query/engine.py +4 -0
- sampler_cli-0.2.1/src/sampler_cli.egg-info/PKG-INFO +182 -0
- sampler_cli-0.2.0/PKG-INFO +0 -130
- sampler_cli-0.2.0/README.md +0 -93
- sampler_cli-0.2.0/src/sampler_cli.egg-info/PKG-INFO +0 -130
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/LICENSE +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/setup.cfg +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/__main__.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/cli/__init__.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/config.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/indexer/__init__.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/indexer/builder.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/indexer/discover.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/indexer/parsers/__init__.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/indexer/parsers/base.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/indexer/parsers/go.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/indexer/parsers/python.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/indexer/parsers/typescript.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/indexer/store.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/mcp/__init__.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/mcp/server.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/models.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/query/__init__.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler/query/semantic.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler_cli.egg-info/SOURCES.txt +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler_cli.egg-info/dependency_links.txt +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler_cli.egg-info/entry_points.txt +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler_cli.egg-info/requires.txt +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/src/sampler_cli.egg-info/top_level.txt +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/tests/test_cli.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/tests/test_config.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/tests/test_db.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/tests/test_discover.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/tests/test_index_query.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/tests/test_python_parser.py +0 -0
- {sampler_cli-0.2.0 → sampler_cli-0.2.1}/tests/test_smoke.py +0 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sampler-cli
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Token-efficient CLI for indexing and searching code symbols (Python-first, designed for minimal LLM/agent context size)
|
|
5
|
+
Author: Samuel Ignacio Carmona Rodriguez
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/sicr0/sampler-cli
|
|
8
|
+
Project-URL: Repository, https://github.com/sicr0/sampler-cli
|
|
9
|
+
Project-URL: Issues, https://github.com/sicr0/sampler-cli/issues
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: typer>=0.12.0
|
|
21
|
+
Requires-Dist: rich>=13.7.0
|
|
22
|
+
Requires-Dist: tree-sitter>=0.21.0
|
|
23
|
+
Requires-Dist: tree-sitter-python>=0.23.0
|
|
24
|
+
Requires-Dist: gitignore-parser>=0.1.11
|
|
25
|
+
Requires-Dist: pydantic>=2.6.0
|
|
26
|
+
Requires-Dist: pyyaml>=6.0.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=7.4.0; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
30
|
+
Requires-Dist: ruff>=0.5.0; extra == "dev"
|
|
31
|
+
Requires-Dist: mypy>=1.7.0; extra == "dev"
|
|
32
|
+
Provides-Extra: mcp
|
|
33
|
+
Requires-Dist: fastmcp>=0.1.0; extra == "mcp"
|
|
34
|
+
Provides-Extra: semantic
|
|
35
|
+
Requires-Dist: sentence-transformers>=2.2.0; extra == "semantic"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# Sampler
|
|
39
|
+
|
|
40
|
+
**Token-efficient CLI for indexing and searching code symbols across multiple projects.**
|
|
41
|
+
|
|
42
|
+
Current version: 0.2.1
|
|
43
|
+
|
|
44
|
+
Designed for humans and LLMs/agents: default outputs are compact, single-line, with short paths and no noisy table formatting.
|
|
45
|
+
|
|
46
|
+
## Requirements
|
|
47
|
+
|
|
48
|
+
- Python 3.11+
|
|
49
|
+
- (Optional) Go, if you plan to use Go parser support in the future
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install sampler-cli
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
For development (tests, linters, etc.):
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install -e '.[dev]'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Quick Start
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
sampler init
|
|
67
|
+
sampler project add myproj /absolute/path/to/project --language python
|
|
68
|
+
sampler project list
|
|
69
|
+
sampler index myproj
|
|
70
|
+
sampler search add --project myproj
|
|
71
|
+
sampler overview /absolute/path/to/project/some/file.py
|
|
72
|
+
sampler symbols myproj
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Examples with Output
|
|
76
|
+
|
|
77
|
+
**List projects (compact):**
|
|
78
|
+
```bash
|
|
79
|
+
$ sampler project list
|
|
80
|
+
myproj /home/user/projects/myproj
|
|
81
|
+
demo ~/work/demo
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Search (default compact, LLM-friendly):**
|
|
85
|
+
```bash
|
|
86
|
+
$ sampler search worker --project myproj
|
|
87
|
+
myproj:src/tasks/celery_app.py:70 function on_worker_ready def on_worker_ready(sender)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**List all symbols for a project:**
|
|
91
|
+
```bash
|
|
92
|
+
$ sampler symbols myproj --type function --limit 5
|
|
93
|
+
myproj:src/utils.py:10 function helper def helper(x)
|
|
94
|
+
myproj:src/models.py:25 function validate def validate(data)
|
|
95
|
+
...
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Overview of a file (supports relative paths):**
|
|
99
|
+
```bash
|
|
100
|
+
$ sampler overview src/app.py
|
|
101
|
+
12: function main def main()
|
|
102
|
+
25: class App class App
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
If the file has no indexed symbols (or was never indexed):
|
|
106
|
+
```bash
|
|
107
|
+
$ sampler overview nonexistent.py
|
|
108
|
+
No symbols found for file: nonexistent.py
|
|
109
|
+
Tip: Make sure the project is registered with 'sampler project add' and indexed with 'sampler index <project>'.
|
|
110
|
+
The path must match a file that was indexed (relative paths are resolved to absolute).
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Why "project add" is required
|
|
114
|
+
|
|
115
|
+
- `sampler project add <name> <path>` registers the project in `~/.sampler/config.yaml`.
|
|
116
|
+
- `index` looks up the project there to know the root path and language.
|
|
117
|
+
- Without it, commands like `index`, `symbols`, and filtered searches will fail with a clear "not found" message and usage hint.
|
|
118
|
+
- The actual symbol data lives in the SQLite DB (`~/.sampler/graph.db`), but registration is the control plane.
|
|
119
|
+
|
|
120
|
+
You can have data in the DB without the config entry (e.g. after `project remove`), but you won't be able to re-index or easily manage it.
|
|
121
|
+
|
|
122
|
+
## Relative Paths
|
|
123
|
+
|
|
124
|
+
- `overview` now resolves relative paths against the current working directory (e.g. `sampler overview ./src/app.py` or `sampler overview ../other/file.py`).
|
|
125
|
+
- Stored paths are absolute (resolved at index time), so the resolution makes overview work naturally.
|
|
126
|
+
- Other file-based commands behave similarly where applicable.
|
|
127
|
+
|
|
128
|
+
## Error Messages & Help
|
|
129
|
+
|
|
130
|
+
We try to give actionable errors:
|
|
131
|
+
|
|
132
|
+
- Unknown project → tells you the exact `project add` command to run and suggests `project list`.
|
|
133
|
+
- File with no symbols → clear "No symbols found" + tips.
|
|
134
|
+
- Typer automatically shows command usage and available options on invalid arguments.
|
|
135
|
+
|
|
136
|
+
Run any command with `--help` for full details (e.g. `sampler search --help`, `sampler symbols --help`).
|
|
137
|
+
|
|
138
|
+
## Current Features
|
|
139
|
+
|
|
140
|
+
- Global config in `~/.sampler/config.yaml`
|
|
141
|
+
- Project management (`add`, `list`, `remove`)
|
|
142
|
+
- Incremental indexing with file hashing (Python AST-based parser)
|
|
143
|
+
- Compact, token-efficient output by default (great for LLMs)
|
|
144
|
+
- Search with type filters and limits
|
|
145
|
+
- `search-all` across every registered project
|
|
146
|
+
- `symbols <project>` to dump/list symbols for a project
|
|
147
|
+
- `overview <file>` (relative paths supported)
|
|
148
|
+
- Basic relationship extraction (CALLS, CONTAINS)
|
|
149
|
+
|
|
150
|
+
## Stability Note
|
|
151
|
+
|
|
152
|
+
- Python parser uses stdlib `ast` (we switched from tree-sitter-python after native crashes on macOS ARM during real indexing).
|
|
153
|
+
- Go and TypeScript/JavaScript parsers are stubs for now (return no symbols).
|
|
154
|
+
|
|
155
|
+
## Project Structure
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
src/sampler/
|
|
159
|
+
├── cli/main.py # Typer commands (search, overview, symbols, index, project ...)
|
|
160
|
+
├── config.py # YAML config manager
|
|
161
|
+
├── db.py # SQLite layer
|
|
162
|
+
├── indexer/
|
|
163
|
+
│ ├── builder.py
|
|
164
|
+
│ ├── discover.py
|
|
165
|
+
│ ├── store.py
|
|
166
|
+
│ └── parsers/python.py
|
|
167
|
+
└── query/engine.py
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Running Tests
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
pytest -q
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Roadmap Highlights (see TODO.md and PLAN.md)
|
|
177
|
+
|
|
178
|
+
- Cross-file relation improvements
|
|
179
|
+
- Better call graph queries (`callers`, `usages`, ...)
|
|
180
|
+
- Real Go / TypeScript parsers
|
|
181
|
+
- Semantic search + MCP server (for agents)
|
|
182
|
+
- More context-generation helpers
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Sampler
|
|
2
|
+
|
|
3
|
+
**Token-efficient CLI for indexing and searching code symbols across multiple projects.**
|
|
4
|
+
|
|
5
|
+
Current version: 0.2.1
|
|
6
|
+
|
|
7
|
+
Designed for humans and LLMs/agents: default outputs are compact, single-line, with short paths and no noisy table formatting.
|
|
8
|
+
|
|
9
|
+
## Requirements
|
|
10
|
+
|
|
11
|
+
- Python 3.11+
|
|
12
|
+
- (Optional) Go, if you plan to use Go parser support in the future
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install sampler-cli
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
For development (tests, linters, etc.):
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install -e '.[dev]'
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
sampler init
|
|
30
|
+
sampler project add myproj /absolute/path/to/project --language python
|
|
31
|
+
sampler project list
|
|
32
|
+
sampler index myproj
|
|
33
|
+
sampler search add --project myproj
|
|
34
|
+
sampler overview /absolute/path/to/project/some/file.py
|
|
35
|
+
sampler symbols myproj
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Examples with Output
|
|
39
|
+
|
|
40
|
+
**List projects (compact):**
|
|
41
|
+
```bash
|
|
42
|
+
$ sampler project list
|
|
43
|
+
myproj /home/user/projects/myproj
|
|
44
|
+
demo ~/work/demo
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Search (default compact, LLM-friendly):**
|
|
48
|
+
```bash
|
|
49
|
+
$ sampler search worker --project myproj
|
|
50
|
+
myproj:src/tasks/celery_app.py:70 function on_worker_ready def on_worker_ready(sender)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**List all symbols for a project:**
|
|
54
|
+
```bash
|
|
55
|
+
$ sampler symbols myproj --type function --limit 5
|
|
56
|
+
myproj:src/utils.py:10 function helper def helper(x)
|
|
57
|
+
myproj:src/models.py:25 function validate def validate(data)
|
|
58
|
+
...
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Overview of a file (supports relative paths):**
|
|
62
|
+
```bash
|
|
63
|
+
$ sampler overview src/app.py
|
|
64
|
+
12: function main def main()
|
|
65
|
+
25: class App class App
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
If the file has no indexed symbols (or was never indexed):
|
|
69
|
+
```bash
|
|
70
|
+
$ sampler overview nonexistent.py
|
|
71
|
+
No symbols found for file: nonexistent.py
|
|
72
|
+
Tip: Make sure the project is registered with 'sampler project add' and indexed with 'sampler index <project>'.
|
|
73
|
+
The path must match a file that was indexed (relative paths are resolved to absolute).
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Why "project add" is required
|
|
77
|
+
|
|
78
|
+
- `sampler project add <name> <path>` registers the project in `~/.sampler/config.yaml`.
|
|
79
|
+
- `index` looks up the project there to know the root path and language.
|
|
80
|
+
- Without it, commands like `index`, `symbols`, and filtered searches will fail with a clear "not found" message and usage hint.
|
|
81
|
+
- The actual symbol data lives in the SQLite DB (`~/.sampler/graph.db`), but registration is the control plane.
|
|
82
|
+
|
|
83
|
+
You can have data in the DB without the config entry (e.g. after `project remove`), but you won't be able to re-index or easily manage it.
|
|
84
|
+
|
|
85
|
+
## Relative Paths
|
|
86
|
+
|
|
87
|
+
- `overview` now resolves relative paths against the current working directory (e.g. `sampler overview ./src/app.py` or `sampler overview ../other/file.py`).
|
|
88
|
+
- Stored paths are absolute (resolved at index time), so the resolution makes overview work naturally.
|
|
89
|
+
- Other file-based commands behave similarly where applicable.
|
|
90
|
+
|
|
91
|
+
## Error Messages & Help
|
|
92
|
+
|
|
93
|
+
We try to give actionable errors:
|
|
94
|
+
|
|
95
|
+
- Unknown project → tells you the exact `project add` command to run and suggests `project list`.
|
|
96
|
+
- File with no symbols → clear "No symbols found" + tips.
|
|
97
|
+
- Typer automatically shows command usage and available options on invalid arguments.
|
|
98
|
+
|
|
99
|
+
Run any command with `--help` for full details (e.g. `sampler search --help`, `sampler symbols --help`).
|
|
100
|
+
|
|
101
|
+
## Current Features
|
|
102
|
+
|
|
103
|
+
- Global config in `~/.sampler/config.yaml`
|
|
104
|
+
- Project management (`add`, `list`, `remove`)
|
|
105
|
+
- Incremental indexing with file hashing (Python AST-based parser)
|
|
106
|
+
- Compact, token-efficient output by default (great for LLMs)
|
|
107
|
+
- Search with type filters and limits
|
|
108
|
+
- `search-all` across every registered project
|
|
109
|
+
- `symbols <project>` to dump/list symbols for a project
|
|
110
|
+
- `overview <file>` (relative paths supported)
|
|
111
|
+
- Basic relationship extraction (CALLS, CONTAINS)
|
|
112
|
+
|
|
113
|
+
## Stability Note
|
|
114
|
+
|
|
115
|
+
- Python parser uses stdlib `ast` (we switched from tree-sitter-python after native crashes on macOS ARM during real indexing).
|
|
116
|
+
- Go and TypeScript/JavaScript parsers are stubs for now (return no symbols).
|
|
117
|
+
|
|
118
|
+
## Project Structure
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
src/sampler/
|
|
122
|
+
├── cli/main.py # Typer commands (search, overview, symbols, index, project ...)
|
|
123
|
+
├── config.py # YAML config manager
|
|
124
|
+
├── db.py # SQLite layer
|
|
125
|
+
├── indexer/
|
|
126
|
+
│ ├── builder.py
|
|
127
|
+
│ ├── discover.py
|
|
128
|
+
│ ├── store.py
|
|
129
|
+
│ └── parsers/python.py
|
|
130
|
+
└── query/engine.py
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Running Tests
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
pytest -q
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Roadmap Highlights (see TODO.md and PLAN.md)
|
|
140
|
+
|
|
141
|
+
- Cross-file relation improvements
|
|
142
|
+
- Better call graph queries (`callers`, `usages`, ...)
|
|
143
|
+
- Real Go / TypeScript parsers
|
|
144
|
+
- Semantic search + MCP server (for agents)
|
|
145
|
+
- More context-generation helpers
|
|
@@ -9,7 +9,7 @@ from sampler.db import Database
|
|
|
9
9
|
from sampler.indexer.builder import IndexBuilder
|
|
10
10
|
from sampler.query.engine import QueryEngine
|
|
11
11
|
|
|
12
|
-
app = typer.Typer(help="Sampler CLI")
|
|
12
|
+
app = typer.Typer(help="Sampler CLI", no_args_is_help=True)
|
|
13
13
|
project_app = typer.Typer(help="Project management commands")
|
|
14
14
|
app.add_typer(project_app, name="project")
|
|
15
15
|
console = Console()
|
|
@@ -93,7 +93,7 @@ def project_add(name: str, path: str, language: str = "python") -> None:
|
|
|
93
93
|
try:
|
|
94
94
|
project = config.add_project(name=name, path=path, language=language)
|
|
95
95
|
except ValueError as exc:
|
|
96
|
-
raise typer.BadParameter(
|
|
96
|
+
raise typer.BadParameter(f"{exc}\nTip: Use an absolute path that exists.") from exc
|
|
97
97
|
console.print(f"Added project [bold]{project.name}[/bold]")
|
|
98
98
|
|
|
99
99
|
|
|
@@ -147,13 +147,57 @@ def search_all(
|
|
|
147
147
|
search(query=query, project=None, type=type, limit=limit)
|
|
148
148
|
|
|
149
149
|
|
|
150
|
+
@app.command("symbols")
|
|
151
|
+
def symbols(
|
|
152
|
+
project: str,
|
|
153
|
+
type: str | None = typer.Option(None, "--type", "-t", help="filter e.g. function,class"),
|
|
154
|
+
limit: int = typer.Option(100, "--limit", "-l"),
|
|
155
|
+
) -> None:
|
|
156
|
+
"""List all symbols for a project (useful for getting a quick overview)."""
|
|
157
|
+
config = ConfigManager()
|
|
158
|
+
if config.get_project(project) is None:
|
|
159
|
+
raise typer.BadParameter(
|
|
160
|
+
f"Project '{project}' not found.\n"
|
|
161
|
+
f"Run: sampler project add {project} <absolute/path> --language python\n"
|
|
162
|
+
"Use 'sampler project list' to see registered projects."
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
engine = QueryEngine(db=_database())
|
|
166
|
+
types = [x.strip() for x in type.split(",")] if type else None
|
|
167
|
+
if types:
|
|
168
|
+
exp = set(types)
|
|
169
|
+
for t in list(types):
|
|
170
|
+
if t == "function":
|
|
171
|
+
exp.add("async function")
|
|
172
|
+
elif t == "method":
|
|
173
|
+
exp.add("async method")
|
|
174
|
+
types = list(exp)
|
|
175
|
+
|
|
176
|
+
rows = engine.list_symbols(project_name=project, types=types, limit=limit)
|
|
177
|
+
roots = _get_project_roots()
|
|
178
|
+
|
|
179
|
+
for r in rows:
|
|
180
|
+
shortf = _short_path(r["project_name"], r["file_path"], roots)
|
|
181
|
+
name = r["qualified_name"] or r["name"]
|
|
182
|
+
sig = r.get("signature") or ""
|
|
183
|
+
line = f"{r['project_name']}:{shortf}:{r['start_line'] or '-'} {r['type']} {name}"
|
|
184
|
+
if sig:
|
|
185
|
+
line += f" {sig}"
|
|
186
|
+
console.print(line)
|
|
187
|
+
|
|
188
|
+
|
|
150
189
|
@app.command("index")
|
|
151
190
|
def index(project: str) -> None:
|
|
152
191
|
"""Index selected project."""
|
|
153
192
|
config = ConfigManager()
|
|
154
193
|
project_cfg = config.get_project(project)
|
|
155
194
|
if project_cfg is None:
|
|
156
|
-
raise typer.BadParameter(
|
|
195
|
+
raise typer.BadParameter(
|
|
196
|
+
f"Project '{project}' not found.\n"
|
|
197
|
+
f"Run: sampler project add {project} <absolute/path> --language python\n"
|
|
198
|
+
"Then: sampler index {project}\n"
|
|
199
|
+
"Use 'sampler project list' to see registered projects."
|
|
200
|
+
)
|
|
157
201
|
|
|
158
202
|
builder = IndexBuilder(db=_database())
|
|
159
203
|
stats = builder.index_project(
|
|
@@ -170,9 +214,47 @@ def index(project: str) -> None:
|
|
|
170
214
|
|
|
171
215
|
@app.command("overview")
|
|
172
216
|
def overview(filepath: str) -> None:
|
|
173
|
-
"""Show symbols for file.
|
|
217
|
+
"""Show symbols for a file.
|
|
218
|
+
|
|
219
|
+
Supports absolute and relative paths.
|
|
220
|
+
Relative paths are first resolved from cwd; if nothing matches we also try
|
|
221
|
+
resolving relative to each registered project's root (very convenient).
|
|
222
|
+
"""
|
|
223
|
+
config = ConfigManager()
|
|
224
|
+
projects = config.list_projects()
|
|
225
|
+
|
|
226
|
+
candidates = []
|
|
227
|
+
try:
|
|
228
|
+
candidates.append(str(Path(filepath).resolve()))
|
|
229
|
+
except Exception:
|
|
230
|
+
candidates.append(filepath)
|
|
231
|
+
|
|
232
|
+
# Try resolving relative to each project root (helps when you're inside the project)
|
|
233
|
+
for p in projects:
|
|
234
|
+
try:
|
|
235
|
+
root = Path(p.path).resolve()
|
|
236
|
+
rel = root / filepath
|
|
237
|
+
candidates.append(str(rel.resolve()))
|
|
238
|
+
except Exception:
|
|
239
|
+
pass
|
|
240
|
+
|
|
241
|
+
# Dedup while preserving order
|
|
242
|
+
seen = set()
|
|
243
|
+
candidates = [c for c in candidates if not (c in seen or seen.add(c))]
|
|
244
|
+
|
|
174
245
|
engine = QueryEngine(db=_database())
|
|
175
|
-
rows =
|
|
246
|
+
rows = []
|
|
247
|
+
matched_path = None
|
|
248
|
+
for cand in candidates:
|
|
249
|
+
rows = engine.overview(filepath=cand)
|
|
250
|
+
if rows:
|
|
251
|
+
matched_path = cand
|
|
252
|
+
break
|
|
253
|
+
|
|
254
|
+
if not rows:
|
|
255
|
+
console.print(f"No symbols found for file: {filepath}")
|
|
256
|
+
console.print("Tip: Make sure the project is registered with 'sampler project add' and indexed with 'sampler index <project>'.")
|
|
257
|
+
return
|
|
176
258
|
|
|
177
259
|
for r in rows:
|
|
178
260
|
name = r["qualified_name"] or r["name"]
|
|
@@ -314,3 +314,33 @@ class Database:
|
|
|
314
314
|
""",
|
|
315
315
|
params,
|
|
316
316
|
).fetchall()
|
|
317
|
+
|
|
318
|
+
def list_symbols(self, project_name: str, types: list[str] | None = None, limit: int | None = None, offset: int = 0) -> list[sqlite3.Row]:
|
|
319
|
+
where = "WHERE p.name = ?"
|
|
320
|
+
params: list = [project_name]
|
|
321
|
+
if types:
|
|
322
|
+
ph = ",".join("?" * len(types))
|
|
323
|
+
where += f" AND s.type IN ({ph})"
|
|
324
|
+
params.extend(types)
|
|
325
|
+
|
|
326
|
+
sql = f"""
|
|
327
|
+
SELECT
|
|
328
|
+
s.type,
|
|
329
|
+
s.name,
|
|
330
|
+
s.qualified_name,
|
|
331
|
+
s.signature,
|
|
332
|
+
s.start_line,
|
|
333
|
+
f.path AS file_path,
|
|
334
|
+
p.name AS project_name
|
|
335
|
+
FROM symbols s
|
|
336
|
+
JOIN files f ON s.file_id = f.id
|
|
337
|
+
JOIN projects p ON f.project_id = p.id
|
|
338
|
+
{where}
|
|
339
|
+
ORDER BY f.path, s.start_line
|
|
340
|
+
"""
|
|
341
|
+
if limit is not None:
|
|
342
|
+
sql += " LIMIT ? OFFSET ?"
|
|
343
|
+
params.extend([limit, offset])
|
|
344
|
+
|
|
345
|
+
with self.connect() as conn:
|
|
346
|
+
return conn.execute(sql, params).fetchall()
|
|
@@ -14,3 +14,7 @@ class QueryEngine:
|
|
|
14
14
|
def overview(self, filepath: str, project_name: str | None = None) -> list[dict]:
|
|
15
15
|
rows = self.db.get_symbols_by_filepath(filepath=filepath, project_name=project_name)
|
|
16
16
|
return [dict(row) for row in rows]
|
|
17
|
+
|
|
18
|
+
def list_symbols(self, project_name: str, types: list[str] | None = None, limit: int | None = None, offset: int = 0) -> list[dict]:
|
|
19
|
+
rows = self.db.list_symbols(project_name=project_name, types=types, limit=limit, offset=offset)
|
|
20
|
+
return [dict(row) for row in rows]
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sampler-cli
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Token-efficient CLI for indexing and searching code symbols (Python-first, designed for minimal LLM/agent context size)
|
|
5
|
+
Author: Samuel Ignacio Carmona Rodriguez
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/sicr0/sampler-cli
|
|
8
|
+
Project-URL: Repository, https://github.com/sicr0/sampler-cli
|
|
9
|
+
Project-URL: Issues, https://github.com/sicr0/sampler-cli/issues
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: typer>=0.12.0
|
|
21
|
+
Requires-Dist: rich>=13.7.0
|
|
22
|
+
Requires-Dist: tree-sitter>=0.21.0
|
|
23
|
+
Requires-Dist: tree-sitter-python>=0.23.0
|
|
24
|
+
Requires-Dist: gitignore-parser>=0.1.11
|
|
25
|
+
Requires-Dist: pydantic>=2.6.0
|
|
26
|
+
Requires-Dist: pyyaml>=6.0.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=7.4.0; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
30
|
+
Requires-Dist: ruff>=0.5.0; extra == "dev"
|
|
31
|
+
Requires-Dist: mypy>=1.7.0; extra == "dev"
|
|
32
|
+
Provides-Extra: mcp
|
|
33
|
+
Requires-Dist: fastmcp>=0.1.0; extra == "mcp"
|
|
34
|
+
Provides-Extra: semantic
|
|
35
|
+
Requires-Dist: sentence-transformers>=2.2.0; extra == "semantic"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# Sampler
|
|
39
|
+
|
|
40
|
+
**Token-efficient CLI for indexing and searching code symbols across multiple projects.**
|
|
41
|
+
|
|
42
|
+
Current version: 0.2.1
|
|
43
|
+
|
|
44
|
+
Designed for humans and LLMs/agents: default outputs are compact, single-line, with short paths and no noisy table formatting.
|
|
45
|
+
|
|
46
|
+
## Requirements
|
|
47
|
+
|
|
48
|
+
- Python 3.11+
|
|
49
|
+
- (Optional) Go, if you plan to use Go parser support in the future
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install sampler-cli
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
For development (tests, linters, etc.):
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install -e '.[dev]'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Quick Start
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
sampler init
|
|
67
|
+
sampler project add myproj /absolute/path/to/project --language python
|
|
68
|
+
sampler project list
|
|
69
|
+
sampler index myproj
|
|
70
|
+
sampler search add --project myproj
|
|
71
|
+
sampler overview /absolute/path/to/project/some/file.py
|
|
72
|
+
sampler symbols myproj
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Examples with Output
|
|
76
|
+
|
|
77
|
+
**List projects (compact):**
|
|
78
|
+
```bash
|
|
79
|
+
$ sampler project list
|
|
80
|
+
myproj /home/user/projects/myproj
|
|
81
|
+
demo ~/work/demo
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Search (default compact, LLM-friendly):**
|
|
85
|
+
```bash
|
|
86
|
+
$ sampler search worker --project myproj
|
|
87
|
+
myproj:src/tasks/celery_app.py:70 function on_worker_ready def on_worker_ready(sender)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**List all symbols for a project:**
|
|
91
|
+
```bash
|
|
92
|
+
$ sampler symbols myproj --type function --limit 5
|
|
93
|
+
myproj:src/utils.py:10 function helper def helper(x)
|
|
94
|
+
myproj:src/models.py:25 function validate def validate(data)
|
|
95
|
+
...
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Overview of a file (supports relative paths):**
|
|
99
|
+
```bash
|
|
100
|
+
$ sampler overview src/app.py
|
|
101
|
+
12: function main def main()
|
|
102
|
+
25: class App class App
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
If the file has no indexed symbols (or was never indexed):
|
|
106
|
+
```bash
|
|
107
|
+
$ sampler overview nonexistent.py
|
|
108
|
+
No symbols found for file: nonexistent.py
|
|
109
|
+
Tip: Make sure the project is registered with 'sampler project add' and indexed with 'sampler index <project>'.
|
|
110
|
+
The path must match a file that was indexed (relative paths are resolved to absolute).
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Why "project add" is required
|
|
114
|
+
|
|
115
|
+
- `sampler project add <name> <path>` registers the project in `~/.sampler/config.yaml`.
|
|
116
|
+
- `index` looks up the project there to know the root path and language.
|
|
117
|
+
- Without it, commands like `index`, `symbols`, and filtered searches will fail with a clear "not found" message and usage hint.
|
|
118
|
+
- The actual symbol data lives in the SQLite DB (`~/.sampler/graph.db`), but registration is the control plane.
|
|
119
|
+
|
|
120
|
+
You can have data in the DB without the config entry (e.g. after `project remove`), but you won't be able to re-index or easily manage it.
|
|
121
|
+
|
|
122
|
+
## Relative Paths
|
|
123
|
+
|
|
124
|
+
- `overview` now resolves relative paths against the current working directory (e.g. `sampler overview ./src/app.py` or `sampler overview ../other/file.py`).
|
|
125
|
+
- Stored paths are absolute (resolved at index time), so the resolution makes overview work naturally.
|
|
126
|
+
- Other file-based commands behave similarly where applicable.
|
|
127
|
+
|
|
128
|
+
## Error Messages & Help
|
|
129
|
+
|
|
130
|
+
We try to give actionable errors:
|
|
131
|
+
|
|
132
|
+
- Unknown project → tells you the exact `project add` command to run and suggests `project list`.
|
|
133
|
+
- File with no symbols → clear "No symbols found" + tips.
|
|
134
|
+
- Typer automatically shows command usage and available options on invalid arguments.
|
|
135
|
+
|
|
136
|
+
Run any command with `--help` for full details (e.g. `sampler search --help`, `sampler symbols --help`).
|
|
137
|
+
|
|
138
|
+
## Current Features
|
|
139
|
+
|
|
140
|
+
- Global config in `~/.sampler/config.yaml`
|
|
141
|
+
- Project management (`add`, `list`, `remove`)
|
|
142
|
+
- Incremental indexing with file hashing (Python AST-based parser)
|
|
143
|
+
- Compact, token-efficient output by default (great for LLMs)
|
|
144
|
+
- Search with type filters and limits
|
|
145
|
+
- `search-all` across every registered project
|
|
146
|
+
- `symbols <project>` to dump/list symbols for a project
|
|
147
|
+
- `overview <file>` (relative paths supported)
|
|
148
|
+
- Basic relationship extraction (CALLS, CONTAINS)
|
|
149
|
+
|
|
150
|
+
## Stability Note
|
|
151
|
+
|
|
152
|
+
- Python parser uses stdlib `ast` (we switched from tree-sitter-python after native crashes on macOS ARM during real indexing).
|
|
153
|
+
- Go and TypeScript/JavaScript parsers are stubs for now (return no symbols).
|
|
154
|
+
|
|
155
|
+
## Project Structure
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
src/sampler/
|
|
159
|
+
├── cli/main.py # Typer commands (search, overview, symbols, index, project ...)
|
|
160
|
+
├── config.py # YAML config manager
|
|
161
|
+
├── db.py # SQLite layer
|
|
162
|
+
├── indexer/
|
|
163
|
+
│ ├── builder.py
|
|
164
|
+
│ ├── discover.py
|
|
165
|
+
│ ├── store.py
|
|
166
|
+
│ └── parsers/python.py
|
|
167
|
+
└── query/engine.py
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Running Tests
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
pytest -q
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Roadmap Highlights (see TODO.md and PLAN.md)
|
|
177
|
+
|
|
178
|
+
- Cross-file relation improvements
|
|
179
|
+
- Better call graph queries (`callers`, `usages`, ...)
|
|
180
|
+
- Real Go / TypeScript parsers
|
|
181
|
+
- Semantic search + MCP server (for agents)
|
|
182
|
+
- More context-generation helpers
|
sampler_cli-0.2.0/PKG-INFO
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: sampler-cli
|
|
3
|
-
Version: 0.2.0
|
|
4
|
-
Summary: Token-efficient CLI for indexing and searching code symbols (Python-first, designed for minimal LLM/agent context size)
|
|
5
|
-
Author: Samuel Ignacio Carmona Rodriguez
|
|
6
|
-
License: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/sicr0/sampler-cli
|
|
8
|
-
Project-URL: Repository, https://github.com/sicr0/sampler-cli
|
|
9
|
-
Project-URL: Issues, https://github.com/sicr0/sampler-cli/issues
|
|
10
|
-
Classifier: Development Status :: 4 - Beta
|
|
11
|
-
Classifier: Intended Audience :: Developers
|
|
12
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
-
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
-
Classifier: Topic :: Software Development :: Code Generators
|
|
17
|
-
Requires-Python: >=3.11
|
|
18
|
-
Description-Content-Type: text/markdown
|
|
19
|
-
License-File: LICENSE
|
|
20
|
-
Requires-Dist: typer>=0.12.0
|
|
21
|
-
Requires-Dist: rich>=13.7.0
|
|
22
|
-
Requires-Dist: tree-sitter>=0.21.0
|
|
23
|
-
Requires-Dist: tree-sitter-python>=0.23.0
|
|
24
|
-
Requires-Dist: gitignore-parser>=0.1.11
|
|
25
|
-
Requires-Dist: pydantic>=2.6.0
|
|
26
|
-
Requires-Dist: pyyaml>=6.0.0
|
|
27
|
-
Provides-Extra: dev
|
|
28
|
-
Requires-Dist: pytest>=7.4.0; extra == "dev"
|
|
29
|
-
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
30
|
-
Requires-Dist: ruff>=0.5.0; extra == "dev"
|
|
31
|
-
Requires-Dist: mypy>=1.7.0; extra == "dev"
|
|
32
|
-
Provides-Extra: mcp
|
|
33
|
-
Requires-Dist: fastmcp>=0.1.0; extra == "mcp"
|
|
34
|
-
Provides-Extra: semantic
|
|
35
|
-
Requires-Dist: sentence-transformers>=2.2.0; extra == "semantic"
|
|
36
|
-
Dynamic: license-file
|
|
37
|
-
|
|
38
|
-
# Sampler
|
|
39
|
-
|
|
40
|
-
CLI indexer para navegar símbolos y relaciones en codebases multiproyecto.
|
|
41
|
-
|
|
42
|
-
Versión actual: 0.1.2
|
|
43
|
-
|
|
44
|
-
## Requisitos
|
|
45
|
-
|
|
46
|
-
- Python 3.11+
|
|
47
|
-
- `uv` (recomendado)
|
|
48
|
-
- Go (instalado para soporte parser Fase 1)
|
|
49
|
-
|
|
50
|
-
## Instalación de Go (macOS)
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
brew install go
|
|
54
|
-
go version
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## Instalación
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
pip install sampler-cli
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Para desarrollo (incluye tests, linters):
|
|
64
|
-
|
|
65
|
-
```bash
|
|
66
|
-
pip install -e '.[dev]'
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## Uso rápido
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
pip install sampler-cli
|
|
73
|
-
sampler init
|
|
74
|
-
sampler project add myproj /absolute/path --language python
|
|
75
|
-
sampler project list
|
|
76
|
-
sampler index myproj
|
|
77
|
-
sampler search add --project myproj
|
|
78
|
-
sampler overview /absolute/path/file.py
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
**Demo / LLM use (token-efficient by design):**
|
|
82
|
-
- Default outputs are compact single-line (no tables, short paths, no noise).
|
|
83
|
-
- Ideal for pasting into agents/LLMs with minimal context size.
|
|
84
|
-
- Example: `sampler search worker --project myproj` → `myproj:src/tasks.py:42 function process def process()`
|
|
85
|
-
|
|
86
|
-
## Estado actual
|
|
87
|
-
|
|
88
|
-
Implementado:
|
|
89
|
-
|
|
90
|
-
- Bootstrap inicial de Fase 0
|
|
91
|
-
- Configuración global con archivo `~/.sampler/config.yaml`
|
|
92
|
-
- CRUD de proyectos en config (`add`, `list`, `remove`)
|
|
93
|
-
- Esquema SQLite core + queries de index/search en `src/sampler/db.py`
|
|
94
|
-
- Discovery de archivos por lenguaje con soporte `.gitignore`
|
|
95
|
-
- Parser Python estable basado en AST
|
|
96
|
-
- Indexer real (hash incremental + persistencia)
|
|
97
|
-
- Query engine real (`search`, `overview`)
|
|
98
|
-
- CI básico con GitHub Actions (`pytest -q`)
|
|
99
|
-
- Tests: smoke, config, db, cli, discovery, python_parser, index_query
|
|
100
|
-
|
|
101
|
-
Nota de estabilidad:
|
|
102
|
-
|
|
103
|
-
- Se desactivó uso runtime de tree-sitter en parser Python por crash nativo (`BUS/SEGV`) en indexación real.
|
|
104
|
-
- Se mantiene estrategia AST para estabilidad en producción local.
|
|
105
|
-
|
|
106
|
-
Pendiente inmediato:
|
|
107
|
-
|
|
108
|
-
- Filtros y paginación en búsqueda
|
|
109
|
-
- Comandos `callers`, `usages`, `related`
|
|
110
|
-
- Parsers Go y TypeScript/JavaScript
|
|
111
|
-
|
|
112
|
-
## Estructura clave
|
|
113
|
-
|
|
114
|
-
```text
|
|
115
|
-
src/sampler/cli/main.py # comandos CLI
|
|
116
|
-
src/sampler/config.py # config global YAML
|
|
117
|
-
src/sampler/db.py # capa SQLite
|
|
118
|
-
src/sampler/indexer/builder.py # indexación de proyectos
|
|
119
|
-
src/sampler/indexer/store.py # persistencia de símbolos/relaciones
|
|
120
|
-
src/sampler/indexer/parsers/python.py # parser python estable
|
|
121
|
-
src/sampler/query/engine.py # search/overview
|
|
122
|
-
src/sampler/indexer/discover.py # discovery y filtros
|
|
123
|
-
tests/ # pruebas base
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
## Ejecutar pruebas
|
|
127
|
-
|
|
128
|
-
```bash
|
|
129
|
-
pytest -q
|
|
130
|
-
```
|
sampler_cli-0.2.0/README.md
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
# Sampler
|
|
2
|
-
|
|
3
|
-
CLI indexer para navegar símbolos y relaciones en codebases multiproyecto.
|
|
4
|
-
|
|
5
|
-
Versión actual: 0.1.2
|
|
6
|
-
|
|
7
|
-
## Requisitos
|
|
8
|
-
|
|
9
|
-
- Python 3.11+
|
|
10
|
-
- `uv` (recomendado)
|
|
11
|
-
- Go (instalado para soporte parser Fase 1)
|
|
12
|
-
|
|
13
|
-
## Instalación de Go (macOS)
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
brew install go
|
|
17
|
-
go version
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## Instalación
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
pip install sampler-cli
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
Para desarrollo (incluye tests, linters):
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
pip install -e '.[dev]'
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Uso rápido
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
pip install sampler-cli
|
|
36
|
-
sampler init
|
|
37
|
-
sampler project add myproj /absolute/path --language python
|
|
38
|
-
sampler project list
|
|
39
|
-
sampler index myproj
|
|
40
|
-
sampler search add --project myproj
|
|
41
|
-
sampler overview /absolute/path/file.py
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
**Demo / LLM use (token-efficient by design):**
|
|
45
|
-
- Default outputs are compact single-line (no tables, short paths, no noise).
|
|
46
|
-
- Ideal for pasting into agents/LLMs with minimal context size.
|
|
47
|
-
- Example: `sampler search worker --project myproj` → `myproj:src/tasks.py:42 function process def process()`
|
|
48
|
-
|
|
49
|
-
## Estado actual
|
|
50
|
-
|
|
51
|
-
Implementado:
|
|
52
|
-
|
|
53
|
-
- Bootstrap inicial de Fase 0
|
|
54
|
-
- Configuración global con archivo `~/.sampler/config.yaml`
|
|
55
|
-
- CRUD de proyectos en config (`add`, `list`, `remove`)
|
|
56
|
-
- Esquema SQLite core + queries de index/search en `src/sampler/db.py`
|
|
57
|
-
- Discovery de archivos por lenguaje con soporte `.gitignore`
|
|
58
|
-
- Parser Python estable basado en AST
|
|
59
|
-
- Indexer real (hash incremental + persistencia)
|
|
60
|
-
- Query engine real (`search`, `overview`)
|
|
61
|
-
- CI básico con GitHub Actions (`pytest -q`)
|
|
62
|
-
- Tests: smoke, config, db, cli, discovery, python_parser, index_query
|
|
63
|
-
|
|
64
|
-
Nota de estabilidad:
|
|
65
|
-
|
|
66
|
-
- Se desactivó uso runtime de tree-sitter en parser Python por crash nativo (`BUS/SEGV`) en indexación real.
|
|
67
|
-
- Se mantiene estrategia AST para estabilidad en producción local.
|
|
68
|
-
|
|
69
|
-
Pendiente inmediato:
|
|
70
|
-
|
|
71
|
-
- Filtros y paginación en búsqueda
|
|
72
|
-
- Comandos `callers`, `usages`, `related`
|
|
73
|
-
- Parsers Go y TypeScript/JavaScript
|
|
74
|
-
|
|
75
|
-
## Estructura clave
|
|
76
|
-
|
|
77
|
-
```text
|
|
78
|
-
src/sampler/cli/main.py # comandos CLI
|
|
79
|
-
src/sampler/config.py # config global YAML
|
|
80
|
-
src/sampler/db.py # capa SQLite
|
|
81
|
-
src/sampler/indexer/builder.py # indexación de proyectos
|
|
82
|
-
src/sampler/indexer/store.py # persistencia de símbolos/relaciones
|
|
83
|
-
src/sampler/indexer/parsers/python.py # parser python estable
|
|
84
|
-
src/sampler/query/engine.py # search/overview
|
|
85
|
-
src/sampler/indexer/discover.py # discovery y filtros
|
|
86
|
-
tests/ # pruebas base
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
## Ejecutar pruebas
|
|
90
|
-
|
|
91
|
-
```bash
|
|
92
|
-
pytest -q
|
|
93
|
-
```
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: sampler-cli
|
|
3
|
-
Version: 0.2.0
|
|
4
|
-
Summary: Token-efficient CLI for indexing and searching code symbols (Python-first, designed for minimal LLM/agent context size)
|
|
5
|
-
Author: Samuel Ignacio Carmona Rodriguez
|
|
6
|
-
License: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/sicr0/sampler-cli
|
|
8
|
-
Project-URL: Repository, https://github.com/sicr0/sampler-cli
|
|
9
|
-
Project-URL: Issues, https://github.com/sicr0/sampler-cli/issues
|
|
10
|
-
Classifier: Development Status :: 4 - Beta
|
|
11
|
-
Classifier: Intended Audience :: Developers
|
|
12
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
-
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
-
Classifier: Topic :: Software Development :: Code Generators
|
|
17
|
-
Requires-Python: >=3.11
|
|
18
|
-
Description-Content-Type: text/markdown
|
|
19
|
-
License-File: LICENSE
|
|
20
|
-
Requires-Dist: typer>=0.12.0
|
|
21
|
-
Requires-Dist: rich>=13.7.0
|
|
22
|
-
Requires-Dist: tree-sitter>=0.21.0
|
|
23
|
-
Requires-Dist: tree-sitter-python>=0.23.0
|
|
24
|
-
Requires-Dist: gitignore-parser>=0.1.11
|
|
25
|
-
Requires-Dist: pydantic>=2.6.0
|
|
26
|
-
Requires-Dist: pyyaml>=6.0.0
|
|
27
|
-
Provides-Extra: dev
|
|
28
|
-
Requires-Dist: pytest>=7.4.0; extra == "dev"
|
|
29
|
-
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
30
|
-
Requires-Dist: ruff>=0.5.0; extra == "dev"
|
|
31
|
-
Requires-Dist: mypy>=1.7.0; extra == "dev"
|
|
32
|
-
Provides-Extra: mcp
|
|
33
|
-
Requires-Dist: fastmcp>=0.1.0; extra == "mcp"
|
|
34
|
-
Provides-Extra: semantic
|
|
35
|
-
Requires-Dist: sentence-transformers>=2.2.0; extra == "semantic"
|
|
36
|
-
Dynamic: license-file
|
|
37
|
-
|
|
38
|
-
# Sampler
|
|
39
|
-
|
|
40
|
-
CLI indexer para navegar símbolos y relaciones en codebases multiproyecto.
|
|
41
|
-
|
|
42
|
-
Versión actual: 0.1.2
|
|
43
|
-
|
|
44
|
-
## Requisitos
|
|
45
|
-
|
|
46
|
-
- Python 3.11+
|
|
47
|
-
- `uv` (recomendado)
|
|
48
|
-
- Go (instalado para soporte parser Fase 1)
|
|
49
|
-
|
|
50
|
-
## Instalación de Go (macOS)
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
brew install go
|
|
54
|
-
go version
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## Instalación
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
pip install sampler-cli
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Para desarrollo (incluye tests, linters):
|
|
64
|
-
|
|
65
|
-
```bash
|
|
66
|
-
pip install -e '.[dev]'
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## Uso rápido
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
pip install sampler-cli
|
|
73
|
-
sampler init
|
|
74
|
-
sampler project add myproj /absolute/path --language python
|
|
75
|
-
sampler project list
|
|
76
|
-
sampler index myproj
|
|
77
|
-
sampler search add --project myproj
|
|
78
|
-
sampler overview /absolute/path/file.py
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
**Demo / LLM use (token-efficient by design):**
|
|
82
|
-
- Default outputs are compact single-line (no tables, short paths, no noise).
|
|
83
|
-
- Ideal for pasting into agents/LLMs with minimal context size.
|
|
84
|
-
- Example: `sampler search worker --project myproj` → `myproj:src/tasks.py:42 function process def process()`
|
|
85
|
-
|
|
86
|
-
## Estado actual
|
|
87
|
-
|
|
88
|
-
Implementado:
|
|
89
|
-
|
|
90
|
-
- Bootstrap inicial de Fase 0
|
|
91
|
-
- Configuración global con archivo `~/.sampler/config.yaml`
|
|
92
|
-
- CRUD de proyectos en config (`add`, `list`, `remove`)
|
|
93
|
-
- Esquema SQLite core + queries de index/search en `src/sampler/db.py`
|
|
94
|
-
- Discovery de archivos por lenguaje con soporte `.gitignore`
|
|
95
|
-
- Parser Python estable basado en AST
|
|
96
|
-
- Indexer real (hash incremental + persistencia)
|
|
97
|
-
- Query engine real (`search`, `overview`)
|
|
98
|
-
- CI básico con GitHub Actions (`pytest -q`)
|
|
99
|
-
- Tests: smoke, config, db, cli, discovery, python_parser, index_query
|
|
100
|
-
|
|
101
|
-
Nota de estabilidad:
|
|
102
|
-
|
|
103
|
-
- Se desactivó uso runtime de tree-sitter en parser Python por crash nativo (`BUS/SEGV`) en indexación real.
|
|
104
|
-
- Se mantiene estrategia AST para estabilidad en producción local.
|
|
105
|
-
|
|
106
|
-
Pendiente inmediato:
|
|
107
|
-
|
|
108
|
-
- Filtros y paginación en búsqueda
|
|
109
|
-
- Comandos `callers`, `usages`, `related`
|
|
110
|
-
- Parsers Go y TypeScript/JavaScript
|
|
111
|
-
|
|
112
|
-
## Estructura clave
|
|
113
|
-
|
|
114
|
-
```text
|
|
115
|
-
src/sampler/cli/main.py # comandos CLI
|
|
116
|
-
src/sampler/config.py # config global YAML
|
|
117
|
-
src/sampler/db.py # capa SQLite
|
|
118
|
-
src/sampler/indexer/builder.py # indexación de proyectos
|
|
119
|
-
src/sampler/indexer/store.py # persistencia de símbolos/relaciones
|
|
120
|
-
src/sampler/indexer/parsers/python.py # parser python estable
|
|
121
|
-
src/sampler/query/engine.py # search/overview
|
|
122
|
-
src/sampler/indexer/discover.py # discovery y filtros
|
|
123
|
-
tests/ # pruebas base
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
## Ejecutar pruebas
|
|
127
|
-
|
|
128
|
-
```bash
|
|
129
|
-
pytest -q
|
|
130
|
-
```
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|