How to Install tree-sitter-cli on Debian: Generate, Test and Run Tree-sitter Parsers
Tree-sitter is a parser generator and incremental parsing library. It builds a concrete syntax tree for a source file and updates it cheaply as the file is edited, which is why editors such as Neovim, Helix and Zed rely on it for syntax highlighting, code folding and structural navigation. The Tree-sitter CLI is the companion command-line tool: it scaffolds grammar repositories, generates and compiles parsers, runs corpus tests, and lets you parse, query and highlight files straight from the terminal.
Debian does package tree-sitter-cli, but the archive lags well behind upstream: Bookworm has no package at all and Trixie ships 0.22.6. Upstream’s own prebuilt Linux binary is no easy way out either, since it is built against glibc 2.39 and refuses to start on Bookworm. The remaining options, cargo install or a global npm package, pull in a toolchain and leave updates to you.
The unofficial deb.griffo.io repository fills the gap: it packages the latest Tree-sitter CLI as a standard Debian .deb served over APT, so installation and updates use the tooling you already run for the rest of your system.
Install the Latest tree-sitter-cli on Debian: The Short Version
If you only came for the commands, this adds the repository and installs the latest tree-sitter-cli .deb package on Debian:
sudo install -d -m 0755 /etc/apt/keyrings
curl -fsSL https://deb.griffo.io/EA0F721D231FDD3A0A17B9AC7808B4DD62C41256.asc | sudo gpg --dearmor --yes -o /etc/apt/keyrings/deb.griffo.io.gpg
echo "deb [signed-by=/etc/apt/keyrings/deb.griffo.io.gpg] https://deb.griffo.io/apt $(lsb_release -sc 2>/dev/null) main" | sudo tee /etc/apt/sources.list.d/deb.griffo.io.list > /dev/null
sudo apt update
sudo apt install tree-sitter-cli
The rest of this guide explains what each command does, how to verify the install, how to keep the CLI up to date, and what to check when something goes wrong.
What Makes the Tree-sitter CLI Special?
- 🌳 Parser generator - Turns a
grammar.jsdescription into a fast, dependency-free C parser withtree-sitter generate. - 🧪 Built-in test runner - Corpus tests pair source snippets with the syntax tree you expect, and
tree-sitter testchecks them all. - 🔍 Query and highlight from the shell - Run S-expression queries, highlighting and tagging against real files without writing any code.
- 🏗️ Project scaffolding -
tree-sitter initcreates a grammar repository complete with bindings for languages such as C, Rust, Node.js, Python, Go and Swift. - 🧩 Native and Wasm builds -
tree-sitter buildcompiles a shared library, or a.wasmmodule with--wasm. - 🕹️ Web playground -
tree-sitter playgroundopens an interactive parse-tree explorer for your grammar in the browser. - ⚙️ No Node.js required - The embedded QuickJS runtime can evaluate grammars with
--js-runtime native. - 🐛 Debugging tools - Parse logs,
log.htmldebug graphs, conflict reports and a fuzzer help track down grammar problems.
Why Use the deb.griffo.io Repository?
- Easy installation and updates through APT, no
cargoornpmrequired. - Newer than the Debian archive, and available on Bookworm, where Debian has no package.
- Runs on every supported release: the binary is compiled from the upstream release tag against an older glibc, so it works on Bookworm too.
- Shell completions included for bash, fish, zsh and nushell, installed where your shell already looks.
- Always tracks upstream releases so you stay close to the latest Tree-sitter.
- Works across supported Debian releases on amd64, arm64, armhf and i386, with the codename detected automatically.
Prerequisites
Before you start, make sure you have:
- A Debian-based system (Bookworm 12, Trixie 13, Forky 14, or Sid)
- An amd64, arm64, armhf or i386 machine
sudoprivilegescurlinstalled (sudo apt install curlif needed)
The package itself only depends on the C library. Some commands need extra tools that are not pulled in automatically:
- A C compiler to build or test a parser:
sudo apt install build-essential - Node.js for
tree-sitter generate, unless you pass--js-runtime nativeto use the built-in QuickJS runtime
Step 1: Add the deb.griffo.io Repository
Add the signing key and repository source:
# Create the keyrings directory
sudo install -d -m 0755 /etc/apt/keyrings
# Download and install the repository GPG key
curl -fsSL https://deb.griffo.io/EA0F721D231FDD3A0A17B9AC7808B4DD62C41256.asc | sudo gpg --dearmor --yes -o /etc/apt/keyrings/deb.griffo.io.gpg
# Add the repository (auto-detects your distro codename)
echo "deb [signed-by=/etc/apt/keyrings/deb.griffo.io.gpg] https://deb.griffo.io/apt $(lsb_release -sc 2>/dev/null) main" | sudo tee /etc/apt/sources.list.d/deb.griffo.io.list > /dev/null
# Update the package list
sudo apt update
What each command does:
- Create the keyrings directory - ensures
/etc/apt/keyringsexists with proper permissions. - Install the GPG key - downloads the repository key and de-armours it into a dedicated keyring for verification.
- Add the repository - writes a
signed-bysource line, withlsb_release -scsupplying your Debian codename. - Update the package list - refreshes APT so it knows about the new packages.
Step 2: Update the Package List
If you skipped the last line, run the update now:
sudo apt update
On Trixie, Forky and Sid, Debian’s own tree-sitter-cli is also visible. Check that APT picked the newer build from deb.griffo.io:
apt policy tree-sitter-cli
The candidate should carry a ~trixie-style suffix (for example 0.27.0-1~trixie) and point at https://deb.griffo.io/apt.
Step 3: Install tree-sitter-cli
Install the package with APT, and add a C compiler while you are at it if you plan to build parsers:
sudo apt install tree-sitter-cli build-essential
APT installs the CLI system-wide, along with its bash, fish, zsh and nushell completions.
Step 4: Verify the Installation
Note that the package is called tree-sitter-cli, but the command it installs is tree-sitter. Confirm the version:
tree-sitter --version
You should see output similar to:
tree-sitter 0.27.0
Upstream ships no man page, so tree-sitter --help is the command reference, and tree-sitter <command> --help covers each subcommand.
Getting Started with the Tree-sitter CLI
Creating a Grammar
Grammars live in their own repository, conventionally named tree-sitter-<language>. Create an empty directory and let the CLI scaffold it:
mkdir tree-sitter-kv && cd tree-sitter-kv
tree-sitter init
tree-sitter init asks a few questions (language name, file types, author, licence) and writes tree-sitter.json, a starter grammar.js and language bindings. Run tree-sitter init --update later to refresh the generated files after a CLI upgrade.
Now describe the language in grammar.js. This one covers a tiny key = value configuration format:
module.exports = grammar({
name: 'kv',
extras: $ => [/\s/, $.comment],
rules: {
document: $ => repeat($.pair),
pair: $ => seq(field('key', $.key), '=', field('value', $.value)),
key: _ => /[a-zA-Z_][a-zA-Z0-9_]*/,
value: $ => choice($.number, $.string),
number: _ => /\d+/,
string: _ => /"[^"]*"/,
comment: _ => token(seq('#', /.*/)),
},
});
Generating the Parser
tree-sitter generate evaluates the grammar and writes the parser to src/parser.c, together with src/grammar.json and src/node-types.json:
# Uses node to evaluate grammar.js
tree-sitter generate
# No Node.js installed? Use the embedded QuickJS runtime instead
tree-sitter generate --js-runtime native
Setting TREE_SITTER_JS_RUNTIME=native in your shell makes the second form the default.
Writing and Running Tests
Tests live in test/corpus/ as plain text files. Each case has a name, the input, and the syntax tree you expect:
==================
Simple pairs
==================
name = "tree-sitter"
port = 8080
---
(document
(pair
key: (key)
value: (value
(string)))
(pair
key: (key)
value: (value
(number))))
Run the whole corpus, or just part of it:
# Compile the parser if needed, then run every test
tree-sitter test
# Only the cases whose name matches a regex
tree-sitter test --include "pairs"
# Accept the parser's current output as the expected trees
tree-sitter test --update
tree-sitter test compiles the parser with your C compiler before running, which is why build-essential matters here.
Parsing Files
Point tree-sitter parse at real input to see the tree it produces:
tree-sitter parse example.kv
(document [0, 0] - [3, 0]
(comment [0, 0] - [0, 6])
(pair [1, 0] - [1, 20]
key: (key [1, 0] - [1, 4])
value: (value [1, 7] - [1, 20]
(string [1, 7] - [1, 20])))
(pair [2, 0] - [2, 11]
key: (key [2, 0] - [2, 4])
value: (value [2, 7] - [2, 11]
(number [2, 7] - [2, 11]))))
A few flags are worth knowing:
# Pretty-printed concrete syntax tree, including anonymous nodes
tree-sitter parse --cst example.kv
# Only report errors and statistics, handy across a large sample set
tree-sitter parse --quiet --stat samples/*.kv
# Write log.html with graphs of every parsing step
tree-sitter parse --debug-graph example.kv
When a file contains a syntax error, the tree shows ERROR or MISSING nodes and the command exits with status 1, which makes it easy to check a grammar against a folder of real-world files.
Queries, Highlighting and Tags
Tree-sitter queries are S-expression patterns with @captures. Save one to a file:
(pair
key: (key) @name
value: (value (number)) @port)
Then run it against your input:
tree-sitter query ports.scm example.kv
example.kv
pattern: 0
capture: 0 - name, start: (2, 0), end: (2, 4), text: `port`
capture: 1 - port, start: (2, 7), end: (2, 11), text: `8080`
Editors use the same query language for highlighting. With a queries/highlights.scm in your grammar, the CLI can render a file directly:
# Coloured output in the terminal
tree-sitter highlight example.kv
# A standalone HTML page, with line numbers
tree-sitter highlight --html --layout line-numbers example.kv > example.html
# Code-navigation tags from queries/tags.scm
tree-sitter tags example.kv
Building Parsers and the Playground
tree-sitter build compiles the parser into a shared library, or into a Wasm module for browsers and Wasm-based hosts:
# Native shared library (kv.so)
tree-sitter build
# Wasm module (tree-sitter-kv.wasm)
tree-sitter build --wasm
# Explore the grammar interactively in the browser
tree-sitter playground
The first --wasm build downloads the WASI SDK and wasm-opt into ~/.cache/tree-sitter/, so it needs network access once. The playground loads the .wasm file, so build that first. Loading Wasm parsers in parse and test and the embedded playground are available on amd64 and arm64, matching upstream’s own release binaries.
Parsing Files Outside a Grammar Directory
Inside a grammar repository the CLI knows which parser to use. To parse files anywhere else, tell it where your grammars live:
tree-sitter init-config
This writes ~/.config/tree-sitter/config.json. Edit its parser-directories list (it defaults to folders such as ~/github, ~/src and ~/projects) so it includes the directory holding your tree-sitter-* checkouts, then check what the CLI found:
tree-sitter dump-languages
From then on, tree-sitter parse, highlight and query pick a parser by file extension, or by --scope source.kv when the extension is ambiguous.
Using the CLI with Neovim
The rewritten main branch of nvim-treesitter compiles parsers locally with the Tree-sitter CLI, so it needs a recent tree-sitter on your PATH plus a C compiler. With both installed from APT, confirm Neovim is happy:
:checkhealth nvim-treesitter
Keeping tree-sitter-cli Updated
Because tree-sitter-cli arrived via APT, updates come with the rest of the system:
sudo apt update && sudo apt upgrade
Whenever deb.griffo.io ships a newer Tree-sitter CLI, apt upgrade installs it automatically. Generated parsers embed an ABI version, and grammar repositories increasingly expect a recent CLI, so staying current avoids “incompatible language version” surprises when you pull someone else’s grammar.
Other Tools from deb.griffo.io
The repository packages plenty of tools that fit naturally alongside the Tree-sitter CLI:
- Neovim - the hyperextensible Vim-based text editor, whose highlighting runs on Tree-sitter parsers.
- Helix - a post-modern modal editor with Tree-sitter built into its core.
- Zed - a high-performance, collaborative code editor that uses Tree-sitter for syntax awareness.
- just - a handy command runner for wiring
tree-sitter generateandtree-sitter testinto project tasks.
Troubleshooting
GPG or Key Errors
If APT reports an unsigned repository or an invalid key, import it again:
curl -fsSL https://deb.griffo.io/EA0F721D231FDD3A0A17B9AC7808B4DD62C41256.asc | sudo gpg --dearmor --yes -o /etc/apt/keyrings/deb.griffo.io.gpg
sudo apt update
Package Not Found
If APT cannot see the tree-sitter-cli package:
- Re-run
sudo apt updateafter adding the repository. - Confirm your release is supported (Bookworm, Trixie, Forky, or Sid).
- Confirm your architecture is amd64, arm64, armhf or i386 with
dpkg --print-architecture. - Inspect the source list:
cat /etc/apt/sources.list.d/deb.griffo.io.list.
Remember to search for the package name, not the command: apt install tree-sitter will not find anything.
Debian’s Older Package Was Installed
On Trixie, Forky and Sid the Debian archive also provides tree-sitter-cli. If tree-sitter --version reports an older release than expected, compare the candidates:
apt policy tree-sitter-cli
If the Debian build is installed, install the deb.griffo.io version explicitly, using the exact version string apt policy printed:
sudo apt install tree-sitter-cli=0.27.0-1~trixie
Should Debian ever publish the same upstream version, its revision can sort above the ~trixie build. To always prefer this repository, pin it in /etc/apt/preferences.d/tree-sitter-cli:
Package: tree-sitter-cli
Pin: origin deb.griffo.io
Pin-Priority: 900
Conflicting tree-sitter Installations
The CLI is also distributed through Cargo, npm and GitHub release binaries, so an earlier install may shadow the packaged one:
which -a tree-sitter
Remove the stray copy with whichever tool installed it (cargo uninstall tree-sitter-cli or npm uninstall -g tree-sitter-cli), or delete a binary you dropped into /usr/local/bin, so the APT-managed tree-sitter in /usr/bin is the one you run.
Build or Generate Commands Fail
Failed to execute the C compilerfrombuild,testorparse- install a compiler withsudo apt install build-essential.tree-sitter generatecomplains thatnodeis missing - install Node.js, or runtree-sitter generate --js-runtime native.version `GLIBC_2.39' not found- you are running upstream’s release binary, not this package. Find it withwhich -a tree-sitterand remove it.
Uninstalling
Remove the Tree-sitter CLI with:
sudo apt remove tree-sitter-cli
To also drop the repository and key:
sudo rm /etc/apt/sources.list.d/deb.griffo.io.list
sudo rm /etc/apt/keyrings/deb.griffo.io.gpg
sudo apt update
Your configuration in ~/.config/tree-sitter/ and compiled parsers in ~/.cache/tree-sitter/ are left in place; delete them by hand if you no longer need them.
Conclusion
Installing tree-sitter-cli from deb.griffo.io gives Debian users the current Tree-sitter CLI on every supported release, Bookworm included, without pulling in Rust or Node.js just to get the binary. Generating, testing, parsing, querying and highlighting all live behind one tree-sitter command, and keeping it current is just another apt upgrade.
Whether you are writing a grammar for a new language, fixing a highlighting query for your editor or simply need a recent CLI for nvim-treesitter, the packaged Tree-sitter CLI gets out of your way, and APT makes it painless to maintain.
Frequently Asked Questions
How do I install the latest tree-sitter-cli on Debian?
Add the deb.griffo.io APT repository and its signing key, then run sudo apt install tree-sitter-cli. The repository tracks upstream Tree-sitter releases, so you get the latest packaged version without installing Cargo or npm.
Is there a .deb package for tree-sitter-cli?
Yes. deb.griffo.io publishes tree-sitter-cli as a signed .deb for Debian. You could download that .deb and install it by hand, but adding the repository is the better option: APT then picks up new versions on its own.
How do I update tree-sitter-cli to the latest version?
Run sudo apt update && sudo apt upgrade. Once tree-sitter-cli is installed from APT there is no separate updater to remember, since new releases arrive with the rest of your system updates.
Why is the command tree-sitter and not tree-sitter-cli?
tree-sitter-cli is the package name, matching Debian’s own package and the upstream crate. The binary it installs has always been called tree-sitter, so every command in the upstream documentation works as written.
Do I need Node.js to use the Tree-sitter CLI?
No. Only tree-sitter generate evaluates grammar.js, and it defaults to node. Pass --js-runtime native, or set TREE_SITTER_JS_RUNTIME=native, to use the QuickJS runtime compiled into the CLI instead.
How do I install tree-sitter-cli on Ubuntu?
Exactly the same way; lsb_release -sc simply resolves to a different codename. There is a companion guide with the Ubuntu specifics: How to install tree-sitter-cli on Ubuntu.
Which Debian releases are supported?
Bookworm 12, Trixie 13, Forky 14 and Sid, on amd64, arm64, armhf and i386. Because the repository line is built from lsb_release -sc, the matching suite is selected for you.
Resources
- Tree-sitter Documentation
- Tree-sitter GitHub Repository
- tree-sitter-cli Packaging Repository
- deb.griffo.io Repository
- Install guide on deb.griffo.io
Disclaimer: The deb.griffo.io repository is an unofficial community project and is not affiliated with the official Debian or Ubuntu projects, or with the upstream Tree-sitter project.