You can add parsers that aren’t included in nvim-treesitter’s default list, either from a GitHub repository or from a local directory.
Adding a Parser from GitHub
To add a parser from a GitHub repository:
Create a User TSUpdate autocommand
Add this configuration before calling :TSInstall: vim . api . nvim_create_autocmd ( 'User' , {
pattern = 'TSUpdate' ,
callback = function ()
require ( 'nvim-treesitter.parsers' ). zimbu = {
install_info = {
url = 'https://github.com/zimbulang/tree-sitter-zimbu' ,
revision = 'v1.2.3' , -- Tag or commit hash
},
}
end
})
Register the filetype (if needed)
If the parser name differs from Neovim’s filetype: vim . treesitter . language . register ( 'zimbu' , { 'zu' })
This maps the zu filetype to use the zimbu parser.
Parser Configuration Options
Basic Configuration
require ( 'nvim-treesitter.parsers' ). mylang = {
install_info = {
url = 'https://github.com/username/tree-sitter-mylang' ,
revision = 'abc123' , -- Commit hash or tag
},
}
Using a Different Branch
require ( 'nvim-treesitter.parsers' ). mylang = {
install_info = {
url = 'https://github.com/username/tree-sitter-mylang' ,
revision = 'def456' ,
branch = 'develop' , -- Use 'develop' instead of default branch
},
}
If you don’t specify revision, the HEAD of the specified branch (or default branch) will be used.
Parser in Subdirectory (Monorepo)
If the parser is in a subdirectory of the repository:
require ( 'nvim-treesitter.parsers' ). mylang = {
install_info = {
url = 'https://github.com/username/monorepo' ,
revision = 'abc123' ,
location = 'packages/tree-sitter-mylang' , -- Subdirectory path
},
}
Generate Parser from Grammar
If the repository doesn’t contain pre-generated src/parser.c:
require ( 'nvim-treesitter.parsers' ). mylang = {
install_info = {
url = 'https://github.com/username/tree-sitter-mylang' ,
revision = 'abc123' ,
generate = true , -- Run tree-sitter generate
},
}
This requires tree-sitter-cli (0.26.1 or later) in your PATH.
Generate from grammar.js
If the repository has only src/grammar.js (not src/grammar.json):
require ( 'nvim-treesitter.parsers' ). mylang = {
install_info = {
url = 'https://github.com/username/tree-sitter-mylang' ,
revision = 'abc123' ,
generate = true ,
generate_from_json = false , -- Generate from grammar.js
},
}
Install Queries from Repository
If the parser repository includes queries:
require ( 'nvim-treesitter.parsers' ). mylang = {
install_info = {
url = 'https://github.com/username/tree-sitter-mylang' ,
revision = 'abc123' ,
queries = 'queries/neovim' , -- Directory containing query files
},
}
This copies or symlinks queries from the specified directory in the parser repo.
Adding a Local Parser
To use a parser from a local directory:
vim . api . nvim_create_autocmd ( 'User' , {
pattern = 'TSUpdate' ,
callback = function ()
require ( 'nvim-treesitter.parsers' ). mylang = {
install_info = {
path = '~/code/tree-sitter-mylang' , -- Local directory
},
}
end
})
When using a local path:
The directory is used as-is (no cloning or downloading)
branch and revision fields are ignored
Changes to the directory are immediately reflected
Local Parser with Queries
require ( 'nvim-treesitter.parsers' ). mylang = {
install_info = {
path = '~/code/tree-sitter-mylang' ,
queries = 'queries' , -- Symlink queries from local directory
},
}
Local Parser in Subdirectory
require ( 'nvim-treesitter.parsers' ). mylang = {
install_info = {
path = '~/code/monorepo' ,
location = 'parsers/mylang' , -- Parser is in subdirectory
},
}
Local Parser Requiring Generation
require ( 'nvim-treesitter.parsers' ). mylang = {
install_info = {
path = '~/code/tree-sitter-mylang' ,
generate = true , -- Run tree-sitter generate on install
},
}
Complete Examples
Example 1: Remote Parser with All Options
vim . api . nvim_create_autocmd ( 'User' , {
pattern = 'TSUpdate' ,
callback = function ()
require ( 'nvim-treesitter.parsers' ). mylang = {
install_info = {
url = 'https://github.com/username/tree-sitter-mylang' ,
revision = 'v2.1.0' ,
branch = 'main' ,
location = 'parser' ,
generate = true ,
generate_from_json = false ,
queries = 'queries/neovim' ,
},
}
end
})
-- Register filetype mapping
vim . treesitter . language . register ( 'mylang' , { 'ml' , 'myl' })
-- Install the parser
vim . defer_fn ( function ()
require ( 'nvim-treesitter' ). install ({ 'mylang' })
end , 100 )
Example 2: Local Development Parser
vim . api . nvim_create_autocmd ( 'User' , {
pattern = 'TSUpdate' ,
callback = function ()
require ( 'nvim-treesitter.parsers' ). mydevlang = {
install_info = {
path = vim . fn . expand ( '~/code/tree-sitter-mydevlang' ),
generate = true ,
queries = 'queries' ,
},
}
end
})
vim . treesitter . language . register ( 'mydevlang' , 'mdl' )
Modifying Existing Parsers
You can override settings for parsers already in nvim-treesitter:
-- Always generate the Lua parser from grammar
vim . api . nvim_create_autocmd ( 'User' , {
pattern = 'TSUpdate' ,
callback = function ()
require ( 'nvim-treesitter.parsers' ). lua . install_info . generate = true
end
})
Use custom branch
Override revision
Use local development version
vim . api . nvim_create_autocmd ( 'User' , {
pattern = 'TSUpdate' ,
callback = function ()
require ( 'nvim-treesitter.parsers' ). rust . install_info . branch = 'develop'
end
})
Filetype Registration
If Neovim doesn’t automatically detect your language’s filetype, add a detection rule:
vim . filetype . add ({
extension = {
zu = 'zimbu' ,
zub = 'zimbu' ,
},
filename = {
[ 'Zimbufile' ] = 'zimbu' ,
},
pattern = {
[ '.*%.zimbu%.conf' ] = 'zimbu' ,
},
})
-- Then map the filetype to parser
vim . treesitter . language . register ( 'zimbu' , 'zimbu' )
External Scanner Requirements
If your parser requires an external scanner, it must be written in C (not C++).
External scanners are additional lexers that parsers can use for complex tokenization. If your parser has a scanner.cc file, you’ll need to ensure it’s rewritten in C as scanner.c.
Troubleshooting
Parser Not Found
Ensure your autocommand runs before :TSInstall:
-- This should be in init.lua, loaded early
vim . api . nvim_create_autocmd ( 'User' , {
pattern = 'TSUpdate' ,
callback = function ()
-- Your parser configuration
end
})
Compilation Fails
Check that tree-sitter-cli is installed: tree-sitter --version
Verify the parser repository is valid
Try generating manually:
cd /path/to/parser
tree-sitter generate
tree-sitter build
Queries Not Working
If queries aren’t loading:
Verify the queries path is correct
Check query files exist: ls ~/code/tree-sitter-mylang/queries/
Manually symlink for testing:
ln -s ~/code/tree-sitter-mylang/queries \
~/.local/share/nvim/site/queries/mylang
Local Parser Not Updating
Changes to local parsers require reinstallation:
:TSUninstall mylang
:TSInstall mylang
Best Practices
Pin revisions : Always specify a revision for stability
Use User TSUpdate : Ensure modifications happen at the right time
Test locally first : Develop parsers locally before publishing
Include queries : Provide highlights.scm at minimum
Document filetypes : Make it clear which filetypes your parser supports
Next Steps