ast-bro 2.2.0__py3-none-any.whl
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.
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ast-bro
|
|
3
|
+
Version: 2.2.0
|
|
4
|
+
Summary: Fast, AST-based code-navigation: shape, public API, deps & call graphs, hybrid semantic search, structural rewrite. MCP server included.
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/aeroxy/ast-bro
|
|
7
|
+
Project-URL: Repository, https://github.com/aeroxy/ast-bro
|
|
8
|
+
Project-URL: Documentation, https://github.com/aeroxy/ast-bro#readme
|
|
9
|
+
Keywords: ast,tree-sitter,mcp,refactoring,code-search
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: MacOS
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Programming Language :: Rust
|
|
15
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
16
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
17
|
+
Requires-Python: >=3.8
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
Requires-Dist: httpx>=0.24.0
|
|
20
|
+
|
|
21
|
+
# ast-bro
|
|
22
|
+
|
|
23
|
+
[](https://pypi.org/project/ast-bro/)
|
|
24
|
+
[](https://github.com/aeroxy/ast-bro/blob/main/LICENSE)
|
|
25
|
+
|
|
26
|
+
PyPI installer for [ast-bro](https://github.com/aeroxy/ast-bro) — a fast, AST-based code-navigation toolkit for source files (shape, public API, dep & call graphs, hybrid semantic search, structural rewrite, MCP server). Downloads the pre-built Rust binary on first run.
|
|
27
|
+
|
|
28
|
+
> **Formerly `ast-outline-cli`.** Same project under a new name (the `ast-outline` name became overloaded after the tool grew beyond outlining). The `ast-outline` command is still installed as a thin proxy that forwards to `ast-bro`, so existing scripts keep working.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install ast-bro
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
This installs three commands, all forwarding to the same binary:
|
|
37
|
+
|
|
38
|
+
- `ast-bro` — canonical name
|
|
39
|
+
- `sb` — short alias (same tool, fewer keystrokes)
|
|
40
|
+
- `ast-outline` — backward-compat shim
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Map the structure of a file (signatures + line ranges, no bodies)
|
|
46
|
+
ast-bro map src/player.rs
|
|
47
|
+
|
|
48
|
+
# Show the exact source of a specific method
|
|
49
|
+
ast-bro show Player.cs TakeDamage
|
|
50
|
+
|
|
51
|
+
# Compact digest of a whole module
|
|
52
|
+
ast-bro digest src/services/
|
|
53
|
+
|
|
54
|
+
# True public API (resolves pub use / __all__ re-exports)
|
|
55
|
+
ast-bro surface .
|
|
56
|
+
|
|
57
|
+
# Find all implementations of a type
|
|
58
|
+
ast-bro implements IDamageable src/
|
|
59
|
+
|
|
60
|
+
# Dependency graph
|
|
61
|
+
ast-bro deps src/auth.rs --depth 2
|
|
62
|
+
ast-bro reverse-deps src/auth.rs
|
|
63
|
+
ast-bro cycles
|
|
64
|
+
|
|
65
|
+
# Call graph (AST-accurate)
|
|
66
|
+
ast-bro callers TakeDamage
|
|
67
|
+
ast-bro callees Player.TakeDamage
|
|
68
|
+
|
|
69
|
+
# Hybrid BM25 + dense semantic search
|
|
70
|
+
ast-bro search "how does login work"
|
|
71
|
+
|
|
72
|
+
# Find semantically similar code
|
|
73
|
+
ast-bro find-related src/auth/login.rs:42
|
|
74
|
+
|
|
75
|
+
# AST-aware structural search and rewrite (with metavariables)
|
|
76
|
+
ast-bro run -p '$FUNC($$$)' -l rust
|
|
77
|
+
ast-bro run -p 'foo($A)' -r 'bar($A)' --write # apply to disk
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
On first run, the CLI downloads the pre-built binary for your platform from [GitHub releases](https://github.com/aeroxy/ast-bro/releases) and caches it locally.
|
|
81
|
+
|
|
82
|
+
| Platform | Cache directory |
|
|
83
|
+
|---|---|
|
|
84
|
+
| macOS | `~/Library/Caches/ast-bro/` |
|
|
85
|
+
| Linux | `~/.cache/ast-bro/` |
|
|
86
|
+
|
|
87
|
+
## Supported Platforms
|
|
88
|
+
|
|
89
|
+
| Platform | Status |
|
|
90
|
+
|---|---|
|
|
91
|
+
| macOS ARM64 | Pre-built binary available |
|
|
92
|
+
| Other platforms | Build from source (see below) |
|
|
93
|
+
|
|
94
|
+
For unsupported platforms, build from source:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
cargo install ast-bro
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## What is ast-bro?
|
|
101
|
+
|
|
102
|
+
[ast-bro](https://github.com/aeroxy/ast-bro) is a fast, AST-based code-navigation toolkit built for LLM coding agents and humans. It uses [tree-sitter](https://github.com/tree-sitter/tree-sitter) via [ast-grep](https://github.com/ast-grep/ast-grep) to parse source files and provide:
|
|
103
|
+
|
|
104
|
+
- **File shape** — `map` / `digest` / `show` for signatures with line ranges (95% token savings vs reading full files)
|
|
105
|
+
- **True public API** — `surface` resolves re-export graphs across Rust, Python, TypeScript, and more
|
|
106
|
+
- **Dependency graph** — `deps` / `reverse-deps` / `cycles` / `graph` for import analysis
|
|
107
|
+
- **Call graph** — `callers` / `callees` with AST accuracy across 14 languages
|
|
108
|
+
- **Semantic search** — hybrid BM25 + dense embeddings via `search` and `find-related`
|
|
109
|
+
- **Structural rewrite** — `run` for AST-aware pattern matching with metavariables (find + replace)
|
|
110
|
+
- **MCP server** — every command exposed as an MCP tool for LLM agents
|
|
111
|
+
|
|
112
|
+
Supports Rust, Python, TypeScript, JavaScript, Java, C#, C++, Kotlin, Scala, Go, PHP, Ruby, SQL, and Markdown.
|
|
113
|
+
|
|
114
|
+
## Links
|
|
115
|
+
|
|
116
|
+
- [ast-bro source code](https://github.com/aeroxy/ast-bro)
|
|
117
|
+
- [npm package](https://www.npmjs.com/package/@ast-bro/cli) (Node.js installer)
|
|
118
|
+
- [crates.io](https://crates.io/crates/ast-bro) (Rust library)
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
[MIT](https://github.com/aeroxy/ast-bro/blob/main/LICENSE)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
ast_bro_cli/__init__.py,sha256=ffYTlR077W_LcImxrdtG4GUEQrJDvLle4ONWhDW-mWo,3570
|
|
2
|
+
ast_bro_cli/__main__.py,sha256=Kf7RCGT4hFbSZkrR2sPmJ9kdfybbh2o-TSvr1yQeBCA,37
|
|
3
|
+
ast_bro-2.2.0.dist-info/METADATA,sha256=sFIAptpOPQF0ol4HUIYIcpKtAhqPvbmK4CGjpfk2NI4,4690
|
|
4
|
+
ast_bro-2.2.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
5
|
+
ast_bro-2.2.0.dist-info/entry_points.txt,sha256=HGLmo1XXXz8Z85Oq76PvkcMA2vUgW9eO8oNGlV9KMYc,98
|
|
6
|
+
ast_bro-2.2.0.dist-info/top_level.txt,sha256=4ROcmqhI_CXEmHACEZ-tptfjAsXXV6mpoBJjtmYfjdc,12
|
|
7
|
+
ast_bro-2.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ast_bro_cli
|
ast_bro_cli/__init__.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""ast-bro CLI installer — downloads the Rust binary on first run."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import stat
|
|
6
|
+
import platform
|
|
7
|
+
import subprocess
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
import httpx
|
|
11
|
+
|
|
12
|
+
VERSION = "2.2.0"
|
|
13
|
+
GITHUB_REPO = "aeroxy/ast-bro"
|
|
14
|
+
BINARY_NAME = "ast-bro"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_cache_dir() -> Path:
|
|
18
|
+
if sys.platform == "darwin":
|
|
19
|
+
return Path.home() / "Library" / "Caches" / "ast-bro"
|
|
20
|
+
elif sys.platform == "linux":
|
|
21
|
+
return Path.home() / ".cache" / "ast-bro"
|
|
22
|
+
else:
|
|
23
|
+
return Path.home() / ".cache" / "ast-bro"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def get_platform() -> tuple[str, str]:
|
|
27
|
+
"""Return (os, arch) for download URL."""
|
|
28
|
+
system = platform.system().lower()
|
|
29
|
+
machine = platform.machine().lower()
|
|
30
|
+
|
|
31
|
+
os_map = {"darwin": "macos", "linux": "linux", "windows": "windows"}
|
|
32
|
+
arch_map = {"arm64": "arm64", "aarch64": "arm64", "x86_64": "x86_64", "amd64": "x86_64"}
|
|
33
|
+
|
|
34
|
+
os_name = os_map.get(system)
|
|
35
|
+
arch = arch_map.get(machine)
|
|
36
|
+
|
|
37
|
+
if not os_name or not arch:
|
|
38
|
+
raise RuntimeError(
|
|
39
|
+
f"No pre-built binary for {system}/{machine}. "
|
|
40
|
+
f"Build from source: cargo install ast-bro"
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# Check if pre-built binary exists (only macos-arm64 for now)
|
|
44
|
+
available = {("macos", "arm64")}
|
|
45
|
+
if (os_name, arch) not in available:
|
|
46
|
+
raise RuntimeError(
|
|
47
|
+
f"No pre-built binary for {os_name}-{arch} yet (available: macos-arm64). "
|
|
48
|
+
f"Build from source: cargo install ast-bro"
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
return os_name, arch
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def download_binary() -> Path:
|
|
55
|
+
"""Download the ast-bro binary to cache dir."""
|
|
56
|
+
cache_dir = get_cache_dir()
|
|
57
|
+
cache_dir.mkdir(parents=True, exist_ok=True)
|
|
58
|
+
|
|
59
|
+
os_name, arch = get_platform()
|
|
60
|
+
# All platform release artifacts are `.zip` (same archive Homebrew pulls).
|
|
61
|
+
# If we ever ship a Linux `.tar.gz` build, branch here on os_name.
|
|
62
|
+
ext = ".zip"
|
|
63
|
+
binary_ext = ".exe" if os_name == "windows" else ""
|
|
64
|
+
binary_path = cache_dir / f"{BINARY_NAME}{binary_ext}"
|
|
65
|
+
|
|
66
|
+
# Check if already downloaded
|
|
67
|
+
if binary_path.exists():
|
|
68
|
+
return binary_path
|
|
69
|
+
|
|
70
|
+
url = f"https://github.com/{GITHUB_REPO}/releases/download/{VERSION}/{BINARY_NAME}-{os_name}-{arch}{ext}"
|
|
71
|
+
print(f"Downloading ast-bro {VERSION} for {os_name}-{arch}...")
|
|
72
|
+
print(f" {url}")
|
|
73
|
+
|
|
74
|
+
archive_path = cache_dir / f"archive{ext}"
|
|
75
|
+
|
|
76
|
+
with httpx.Client(follow_redirects=True) as client:
|
|
77
|
+
resp = client.get(url)
|
|
78
|
+
resp.raise_for_status()
|
|
79
|
+
archive_path.write_bytes(resp.content)
|
|
80
|
+
|
|
81
|
+
# Extract
|
|
82
|
+
import tarfile
|
|
83
|
+
import zipfile
|
|
84
|
+
|
|
85
|
+
if ext == ".tar.gz":
|
|
86
|
+
with tarfile.open(archive_path, "r:gz") as tar:
|
|
87
|
+
tar.extractall(path=cache_dir)
|
|
88
|
+
else:
|
|
89
|
+
with zipfile.ZipFile(archive_path) as zf:
|
|
90
|
+
zf.extractall(path=cache_dir)
|
|
91
|
+
|
|
92
|
+
archive_path.unlink()
|
|
93
|
+
|
|
94
|
+
# Make executable
|
|
95
|
+
if sys.platform != "windows":
|
|
96
|
+
binary_path.chmod(binary_path.stat().st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)
|
|
97
|
+
|
|
98
|
+
print(f"Installed ast-bro to {binary_path}")
|
|
99
|
+
return binary_path
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def get_binary_path() -> Path:
|
|
103
|
+
"""Get path to the ast-bro binary, downloading if needed."""
|
|
104
|
+
cache_dir = get_cache_dir()
|
|
105
|
+
os_name, _ = get_platform()
|
|
106
|
+
ext = ".exe" if os_name == "windows" else ""
|
|
107
|
+
binary_path = cache_dir / f"{BINARY_NAME}{ext}"
|
|
108
|
+
|
|
109
|
+
if not binary_path.exists():
|
|
110
|
+
return download_binary()
|
|
111
|
+
return binary_path
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def main():
|
|
115
|
+
"""CLI entry point — forwards to the Rust binary."""
|
|
116
|
+
binary = get_binary_path()
|
|
117
|
+
args = sys.argv[1:]
|
|
118
|
+
result = subprocess.run([str(binary)] + args, cwd=os.getcwd())
|
|
119
|
+
sys.exit(result.returncode)
|
ast_bro_cli/__main__.py
ADDED