Repository: ast-grep/langs
Pull request #46: ✨ Bash
Author: login: NatoBoram
Created: 2025-04-01T21:08:55Z | Merged: 2025-04-04T19:10:36Z

*And so it begins...*

I'll write a test in the other ones before opening them.

[![CI](https://github.com/coderabbitai/langs/actions/workflows/ci.yml/badge.svg?branch=feature%2Fbash)](https://github.com/coderabbitai/langs/actions/workflows/ci.yml)

<details>
<summary>CodeRabbit Metadata</summary>

* Closes https://github.com/coderabbitai/langs/pull/5

</details>



<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Launched a new package offering Bash language support with dynamic registration and configurable parser options.
- **Documentation**
  - Introduced a detailed README outlining installation, integration instructions, and usage examples.
- **Tests**
  - Established an automated testing environment to validate Bash command parsing.
- **Chores**
  - Implemented post-installation routines to streamline the package setup.
- **Package Management**
  - Added a new `package.json` file for the `@ast-grep/lang-bash` package, specifying metadata and scripts for management.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/.changeset/brave-hairs-dress.md b/.changeset/brave-hairs-dress.md
new file mode 100644
index 0000000..9b6490c
--- /dev/null
+++ b/.changeset/brave-hairs-dress.md
@@ -0,0 +1,5 @@
+---
+"@ast-grep/lang-bash": patch
+---
+
+Added @ast-grep/lang-bash
diff --git a/packages/bash/README.md b/packages/bash/README.md
new file mode 100644
index 0000000..4fb2717
--- /dev/null
+++ b/packages/bash/README.md
@@ -0,0 +1,24 @@
+# ast-grep napi language for bash
+
+## Installation
+
+In a pnpm project, run:
+
+```bash
+pnpm install @ast-grep/lang-bash
+pnpm install @ast-grep/napi
+# install the tree-sitter-cli if no prebuild is available
+pnpm install @tree-sitter/cli --save-dev
+```
+
+## Usage
+
+```js
+import bash from '@ast-grep/lang-bash'
+import { registerDynamicLanguage, parse } from '@ast-grep/napi'
+
+registerDynamicLanguage({ bash })
+
+const sg = parse('bash', `your code`)
+sg.root().kind()
+```
diff --git a/packages/bash/index.d.ts b/packages/bash/index.d.ts
new file mode 100644
index 0000000..11140a6
--- /dev/null
+++ b/packages/bash/index.d.ts
@@ -0,0 +1,10 @@
+type LanguageRegistration = {
+  libraryPath: string
+  extensions: string[]
+  languageSymbol?: string
+  metaVarChar?: string
+  expandoChar?: string
+}
+
+declare const registration: LanguageRegistration
+export default registration
diff --git a/packages/bash/index.js b/packages/bash/index.js
new file mode 100644
index 0000000..9056f2d
--- /dev/null
+++ b/packages/bash/index.js
@@ -0,0 +1,21 @@
+const path = require('node:path')
+const libPath = path.join(__dirname, 'parser.so')
+
+module.exports = {
+  libraryPath: libPath,
+  extensions: [
+    'bash',
+    'bats',
+    'cgi',
+    'command',
+    'env',
+    'fcgi',
+    'ksh',
+    'sh',
+    'tmux',
+    'tool',
+    'zsh',
+  ],
+  languageSymbol: 'tree_sitter_bash',
+  expandoChar: '$',
+}
diff --git a/packages/bash/nursery.js b/packages/bash/nursery.js
new file mode 100644
index 0000000..6feaa8c
--- /dev/null
+++ b/packages/bash/nursery.js
@@ -0,0 +1,16 @@
+const { setup } = require('@ast-grep/nursery')
+const assert = require('node:assert')
+const languageRegistration = require('./index')
+
+setup({
+  dirname: __dirname,
+  name: 'bash',
+  treeSitterPackage: 'tree-sitter-bash',
+  languageRegistration,
+  testRunner: parse => {
+    const sg = parse('echo test')
+    const root = sg.root()
+    const node = root.find('echo $A')
+    assert.equal(node.kind(), 'command')
+  },
+})
diff --git a/packages/bash/package.json b/packages/bash/package.json
new file mode 100644
index 0000000..f49b65c
--- /dev/null
+++ b/packages/bash/package.json
@@ -0,0 +1,47 @@
+{
+  "name": "@ast-grep/lang-bash",
+  "version": "0.0.1",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "build": "tree-sitter build -o parser.so",
+    "source": "node nursery.js source",
+    "prepublishOnly": "node nursery.js source",
+    "postinstall": "node postinstall.js",
+    "test": "node nursery.js test"
+  },
+  "files": [
+    "index.js",
+    "index.d.ts",
+    "type.d.ts",
+    "postinstall.js",
+    "src",
+    "prebuilds"
+  ],
+  "keywords": ["ast-grep"],
+  "author": "",
+  "license": "ISC",
+  "dependencies": {
+    "@ast-grep/setup-lang": "0.0.3"
+  },
+  "peerDependencies": {
+    "tree-sitter-cli": "0.24.6"
+  },
+  "peerDependenciesMeta": {
+    "tree-sitter-cli": {
+      "optional": true
+    }
+  },
+  "devDependencies": {
+    "@ast-grep/nursery": "0.0.2",
+    "tree-sitter-bash": "0.23.3",
+    "tree-sitter-cli": "0.24.6"
+  },
+  "publishConfig": {
+    "access": "public",
+    "registry": "https://registry.npmjs.org/"
+  },
+  "pnpm": {
+    "onlyBuiltDependencies": ["@ast-grep/lang-bash", "tree-sitter-cli"]
+  }
+}
diff --git a/packages/bash/postinstall.js b/packages/bash/postinstall.js
new file mode 100644
index 0000000..b9141ff
--- /dev/null
+++ b/packages/bash/postinstall.js
@@ -0,0 +1,4 @@
+const { postinstall } = require('@ast-grep/setup-lang')
+postinstall({
+  dirname: __dirname,
+})
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 08634c8..82d59be 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -34,6 +34,22 @@ importers:
         specifier: 0.24.6
         version: 0.24.6
 
+  packages/bash:
+    dependencies:
+      '@ast-grep/setup-lang':
+        specifier: 0.0.3
+        version: 0.0.3
+    devDependencies:
+      '@ast-grep/nursery':
+        specifier: 0.0.2
+        version: 0.0.2
+      tree-sitter-bash:
+        specifier: 0.23.3
+        version: 0.23.3(tree-sitter@0.21.1)
+      tree-sitter-cli:
+        specifier: 0.24.6
+        version: 0.24.6
+
   packages/c:
     dependencies:
       '@ast-grep/setup-lang':
@@ -789,6 +805,14 @@ packages:
       tree_sitter:
         optional: true
 
+  tree-sitter-bash@0.23.3:
+    resolution: {integrity: sha512-36cg/GQ2YmIbeiBeqeuh4fBJ6i4kgVouDaqTxqih5ysPag+zHufyIaxMOFeM8CeplwAK/Luj1o5XHqgdAfoCZg==}
+    peerDependencies:
+      tree-sitter: ^0.21.1
+    peerDependenciesMeta:
+      tree-sitter:
+        optional: true
+
   tree-sitter-c-sharp@0.23.1:
     resolution: {integrity: sha512-9zZ4FlcTRWWfRf6f4PgGhG8saPls6qOOt75tDfX7un9vQZJmARjPrAC6yBNCX2T/VKcCjIDbgq0evFaB3iGhQw==}
     peerDependencies:
@@ -1447,6 +1471,13 @@ snapshots:
       tree-sitter: 0.21.1
       tree-sitter-html: 0.20.4(tree-sitter@0.21.1)
 
+  tree-sitter-bash@0.23.3(tree-sitter@0.21.1):
+    dependencies:
+      node-addon-api: 8.3.1
+      node-gyp-build: 4.8.4
+    optionalDependencies:
+      tree-sitter: 0.21.1
+
   tree-sitter-c-sharp@0.23.1(tree-sitter@0.21.1):
     dependencies:
       node-addon-api: 8.3.0


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>🧹 Nitpick comments (5)</summary><blockquote>

<details>
<summary>packages/bash/README.md (1)</summary><blockquote>

`14-24`: **Consider expanding usage examples.**

The usage example demonstrates the basic functionality but could benefit from more complex examples showing different Bash constructs and how to query them.


Consider adding examples like:
- Parsing conditional statements
- Handling pipes
- Working with variable assignments
- Extracting specific nodes from more complex scripts

This would help users understand the full capabilities of the Bash language support.

</blockquote></details>
<details>
<summary>packages/bash/index.d.ts (1)</summary><blockquote>

`1-7`: **Add JSDoc comments to improve documentation.**

The type definition is clear but could benefit from JSDoc comments explaining the purpose of each field, especially for the optional properties like `languageSymbol`, `metaVarChar`, and `expandoChar`.


```diff
+/**
+ * Configuration for registering a language with ast-grep
+ */
type LanguageRegistration = {
+  /** Path to the language library file */
  libraryPath: string
+  /** File extensions associated with this language */
  extensions: string[]
+  /** Symbol used to identify the language */
  languageSymbol?: string
+  /** Character used for meta variables in patterns */
  metaVarChar?: string
+  /** Character used for expanding nodes in patterns */
  expandoChar?: string
}
```

</blockquote></details>
<details>
<summary>packages/bash/index.js (1)</summary><blockquote>

`4-21`: **Well-structured language configuration with comprehensive file extensions.**

The exported configuration object properly defines all necessary properties for Bash language support, with an extensive list of file extensions covering various Bash-related file types.


Consider adding a brief comment explaining the purpose of the `expandoChar` property for better code documentation.

```diff
 module.exports = {
   libraryPath: libPath,
   extensions: [
     'bash',
     'bats',
     'cgi',
     'command',
     'env',
     'fcgi',
     'ksh',
     'sh',
     'tmux',
     'tool',
     'zsh',
   ],
   languageSymbol: 'tree_sitter_bash',
+  // Character used for variable expansion in Bash
   expandoChar: '$',
 }
```

</blockquote></details>
<details>
<summary>packages/bash/package.json (2)</summary><blockquote>

`1-5`: **Add package description for better discoverability.**

The package metadata is generally correct with appropriate naming and versioning, but the description field is empty.

Add a meaningful description to provide context about the package purpose:

```diff
{
  "name": "@ast-grep/lang-bash",
  "version": "0.0.1",
-  "description": "",
+  "description": "Bash language support for ast-grep",
  "main": "index.js",
```

---

`21-23`: **Complete the author field.**

The author field is empty and should be filled with appropriate information.

```diff
  "keywords": ["ast-grep"],
-  "author": "",
+  "author": "NatoBoram",
  "license": "ISC",
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 002639cb8b0570afad2b5559a0e23fec0aac5be1 and acfc4dfb590cebb7393312a37184f8d50d1faab7.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `pnpm-lock.yaml` is excluded by `!**/pnpm-lock.yaml`

</details>

<details>
<summary>📒 Files selected for processing (6)</summary>

* `packages/bash/README.md` (1 hunks)
* `packages/bash/index.d.ts` (1 hunks)
* `packages/bash/index.js` (1 hunks)
* `packages/bash/nursery.js` (1 hunks)
* `packages/bash/package.json` (1 hunks)
* `packages/bash/postinstall.js` (1 hunks)

</details>

<details>
<summary>🔇 Additional comments (8)</summary><blockquote>

<details>
<summary>packages/bash/postinstall.js (1)</summary>

`1-4`: **LGTM! Good implementation of the postinstall script.**

The script correctly imports and calls the `postinstall` function from `@ast-grep/setup-lang` with the current directory, following the pattern used by other language packages.

</details>
<details>
<summary>packages/bash/nursery.js (1)</summary>

`1-4`: **LGTM! Good setup of dependencies for the test environment.**

The required dependencies are properly imported to set up the testing environment for the Bash language.

</details>
<details>
<summary>packages/bash/README.md (1)</summary>

`1-13`: **LGTM! Clear installation instructions.**

The installation section provides clear steps for setting up the Bash language support in a pnpm project, including the appropriate dependencies.

</details>
<details>
<summary>packages/bash/index.d.ts (1)</summary>

`9-10`: **LGTM! Proper export of the language registration.**

The constant declaration and default export are correctly implemented.

</details>
<details>
<summary>packages/bash/index.js (1)</summary>

`1-3`: **LGTM: Module path handling is correctly implemented.**

The use of the `node:` prefix for the built-in path module is a good practice, and the library path is correctly constructed using `__dirname` for cross-platform compatibility.

</details>
<details>
<summary>packages/bash/package.json (3)</summary>

`6-12`: **LGTM: Build and test scripts are properly configured.**

The scripts section defines appropriate commands for building, testing, and package lifecycle events.

---

`24-39`: **LGTM: Dependencies are appropriately structured.**

The dependency structure is well-organized with clear separation between runtime, peer, and development dependencies. The optional peer dependency for tree-sitter-cli is a good practice.

---

`40-46`: **LGTM: Publishing and pnpm configurations are properly set.**

The publishing configuration correctly sets public access, and the pnpm configuration for built dependencies is appropriate.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-01T21:12:25Z
user: login: HerringtonDarkholme
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-04T19:10:15Z

Review comments:
diff_hunk: @@ -0,0 +1,16 @@
+const { setup } = require('@ast-grep/nursery')
+const assert = require('node:assert')
+const languageRegistration = require('./index')
+
+setup({
+  dirname: __dirname,
+  name: 'bash',
+  treeSitterPackage: 'tree-sitter-bash',
+  languageRegistration,
+  testRunner: parse => {
+    const sg = parse('echo test')
+    const root = sg.root()
+    const node = root.find('echo $A')
+    assert.equal(node.kind(), 'command')
+  },
+})
path: packages/bash/nursery.js
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix the test pattern mismatch.**

There's a discrepancy in the test runner: you parse `echo test` but then try to find `echo $A`. This pattern mismatch will likely cause the test to fail since the node being searched for doesn't exist in the parsed code.


```diff
-    const sg = parse('echo test')
+    const sg = parse('echo $A')
```

Or alternatively:

```diff
-    const node = root.find('echo $A')
+    const node = root.find('echo test')
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
setup({
  dirname: __dirname,
  name: 'bash',
  treeSitterPackage: 'tree-sitter-bash',
  languageRegistration,
  testRunner: parse => {
-    const sg = parse('echo test')
+    const sg = parse('echo $A')
    const root = sg.root()
    const node = root.find('echo $A')
    assert.equal(node.kind(), 'command')
  },
})
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-01T21:12:25Z
author_association: NONE
diff_hunk: @@ -0,0 +1,47 @@
+{
+  "name": "@ast-grep/lang-bash",
+  "version": "0.0.1",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "build": "tree-sitter build -o parser.so",
+    "source": "node nursery.js source",
+    "prepublishOnly": "node nursery.js source",
+    "postinstall": "node postinstall.js",
+    "test": "node nursery.js test"
+  },
+  "files": [
+    "index.js",
+    "index.d.ts",
+    "type.d.ts",
+    "postinstall.js",
+    "src",
+    "prebuilds"
+  ],
path: packages/bash/package.json
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Verify the existence of type.d.ts and consider adding nursery.js to files.**

The files list appears to include most necessary files, but has potential issues.

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if type.d.ts exists and if nursery.js is needed in the files array

# Check for type.d.ts
echo "Checking for type.d.ts file..."
if [ -f "packages/bash/type.d.ts" ]; then
  echo "type.d.ts exists."
else
  echo "type.d.ts is listed in files array but does not exist."
fi

# Check for nursery.js
echo "Checking for nursery.js file..."
if [ -f "packages/bash/nursery.js" ]; then
  echo "nursery.js exists but is not included in the files array."
else
  echo "nursery.js does not exist."
fi
```

Length of output: 462

---



</details>

**Action Required: Update Files Array in packages/bash/package.json**

- **Missing File:** The entry `type.d.ts` is listed but does not exist in the repository. Please either create this file if it's needed or remove the entry from the files array.
- **Omitted File:** The file `nursery.js` exists in the repository but is not included in the files array. Please consider adding it if it’s meant to be part of the package distribution.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-01T21:12:25Z
author_association: NONE

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-04-01T21:09:03Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
This pull request introduces a new Bash language package (`@ast-grep/lang-bash`). It adds documentation with installation and usage instructions, defines a `LanguageRegistration` type and corresponding configuration in the source files, and provides a post-install script to invoke language setup. A test environment is also established via a nursery script. Additionally, the package metadata, dependencies, and publishing configuration are defined for proper package management.

## Changes

| File(s)                                           | Change Summary                                                                                                                                                       |
|---------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| packages/bash/README.md                           | Added documentation covering installation commands, usage examples, and integration steps for the Bash language package.                                           |
| packages/bash/index.d.ts \| packages/bash/index.js| Introduced the `LanguageRegistration` type and a configuration object exporting language details (libraryPath, extensions, languageSymbol, expandoChar).           |
| packages/bash/nursery.js                          | Created a test script that sets up a testing environment using `@ast-grep/nursery` to parse Bash code and validate the syntax tree.                                  |
| packages/bash/package.json                        | Added package metadata, scripts for build/test tasks, dependency definitions, and publish configuration for the new Bash language package.                         |
| packages/bash/postinstall.js                      | Added a post-installation script that calls the `postinstall` function from `@ast-grep/setup-lang` with the current directory information.                           |
| .changeset/brave-hairs-dress.md                  | Added a changeset entry for the introduction of the `@ast-grep/lang-bash` package.                                                                                 |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
  participant U as User
  participant PM as Package Manager
  participant PI as postinstall.js
  participant SL as @ast-grep/setup-lang

  U->>PM: Install @ast-grep/lang-bash
  PM->>PI: Execute postinstall script
  PI->>SL: Call setup({ dirname: __dirname })
  SL-->>PI: Confirm setup completion
```

```mermaid
sequenceDiagram
  participant TR as Test Runner
  participant NS as nursery.js
  participant LC as Language Config (index.js)
  participant P as Parser (Tree-sitter)

  TR->>NS: Start testing Bash language
  NS->>LC: Load registration configuration
  NS->>P: Parse "echo test" snippet
  P-->>NS: Return syntax tree
  NS->>TR: Assert node kind "command" exists
```

## Suggested reviewers
- HerringtonDarkholme

## Poem
> I hopped through lines of code so bright,  
> Adding Bash support with all my might.  
> New docs, new tests, and types in place,  
> A neat registration to embrace.  
> Hop along and code with glee—  
> A bunny's work is fun and free! 🐰✨

<!-- walkthrough_end -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between acfc4dfb590cebb7393312a37184f8d50d1faab7 and 76a067e96524ac6006a0cce33792dc0e65a46003.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `pnpm-lock.yaml` is excluded by `!**/pnpm-lock.yaml`

</details>

<details>
<summary>📒 Files selected for processing (7)</summary>

* `.changeset/brave-hairs-dress.md` (1 hunks)
* `packages/bash/README.md` (1 hunks)
* `packages/bash/index.d.ts` (1 hunks)
* `packages/bash/index.js` (1 hunks)
* `packages/bash/nursery.js` (1 hunks)
* `packages/bash/package.json` (1 hunks)
* `packages/bash/postinstall.js` (1 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (1)</summary>

* .changeset/brave-hairs-dress.md

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (6)</summary>

* packages/bash/index.d.ts
* packages/bash/nursery.js
* packages/bash/README.md
* packages/bash/index.js
* packages/bash/postinstall.js
* packages/bash/package.json

</details>

</details>
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=ast-grep/langs&utm_content=46):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai plan` to trigger planning for file edits and PR creation.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: HerringtonDarkholme
created_at: 2025-04-02T03:30:27Z
body: Hi! thanks for the language contribution. However, given that we will have more languages in the foreseeable future, I think changeset https://github.com/ast-grep/langs/issues/31 should be first introduced to the repo. 

I don't have time during the weekday but I will give it a try during the upcoming weekend. Thank you for your patience!
author_association: MEMBER
user: login: NatoBoram
created_at: 2025-04-02T17:54:15Z
body: That looks like difficult operation

I think I'll continue with adding the test and opening the PRs and later on I'll add all the changesets all at once after it's implemented
author_association: COLLABORATOR
user: login: HerringtonDarkholme
created_at: 2025-04-04T04:34:15Z
body: @NatoBoram changeset is added! you can update main branch and use `pnpm changeset` 
author_association: MEMBER
user: login: HerringtonDarkholme
created_at: 2025-04-04T19:10:07Z
body: Thanks!
author_association: MEMBER
user: login: NatoBoram
created_at: 2025-04-04T19:33:16Z
body: Alright, I should've added a changeset for every opened PR!
author_association: COLLABORATOR