Contributing
Contributions are welcome: adding a grammar, fixing a bug, improving a binding, or writing documentation.
For CI/CD workflow details, see the CI/CD reference.
Prerequisites
Section titled “Prerequisites”You’ll need the following tools installed:
- Task — the project task runner
- Rust stable toolchain via rustup
- Python 3.10+ and uv
- Node.js 18+ and pnpm
Getting started
Section titled “Getting started”# Install Task (macOS)brew install go-task
# Clone the repositorygit clone https://github.com/xberg-io/tree-sitter-language-pack.gitcd tree-sitter-language-pack
# Install all language dependenciestask setup
# Build the Rust coretask build
# Run all teststask testOn Debian/Ubuntu, install Task with apt install go-task or download from taskfile.dev.
Common tasks
Section titled “Common tasks”task --list # show all available taskstask build # build Rust core + bindingstask test # run all test suitestask lint # run all linters (clippy, ruff, oxlint, rubocop, …)task format # auto-format all codetask generate:e2e # regenerate e2e test suites from fixturestask test:e2e # run e2e testsRun task --list to see all available tasks.
Adding a language
Section titled “Adding a language”The most common contribution is adding a new tree-sitter grammar.
1. Find or create a grammar
Section titled “1. Find or create a grammar”The grammar must:
- Be permissively licensed — MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, or Unlicense only. We do not accept GPL, AGPL, LGPL, MPL, or any copyleft license. This ensures tree-sitter-language-pack can be used freely in any project without imposing license obligations on downstream users.
- Have a public Git repository.
- Produce valid
parser.coutput fromtree-sitter generate. - Compile cleanly on Linux, macOS, and Windows.
2. Add the grammar definition
Section titled “2. Add the grammar definition”Edit sources/language_definitions.json and add an entry:
{ "mylang": { "repo": "https://github.com/example/tree-sitter-mylang", "rev": "abc123def456", "branch": "main" }}Always pin to an exact commit (rev), not a branch tip. This ensures reproducible builds.
Available fields:
| Field | Required | Description |
|---|---|---|
repo |
Yes | Grammar repository URL |
rev |
Yes | Exact commit SHA to pin |
branch |
No | Branch name (used by scripts/pin_vendors.py to find latest) |
directory |
No | Subdirectory within the repo containing the grammar |
extensions |
No | File extensions that map to this language (e.g. ["rs"]) |
ambiguous |
No | Extensions shared with other languages (e.g. {"h": ["cpp", "objc"]}) |
c_symbol |
No | Override for the C symbol name when it differs from the language name |
generate |
No | Set to true to force running tree-sitter generate before compiling |
3. Build and test
Section titled “3. Build and test”# Compile the new parsertask build
# Run the test suitetask test
# Verify the parser works end-to-endts-pack download mylangts-pack parse example.mylang --language mylang4. Add test fixtures
Section titled “4. Add test fixtures”Add at least one fixture under fixtures/ (the e2e suite consumes them) and a runnable snippet under docs/snippets/<lang>/:
[ { "id": "mylang_basic_parse", "category": "basic", "description": "Parse a simple mylang file", "language": "mylang", "source_code": "// example mylang source", "assertions": { "tree_not_null": true, "has_error_nodes": false }, "tags": ["smoke"] }]Then regenerate and run e2e tests:
task generate:e2etask test:e2e5. Open a pull request
Section titled “5. Open a pull request”- Title:
feat: add <language> parser - Body: link to the upstream grammar repository, note any quirks or limitations
Fixing a bug
Section titled “Fixing a bug”- Check the issue tracker — the bug may already be reported.
- Write a failing test that reproduces the issue.
- Fix the bug in the appropriate crate.
- Confirm all tests pass with
task test. - Open a PR with a clear description of the root cause and fix.
Improving bindings
Section titled “Improving bindings”Binding improvements (better error messages, idiomatic APIs, new methods) are
welcome. Each binding lives in crates/ts-pack-<language>/. See the
Architecture page for the full crate layout.
Binding changes must:
- Not add logic that belongs in the Rust core. Bindings are pure translation layers.
- Have test coverage in the binding’s native test suite.
- Follow the existing API surface documented in
docs/api-mapping.yaml.
Documentation
Section titled “Documentation”Doc fixes and new guides follow the same workflow as code changes:
- Fork and create a branch.
- Edit files under
docs/. - Preview locally with
zensical serve. - Run
task lintif you touch any scripted checks. - Open a pull request.
Use the Edit button in the page header to jump directly from any docs page to the matching file on GitHub.
Code quality
Section titled “Code quality”The project uses pre-commit hooks managed by prek:
prek installprek install --hook-type commit-msgBefore committing, verify these three commands pass:
task lint # zero warnings requiredtask test # all tests must passtask format # code must be formattedCommit style
Section titled “Commit style”Follow Conventional Commits:
feat: add kotlin parserfix: correct memory layout in Java FFI array freeingchore: update tree-sitter to 0.25docs: add chunking guidetest: add e2e fixtures for rubyKeep commits small and focused. Each commit should represent one logical change.
Pull request checklist
Section titled “Pull request checklist”-
task testpasses -
task lintpasses (zero warnings) - New language has runnable snippets under
docs/snippets/<lang>/(validated viatask docs:snippets:check) -
task generate:e2e && task test:e2epasses -
task sync-versionsrun if any manifest was bumped - PR description explains the change and links related issues
Getting help
Section titled “Getting help”- GitHub Discussions — questions and design conversations
- Discord — real-time chat with maintainers
- Issue tracker — bug reports and feature requests