@xberg-io/opencode-tree-sitter-language-pack 0.1.0

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,145 @@
1
+ import { spawn } from "node:child_process";
2
+ import { tool } from "@opencode-ai/plugin";
3
+
4
+ const schema = tool.schema;
5
+
6
+ const parseFormat = schema.enum(["sexp", "json"]).default("sexp").describe("Parse output format.");
7
+
8
+ function hasValue(value) {
9
+ return value !== undefined && value !== null && value !== "";
10
+ }
11
+
12
+ function pushOption(args, name, value) {
13
+ if (hasValue(value)) {
14
+ args.push(name, String(value));
15
+ }
16
+ }
17
+
18
+ function pushFlag(args, name, enabled) {
19
+ if (enabled) {
20
+ args.push(name);
21
+ }
22
+ }
23
+
24
+ function runCli(args, context) {
25
+ const directory = context?.directory ?? context?.worktree ?? process.cwd();
26
+
27
+ return new Promise((resolve, reject) => {
28
+ const child = spawn("ts-pack", args, {
29
+ cwd: directory,
30
+ env: process.env,
31
+ signal: context?.abort,
32
+ stdio: ["ignore", "pipe", "pipe"],
33
+ });
34
+
35
+ const stdout = [];
36
+ const stderr = [];
37
+
38
+ child.stdout.on("data", (chunk) => stdout.push(chunk));
39
+ child.stderr.on("data", (chunk) => stderr.push(chunk));
40
+ child.on("error", (error) => {
41
+ if (error.code === "ENOENT") {
42
+ resolve({
43
+ title: "ts-pack CLI not found",
44
+ output:
45
+ "Install the ts-pack CLI with `brew install xberg-io/tap/ts-pack`, or run it via `npx @xberg-io/ts-pack-cli` (the CLI proxy's bin is `ts-pack`).",
46
+ metadata: { exitCode: 127, command: "ts-pack", subcommand: args[0] },
47
+ });
48
+ return;
49
+ }
50
+ reject(error);
51
+ });
52
+ child.on("close", (exitCode, signal) => {
53
+ const stdoutText = Buffer.concat(stdout).toString("utf8").trim();
54
+ const stderrText = Buffer.concat(stderr).toString("utf8").trim();
55
+ const output = [stdoutText, stderrText && `stderr:\n${stderrText}`]
56
+ .filter(Boolean)
57
+ .join("\n\n");
58
+
59
+ resolve({
60
+ title: exitCode === 0 ? `ts-pack ${args[0]}` : `ts-pack ${args[0]} failed`,
61
+ output: output || "(no output)",
62
+ metadata: {
63
+ exitCode,
64
+ signal,
65
+ command: "ts-pack",
66
+ subcommand: args[0],
67
+ },
68
+ });
69
+ });
70
+ });
71
+ }
72
+
73
+ export const TreeSitterLanguagePackPlugin = async () => ({
74
+ tool: {
75
+ tspack_parse: tool({
76
+ description: "Parse a source file into a tree-sitter syntax tree with the ts-pack CLI.",
77
+ args: {
78
+ file: schema.string().min(1).describe("Path to the source file."),
79
+ language: schema
80
+ .string()
81
+ .min(1)
82
+ .optional()
83
+ .describe("Language override (auto-detected from extension if omitted)."),
84
+ format: parseFormat,
85
+ },
86
+ async execute(args, context) {
87
+ const cliArgs = ["parse", args.file, "--format", args.format];
88
+ pushOption(cliArgs, "--language", args.language);
89
+ return runCli(cliArgs, context);
90
+ },
91
+ }),
92
+ tspack_process: tool({
93
+ description:
94
+ "Extract code intelligence (structure, imports, exports, symbols, docstrings, comments, diagnostics) from a source file with the ts-pack CLI. Output is JSON.",
95
+ args: {
96
+ file: schema.string().min(1).describe("Path to the source file."),
97
+ language: schema
98
+ .string()
99
+ .min(1)
100
+ .optional()
101
+ .describe("Language override (auto-detected from extension if omitted)."),
102
+ all: schema.boolean().optional().describe("Enable all analysis features."),
103
+ structure: schema.boolean().optional().describe("Extract structure (functions, classes)."),
104
+ imports: schema.boolean().optional().describe("Extract imports."),
105
+ exports: schema.boolean().optional().describe("Extract exports."),
106
+ comments: schema.boolean().optional().describe("Extract comments."),
107
+ symbols: schema.boolean().optional().describe("Extract symbols."),
108
+ docstrings: schema.boolean().optional().describe("Extract docstrings."),
109
+ diagnostics: schema.boolean().optional().describe("Include syntax diagnostics."),
110
+ chunk_size: schema
111
+ .number()
112
+ .int()
113
+ .positive()
114
+ .optional()
115
+ .describe("Maximum chunk size in bytes (enables syntax-aware chunking)."),
116
+ },
117
+ async execute(args, context) {
118
+ const cliArgs = ["process", args.file];
119
+ pushOption(cliArgs, "--language", args.language);
120
+ pushFlag(cliArgs, "--all", args.all);
121
+ pushFlag(cliArgs, "--structure", args.structure);
122
+ pushFlag(cliArgs, "--imports", args.imports);
123
+ pushFlag(cliArgs, "--exports", args.exports);
124
+ pushFlag(cliArgs, "--comments", args.comments);
125
+ pushFlag(cliArgs, "--symbols", args.symbols);
126
+ pushFlag(cliArgs, "--docstrings", args.docstrings);
127
+ pushFlag(cliArgs, "--diagnostics", args.diagnostics);
128
+ pushOption(cliArgs, "--chunk-size", args.chunk_size);
129
+ return runCli(cliArgs, context);
130
+ },
131
+ }),
132
+ tspack_info: tool({
133
+ description:
134
+ "Show details about a language (whether it is known and cached) with the ts-pack CLI. Use to confirm a language is supported before parsing.",
135
+ args: {
136
+ language: schema.string().min(1).describe("Language name (e.g. python, rust, typescript)."),
137
+ },
138
+ async execute(args, context) {
139
+ return runCli(["info", args.language], context);
140
+ },
141
+ }),
142
+ },
143
+ });
144
+
145
+ export default TreeSitterLanguagePackPlugin;
package/README.md ADDED
@@ -0,0 +1,191 @@
1
+ # tree-sitter-language-pack
2
+
3
+ Parse and extract code intelligence from 300+ programming languages with tree-sitter — structure, imports, symbols, and syntax-aware chunking — using the local `ts-pack` CLI in your agent.
4
+
5
+ <!-- TODO: screenshot -->
6
+
7
+ ## Install
8
+
9
+ ### From the marketplace (recommended)
10
+
11
+ Pending review for official Claude marketplace.
12
+
13
+ Self-host:
14
+
15
+ ```text
16
+ /plugin marketplace add xberg-io/plugins
17
+ /plugin install tree-sitter-language-pack@xberg
18
+ ```
19
+
20
+ ### Binary requirement
21
+
22
+ The bundled MCP launcher (`scripts/mcp-launch.sh`) resolves a `ts-pack` binary
23
+ automatically on first run: it reuses one already on `PATH`, then tries
24
+ `npx`/`uvx`, then Homebrew, then a prebuilt download from the tool's latest
25
+ GitHub release. No manual install is required to use the MCP server.
26
+
27
+ To install the `ts-pack` CLI yourself:
28
+
29
+ ```bash
30
+ brew install xberg-io/tap/ts-pack
31
+ # or run it without a persistent install (the CLI proxy package self-installs the binary):
32
+ npx @xberg-io/ts-pack-cli --help
33
+ uvx --from ts-pack-cli ts-pack --help
34
+ # or download a prebuilt binary from the latest GitHub release:
35
+ # https://github.com/xberg-io/tree-sitter-language-pack/releases/latest
36
+ # or install from crates.io (binary is installed as `ts-pack`):
37
+ cargo install ts-pack-cli
38
+ ```
39
+
40
+ Parser libraries download on demand the first time a language is used. For
41
+ offline or CI runs, prefetch them:
42
+
43
+ ```bash
44
+ ts-pack download --all # every language
45
+ ts-pack download python rust # specific languages
46
+ ```
47
+
48
+ ### SDKs (optional)
49
+
50
+ ```bash
51
+ pip install tree-sitter-language-pack # Python
52
+ npm install @xberg-io/tree-sitter-language-pack # Node.js / TypeScript
53
+ ```
54
+
55
+ Rust, Ruby, Go, Java, C#, PHP, Elixir, Dart, Kotlin (Android), Swift, Zig, and WebAssembly bindings are also published.
56
+
57
+ ## Skills shipped
58
+
59
+ | Skill | Trigger |
60
+ |-------|---------|
61
+ | **tree-sitter-language-pack** | Parse and extract code intelligence from 306 languages. Use when writing code that parses source, extracts structure/imports/exports/symbols/docstrings/comments, detects a language, runs diagnostics, or chunks code for LLMs — in Rust, Python, Node.js/TypeScript, or the ts-pack CLI. |
62
+ | **parsing-source** | Use when the user wants a tree-sitter syntax tree for a source file — an s-expression dump or JSON tree. |
63
+ | **extracting-code-structure** | Use when the user wants structured code metadata — functions, classes, imports, exports, symbols, docstrings, comments, or syntax diagnostics. |
64
+ | **chunking-for-llms** | Use when splitting source code into chunks for an LLM context window without breaking syntax mid-construct. |
65
+ | **detecting-languages** | Use when the user wants to know which programming language a file or snippet is — by path, extension, or content. |
66
+ | **managing-parsers** | Use when managing the parser cache — prefetch for offline/CI, list downloaded languages, inspect a language, find the cache dir, or clean it. |
67
+ | **using-the-mcp-server** | Use when parsing, processing, or detecting languages through the MCP server's `parse`/`process`/`detect` tools instead of the CLI. Covers the tool surface and the auto-installing launcher. |
68
+
69
+ ## MCP server
70
+
71
+ The plugin auto-registers an MCP server named `tree-sitter-language-pack`,
72
+ launched via `scripts/mcp-launch.sh` (which execs `ts-pack mcp`). It exposes
73
+ eight tools for parsing, analysis, and cache management; resources for language
74
+ discovery; a code-analysis prompt; and language-name completions.
75
+
76
+ **Tools** (8):
77
+
78
+ - **parse** — syntax tree (s-expression or JSON), auto-detecting language from path or explicit.
79
+ - **process** — code intelligence: structure, imports, exports, symbols, docstrings, comments, diagnostics, chunks. Use `all` flag for all features.
80
+ - **detect_language** — identify language by path or content (the tool takes `path` and `content` only).
81
+ - **list_languages** — available, downloaded, or manifest languages; filter by name.
82
+ - **info** — show language availability and cache status.
83
+ - **download** — prefetch parsers: specific languages, groups, all, or fresh updates.
84
+ - **cache_dir** — return the cache directory path.
85
+ - **clean_cache** — remove all cached parsers.
86
+
87
+ **Resources**:
88
+
89
+ - `ts-pack://languages` — catalog of all known languages.
90
+ - `ts-pack://languages/downloaded` — currently cached languages.
91
+ - `ts-pack://language/{name}` — per-language metadata template.
92
+
93
+ **Prompt**: `analyze-code` (args: `language`, optional `focus`).
94
+
95
+ **Completions**: language-name autocomplete.
96
+
97
+ The launcher auto-installs a binary on first run (override with
98
+ `TS_PACK_LAUNCHER=auto|npx|uvx|brew|download`). The `mcp` subcommand ships in a
99
+ recent release of the tool; an older binary on `PATH` may need an upgrade to
100
+ expose it. See the **using-the-mcp-server** skill for details.
101
+
102
+ ## CLI
103
+
104
+ `ts-pack` subcommands:
105
+
106
+ | Command | Purpose |
107
+ |---------|---------|
108
+ | `parse <file>` | Parse into a syntax tree (`--format sexp\|json`). |
109
+ | `process <file>` | Code-intelligence pipeline → JSON (feature flags below). |
110
+ | `list` | List languages (`--downloaded`, `--manifest`, `--filter`). |
111
+ | `info <language>` | Show whether a language is known and cached. |
112
+ | `download [langs...]` | Download parsers (`--all`, `--groups`, `--fresh`). |
113
+ | `clean` | Remove all cached parsers (`--force`). |
114
+ | `cache-dir` | Print the cache directory. |
115
+ | `init` | Write a `language-pack.toml` config. |
116
+ | `completions <shell>` | Generate shell completions. |
117
+ | `mcp` | Start the MCP server (`--transport stdio`). |
118
+
119
+ `process` flags: `--structure`, `--imports`, `--exports`, `--comments`,
120
+ `--symbols`, `--docstrings`, `--diagnostics`, `--all`, `--chunk-size <bytes>`,
121
+ `--language <name>`. With no feature flags it defaults to
122
+ `--structure --imports --exports`.
123
+
124
+ There is no `detect` or `validate` subcommand: language detection is
125
+ implicit in `parse`/`process` (from the file extension), and diagnostics
126
+ come from `process --diagnostics`. Content-based detection is available in
127
+ the SDK (`detect_language_from_content`).
128
+
129
+ ## SDK
130
+
131
+ ```python
132
+ from tree_sitter_language_pack import process, ProcessConfig
133
+
134
+ result = process(source_code, ProcessConfig("python", symbols=True, docstrings=True))
135
+ for item in result.structure: # ProcessResult is an object, not a dict
136
+ print(item.kind, item.name, item.span.start_line)
137
+ ```
138
+
139
+ ```typescript
140
+ import { process, detectLanguageFromPath } from "@xberg-io/tree-sitter-language-pack";
141
+
142
+ const lang = detectLanguageFromPath("src/app.ts");
143
+ const result = process(source, { language: lang ?? "typescript", structure: true, imports: true });
144
+ ```
145
+
146
+ ## Configuration
147
+
148
+ `ts-pack init` writes a `language-pack.toml` pinning a cache directory and a
149
+ language set:
150
+
151
+ ```toml
152
+ cache_dir = ".ts-pack-cache"
153
+ languages = ["python", "rust", "typescript"]
154
+ ```
155
+
156
+ Commit it to pin the parser set across a team or CI. The cache location can
157
+ also be inspected with `ts-pack cache-dir`.
158
+
159
+ ## Examples
160
+
161
+ Parse a file into a syntax tree:
162
+
163
+ ```text
164
+ ts-pack parse src/main.rs
165
+ ```
166
+
167
+ Extract structure and imports as JSON:
168
+
169
+ ```text
170
+ ts-pack process src/app.ts --structure --imports
171
+ ```
172
+
173
+ Chunk a large file for an LLM:
174
+
175
+ ```text
176
+ ts-pack process big_module.py --chunk-size 2000
177
+ ```
178
+
179
+ ## Versioning
180
+
181
+ The plugin version tracks the marketplace `VERSION` file. See [CHANGELOG.md](../../CHANGELOG.md) for release notes.
182
+
183
+ ## License
184
+
185
+ MIT. The upstream [tree-sitter-language-pack](https://github.com/xberg-io/tree-sitter-language-pack) library is also MIT-licensed.
186
+
187
+ ## See also
188
+
189
+ - **Marketplace**: [xberg-io/plugins](https://github.com/xberg-io/plugins)
190
+ - **Upstream**: [xberg-io/tree-sitter-language-pack](https://github.com/xberg-io/tree-sitter-language-pack)
191
+ - **Sibling plugins**: [xberg](../xberg/README.md), [crawlberg](../crawlberg/README.md)
@@ -0,0 +1,4 @@
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M8 12.6666H13.3333" stroke="#DA2AE0" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
3
+ <path d="M2.6665 11.3334L6.6665 7.33337L2.6665 3.33337" stroke="#DA2AE0" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
@@ -0,0 +1,26 @@
1
+ <svg width="800" height="800" viewBox="0 0 800 800" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <circle cx="400" cy="400" r="313.839" fill="#58FBDA" stroke="#2E2D36" stroke-width="7.67819"/>
3
+ <path d="M469.155 481.996L497.619 509.815L517.95 513.534L529.157 523.7" stroke="#2E2D36" stroke-width="7.67819" stroke-linecap="round"/>
4
+ <path d="M428.146 495.931V565.751L454.576 592.876V615.587" stroke="#2E2D36" stroke-width="7.67819" stroke-linecap="round"/>
5
+ <path d="M333.878 482.343L310.522 509.468L289.15 512.543L271.199 525.733" stroke="#2E2D36" stroke-width="7.67819" stroke-linecap="round"/>
6
+ <path d="M404.521 155.839C498.389 155.839 574.411 231.075 574.411 323.792C574.411 416.509 498.389 491.744 404.521 491.744C310.653 491.744 234.631 416.509 234.631 323.792C234.631 231.075 310.653 155.839 404.521 155.839Z" fill="#79FFE6" stroke="#2E2D36" stroke-width="7.67819"/>
7
+ <path d="M401.021 218.481C450.893 218.481 491.275 258.538 491.275 307.892C491.275 357.246 450.893 397.303 401.021 397.303C351.149 397.303 310.767 357.246 310.767 307.892C310.767 258.538 351.149 218.481 401.021 218.481Z" fill="white" stroke="#2E2D36" stroke-width="6.14255"/>
8
+ <circle cx="231.379" cy="476.492" r="14.8269" fill="white" stroke="#2E2D36" stroke-width="4.60691"/>
9
+ <circle cx="256.471" cy="535.8" r="14.8269" fill="white" stroke="#2E2D36" stroke-width="4.60691"/>
10
+ <circle cx="300.109" cy="582.413" r="14.8269" fill="white" stroke="#2E2D36" stroke-width="4.60691"/>
11
+ <circle cx="401.071" cy="643.307" r="14.8269" fill="white" stroke="#2E2D36" stroke-width="4.60691"/>
12
+ <circle cx="457.998" cy="631.009" r="14.8269" fill="white" stroke="#2E2D36" stroke-width="4.60691"/>
13
+ <path d="M457.304 487.798V535.601L489.139 569.123" stroke="#2E2D36" stroke-width="7.67819" stroke-linecap="round"/>
14
+ <circle cx="499.354" cy="582.413" r="14.8269" fill="white" stroke="#2E2D36" stroke-width="4.60691"/>
15
+ <circle cx="542.695" cy="535.006" r="14.8269" fill="white" stroke="#2E2D36" stroke-width="4.60691"/>
16
+ <circle cx="562.332" cy="476.393" r="14.8269" fill="white" stroke="#2E2D36" stroke-width="4.60691"/>
17
+ <path d="M303.381 465.483L289.993 476.988H248.834" stroke="#2E2D36" stroke-width="7.67819" stroke-linecap="round"/>
18
+ <path d="M351.532 489.484V531.188L312.555 569.817" stroke="#2E2D36" stroke-width="7.67819" stroke-linecap="round"/>
19
+ <path d="M371.863 494.889V569.123L345.78 596.942V615.24" stroke="#2E2D36" stroke-width="7.67819" stroke-linecap="round"/>
20
+ <path d="M401.368 498.311V625.753" stroke="#2E2D36" stroke-width="7.67819" stroke-linecap="round"/>
21
+ <path d="M496.925 465.731L505.057 473.566H545.422" stroke="#2E2D36" stroke-width="7.67819" stroke-linecap="round"/>
22
+ <ellipse cx="401.021" cy="307.892" rx="51.671" ry="53.0099" fill="#2E2D36"/>
23
+ <ellipse cx="411.286" cy="294.106" rx="18.5956" ry="19.0915" fill="white"/>
24
+ <ellipse cx="428.493" cy="322.471" rx="8.43002" ry="8.67796" fill="white"/>
25
+ <circle cx="344.143" cy="632.299" r="14.8269" fill="white" stroke="#2E2D36" stroke-width="4.60691"/>
26
+ </svg>
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@xberg-io/opencode-tree-sitter-language-pack",
3
+ "version": "0.1.0",
4
+ "description": "OpenCode tools for parsing and code intelligence with the ts-pack CLI.",
5
+ "keywords": [
6
+ "chunking",
7
+ "code-intelligence",
8
+ "opencode",
9
+ "parsing",
10
+ "tree-sitter"
11
+ ],
12
+ "homepage": "https://github.com/xberg-io/plugins/tree/main/plugins/tree-sitter-language-pack",
13
+ "bugs": {
14
+ "url": "https://github.com/xberg-io/plugins/issues"
15
+ },
16
+ "license": "MIT",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/xberg-io/plugins.git",
20
+ "directory": "plugins/tree-sitter-language-pack"
21
+ },
22
+ "files": [
23
+ ".opencode/",
24
+ "assets/",
25
+ "README.md"
26
+ ],
27
+ "type": "module",
28
+ "main": ".opencode/plugins/tree-sitter-language-pack.js",
29
+ "exports": {
30
+ ".": "./.opencode/plugins/tree-sitter-language-pack.js"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public",
34
+ "provenance": true
35
+ },
36
+ "dependencies": {
37
+ "@opencode-ai/plugin": "^1.17.8"
38
+ },
39
+ "engines": {
40
+ "node": ">=22.14.0"
41
+ }
42
+ }