JetBrains IDE plugin
Go to definition, for Ansible variables.
Ctrl-click a variable and Yamlix lists every place it is defined — ordered by the one that actually applies at your caret.
- 8500set_factroles/app/tasks/main.ymlapplies here
- 8100include_varsroles/app/vars/Darwin.yml
- 8090role varsroles/app/vars/main.yml
- 8070vars_filesvars/common.yml
- 8060play varssite-playbook.yml
- 8050host_varsinventories/stag/host_vars/stag-web-1.yml
- 8040group_varsinventories/stag/group_vars/canary.yml
- 8030group_varsinventories/stag/group_vars/webservers.yml
- 8020group_varsinventories/stag/group_vars/platform.yml
- 8010group_vars/allinventories/stag/group_vars/all.yml
- 8000role defaultsroles/app/defaults/main.yml
Reconstruction of the go-to-definition list, not a screenshot. The order is by what applies at the caret, not alphabetical or by file.
Why the answer is hard
The winner moves with the caret
Precedence is not a property of a variable. It is a property of a position in a play.
Below is the same variable in the same repository, read at four positions in one playbook, for two hosts. The first two rows agree. The third does not, because the set_fact that produces 8500 sits behind a when: that is true on staging and false on production.
Same file. Same line. Two answers. Grep cannot tell you which one you are about to ship, and neither can reading the precedence table, because the table does not know where your caret is.
| Caret position | In the play | stag-web-1 | prod-web-1 | Winning level |
|---|---|---|---|---|
| site-playbook.yml:21 | pre_tasks, before any role has run | 8090 | 8090 | role vars |
| roles/app/tasks/main.yml:11 | inside the role, after include_vars | 8100 | 8100 | include_vars |
| roles/app/tasks/configure.yml:4 | after a set_fact guarded by when: | 8500 | 8100 | set_fact on stag, include_vars on prod |
| site-playbook.yml:41 | post_tasks, after every role | 8500 | 8100 | set_fact on stag, include_vars on prod |
What it does
Four things, in the places you already look
Ctrl-click a variable
⌘-click on macOSLists every definition site, ordered by what applies at the caret rather than alphabetically. The definition you are looking for is the one your eye lands on first, not the one that happens to start with an early letter.
Quick Documentation
Shows the effective value per inventory and per host, collapsing the hosts that agree. Where twenty hosts resolve to the same value and one does not, you see two rows, and the interesting one is not buried.
A tool window for the open file
Lists every variable the file uses and defines, its effective value, and each definition site under the Ansible precedence level it sits at. Definitions that lost are folded behind one row, so the list stays the length of the question rather than the length of the repository. It also shows which playbooks reach the file, and which hosts that means.
Open an inventory instead and it lists that inventory's groups: host counts, child groups, the group_vars that apply, and every play whose hosts: pattern selects each group — including the groups nothing targets.
There is also completion for variable names and hosts: patterns, and an inspection that reports roles, includes and file references resolving to nothing.
The design decision
Unresolved is an answer
Some things cannot be known from a repository. The plugin says so instead of picking one.
Gathered facts, register, hostvars, lookup(), vault: none of these exist until the play runs. Where a value depends on them, Yamlix reports it as unresolved and shows the raw template exactly as written, rather than expanding it into a value that may be wrong.
The same rule holds for a fact-templated include_vars. Its target is not one file but a set, so the plugin lists every candidate and promotes none of them. The variable still resolves — to the highest-precedence definition that does not depend on run time — and the candidates are shown alongside it.
A tool that guesses correctly nine times out of ten cannot be trusted the tenth time, which is the time you needed it. Yamlix would rather show you a template than a plausible number.
- 8100include_varsroles/app/vars/Darwin.ymlneeds facts
- 8200include_varsroles/app/vars/RedHat.ymlneeds facts
- 8090role varsroles/app/vars/main.ymlapplies here
Extra vars (-e) override everything and are not visible from a repository.
Getting it
Install
Requires a JetBrains IDE, build 2025.2 or newer. No upper bound is declared.
Awaiting approval
The plugin has been submitted to the JetBrains Marketplace and is awaiting moderation. Until the listing is live, install the release zip from disk.
Download the latest release from GitHub
- Download the plugin zip from the GitHub releases page.
- In the IDE, open Settings, then Plugins.
- Open the gear menu beside the Marketplace tab and choose Install plugin from disk…
- Select the downloaded zip and restart the IDE when prompted.
This page will describe the Marketplace route instead once the listing is approved.
Where it runs
Verified by the JetBrains Plugin Verifier against
- IntelliJ IDEA Community
- IntelliJ IDEA Ultimate
- PyCharm
- GoLand
Runs in
Yamlix depends only on the platform and the bundled YAML support, so it runs in any JetBrains IDE, not only IntelliJ IDEA. The four products above are the ones actually tested; the rest are expected to work but have not been verified.
If it does not fit your project
There is no one way to lay out an Ansible project
Yamlix works out your project's structure rather than assuming a convention. It has not seen every arrangement.
All of these are normal, and they are not the only options
- ansible.cfg at the repository root — or in a subdirectory, or not present at all
- one inventory file, or a directory per environment, or both at once
- roles/ beside the playbooks, or a roles_path pointing somewhere else entirely
- collections vendored under collections/ansible_collections/
- several unrelated Ansible projects sharing one repository
- playbooks run from a wrapper script that changes directory first
If a variable is reported as undefined when it plainly is defined, or roles and inventories that exist are not being found, that is usually the layout detection rather than the resolution — and it is worth reporting.
Open an issue with your project's structure: the directory tree from the repository root, plus your ansible.cfg, is normally enough to reproduce it. A link to the repository, if it is public, is better still. Working around it on your side is the wrong fix; I would rather teach the plugin the layout.
What it is not
It is not a linter, and it does not replace ansible-lint. It is not a replacement for the official Red Hat Ansible plugin either — that one knows about modules, syntax and playbook structure, and Yamlix does not try to.
Yamlix answers one question those tools do not: given this file, this host and this position, which definition of this variable applies. Run it alongside them.
What it does to your project
Nothing. Yamlix reuses the platform's YAML support rather than registering a file type of its own, so it does not claim *.yml and does not change how your files open. Ansible context is detected structurally, per file.
It never shells out to ansible, makes no network calls, and collects no data of any kind. There is no telemetry to opt out of, and this site carries no analytics or third-party scripts.