Metadata-Version: 2.4
Name: iaclineage
Version: 0.1.0
Summary: Local Terraform source explorer
Author: Mayur Mahajan
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/mayurmhjn/iaclineage
Project-URL: Repository, https://github.com/mayurmhjn/iaclineage
Project-URL: Issues, https://github.com/mayurmhjn/iaclineage/issues
Project-URL: Changelog, https://github.com/mayurmhjn/iaclineage/blob/main/CHANGELOG.md
Project-URL: Security, https://github.com/mayurmhjn/iaclineage/security/policy
Keywords: terraform,lineage,static-analysis,infrastructure-as-code
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: tree-sitter==0.26.0
Requires-Dist: tree-sitter-hcl==1.2.0
Dynamic: license-file

# IaCLineage

Explore Terraform declarations and trace their source references from a local
checkout. IaCLineage provides a Python CLI and a self-contained HTML report with
searchable declarations, field-level lineage, and source locations.

No Terraform execution, cloud credentials, server, or network access is required
to analyze source or open a report. The current version is 0.1.0.

<img src="docs/images/demo.gif" alt="IaCLineage: search a declaration and trace its dependencies"/>

## Installation

Requires Python 3.12 or newer. Install from PyPI:

```sh
pip install iaclineage
iaclineage --version
```

To upgrade an existing installation, run `pip install --upgrade iaclineage`.
To explicitly select the latest beta, add `--pre` to the upgrade command.
Cloning this repository is only needed for source development.

See the [tester guide](https://github.com/mayurmhjn/iaclineage/blob/main/docs/tester-guide.md) for TestPyPI installation and the
[platform guide](https://github.com/mayurmhjn/iaclineage/blob/main/docs/platform-support.md) for Windows, Linux, and macOS setup.

## Quick start

Point the CLI at a Terraform root module. Replace these paths with directories
on your machine; the output directory must already exist.

If the project uses registry or remote modules, download their source before
running IaCLineage. Run this inside each Terraform project root:

```sh
cd /path/to/terraform
terraform get
```

[`terraform get`](https://developer.hashicorp.com/terraform/cli/commands/get)
requires Terraform and any credentials needed to download private modules.
Keep the default `.terraform/modules` cache. If the required modules are already
downloaded, this step is unnecessary. Projects using only local modules can skip it.

Then inspect the project:

```sh
iaclineage scan /path/to/terraform
iaclineage find /path/to/terraform aws_vpc.main
iaclineage report /path/to/terraform --format interactive-html --output /path/to/reports/lineage.html
```

Open `lineage.html` locally in Chrome or Edge. Select a declaration, choose a
field, then trace **Upstream**, **Downstream**, or **Both**. References include
the consuming field, target, resolution status, and source range. The report
works offline and can be shared as a single file.

Local module calls are followed automatically, including relative paths outside
the scanned directory. IaCLineage reads downloaded modules through
`.terraform/modules/modules.json`; it never runs Terraform or downloads modules.
Missing remote-module source produces `IAC103` diagnostics and leaves references
into those modules unresolved. The available local source can still be inspected.

## Find declarations

`find` accepts a full IaCLineage address, a standard Terraform resource address,
`var.NAME` for a variable, or a declaration's final name. Exact full addresses
take precedence.

```sh
iaclineage find . aws_vpc.main
iaclineage find . resource.aws_vpc.main
iaclineage find . main
iaclineage find . var.region
iaclineage find . provider.aws.west
iaclineage find . aws --format json
iaclineage find . aws_vpc.main --format json --output /path/to/results.json
```

Provider aliases have distinct addresses: `provider.aws` and
`provider.aws.west`. Searching `aws` lists matching provider configurations.
Explicit `provider = aws.west` bindings on resources, data sources, and imports
link to the declared provider. Duplicate target addresses remain ambiguous.

Child-module addresses include the call path, such as
`module.network.resource.aws_vpc.main`; `module.network.aws_vpc.main` also works
with `find`. Scanning a directory with no root `.tf` files discovers independent
projects beneath it, each with a prefix such as `production::`.

Text and JSON use the same search exit codes:

| Result | Exit code | JSON shape |
| --- | --- | --- |
| One match | `0` | `{ "query": "...", "match": { ... } }` |
| Multiple matches | `1` | `{ "query": "...", "matches": [ ... ] }` |
| No match | `1` | `{ "error": "no match", "query": "..." }` |

Multiple matches include every declaration and its location. Refine the query
when possible. Progress and diagnostics go to stderr, leaving stdout suitable
for JSON consumers. Use `--color never` before the command to disable color.

## Trace lineage

`trace` follows references from one declaration across files and modules. It
accepts the same queries as `find`.

```sh
iaclineage trace . output.app_id --direction up
iaclineage trace . variable.region --direction down --depth 2
iaclineage trace . aws_vpc.main --format json --output /path/to/trace.json
```

`--direction up` follows what the declaration uses, `down` follows what uses
it, and `both` (the default) prints both lists. Each hop shows its depth, the
two declarations, the edge kind, the resolution state, the source range of the
reference, and the field or module argument that holds it. `A -> B` always means A uses B. `--depth N` stops after N hops;
without it the trace continues until nothing new is reachable, and a cycle is
listed once instead of being followed again.

When a trace passes through a module call, it continues only through the
argument it arrived by and to readers of the whole module, so tracing one input
does not pull in the module's other inputs. A reference to the whole module
object, such as `module.app`, `module.app[*].id`, or `depends_on =
[module.app]`, connects the call to its outputs with a `module-output` hop. A
trace stops at unresolved targets. It works on whole declarations; to narrow a
trace to one field, use the interactive report. Like `find`, `trace` exits `1`
when the query does not match exactly one declaration.

## Reports

```sh
# Interactive explorer
iaclineage report . --format interactive-html --output /path/to/reports/lineage.html

# Static HTML summary (the default format)
iaclineage report . --output /path/to/reports/summary.html

# Structural JSON
iaclineage report . --format json --output /path/to/reports/lineage.json
```

Reports exclude raw source values by default. To inspect source in a trusted
local interactive report, use `--include-source-values`:

```sh
# Interactive report with raw source values
iaclineage report . --format interactive-html --include-source-values --output /path/to/reports/lineage-with-source.html
```

This option is available only with `--format interactive-html`. The resulting
file can contain secrets, comments, and literal values; review it before sharing.
Keep report files outside scanned repositories and followed modules.

The interactive report includes declaration and field search, project and kind
filters, module input/output connections, conditional evidence, and a resizable
lineage workspace. See the [interactive report guide](https://github.com/mayurmhjn/iaclineage/blob/main/docs/interactive-report.md)
for controls and tracing behavior.

## Unused declarations

`unused` lists variables, locals, and child-module outputs that no expression
references:

```sh
iaclineage unused /path/to/terraform
```

Each line gives the address, kind, and source location. The command exits `1`
when it finds anything and `0` when it finds nothing, so it can run in CI.

A variable counts as unused when a module call sets it but nothing inside the
module reads it. References from a variable's own `validation` block do not
count. A reference to a whole module object, such as `module.app` or
`module.app[*].id`, uses all of that module's outputs; `depends_on` and `moved`
blocks do not. When several calls share one module source, a declaration in it
is reported only if no call uses it. Root module outputs are skipped because
they are read from outside the configuration, and so are declarations inside
downloaded modules under `.terraform`. IaCLineage only sees static references,
so check each result before deleting it.

## CI checks

`report --fail-on` writes the report as usual, then exits `1` if any reference
has one of the listed resolution states:

```sh
iaclineage report . --format json --output /path/to/reports/lineage.json --fail-on unresolved,ambiguous
```

Accepted states are `unresolved` and `ambiguous`. References into remote modules
whose source has not been downloaded stay unresolved, so run `terraform get`
first when the configuration uses them. Provider aliases that a child module
receives through a `providers` map also stay unresolved, because IaCLineage does
not follow those mappings. Attribute names in `lifecycle { ignore_changes =
[...] }` and the old address in a `moved` block's `from` are reported as
unresolved too.

## Use with coding agents

The `skills/iaclineage` folder is an agent skill. It tells coding agents such as
Claude Code and Codex when to run IaCLineage, which commands answer which
questions, and how to read the results. Install it with the
[skills CLI](https://skills.sh/):

```sh
npx skills add mayurmhjn/iaclineage
```

The skill does not install IaCLineage itself. Install the CLI as described in
[Installation](#installation).

## Analysis scope

- Analyzes `.tf` source using a parser; does not read plan/state JSON or evaluate Terraform.
- Resolves declarations and static references across local and installed modules.
- Treats dynamic-block and comprehension iterators as local symbols. Built-ins
  such as `terraform.workspace`, `path.module`, `each`, and `count` do not create entity edges.
- Keeps references in iterator collections and other external expressions.
  Iterator values themselves are not evaluated or expanded into infrastructure instances.
- Reports missing module sources and parse recovery as diagnostics. Unresolved
  references remain visible; source resolution does not verify provider-computed values.
- Does not resolve implicit provider inheritance or module `providers` mappings.
  Custom `TF_DATA_DIR` and remote state resolution are unsupported.

A missing source reference does not prove runtime independence. Tracing stops
at expression and instance-selection boundaries. Installed module snapshots
also do not prove cache freshness or version-constraint satisfaction.

## Development

```sh
uv sync --locked --group dev
uv run --no-sync pytest
node --test tests/test_lineage_ui.cjs
npm ci --ignore-scripts
npm run test:browser
```

Node and Playwright are developer tools only. Browser setup and native-platform
checks are documented in the [platform guide](https://github.com/mayurmhjn/iaclineage/blob/main/docs/platform-support.md).
See [CONTRIBUTING.md](https://github.com/mayurmhjn/iaclineage/blob/main/CONTRIBUTING.md) for contribution guidelines and
[CHANGELOG.md](https://github.com/mayurmhjn/iaclineage/blob/main/CHANGELOG.md) for release notes.

Report bugs through [GitHub Issues](https://github.com/mayurmhjn/iaclineage/issues)
with the installed version and a synthetic example. Report security issues
privately as described in [SECURITY.md](https://github.com/mayurmhjn/iaclineage/blob/main/SECURITY.md).

Licensed under [Apache License 2.0](https://github.com/mayurmhjn/iaclineage/blob/main/LICENSE).
