untaped-ansible
Install it as part of untaped: uv tool install 'untaped[ansible]' or pip install 'untaped[ansible]'.
To add it to an existing install, see Getting started.
untaped ansible answers questions about how Ansible roles and projects
depend on each other through their requirements files:
| Command | Question | Output |
|---|---|---|
deps ROLE |
What does ROLE depend on (downstream)? | one ansible.dependency row per repo reached, per ROLE ref |
impact ROLE |
What depends on ROLE (upstream)? | one ansible.dependent row per repo reached, per ROLE ref |
find REPO --root ROOT / --stdin |
Which roots contain REPO downstream? | one ansible.dependency_match row per match |
graph TARGET |
The whole picture, both directions | a tree, Mermaid diagram or JSON graph |
Downstream works from live GitHub reads. Upstream needs a source: a saved
set of orgs, teams or repos whose dependency files untaped scans and caches.
The packaged skill is the full reference: sources and refreshes and graph resolution and output.
Set up
untaped ansible reads GitHub through the github settings, so set a GitHub
token first (see GitHub):
untaped config set github.token --prompt
Private repos also need Git access over HTTPS with that token, or over SSH
when ansible.git_clone_protocol is ssh.
Save a source, refresh it once, and make it the default so you can leave out
--source:
untaped ansible source set platform --org acme --team acme/platform
untaped ansible source refresh platform
untaped config set ansible.default_source platform
ansible.default_source is used by deps, impact, find and graph
whenever you give neither --source nor an inline selector. With a source
selected, every command reads the cached data and never touches GitHub; pass
--live to read downstream dependencies from GitHub anyway.
Scanned files, clone protocol, cache locations and refresh tuning are in the configuration reference.
Show what a role depends on
untaped ansible deps acme/base-role
untaped ansible deps acme/base-role --ref v2.1.0 --depth 2
untaped ansible deps ./roles/web --target-repo acme/web --format json
ROLE is owner/repo, a GitHub URL, a source alias, or a local path (for a
subdirectory of a checkout, add --target-repo OWNER/NAME).
Without a source, deps reads GitHub live. With one, it reads the source's
cache: a role outside the source gets a "not cached" warning and no rows.
Pass --live to read GitHub anyway. The same holds for find and for
graph's downstream half. Collections in requirements files are not
followed; the command warns once and lists them.
Find what depends on a role
untaped ansible impact acme/base-role
untaped ansible impact acme/base-role --source platform --refresh
untaped ansible impact acme/base-role --ref main --format pipe
impact reads cached source data only: from --source NAME (repeat to
combine), from inline selectors, or from ansible.default_source. Pass
--refresh (or run source refresh) when you want current data. For a
one-off question, use inline selectors instead of a saved source; the scan is
cached, so repeating the same command reuses it:
untaped ansible impact acme/base-role --org acme --refresh
Find which roots contain a repository
find REPO walks the downstream graph of each root and prints one row per
node of REPO it reaches, and nothing for roots that never reach it. Give
roots with --root (repeatable) or through --stdin, and one or more repos
to look for:
untaped ansible find acme/base-role --root acme/site@main --root acme/app
printf 'acme/site@main\nacme/app@v2.1.0\nacme/tools\n' \
| untaped ansible find acme/base-role --stdin
untaped awx job-templates list --organization Default --with-scm --format pipe \
| untaped ansible find acme/base-role --stdin --format pipe
A root is owner/repo@ref (the ref is optional), a Git URL, a source alias,
or a local path. Stdin carries either such lines or --format pipe records
naming a repository and ref, such as AWX job templates.
Each ansible.dependency_match row names the root, the matched repo, the
dependency file and the shortest path from the root, plus the input
record's kind, id and name. Every input record gets its own rows, so a
pipeline can join the results back to its inputs.
Draw the graph
untaped ansible graph acme/base-role
untaped ansible graph acme/base-role --direction down --format mermaid --out deps.mmd
untaped ansible graph acme/base-role --direction up --depth 2 --format json
graph shows both directions by default; --direction up shows only what
depends on the target and --direction down only what it depends on.
Without a source it shows only downstream and warns that upstream was
omitted. The tree looks like this:
acme/base-role@main source platform · unlimited depth
used by
└── acme/site@main roles/requirements.yml · unpinned
depends on
├── acme/legacy@v1 meta/main.yml
│ └── acme/shared@main [1] meta/main.yml · unpinned
│ └── acme/leaf@main requirements.yml
└── acme/users@v1.2.0 requirements.yml
└── acme/shared@main see [1] requirements.yml · unpinned
5 repos · 6 edges
The first line names the target, where the data came from and the depth.
After each repo comes the file that declares that dependency, plus
unpinned when it names no version, or pins X when the declared version
differs from the ref it resolved to. A repo marked … with a not read:
note is stopped: its own dependencies (or dependents) were not read, because
--depth ran out (depth) or its ref is not in the source's cache
(not_cached), so the graph beyond it may be incomplete. The
graph reference lists every marker.
Flags
deps, impact, find and graph share their options:
--source NAME(repeatable) picks saved sources; inline--org,--teamand--reposelectors describe a one-off source instead. Without either,ansible.default_sourceis used.--refreshrefreshes the source first;--livereads downstream from GitHub even with a source (impacthas no--live).--depth Nlimits the walk; the default isunlimited.--ref REFpicks the target's branch, tag or SHA; without it, what the target depends on is read at its default branch, and--all-refsreads every cached ref instead. What depends on a target always covers all of its refs, since a repo pinning an older tag still uses it.
A table shortens each path to its first and last hop (a → … → z);
other formats keep it whole.
Manage sources
untaped ansible source status
untaped ansible source patch platform --add-repo acme/legacy-app --remove-team acme/platform
untaped ansible source remove platform --dry-run
source set NAME creates or replaces a source from --org, --team and
--repo; source patch NAME edits it with --add-*, --remove-* and
--clear-*. source status shows whether each source is fresh, stale
or not_refreshed.
source refresh saves each repo that succeeds. When some repos fail it
lists them and exits non-zero; run it again to retry only those. A large
refresh that runs low on GitHub API budget stops early, exits 5 and resumes
where it left off when you run it again. Backends, rate-limit fallbacks and
tuning are in the
sources reference.
Source aliases
When a requirements file names a role by Galaxy name rather than a Git URL, map it to its repo:
untaped ansible source-alias set acme.base acme/ansible-role-base
untaped ansible source refresh platform
Source aliases apply when a source is refreshed, which is why the refresh follows.
Read the output
stoppedon a row or node (depthornot_cached) means the next level beyond that repo was not read: its dependencies fordeps, its dependents forimpact. Treat the answer as incomplete there.- Each repo appears once per root ref, at its shortest path;
root_refsays which ROLE ref a row came from. - A dependency at
repo@v1and one atrepo@mainare different nodes; an unpinned dependency points at the dependency's default-branch node. - A cycle is found only within the depth you asked for.
- A malformed or templated dependency file is skipped with a warning; it never fails the command.
Every row field, the tree markers and the JSON graph shape are in the graph reference.
Troubleshooting
- "no cached source data found": the source was never refreshed. Run the
source refreshcommand the error prints, or add--refresh. - An older index is rebuilt: after an upgrade the SQLite cache
(
ansible.index_path) may be rebuilt empty with a warning. Refresh each source again.
Output
See Scripting and Exit codes.
See also
Metadata
Release files for untaped-ansible 10.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| untaped_ansible-10.0.0.tar.gz | 81.9 kB | With provenance | Details for untaped_ansible-10.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| untaped_ansible-10.0.0-py3-none-any.whl | Python 3 | none | any | Details for untaped_ansible-10.0.0-py3-none-any.whl |
Total release size: 186.4 kB
Release files / untaped_ansible-10.0.0.tar.gz
| Download URL | untaped_ansible-10.0.0.tar.gz |
|---|---|
| Size | 81.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
527c8954ff90b12b43b1813a31f0d7dab3a2c573723c3b680d5f4483b5ca1c4b
|
|
BLAKE2b-256 checksum How to use checksums |
c0d37782227414794f76b5fd6660613e94e6092ede924df7dbf50a1bf0f12a23
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency logRelease files / untaped_ansible-10.0.0-py3-none-any.whl
| Download URL | untaped_ansible-10.0.0-py3-none-any.whl |
|---|---|
| Size | 104.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0731df6fe0fc5271185c1c2601732e5008d25591393c27496517f1b403e9e48b
|
|
BLAKE2b-256 checksum How to use checksums |
7c1466fcd57a2cf41c24fb848919b310ab0b80b899bcd3567d1fa0dbebf38fd8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency logSecurity for untaped-ansible 10.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for untaped_ansible-10.0.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.