ansible-vim: Ansible syntax highlighting for Vim and Neovim
A vim plugin for syntax highlighting Ansible's common filetypes
At a glance
- What is it?
- ansible-vim is a Vim plugin that highlights Ansible YAML playbooks, Jinja2 templates and hosts files by extending the original YAML and Jinja syntax rather than replacing it, with a separate tree-sitter path for Neovim 0.12 and later. It is a highlighting layer, not a linter, and some of its limits are deliberate.
- Who is it for?
- ansible-vim suits a team editing Ansible on a small screen or over SSH who wants module keywords and name keys to stand out without leaving Vim, and it is the wrong tool for a team that wants validation, because it highlights and never checks your playbooks.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 155 days ago.
- What is it written in?
- Mainly Vim Script, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
It extends the original syntax instead of replacing it
There is a design decision at the centre of this plugin, and the documentation states it directly. The plugin sources the original formats and simply modifies the highlights as appropriate, and that is presented as the reason it should be reliable. The stated benefit is a focus on simplicity and configurability instead of patching bad syntax detection.
That is worth understanding, because it explains what the plugin does not do. It does not define a new syntax for Ansible. It takes the YAML syntax that already exists in your editor and adds Ansible awareness on top of it: module keywords, the name: key that modules use for self-documentation, and the key=value attribute syntax that Ansible modules use inside playbooks. Jinja2 templates get the same treatment, and files named hosts get the hosts file handling.
The audience is a Vim or Neovim user who writes Ansible and wants the editor to understand the domain a little. The plugin is written in Vim Script, it covers Ansible 2.x, and the licence is MIT. The repository is small and readable: UltiSnips, ftdetect, ftplugin, indent, lua, queries, syntax, tests, and a Makefile.
What it is not is a linter or a validator. Nothing here checks that your playbook is correct, and the plugin never talks to Ansible itself. The one place it comes closest is the UltiSnips generation script, which is discussed later.
Detection is folder names and file suffixes
Because the plugin extends existing syntax, it has to decide when to extend it, and that decision is a set of fairly literal rules.
A YAML file is treated as a playbook if it sits in a group_vars or host_vars folder, if it is in a tasks, roles or handlers folder and has a .yml or .yaml suffix, or if it is named playbook.yml, site.yml, main.yml, or the .yaml variants of those. A file with a .j2 suffix is a Jinja2 template. A file named hosts is an Ansible hosts file.
When the rules do not match your layout, you can set the filetype by hand with :set ft=yaml.ansible, or use the jinja2 and ansible_hosts filetypes, and the documentation suggests adding a rule of your own in your .vimrc for a custom pattern:
au BufRead,BufNewFile */playbooks/*.yml set filetype=yaml.ansibleOverriding the defaults works the same way, with an augroup so your autocommand does not pile up on repeated sourcing:
augroup ansible_vim_fthosts
autocmd!
autocmd BufNewFile,BufRead hosts setfiletype yaml.ansible
augroup ENDThe example given is a team that uses YAML syntax for its hosts file and wants those files highlighted as Ansible YAML. Note the filetype named in the manual note, :set ft=ruby.jinja2, which looks like a leftover from an earlier approach and is worth testing rather than trusting.
Neovim 0.12 takes a different road entirely
The plugin has two implementations, and the newer one is not a port of the older one.
For Neovim 0.12 and later, the plugin provides tree-sitter based highlighting with Jinja2 template expression support and semantic Ansible keyword highlighting, and it is installed with the built-in package manager:
vim.pack.add({ 'pearofducks/ansible-vim' })The lua and queries directories at the top of the repository are that implementation: a Lua module with a setup function, and tree-sitter queries. The Makefile shows how the pieces fit together. The test target runs Neovim headless with the runtime path extended to a sibling checkout of nvim-treesitter, turns on filetype, plugin and indent detection, calls require("ansible").setup(), sets the filetype to ansible, and then executes a Lua highlight test file. There is also a try target that opens a test playbook with a viewer and a try-clean target that starts with no configuration, which is the honest way to check the plugin in isolation.
The practical consequence is that the classic and tree-sitter paths will not behave identically, and a feature that exists in one may not exist in the other. The documentation points to a separate neovim section for setup instructions, which is where the differences are meant to be reconciled.
Five ways to install, and two of them are distro packages
Installation is well covered, which is not unusual for a Vim plugin but does make the choice easy.
For vim-plug, the declaration is a single line:
Plug 'pearofducks/ansible-vim'There is also a variant with a post-update hook, shown in the documentation as a Plug line with a do key pointing at ./UltiSnips/generate.sh, which regenerates the snippets after every update. That variant is worth understanding before you use it, because the script is where the plugin touches Ansible.
Vundle uses Plugin 'pearofducks/ansible-vim'. Pathogen is installed by cloning into your bundle directory:
git clone https://github.com/pearofducks/ansible-vim ~/.vim/bundle/ansible-vimNeovim's own package layout works too, by cloning into the start directory of a pack path:
git clone https://github.com/pearofducks/ansible-vim.git "${HOME}/.vim/pack/plugins/start/ansible-vim"And for people who would rather not manage a plugin at all, there is a vim-ansible package in the Arch community repository, in the default Fedora repository, and in EPEL for RHEL and CentOS.
The snippet generator needs a recent Ansible
The UltiSnips part deserves its own section, because the documentation attaches a real caveat to it.
The snippets are not checked in as static files. They are generated by a script, generate.sh, which you can point at with the vim-plug post-update hook. Two notes follow. The first is that because of Ansible API changes, generate.sh may require the latest or near-latest version of Ansible, which is a dependency the README is stating plainly: this script talks to Ansible, and it will break against an old installation. The second is that the script can receive parameters, with the details in the UltiSnips Readme in the repository.
So the trade is explicit. If you want the snippets, you need a current Ansible on the machine that runs the update, and the generation runs on every plugin update rather than once. If you do not need the snippets, you can install without the hook and keep the plugin purely as a highlighting layer with no dependency on Ansible being present at all.
The repository also carries a post-update hook note aimed at exactly this kind of user, and the UltiSnips directory is where the snippet definitions and the script live.
The options are flag strings, and most default to subtle
The configuration surface is a set of global variables, and the defaults are deliberately quiet.
g:ansible_attribute_highlight controls the key=value module attributes and the same syntax in hosts files. It takes a flag string, and the documentation marks the defaults in bold: o highlights only instances of key= found on newlines, and b brightens them. The other flags are a for all instances, d to dim, and n to turn the highlight off completely.
g:ansible_name_highlight does the same for the name: key that modules use for self-documentation, and it is off by default, with d and b as the two choices.
g:ansible_extra_keywords_highlight is enabled when set and disabled when not, and it lights up a long list of additional keywords including the become family, check_mode, diff, no_log, delegate_to, ignore_errors, max_fail_percentage, gather_facts, async, poll, throttle, timeout, run_once and serial. The default set is smaller and covers the module keywords, the include and import family, when, changed_when, failed_when, block, rescue, always, notify, listen, register, the pre_tasks and post_tasks style keys, and the loop keywords including with_.+, loop, loop_control, until, retries and delay.
The group names are configurable too, and each accepts any syntax group name from :help E669. g:ansible_extra_keywords_highlight_group defaults to Structure, while g:ansible_fqcn_highlight and g:ansible_normal_keywords_highlight default to Statement, and both fall back to Statement when not set. Two smaller ones round it out: g:ansible_unindent_after_newline resets indentation to column zero after two newlines in insert mode, which departs from normal YAML behaviour, and g:ansible_yamlKeyName exists for compatibility with stephpy/vim-yaml.
The FQCN dot is deliberately left to Vim
There is one gap the documentation is unusually candid about, and it is worth knowing before you file a bug.
Ansible fully qualified collection names contain a dot, as in a namespaced collection name. The plugin notes that the dot in the FQCN can also be highlighted, but only through a modification to a Vim syntax internal, and that this plugin will not do it automatically. In other words, the dot is left alone unless you patch Vim's own syntax handling, which the documentation links to a discussion of the technique.
That is a small thing, and it points at the plugin's overall philosophy: it extends rather than replaces, and where the underlying syntax engine has a limitation, the plugin does not work around it by rewriting the engine. The same reasoning explains the naming of the option for compatibility with another YAML plugin, which exists to interoperate rather than to fork.
The alternative to all of this is to use a plain YAML plugin and add the Ansible awareness yourself through ftplugin files and matchadd calls, which gives complete control and no dependency, but means every team member has to carry that configuration. ansible-vim's value is that the same awareness is available to everyone who installs it, and that its behaviour is documented rather than improvised.
Editorial conclusion
ansible-vim suits a team editing Ansible on a small screen or over SSH who wants module keywords and name keys to stand out without leaving Vim, and it is the wrong tool for a team that wants validation, because it highlights and never checks your playbooks. Verify first which path your editor takes, since Neovim 0.12 and later use the tree-sitter implementation under queries/ and lua/ while older setups use the classic syntax files, and note that the release history jumps from 3.4 in 2023 straight to 4.0 in April 2026, so the version you install changes what you get.
Frequently asked questions
How do I install ansible-vim in Vim or Neovim?
With vim-plug, add Plug 'pearofducks/ansible-vim'. Neovim 0.12 and later can use vim.pack.add({ 'pearofducks/ansible-vim' }). There are also pathogen, vundle, vim packages, and distro packages named vim-ansible for Arch, Fedora, RHEL and CentOS.
How does ansible-vim decide that a YAML file is an Ansible playbook?
A YAML file is treated as a playbook when it is in a group_vars or host_vars folder, when it is in a tasks, roles or handlers folder with a .yml or .yaml suffix, or when it is named playbook.yml, site.yml, main.yml or their .yaml equivalents. Files with a .j2 suffix are Jinja2 templates, and files named hosts are treated as hosts files.
What does the UltiSnips generate.sh script do in ansible-vim?
It generates the plugin's snippet definitions, and the documentation recommends running it through a vim-plug post-update hook. Because of Ansible API changes, generate.sh may require the latest or near-latest version of Ansible, and it can take parameters documented in the UltiSnips Readme.
Which options does ansible-vim expose?
Global variables such as g:ansible_attribute_highlight, g:ansible_name_highlight, g:ansible_extra_keywords_highlight, g:ansible_extra_keywords_highlight_group, g:ansible_fqcn_highlight, g:ansible_normal_keywords_highlight, g:ansible_unindent_after_newline and g:ansible_yamlKeyName. The highlight group options accept any syntax group name listed in :help E669.
Does ansible-vim validate playbooks or check for errors?
No. It is a syntax highlighting plugin that extends the original YAML and Jinja2 formats with Ansible awareness. The only component that talks to Ansible itself is the snippet generation script, and the README does not document any linting or validation feature.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pearofducks-ansible-vim)