python-hcl2 8.0.0rc2__tar.gz → 8.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/CHANGELOG.md +7 -6
  2. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/CLAUDE.md +65 -5
  3. {python_hcl2-8.0.0rc2/python_hcl2.egg-info → python_hcl2-8.1.0}/PKG-INFO +36 -7
  4. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/README.md +35 -6
  5. python_hcl2-8.1.0/cli/hcl_to_json.py +465 -0
  6. python_hcl2-8.1.0/cli/helpers.py +254 -0
  7. python_hcl2-8.1.0/cli/hq.py +870 -0
  8. python_hcl2-8.1.0/cli/json_to_hcl.py +462 -0
  9. python_hcl2-8.1.0/docs/01_getting_started.md +264 -0
  10. python_hcl2-8.1.0/docs/02_querying.md +221 -0
  11. python_hcl2-8.1.0/docs/03_advanced_api.md +147 -0
  12. python_hcl2-8.1.0/docs/04_hq.md +667 -0
  13. python_hcl2-8.1.0/docs/05_hq_examples.md +207 -0
  14. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/__init__.py +1 -0
  15. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/api.py +12 -0
  16. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/deserializer.py +32 -7
  17. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/hcl2.lark +30 -2
  18. python_hcl2-8.1.0/hcl2/query/__init__.py +46 -0
  19. python_hcl2-8.1.0/hcl2/query/_base.py +120 -0
  20. python_hcl2-8.1.0/hcl2/query/attributes.py +51 -0
  21. python_hcl2-8.1.0/hcl2/query/blocks.py +100 -0
  22. python_hcl2-8.1.0/hcl2/query/body.py +124 -0
  23. python_hcl2-8.1.0/hcl2/query/builtins.py +115 -0
  24. python_hcl2-8.1.0/hcl2/query/containers.py +53 -0
  25. python_hcl2-8.1.0/hcl2/query/diff.py +88 -0
  26. python_hcl2-8.1.0/hcl2/query/expressions.py +27 -0
  27. python_hcl2-8.1.0/hcl2/query/for_exprs.py +112 -0
  28. python_hcl2-8.1.0/hcl2/query/functions.py +35 -0
  29. python_hcl2-8.1.0/hcl2/query/introspect.py +186 -0
  30. python_hcl2-8.1.0/hcl2/query/path.py +258 -0
  31. python_hcl2-8.1.0/hcl2/query/pipeline.py +474 -0
  32. python_hcl2-8.1.0/hcl2/query/predicate.py +570 -0
  33. python_hcl2-8.1.0/hcl2/query/resolver.py +350 -0
  34. python_hcl2-8.1.0/hcl2/query/safe_eval.py +165 -0
  35. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/reconstructor.py +73 -0
  36. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/base.py +2 -2
  37. python_hcl2-8.1.0/hcl2/rules/directives.py +429 -0
  38. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/expressions.py +32 -0
  39. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/strings.py +51 -6
  40. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/tokens.py +7 -0
  41. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/whitespace.py +40 -16
  42. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/transformer.py +118 -0
  43. python_hcl2-8.1.0/hcl2/version.py +24 -0
  44. python_hcl2-8.1.0/hcl2/walk.py +62 -0
  45. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/pylintrc +4 -1
  46. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/pyproject.toml +2 -1
  47. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0/python_hcl2.egg-info}/PKG-INFO +36 -7
  48. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/python_hcl2.egg-info/SOURCES.txt +25 -1
  49. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/python_hcl2.egg-info/entry_points.txt +1 -0
  50. python_hcl2-8.0.0rc2/cli/hcl_to_json.py +0 -138
  51. python_hcl2-8.0.0rc2/cli/helpers.py +0 -96
  52. python_hcl2-8.0.0rc2/cli/json_to_hcl.py +0 -136
  53. python_hcl2-8.0.0rc2/docs/usage.md +0 -306
  54. python_hcl2-8.0.0rc2/hcl2/version.py +0 -34
  55. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.codacy.yml +0 -0
  56. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.coveragerc +0 -0
  57. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.github/CODEOWNERS +0 -0
  58. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.github/ISSUE_TEMPLATE/hcl2-parsing-error.md +0 -0
  59. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.github/workflows/codeql-analysis.yml +0 -0
  60. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.github/workflows/dependencies_check.yml +0 -0
  61. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.github/workflows/pr_check.yml +0 -0
  62. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.github/workflows/publish.yml +0 -0
  63. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.github/workflows/security.yml +0 -0
  64. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.gitignore +0 -0
  65. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.pre-commit-config.yaml +0 -0
  66. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/.yamllint.yml +0 -0
  67. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/LICENSE +0 -0
  68. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/MANIFEST.in +0 -0
  69. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/bin/check_deps.py +0 -0
  70. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/bin/terraform_test +0 -0
  71. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/cli/__init__.py +0 -0
  72. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/__main__.py +0 -0
  73. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/builder.py +0 -0
  74. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/const.py +0 -0
  75. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/formatter.py +0 -0
  76. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/parser.py +0 -0
  77. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/postlexer.py +0 -0
  78. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/__init__.py +0 -0
  79. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/abstract.py +0 -0
  80. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/containers.py +0 -0
  81. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/for_expressions.py +0 -0
  82. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/functions.py +0 -0
  83. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/indexing.py +0 -0
  84. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/rules/literal_rules.py +0 -0
  85. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/hcl2/utils.py +0 -0
  86. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/mypy.ini +0 -0
  87. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/python_hcl2.egg-info/dependency_links.txt +0 -0
  88. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/python_hcl2.egg-info/not-zip-safe +0 -0
  89. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/python_hcl2.egg-info/requires.txt +0 -0
  90. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/python_hcl2.egg-info/top_level.txt +0 -0
  91. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/reports/.gitignore +0 -0
  92. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/requirements.txt +0 -0
  93. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/setup.cfg +0 -0
  94. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/test-requirements.txt +0 -0
  95. {python_hcl2-8.0.0rc2 → python_hcl2-8.1.0}/tox.ini +0 -0
@@ -9,15 +9,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
9
9
 
10
10
  - Nothing yet.
11
11
 
12
- ## \[8.0.0\] - rc2
12
+ ## \[8.1.0\] - 2026-04-07
13
13
 
14
14
  ### Added
15
15
 
16
16
  - Full architecture overhaul: bidirectional HCL2 ↔ JSON pipeline with typed rule classes. ([#203](https://github.com/amplify-education/python-hcl2/pull/203))
17
- - add function tuples round-trip test suite ([#268](https://github.com/amplify-education/python-hcl2/pull/268))
18
- - Add postlexer to support multiline binary operators and ternary expressions ([#270](https://github.com/amplify-education/python-hcl2/pull/270))
19
- - more robust whitespace handling in reconstruction ([#271](https://github.com/amplify-education/python-hcl2/pull/271))
20
- - SerializationOptions - add an option to strip string quotes in dict/JSON output ([#272](https://github.com/amplify-education/python-hcl2/pull/272))
17
+ - `hq` read-only query CLI for HCL2 files ([#277](https://github.com/amplify-education/python-hcl2/pull/277))
18
+ - Agent-friendly conversion CLIs: `hcl2tojson` and `jsontohcl2` ([#274](https://github.com/amplify-education/python-hcl2/pull/274))
19
+ - Add template directives support (`%{if}`, `%{for}`) in quoted strings ([#276](https://github.com/amplify-education/python-hcl2/pull/276))
20
+ - Support loading comments ([#134](https://github.com/amplify-education/python-hcl2/issues/134))
21
21
  - CLAUDE.md ([#260](https://github.com/amplify-education/python-hcl2/pull/260))
22
22
 
23
23
  ### Fixed
@@ -34,7 +34,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
34
34
  - Interpolation literals added to locals/variables in maps ([#252](https://github.com/amplify-education/python-hcl2/issues/252))
35
35
  - Object literal expression can't be serialized ([#253](https://github.com/amplify-education/python-hcl2/issues/253))
36
36
  - Heredocs should interpret backslash literally ([#262](https://github.com/amplify-education/python-hcl2/issues/262))
37
- - Parsing a multi-line multi-conditional expression causes exception - Unexpected token Token('QMARK', '?') ([#269](https://github.com/amplify-education/python-hcl2/issues/269))
37
+ - Parsing a multi-line multi-conditional expression causes exception Unexpected token Token('QMARK', '?') ([#269](https://github.com/amplify-education/python-hcl2/issues/269))
38
+ - Parsing error for multiline binary operators ([#246](https://github.com/amplify-education/python-hcl2/pull/246))
38
39
 
39
40
  ### Changed
40
41
 
@@ -23,11 +23,30 @@ The **Direct** pipeline (`parse_to_tree` → `transform` → `to_lark` → `reco
23
23
  | `hcl2/formatter.py` | Whitespace alignment and spacing on LarkElement trees |
24
24
  | `hcl2/reconstructor.py` | LarkElement tree → HCL2 text via Lark |
25
25
  | `hcl2/builder.py` | Programmatic HCL document construction |
26
+ | `hcl2/walk.py` | Generic tree-walking primitives for the LarkElement IR tree |
26
27
  | `hcl2/utils.py` | `SerializationOptions`, `SerializationContext`, string helpers |
27
28
  | `hcl2/const.py` | Constants: `IS_BLOCK`, `COMMENTS_KEY`, `INLINE_COMMENTS_KEY` |
28
29
  | `cli/helpers.py` | File/directory/stdin conversion helpers |
29
30
  | `cli/hcl_to_json.py` | `hcl2tojson` entry point |
30
31
  | `cli/json_to_hcl.py` | `jsontohcl2` entry point |
32
+ | `cli/hq.py` | `hq` CLI entry point — query dispatch, formatting, optional operator |
33
+ | `hcl2/query/__init__.py` | Public query API exports |
34
+ | `hcl2/query/_base.py` | `NodeView` base class, view registry, `view_for()` factory |
35
+ | `hcl2/query/body.py` | `DocumentView`, `BodyView` facades for top-level and body queries |
36
+ | `hcl2/query/blocks.py` | `BlockView` facade for block queries |
37
+ | `hcl2/query/attributes.py` | `AttributeView` facade for attribute queries |
38
+ | `hcl2/query/containers.py` | `TupleView`, `ObjectView` facades for container queries |
39
+ | `hcl2/query/expressions.py` | `ConditionalView` facade for conditional expressions |
40
+ | `hcl2/query/functions.py` | `FunctionCallView` facade for function call queries |
41
+ | `hcl2/query/for_exprs.py` | `ForTupleView`, `ForObjectView` facades for for-expressions |
42
+ | `hcl2/query/path.py` | Structural path parser (`PathSegment`, `parse_path`, `[select()]`, `type:name`) |
43
+ | `hcl2/query/resolver.py` | Path resolver — segment-by-segment with label depth, type filter |
44
+ | `hcl2/query/pipeline.py` | Pipe operator — `split_pipeline`, `classify_stage`, `execute_pipeline` |
45
+ | `hcl2/query/builtins.py` | Built-in transforms: `keys`, `values`, `length` |
46
+ | `hcl2/query/diff.py` | Structural diff between two HCL documents |
47
+ | `hcl2/query/predicate.py` | `select()` predicate tokenizer, recursive descent parser, evaluator |
48
+ | `hcl2/query/safe_eval.py` | AST-validated Python expression eval for hybrid/eval modes |
49
+ | `hcl2/query/introspect.py` | `--describe` and `--schema` output generation |
31
50
 
32
51
  `hcl2/__main__.py` is a thin wrapper that imports `cli.hcl_to_json:main`.
33
52
 
@@ -41,10 +60,11 @@ The **Direct** pipeline (`parse_to_tree` → `transform` → `to_lark` → `reco
41
60
  | `rules/containers.py` | `TupleRule`, `ObjectRule`, `ObjectElemRule`, `ObjectElemKeyRule` |
42
61
  | `rules/expressions.py` | `ExprTermRule`, `BinaryOpRule`, `UnaryOpRule`, `ConditionalRule` |
43
62
  | `rules/literal_rules.py` | `IntLitRule`, `FloatLitRule`, `IdentifierRule`, `KeywordRule` |
44
- | `rules/strings.py` | `StringRule`, `InterpolationRule`, `HeredocTemplateRule` |
63
+ | `rules/strings.py` | `StringRule`, `InterpolationRule`, `HeredocTemplateRule`, `TemplateStringRule` |
45
64
  | `rules/functions.py` | `FunctionCallRule`, `ArgumentsRule` |
46
65
  | `rules/indexing.py` | `GetAttrRule`, `SqbIndexRule`, splat rules |
47
66
  | `rules/for_expressions.py` | `ForTupleExprRule`, `ForObjectExprRule`, `ForIntroRule`, `ForCondRule` |
67
+ | `rules/directives.py` | `TemplateIfRule`, `TemplateForRule`, and flat directive start/end rules |
48
68
  | `rules/whitespace.py` | `NewLineOrCommentRule`, `InlineCommentMixIn` |
49
69
 
50
70
  ## Public API (`api.py`)
@@ -53,12 +73,13 @@ Follows the `json` module convention. All option parameters are keyword-only.
53
73
 
54
74
  - `load/loads` — HCL2 text → Python dict
55
75
  - `dump/dumps` — Python dict → HCL2 text
76
+ - `query` — HCL2 text/file → `DocumentView` for structured queries
56
77
  - Intermediate stages: `parse/parses`, `parse_to_tree/parses_to_tree`, `transform`, `serialize`, `from_dict`, `from_json`, `reconstruct`
57
78
 
58
79
  ### Option Dataclasses
59
80
 
60
81
  **`SerializationOptions`** (LarkElement → dict):
61
- `with_comments`, `with_meta`, `wrap_objects`, `wrap_tuples`, `explicit_blocks`, `preserve_heredocs`, `force_operation_parentheses`, `preserve_scientific_notation`
82
+ `with_comments`, `with_meta`, `wrap_objects`, `wrap_tuples`, `explicit_blocks`, `preserve_heredocs`, `force_operation_parentheses`, `preserve_scientific_notation`, `strip_string_quotes`
62
83
 
63
84
  **`DeserializerOptions`** (dict → LarkElement):
64
85
  `heredocs_to_strings`, `strings_to_heredocs`, `object_elements_colon`, `object_elements_trailing_comma`
@@ -68,13 +89,52 @@ Follows the `json` module convention. All option parameters are keyword-only.
68
89
 
69
90
  ## CLI
70
91
 
71
- Console scripts defined in `pyproject.toml`. Each uses argparse flags that map directly to the option dataclass fields above.
92
+ Console scripts defined in `pyproject.toml`. All three CLIs accept positional `PATH` arguments (files, directories, glob patterns, or `-` for stdin). When no `PATH` is given, stdin is read by default (like `jq`).
72
93
 
94
+ ### Exit Codes
95
+
96
+ All CLIs use structured error output (plain text to stderr) and distinct exit codes:
97
+
98
+ | Code | `hcl2tojson` | `jsontohcl2` | `hq` |
99
+ |------|---|---|---|
100
+ | 0 | Success | Success | Success |
101
+ | 1 | Partial (some skipped) | JSON/encoding parse error | No results |
102
+ | 2 | All unparsable | Bad HCL structure | Parse error |
103
+ | 3 | — | — | Query error |
104
+ | 4 | I/O error | I/O error | I/O error |
105
+ | 5 | — | Differences found (`--diff` / `--semantic-diff`) | — |
106
+
107
+ ### `hcl2tojson`
108
+
109
+ ```
110
+ hcl2tojson file.tf # single file to stdout
111
+ hcl2tojson --ndjson dir/ # directory → NDJSON to stdout
112
+ hcl2tojson a.tf b.tf -o out/ # multiple files to output dir
113
+ hcl2tojson --ndjson 'modules/**/*.tf' # glob + NDJSON streaming
114
+ hcl2tojson --only resource,module file.tf # block type filtering
115
+ hcl2tojson --exclude variable file.tf # exclude block types
116
+ hcl2tojson --fields cpu,memory file.tf # field projection
117
+ hcl2tojson --compact file.tf # single-line JSON
118
+ hcl2tojson -q dir/ -o out/ # quiet (no stderr progress)
119
+ echo 'x = 1' | hcl2tojson # stdin (no args needed)
73
120
  ```
74
- hcl2tojson --json-indent 2 --with-meta file.tf
121
+
122
+ Key flags: `--ndjson`, `--compact`, `--only`/`--exclude`, `--fields`, `-q`/`--quiet`, `--json-indent N`, `--with-meta`, `--with-comments`, `--strip-string-quotes` (breaks round-trip). Multi-file NDJSON adds a `__file__` provenance key to each object.
123
+
124
+ ### `jsontohcl2`
125
+
126
+ ```
127
+ jsontohcl2 file.json # single file to stdout
128
+ jsontohcl2 --diff original.tf modified.json # preview text changes
129
+ jsontohcl2 --semantic-diff original.tf modified.json # semantic-only changes
130
+ jsontohcl2 --semantic-diff original.tf --diff-json m.json # semantic diff as JSON
131
+ jsontohcl2 --dry-run file.json # convert without writing
132
+ jsontohcl2 --fragment - # attribute snippets from stdin
75
133
  jsontohcl2 --indent 4 --no-align file.json
76
134
  ```
77
135
 
136
+ Key flags: `--diff ORIGINAL`, `--semantic-diff ORIGINAL`, `--diff-json`, `--dry-run`, `--fragment`, `-q`/`--quiet`, `--indent N`, `--no-align`, `--colon-separator`.
137
+
78
138
  Add new options as `parser.add_argument()` calls in the relevant entry point module.
79
139
 
80
140
  ## PostLexer (`postlexer.py`)
@@ -141,4 +201,4 @@ Hooks are defined in `.pre-commit-config.yaml` (includes black, mypy, pylint, an
141
201
 
142
202
  ## Keeping Docs Current
143
203
 
144
- Update this file when architecture, modules, API surface, or testing conventions change. Also update `README.md` and `docs/usage.md` when changes affect the public API, CLI flags, or option fields.
204
+ Update this file when architecture, modules, API surface, or testing conventions change. Also update `README.md` and the docs in `docs/` (`01_getting_started.md`, `02_querying.md`, `03_advanced_api.md`, `04_hq.md`, `05_hq_examples.md`) when changes affect the public API, CLI flags, or option fields.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-hcl2
3
- Version: 8.0.0rc2
3
+ Version: 8.1.0
4
4
  Summary: A parser for HCL2
5
5
  Author-email: Amplify Education <github@amplify.com>
6
6
  License: MIT
@@ -34,8 +34,9 @@ Dynamic: license-file
34
34
  # Python HCL2
35
35
 
36
36
  A parser for [HCL2](https://github.com/hashicorp/hcl/blob/hcl2/hclsyntax/spec.md) written in Python using
37
- [Lark](https://github.com/lark-parser/lark). This parser only supports HCL2 and isn't backwards compatible
38
- with HCL v1. It can be used to parse any HCL2 config file such as Terraform.
37
+ [Lark](https://github.com/lark-parser/lark). It can be used as a Python library or through its CLI tools:
38
+ `hcl2tojson`, `jsontohcl2`, and `hq` a jq-like query tool for HCL files.
39
+ Supports HCL2 only (not backwards compatible with HCL v1) and works with any HCL2 config file such as Terraform.
39
40
 
40
41
  ## About Amplify
41
42
 
@@ -60,6 +61,12 @@ This package can be installed using `pip`
60
61
  pip3 install python-hcl2
61
62
  ```
62
63
 
64
+ To install the CLI tools (`hcl2tojson`, `jsontohcl2`, `hq`) globally without affecting your project environments, use [pipx](https://pipx.pypa.io/):
65
+
66
+ ```sh
67
+ pipx install python-hcl2
68
+ ```
69
+
63
70
  ### Usage
64
71
 
65
72
  **HCL2 to Python dict:**
@@ -94,12 +101,19 @@ res.block("tags", Name="HelloWorld")
94
101
  hcl_string = hcl2.dumps(doc.build())
95
102
  ```
96
103
 
97
- For the full API reference, option dataclasses, intermediate pipeline stages, and more examples
98
- see [docs/usage.md](https://github.com/amplify-education/python-hcl2/blob/main/docs/usage.md).
104
+ ### Documentation
105
+
106
+ | Guide | Contents |
107
+ |---|---|
108
+ | [Getting Started](docs/01_getting_started.md) | Installation, load/dump, options, CLI converters |
109
+ | [Querying HCL (Python)](docs/02_querying.md) | DocumentView, BlockView, tree walking, view hierarchy |
110
+ | [Advanced API](docs/03_advanced_api.md) | Pipeline stages, Builder |
111
+ | [hq Reference](docs/04_hq.md) | `hq` CLI — structural queries, hybrid/eval, introspection |
112
+ | [hq Examples](docs/05_hq_examples.md) | Real-world queries for discovery, compliance, extraction |
99
113
 
100
114
  ### CLI Tools
101
115
 
102
- python-hcl2 ships two command-line converters:
116
+ python-hcl2 ships three command-line tools:
103
117
 
104
118
  ```sh
105
119
  # HCL2 → JSON
@@ -111,9 +125,13 @@ hcl2tojson terraform/ output/ # converts a directory
111
125
  jsontohcl2 output.json # prints HCL2 to stdout
112
126
  jsontohcl2 output.json main.tf # writes to file
113
127
  jsontohcl2 output/ terraform/ # converts a directory
128
+
129
+ # Query HCL2 files
130
+ hq 'resource.aws_instance.main.ami' main.tf
131
+ hq 'variable[*]' variables.tf --json
114
132
  ```
115
133
 
116
- Both commands accept `-` as PATH to read from stdin. Run `hcl2tojson --help` or `jsontohcl2 --help` for the full list of flags.
134
+ All commands accept `-` as PATH to read from stdin. Run `--help` on any command for the full list of flags.
117
135
 
118
136
  ## Building From Source
119
137
 
@@ -136,6 +154,17 @@ To create a new release go to Releases page, press 'Draft a new release', create
136
154
  with a version you want to be released, fill the release notes and press 'Publish release'.
137
155
  Github actions will take care of publishing it to PyPi.
138
156
 
157
+ ## Roadmap
158
+
159
+ Planned features, roughly in priority order:
160
+
161
+ - **MCP server** — expose parsing, querying, and formatting as MCP tools for AI agents
162
+ - **Predictable formatting** — source-derived formatting heuristics and stable whitespace defaults
163
+ - **In-place tree edits** — `hq set`, `hq delete` for programmatic HCL modification
164
+ - **Comment deserialization** — comments survive JSON round-trips and tree edits
165
+ - **Expression intelligence** — variable reference tracking, unused variable detection, cross-file analysis
166
+ - **Refactoring operations** — `hq rename`, `hq extract-module`, `hq sort` for high-level code transforms
167
+
139
168
  ## Responsible Disclosure
140
169
 
141
170
  If you have any security issue to report, contact project maintainers privately.
@@ -7,8 +7,9 @@
7
7
  # Python HCL2
8
8
 
9
9
  A parser for [HCL2](https://github.com/hashicorp/hcl/blob/hcl2/hclsyntax/spec.md) written in Python using
10
- [Lark](https://github.com/lark-parser/lark). This parser only supports HCL2 and isn't backwards compatible
11
- with HCL v1. It can be used to parse any HCL2 config file such as Terraform.
10
+ [Lark](https://github.com/lark-parser/lark). It can be used as a Python library or through its CLI tools:
11
+ `hcl2tojson`, `jsontohcl2`, and `hq` a jq-like query tool for HCL files.
12
+ Supports HCL2 only (not backwards compatible with HCL v1) and works with any HCL2 config file such as Terraform.
12
13
 
13
14
  ## About Amplify
14
15
 
@@ -33,6 +34,12 @@ This package can be installed using `pip`
33
34
  pip3 install python-hcl2
34
35
  ```
35
36
 
37
+ To install the CLI tools (`hcl2tojson`, `jsontohcl2`, `hq`) globally without affecting your project environments, use [pipx](https://pipx.pypa.io/):
38
+
39
+ ```sh
40
+ pipx install python-hcl2
41
+ ```
42
+
36
43
  ### Usage
37
44
 
38
45
  **HCL2 to Python dict:**
@@ -67,12 +74,19 @@ res.block("tags", Name="HelloWorld")
67
74
  hcl_string = hcl2.dumps(doc.build())
68
75
  ```
69
76
 
70
- For the full API reference, option dataclasses, intermediate pipeline stages, and more examples
71
- see [docs/usage.md](https://github.com/amplify-education/python-hcl2/blob/main/docs/usage.md).
77
+ ### Documentation
78
+
79
+ | Guide | Contents |
80
+ |---|---|
81
+ | [Getting Started](docs/01_getting_started.md) | Installation, load/dump, options, CLI converters |
82
+ | [Querying HCL (Python)](docs/02_querying.md) | DocumentView, BlockView, tree walking, view hierarchy |
83
+ | [Advanced API](docs/03_advanced_api.md) | Pipeline stages, Builder |
84
+ | [hq Reference](docs/04_hq.md) | `hq` CLI — structural queries, hybrid/eval, introspection |
85
+ | [hq Examples](docs/05_hq_examples.md) | Real-world queries for discovery, compliance, extraction |
72
86
 
73
87
  ### CLI Tools
74
88
 
75
- python-hcl2 ships two command-line converters:
89
+ python-hcl2 ships three command-line tools:
76
90
 
77
91
  ```sh
78
92
  # HCL2 → JSON
@@ -84,9 +98,13 @@ hcl2tojson terraform/ output/ # converts a directory
84
98
  jsontohcl2 output.json # prints HCL2 to stdout
85
99
  jsontohcl2 output.json main.tf # writes to file
86
100
  jsontohcl2 output/ terraform/ # converts a directory
101
+
102
+ # Query HCL2 files
103
+ hq 'resource.aws_instance.main.ami' main.tf
104
+ hq 'variable[*]' variables.tf --json
87
105
  ```
88
106
 
89
- Both commands accept `-` as PATH to read from stdin. Run `hcl2tojson --help` or `jsontohcl2 --help` for the full list of flags.
107
+ All commands accept `-` as PATH to read from stdin. Run `--help` on any command for the full list of flags.
90
108
 
91
109
  ## Building From Source
92
110
 
@@ -109,6 +127,17 @@ To create a new release go to Releases page, press 'Draft a new release', create
109
127
  with a version you want to be released, fill the release notes and press 'Publish release'.
110
128
  Github actions will take care of publishing it to PyPi.
111
129
 
130
+ ## Roadmap
131
+
132
+ Planned features, roughly in priority order:
133
+
134
+ - **MCP server** — expose parsing, querying, and formatting as MCP tools for AI agents
135
+ - **Predictable formatting** — source-derived formatting heuristics and stable whitespace defaults
136
+ - **In-place tree edits** — `hq set`, `hq delete` for programmatic HCL modification
137
+ - **Comment deserialization** — comments survive JSON round-trips and tree edits
138
+ - **Expression intelligence** — variable reference tracking, unused variable detection, cross-file analysis
139
+ - **Refactoring operations** — `hq rename`, `hq extract-module`, `hq sort` for high-level code transforms
140
+
112
141
  ## Responsible Disclosure
113
142
 
114
143
  If you have any security issue to report, contact project maintainers privately.