awsquery 1.1.0__tar.gz → 1.2.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 (138) hide show
  1. {awsquery-1.1.0 → awsquery-1.2.0}/.github/workflows/quality.yml +5 -1
  2. {awsquery-1.1.0 → awsquery-1.2.0}/.gitignore +8 -1
  3. awsquery-1.2.0/AGENTS.md +62 -0
  4. {awsquery-1.1.0 → awsquery-1.2.0}/Makefile +35 -0
  5. {awsquery-1.1.0/src/awsquery.egg-info → awsquery-1.2.0}/PKG-INFO +412 -18
  6. {awsquery-1.1.0 → awsquery-1.2.0}/README.md +406 -12
  7. awsquery-1.2.0/llms-full.txt +390 -0
  8. awsquery-1.2.0/llms.txt +21 -0
  9. {awsquery-1.1.0 → awsquery-1.2.0}/pyproject.toml +13 -7
  10. awsquery-1.2.0/src/awsquery/agent-reference.md +390 -0
  11. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery/cli.py +440 -211
  12. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery/config.py +36 -1
  13. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery/core.py +84 -64
  14. awsquery-1.2.0/src/awsquery/data_fields.yaml +41 -0
  15. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery/default_filters.yaml +339 -602
  16. awsquery-1.2.0/src/awsquery/errors.py +245 -0
  17. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery/filter_validator.py +2 -2
  18. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery/formatters.py +191 -99
  19. awsquery-1.2.0/src/awsquery/introspection.py +222 -0
  20. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery/security.py +34 -2
  21. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery/shapes.py +170 -28
  22. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery/utils.py +8 -1
  23. {awsquery-1.1.0 → awsquery-1.2.0/src/awsquery.egg-info}/PKG-INFO +412 -18
  24. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery.egg-info/SOURCES.txt +11 -0
  25. {awsquery-1.1.0 → awsquery-1.2.0}/tests/conftest.py +18 -0
  26. {awsquery-1.1.0 → awsquery-1.2.0}/tests/integration/test_feature_combinations.py +37 -31
  27. {awsquery-1.1.0 → awsquery-1.2.0}/tests/integration/test_keys_behavior.py +30 -12
  28. {awsquery-1.1.0 → awsquery-1.2.0}/tests/integration/test_multi_level.py +4 -4
  29. {awsquery-1.1.0 → awsquery-1.2.0}/tests/integration/test_session_management.py +69 -4
  30. awsquery-1.2.0/tests/unit/test_agent_reference.py +201 -0
  31. awsquery-1.2.0/tests/unit/test_cli_flags.py +1197 -0
  32. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_cli_help_output.py +28 -0
  33. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_cli_session_args.py +3 -1
  34. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_config_loading_simple.py +0 -1
  35. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_core.py +116 -8
  36. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_default_column_filters.py +273 -6
  37. awsquery-1.2.0/tests/unit/test_errors.py +500 -0
  38. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_formatters.py +562 -23
  39. awsquery-1.2.0/tests/unit/test_introspection.py +393 -0
  40. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_keys_display_fix.py +4 -8
  41. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_security.py +6 -5
  42. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_security_edge_cases.py +2 -1
  43. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_shapes.py +209 -10
  44. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_tags_transformation.py +5 -8
  45. awsquery-1.2.0/uv.lock +3395 -0
  46. awsquery-1.1.0/tests/unit/test_cli_flags.py +0 -386
  47. {awsquery-1.1.0 → awsquery-1.2.0}/.claude/agents/code-reviewer.md +0 -0
  48. {awsquery-1.1.0 → awsquery-1.2.0}/.claude/agents/makefile-optimizer.md +0 -0
  49. {awsquery-1.1.0 → awsquery-1.2.0}/.claude/agents/python-infra-automator.md +0 -0
  50. {awsquery-1.1.0 → awsquery-1.2.0}/.claude/agents/test-writer.md +0 -0
  51. {awsquery-1.1.0 → awsquery-1.2.0}/.claude/settings.local.json +0 -0
  52. {awsquery-1.1.0 → awsquery-1.2.0}/.coveragerc +0 -0
  53. {awsquery-1.1.0 → awsquery-1.2.0}/.devcontainer/devcontainer.json +0 -0
  54. {awsquery-1.1.0 → awsquery-1.2.0}/.dockerignore +0 -0
  55. {awsquery-1.1.0 → awsquery-1.2.0}/.flake8 +0 -0
  56. {awsquery-1.1.0 → awsquery-1.2.0}/.github/workflows/release.yml +0 -0
  57. {awsquery-1.1.0 → awsquery-1.2.0}/.github/workflows/test.yml +0 -0
  58. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/archive/e1bzl-fix-remaining-15-broken-suffix-entries-surfaced-by-audit/EXECUTION.html +0 -0
  59. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/archive/e1bzl-fix-remaining-15-broken-suffix-entries-surfaced-by-audit/EXECUTION.md +0 -0
  60. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/archive/e1bzl-fix-remaining-15-broken-suffix-entries-surfaced-by-audit/ISSUE.md +0 -0
  61. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/archive/e1bzl-fix-remaining-15-broken-suffix-entries-surfaced-by-audit/PLAN.md +0 -0
  62. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/archive/sue5t-fix-tags-default-filters-and-add-additive-column-syntax/CONTEXT.md +0 -0
  63. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/archive/sue5t-fix-tags-default-filters-and-add-additive-column-syntax/EXECUTION.html +0 -0
  64. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/archive/sue5t-fix-tags-default-filters-and-add-additive-column-syntax/EXECUTION.md +0 -0
  65. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/archive/sue5t-fix-tags-default-filters-and-add-additive-column-syntax/ISSUE.md +0 -0
  66. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/archive/sue5t-fix-tags-default-filters-and-add-additive-column-syntax/PLAN.html +0 -0
  67. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/archive/sue5t-fix-tags-default-filters-and-add-additive-column-syntax/PLAN.md +0 -0
  68. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/archive/sue5t-fix-tags-default-filters-and-add-additive-column-syntax/RESEARCH.html +0 -0
  69. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/archive/sue5t-fix-tags-default-filters-and-add-additive-column-syntax/RESEARCH.md +0 -0
  70. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/archive/sue5t-fix-tags-default-filters-and-add-additive-column-syntax/research/codebase.md +0 -0
  71. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/archive/sue5t-fix-tags-default-filters-and-add-additive-column-syntax/research/ecosystem.md +0 -0
  72. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/archive/sue5t-fix-tags-default-filters-and-add-additive-column-syntax/research/pitfalls.md +0 -0
  73. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/ty5dx-add-per-service-default-actions-so-awsquery-ec2-runs-without-an-action/CONTEXT.md +0 -0
  74. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/ty5dx-add-per-service-default-actions-so-awsquery-ec2-runs-without-an-action/EXECUTION.md +0 -0
  75. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/ty5dx-add-per-service-default-actions-so-awsquery-ec2-runs-without-an-action/ISSUE.md +0 -0
  76. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/ty5dx-add-per-service-default-actions-so-awsquery-ec2-runs-without-an-action/PLAN.html +0 -0
  77. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/ty5dx-add-per-service-default-actions-so-awsquery-ec2-runs-without-an-action/PLAN.md +0 -0
  78. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/ty5dx-add-per-service-default-actions-so-awsquery-ec2-runs-without-an-action/RESEARCH.html +0 -0
  79. {awsquery-1.1.0 → awsquery-1.2.0}/.issues/ty5dx-add-per-service-default-actions-so-awsquery-ec2-runs-without-an-action/RESEARCH.md +0 -0
  80. {awsquery-1.1.0 → awsquery-1.2.0}/CLAUDE.md +0 -0
  81. {awsquery-1.1.0 → awsquery-1.2.0}/Dockerfile +0 -0
  82. {awsquery-1.1.0 → awsquery-1.2.0}/Dockerfile.prod +0 -0
  83. {awsquery-1.1.0 → awsquery-1.2.0}/LICENSE +0 -0
  84. {awsquery-1.1.0 → awsquery-1.2.0}/compose.yaml +0 -0
  85. {awsquery-1.1.0 → awsquery-1.2.0}/coverage.json +0 -0
  86. {awsquery-1.1.0 → awsquery-1.2.0}/debug-output.txt +0 -0
  87. {awsquery-1.1.0 → awsquery-1.2.0}/docs/DOCKER.md +0 -0
  88. {awsquery-1.1.0 → awsquery-1.2.0}/docs/mutation-testing.md +0 -0
  89. {awsquery-1.1.0 → awsquery-1.2.0}/policy.json +0 -0
  90. {awsquery-1.1.0 → awsquery-1.2.0}/pytest.ini +0 -0
  91. {awsquery-1.1.0 → awsquery-1.2.0}/requirements.txt +0 -0
  92. {awsquery-1.1.0 → awsquery-1.2.0}/scripts/README.md +0 -0
  93. {awsquery-1.1.0 → awsquery-1.2.0}/scripts/audit_default_filters.py +0 -0
  94. {awsquery-1.1.0 → awsquery-1.2.0}/scripts/validate-awsquery.sh +0 -0
  95. {awsquery-1.1.0 → awsquery-1.2.0}/setup.cfg +0 -0
  96. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery/__init__.py +0 -0
  97. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery/auto_filters.py +0 -0
  98. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery/case_utils.py +0 -0
  99. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery/default_actions.yaml +0 -0
  100. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery/filters.py +0 -0
  101. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery/policy.json +0 -0
  102. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery.egg-info/dependency_links.txt +0 -0
  103. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery.egg-info/entry_points.txt +0 -0
  104. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery.egg-info/requires.txt +0 -0
  105. {awsquery-1.1.0 → awsquery-1.2.0}/src/awsquery.egg-info/top_level.txt +0 -0
  106. {awsquery-1.1.0 → awsquery-1.2.0}/tests/__init__.py +0 -0
  107. {awsquery-1.1.0 → awsquery-1.2.0}/tests/fixtures/__init__.py +0 -0
  108. {awsquery-1.1.0 → awsquery-1.2.0}/tests/fixtures/aws_responses.py +0 -0
  109. {awsquery-1.1.0 → awsquery-1.2.0}/tests/fixtures/policy_samples.py +0 -0
  110. {awsquery-1.1.0 → awsquery-1.2.0}/tests/integration/__init__.py +0 -0
  111. {awsquery-1.1.0 → awsquery-1.2.0}/tests/integration/test_autocomplete_resilience.py +0 -0
  112. {awsquery-1.1.0 → awsquery-1.2.0}/tests/integration/test_end_to_end.py +0 -0
  113. {awsquery-1.1.0 → awsquery-1.2.0}/tests/integration/test_multi_level_calls.py +0 -0
  114. {awsquery-1.1.0 → awsquery-1.2.0}/tests/integration/test_parameter_option_integration.py +0 -0
  115. {awsquery-1.1.0 → awsquery-1.2.0}/tests/integration/test_parameter_type_auto_wrapping.py +0 -0
  116. {awsquery-1.1.0 → awsquery-1.2.0}/tests/integration/test_shape_aware_integration.py +0 -0
  117. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/__init__.py +0 -0
  118. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_auto_filters.py +0 -0
  119. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_case_utils.py +0 -0
  120. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_cli_arg_processing.py +0 -0
  121. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_cli_parser.py +0 -0
  122. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_column_ordering.py +0 -0
  123. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_core_inference.py +0 -0
  124. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_core_string_handling.py +0 -0
  125. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_critical_mutations.py +0 -0
  126. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_cross_service_hints.py +0 -0
  127. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_filter_edge_cases.py +0 -0
  128. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_filter_implementation.py +0 -0
  129. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_filter_parameter_extraction.py +0 -0
  130. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_filter_validator.py +0 -0
  131. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_formatter_edge_cases.py +0 -0
  132. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_formatters_data_processing.py +0 -0
  133. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_input_hint_parameter.py +0 -0
  134. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_messaging_enhancements.py +0 -0
  135. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_parameter_option.py +0 -0
  136. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_parameter_type_validation.py +0 -0
  137. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_preemptive_multi_step.py +0 -0
  138. {awsquery-1.1.0 → awsquery-1.2.0}/tests/unit/test_smart_prefix_matching.py +0 -0
@@ -45,4 +45,8 @@ jobs:
45
45
 
46
46
  - name: Run security checks
47
47
  run: |
48
- make security-check
48
+ make security-check
49
+
50
+ - name: Check agent reference mirror
51
+ run: |
52
+ make llms-check
@@ -215,4 +215,11 @@ __marimo__/
215
215
 
216
216
  sample-responses
217
217
  test_env
218
- awsinfo
218
+ awsinfo
219
+ # Codebase graph output (local tooling)
220
+ graphify-out/
221
+
222
+ # Local working directories and captured command output
223
+ .development/
224
+ .worktrees/
225
+ output.txt
@@ -0,0 +1,62 @@
1
+ # AGENTS.md
2
+
3
+ Conventions for agents working **on this repository**. If you are an agent *using* awsquery to query
4
+ AWS, you want `awsquery --docs` instead (source: `src/awsquery/agent-reference.md`).
5
+
6
+ ## Setup and commands
7
+
8
+ ```bash
9
+ uv sync --extra dev # create .venv with dev dependencies (or: make uv-sync)
10
+ uv run pytest tests/ -q # full suite, ~1700 tests, under a minute (or: make uv-test)
11
+ make format # black + isort, line length 100
12
+ make lint # flake8 + pylint
13
+ make type-check # mypy
14
+ make ci # everything CI runs
15
+ ```
16
+
17
+ `make install-dev` / `make test` are the pip equivalents and work the same.
18
+
19
+ Run a single test with `uv run pytest tests/unit/test_x.py::TestClass::test_method -v`.
20
+
21
+ ## Layout
22
+
23
+ - `src/awsquery/cli.py` — argument parsing, filter-group splitting, the `main()` flow
24
+ - `src/awsquery/core.py` — API execution, multi-level parameter resolution
25
+ - `src/awsquery/shapes.py` — botocore service-model introspection (credential-free field discovery)
26
+ - `src/awsquery/security.py` — read-only enforcement by operation prefix
27
+ - `src/awsquery/filters.py`, `formatters.py` — filtering and output rendering
28
+ - `src/awsquery/default_filters.yaml`, `default_actions.yaml` — curated per-service defaults
29
+ - `src/awsquery/agent-reference.md` — the agent/LLM reference printed by `--docs`
30
+
31
+ ## Non-negotiables
32
+
33
+ - **The CLI is the only stable contract.** Never change the behaviour or output of an existing flag.
34
+ Internal APIs have no consumers: change signatures, return types and module boundaries freely, and
35
+ delete dead code rather than deprecating it.
36
+ - **No pytest markers.** `@pytest.mark.parametrize` is the sole exception; every other
37
+ `@pytest.mark.*` is banned and the whole suite always runs. Test selection is directory-based
38
+ (`tests/unit/`, `tests/integration/`).
39
+ - **Test real code.** Mock only external boundaries (boto3, filesystem, network). A test that mocks
40
+ the function it claims to cover, or that only asserts `mock.assert_called()`, does not count.
41
+ - **No filler test docstrings.** No restating the test name, no TDD placeholders, no narration.
42
+ Comment only genuinely non-obvious cases.
43
+ - **Check for an existing test file before creating one.** Flags belong in `test_cli_flags.py`,
44
+ parser behaviour in `test_cli_parser.py`, filters in `test_filter_implementation.py`.
45
+ - **Coverage floor is 80%** (`pytest.ini`).
46
+
47
+ ## Documentation sync
48
+
49
+ `src/awsquery/agent-reference.md` is the single source of truth for the agent-facing reference. After
50
+ editing it, regenerate the mirror and keep the two byte-identical:
51
+
52
+ ```bash
53
+ make llms # copies it to llms-full.txt
54
+ ```
55
+
56
+ A test asserts they match, and that every flag the reference documents exists in the parser. Update
57
+ the reference in the same commit as any CLI change.
58
+
59
+ ## Commits
60
+
61
+ Single-line summary, imperative mood, 72 characters maximum, no body. Group related changes into one
62
+ commit; keep unrelated changes apart.
@@ -13,6 +13,8 @@ NC := \033[0m
13
13
 
14
14
  .PHONY: help clean install-dev test test-unit test-integration test-critical test-slow test-fast test-unit-fast \
15
15
  test-integration-fast coverage coverage-report lint format format-check type-check security-check ci build \
16
+ uv-sync uv-test uv-run uv-lock tool-install tool-uninstall \
17
+ llms llms-check \
16
18
  publish-test publish watch-tests version release update-policy validate-policy all ec2-instances s3-buckets \
17
19
  iam-users iam-roles lambda-functions cloudformation-stacks dynamodb-tables ec2-volumes \
18
20
  ec2-security-groups s3-bucket-versioning cloudwatch-alarms route53-zones shell \
@@ -36,6 +38,32 @@ help: ## Show this help message
36
38
  install-dev: ## Install development dependencies
37
39
  pip3 install --user --break-system-packages -e ".[dev]" || pip3 install -e ".[dev]"
38
40
 
41
+ # =============================================================================
42
+ # UV TARGETS
43
+ # =============================================================================
44
+
45
+ uv-sync: ## Install project + dev dependencies into .venv with uv
46
+ uv sync --extra dev
47
+
48
+ uv-test: ## Run all tests with uv
49
+ uv run --extra dev pytest tests/ -v
50
+
51
+ uv-run: ## Run awsquery from the local checkout (use ARGS="ec2 describe-instances")
52
+ uv run awsquery $(ARGS)
53
+
54
+ uv-lock: ## Regenerate uv.lock
55
+ uv lock
56
+
57
+ tool-install: ## Install awsquery as a global uv tool from this checkout
58
+ uv tool install --force --editable .
59
+
60
+ tool-uninstall: ## Remove the globally installed awsquery uv tool
61
+ uv tool uninstall awsquery
62
+
63
+ # =============================================================================
64
+ # TEST TARGETS
65
+ # =============================================================================
66
+
39
67
  test: ## Run all tests
40
68
  python3 -m pytest tests/ -v
41
69
 
@@ -181,6 +209,13 @@ validate-policy: ## Validate that policy.json is a valid AWS policy document
181
209
  echo "$(GREEN)✓ policy.json validation passed$(NC)" || \
182
210
  echo "$(RED)✗ policy.json validation failed$(NC)"
183
211
 
212
+ llms: ## Regenerate llms-full.txt from the packaged agent reference
213
+ cp src/awsquery/agent-reference.md llms-full.txt
214
+
215
+ llms-check: ## Verify llms-full.txt matches the packaged agent reference
216
+ @cmp -s src/awsquery/agent-reference.md llms-full.txt || \
217
+ { echo "llms-full.txt is out of date with src/awsquery/agent-reference.md - run 'make llms'"; exit 1; }
218
+
184
219
  # =============================================================================
185
220
  # AWS API RESPONSE SAMPLING TARGETS (PRESERVED)
186
221
  # =============================================================================
@@ -1,14 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: awsquery
3
- Version: 1.1.0
3
+ Version: 1.2.0
4
4
  Summary: Advanced CLI tool for querying AWS APIs with flexible filtering and automatic parameter resolution
5
5
  Author-email: Florian Motlik <flo@flomotlik.me>
6
6
  License: MIT
7
- Project-URL: Homepage, https://github.com/yourusername/awsquery
8
- Project-URL: Documentation, https://awsquery.readthedocs.io
9
- Project-URL: Repository, https://github.com/yourusername/awsquery.git
10
- Project-URL: Issues, https://github.com/yourusername/awsquery/issues
11
- Project-URL: Changelog, https://github.com/yourusername/awsquery/blob/main/CHANGELOG.md
7
+ Project-URL: Homepage, https://github.com/flomotlik/awsquery
8
+ Project-URL: Documentation, https://github.com/flomotlik/awsquery#readme
9
+ Project-URL: Repository, https://github.com/flomotlik/awsquery.git
10
+ Project-URL: Issues, https://github.com/flomotlik/awsquery/issues
11
+ Project-URL: Changelog, https://github.com/flomotlik/awsquery/releases
12
12
  Keywords: aws,cli,query,cloud,devops,boto3
13
13
  Classifier: Development Status :: 4 - Beta
14
14
  Classifier: Intended Audience :: Developers
@@ -74,6 +74,25 @@ awsquery ec2 describe-instances prod web -- Tags.Name State InstanceId vpcid
74
74
  This creates endless flexibility to shape your aws cli calls, filter any output and present exactly
75
75
  the data you need during review, debugging or development.
76
76
 
77
+ ## Quick Start
78
+
79
+ With [uv](https://docs.astral.sh/uv/) installed, there is nothing else to set up — no virtualenv, no
80
+ `pip install`, not even a Python of your own:
81
+
82
+ ```bash
83
+ uvx awsquery ec2 describe-instances prod web -- Tags.Name State InstanceId
84
+ ```
85
+
86
+ Want it as a permanent command with tab completion?
87
+
88
+ ```bash
89
+ uv tool install awsquery
90
+ awsquery ec2 describe-instances
91
+ ```
92
+
93
+ See [Installation](#installation) for aliases, version pinning, running straight from GitHub, and CI
94
+ usage.
95
+
77
96
  ## Features
78
97
 
79
98
  - **Smart Multi-Level Calls**: Automatically resolves missing parameters by inferring and calling list operations
@@ -94,32 +113,229 @@ the data you need during review, debugging or development.
94
113
  == `awsquery ec2 describe-instances` (e.g. `awsquery s3 -- Name`)
95
114
  - **Parameter Passing**: Direct parameter passing to AWS APIs with `-p`/`--parameter` for advanced use cases
96
115
  - **Hint-Based Resolution**: Function selection hints with `-i`/`--input` for multi-step calls, including cross-service support and field extraction targeting
116
+ - **Agent/LLM Mode**: `--docs` prints the complete reference in one call; `--schema`, `--list-services` and `--list-actions` answer offline with no AWS credentials
117
+ - **Token-Efficient Output**: `--format csv|tsv|ndjson` and `--limit` keep results small enough for a context window
118
+ - **Predictable Exit Codes**: documented codes 0-4, structured JSON errors, and no interactive prompts when stdin is not a TTY
97
119
 
98
120
  ## Installation
99
121
 
100
- ### Via pip (Recommended)
122
+ `awsquery` is on PyPI, so the fastest way to use it is [uv](https://docs.astral.sh/uv/): no
123
+ virtualenv, no `pip install`, no Python version juggling. uv downloads a matching Python for you if
124
+ you don't have one.
125
+
126
+ | You want to... | Command |
127
+ | --- | --- |
128
+ | Try it once, install nothing | `uvx awsquery ec2 describe-instances` |
129
+ | Use it every day (and get tab completion) | `uv tool install awsquery` |
130
+ | Run a specific version | `uvx awsquery@1.2.0 ec2 describe-instances` |
131
+ | Run unreleased code from GitHub | `uvx --from git+https://github.com/flomotlik/awsquery awsquery ec2` |
132
+ | Hack on it locally | `uv run awsquery ec2` inside a checkout |
133
+
134
+ ### Install uv (one time)
135
+
136
+ ```bash
137
+ # macOS / Linux
138
+ curl -LsSf https://astral.sh/uv/install.sh | sh
139
+
140
+ # Homebrew
141
+ brew install uv
142
+
143
+ # Windows (PowerShell)
144
+ powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
145
+ ```
146
+
147
+ That is the only thing anyone on your team has to install. uv itself is a single binary and brings
148
+ its own Python.
149
+
150
+ ### Run without installing: `uvx`
151
+
152
+ ```bash
153
+ uvx awsquery ec2 describe-instances
154
+ uvx awsquery s3 list-buckets backup -- Name CreationDate
155
+ uvx awsquery -j cloudformation describe-stacks prod
156
+ ```
157
+
158
+ The first run downloads awsquery and its dependencies into uv's cache (a few seconds). Every run
159
+ after that starts in about a tenth of a second. Nothing is added to your `PATH`, no virtualenv is
160
+ created, and nothing is left behind in your project.
161
+
162
+ Pin an exact version when you want reproducibility, or force a check for the newest release:
163
+
164
+ ```bash
165
+ uvx awsquery@1.2.0 ec2 describe-instances # pinned, fully reproducible
166
+ uvx awsquery@latest ec2 describe-instances # re-checks PyPI for a newer version
167
+ ```
168
+
169
+ ### Make it feel like a normal command: alias
170
+
171
+ Add one line to your shell config and the whole team is running the same tool without installing
172
+ anything:
173
+
174
+ ```bash
175
+ # ~/.bashrc or ~/.zshrc
176
+ alias awsquery='uvx awsquery@latest'
177
+
178
+ # pin the version instead, if you want everyone on the same release
179
+ alias awsquery='uvx awsquery@1.2.0'
180
+ ```
181
+
182
+ ```fish
183
+ # ~/.config/fish/config.fish
184
+ alias --save awsquery 'uvx awsquery@latest'
185
+ ```
186
+
187
+ ```powershell
188
+ # PowerShell $PROFILE
189
+ function awsquery { uvx awsquery@latest @args }
190
+ ```
191
+
192
+ Then use it exactly as documented everywhere else in this README:
193
+
194
+ ```bash
195
+ awsquery ec2 describe-instances prod web -- Tags.Name State InstanceId
196
+ ```
197
+
198
+ Two things to know about the alias route: `@latest` contacts PyPI on every invocation (so it needs
199
+ network and adds a moment of latency), and shell tab completion does not work through an alias
200
+ because argcomplete needs a real executable on `PATH`. If either matters to you, use
201
+ `uv tool install` instead — it gives you the same command with neither drawback.
202
+
203
+ ### Install as a persistent tool: `uv tool install`
204
+
205
+ ```bash
206
+ uv tool install awsquery # installs the awsquery command into ~/.local/bin
207
+ awsquery ec2 describe-instances
208
+
209
+ uv tool upgrade awsquery # upgrade later
210
+ uv tool uninstall awsquery # remove it again
211
+ uv tool list # see what's installed
212
+ ```
213
+
214
+ uv keeps awsquery in its own isolated environment, so it can never conflict with your project
215
+ virtualenvs or your system Python. If the command isn't found afterwards, run `uv tool update-shell`
216
+ (it adds uv's bin directory to your `PATH`) and restart your shell.
217
+
218
+ This is the recommended setup for daily use and the one that supports
219
+ [shell autocomplete](#enable-shell-autocomplete).
220
+
221
+ ### Run unreleased code straight from GitHub
222
+
223
+ ```bash
224
+ # latest commit on main, run once
225
+ uvx --from git+https://github.com/flomotlik/awsquery awsquery ec2 describe-instances
226
+
227
+ # a specific branch, tag or commit
228
+ uvx --from git+https://github.com/flomotlik/awsquery@main awsquery ec2 describe-instances
229
+ uvx --from git+https://github.com/flomotlik/awsquery@v1.2.0 awsquery ec2 describe-instances
230
+
231
+ # install that version persistently
232
+ uv tool install git+https://github.com/flomotlik/awsquery
233
+ ```
234
+
235
+ `--from` is needed because the package name (`awsquery`) has to be resolved from the repository
236
+ while the command to execute is still `awsquery`.
237
+
238
+ ### Run from a local checkout
239
+
240
+ ```bash
241
+ git clone https://github.com/flomotlik/awsquery.git
242
+ cd awsquery
243
+
244
+ # run the working tree directly - uv creates and syncs .venv on the fly
245
+ uv run awsquery ec2 describe-instances
246
+
247
+ # or via make
248
+ make uv-run ARGS="ec2 describe-instances"
249
+
250
+ # put your local checkout on PATH as the global awsquery command
251
+ uv tool install --editable . # same as: make tool-install
252
+ ```
253
+
254
+ `uv run` resolves dependencies from `uv.lock`, which is committed to this repository, so every
255
+ contributor gets an identical environment. Use `uv run --frozen awsquery ...` to fail instead of
256
+ silently re-locking if the lockfile is out of date.
257
+
258
+ ### Python versions
259
+
260
+ awsquery requires Python 3.10 or newer. uv fetches a suitable interpreter automatically, so you do
261
+ not need a system Python at all. To force a specific version:
262
+
263
+ ```bash
264
+ uvx --python 3.12 awsquery ec2 describe-instances
265
+ uv tool install --python 3.12 awsquery
266
+ uv run --python 3.12 awsquery ec2 describe-instances
267
+ ```
268
+
269
+ ### AWS credentials with uv
270
+
271
+ uvx does not sandbox anything: the tool runs as you, with your environment and your `~/.aws`
272
+ directory, so credentials, SSO sessions, profiles, assumed roles and `AWS_*` environment variables
273
+ all behave exactly as they do with the AWS CLI.
274
+
275
+ ```bash
276
+ AWS_PROFILE=prod uvx awsquery ec2 describe-instances
277
+ uvx awsquery --profile prod --region eu-central-1 ec2 describe-instances
278
+ ```
279
+
280
+ ### Using awsquery in CI
281
+
282
+ No install step is needed beyond uv itself:
283
+
284
+ ```yaml
285
+ # GitHub Actions
286
+ - uses: astral-sh/setup-uv@v6
287
+ - run: uvx awsquery@1.2.0 -j cloudformation describe-stacks -- StackName StackStatus
288
+ env:
289
+ AWS_REGION: eu-central-1
290
+ ```
291
+
292
+ Pin the version (`awsquery@1.2.0`) in CI so a new release can never change your output format
293
+ underneath a pipeline.
294
+
295
+ ### Via pip
296
+
297
+ If your team does not use uv, the classic routes still work:
101
298
 
102
299
  ```bash
103
- pip install awsquery
300
+ pip install awsquery # into the current environment
301
+ pipx install awsquery # isolated, like uv tool install
104
302
  ```
105
303
 
106
- ### Development Installation
304
+ ### Development installation
107
305
 
108
306
  ```bash
109
- git clone https://github.com/yourusername/awsquery.git
307
+ git clone https://github.com/flomotlik/awsquery.git
110
308
  cd awsquery
111
- pip install -e ".[dev]"
309
+ uv sync --extra dev # or: make uv-sync
310
+ uv run pytest tests/ -v # or: make uv-test
112
311
  ```
113
312
 
313
+ The pip equivalent is `pip install -e ".[dev]"` (`make install-dev`).
314
+
114
315
  ### Enable Shell Autocomplete
115
316
 
116
317
  awsquery supports tab completion for AWS services and actions through argcomplete.
117
318
 
319
+ Completion requires a real `awsquery` executable on your `PATH`, because the shell calls that
320
+ executable to compute the candidates. So it works with `uv tool install awsquery`, `pipx install`
321
+ and `pip install` — but **not** with a `uvx` alias, since the alias is expanded by your shell after
322
+ completion has already run.
323
+
324
+ ```bash
325
+ uv tool install awsquery # the setup below assumes this (or pip/pipx)
326
+ ```
327
+
118
328
  #### Setup
119
329
 
330
+ The `register-python-argcomplete` helper comes from argcomplete. With uv you never have to install
331
+ it: `uvx --from argcomplete register-python-argcomplete` runs it on demand.
332
+
120
333
  ##### Bash
121
334
  ```bash
122
335
  # Add to ~/.bashrc or ~/.bash_profile
336
+ eval "$(uvx --from argcomplete register-python-argcomplete awsquery)"
337
+
338
+ # If argcomplete is already installed in your environment (pip/pipx users):
123
339
  eval "$(register-python-argcomplete awsquery)"
124
340
  ```
125
341
 
@@ -127,13 +343,21 @@ eval "$(register-python-argcomplete awsquery)"
127
343
  ```bash
128
344
  # Add to ~/.zshrc
129
345
  autoload -U bashcompinit && bashcompinit
130
- eval "$(register-python-argcomplete awsquery)"
346
+ eval "$(uvx --from argcomplete register-python-argcomplete awsquery)"
131
347
  ```
132
348
 
133
349
  ##### Fish
134
350
  ```bash
135
351
  # Add to ~/.config/fish/config.fish
136
- register-python-argcomplete --shell fish awsquery | source
352
+ uvx --from argcomplete register-python-argcomplete --shell fish awsquery | source
353
+ ```
354
+
355
+ To keep shell startup instant, write the completion script to a file once and source that instead of
356
+ calling uvx on every new shell:
357
+
358
+ ```bash
359
+ uvx --from argcomplete register-python-argcomplete awsquery > ~/.awsquery-complete.sh
360
+ echo 'source ~/.awsquery-complete.sh' >> ~/.zshrc # or ~/.bashrc
137
361
  ```
138
362
 
139
363
  After adding the appropriate line to your shell configuration, restart your shell or source the file:
@@ -195,7 +419,8 @@ awsquery -d ec2 describe-instances
195
419
  ## Command Structure
196
420
 
197
421
  ```
198
- awsquery [-j|--json] [-k|--keys] [-d|--debug] [-p PARAM] [-i HINT] [--region REGION] [--profile PROFILE] SERVICE ACTION [VALUE_FILTERS...] [-- TABLE_OUTPUT_FILTERS...]
422
+ awsquery [-j|--json] [--format FMT] [--limit N] [-k|--keys] [-d|--debug] [-p PARAM] [-i HINT] [--region REGION] [--profile PROFILE] SERVICE ACTION [VALUE_FILTERS...] [-- TABLE_OUTPUT_FILTERS...]
423
+ awsquery --docs | --list-services | [SERVICE] --list-actions | --schema SERVICE ACTION
199
424
  ```
200
425
 
201
426
  - **SERVICE**: AWS service name (ec2, s3, iam, etc.)
@@ -209,6 +434,12 @@ awsquery [-j|--json] [-k|--keys] [-d|--debug] [-p PARAM] [-i HINT] [--region REG
209
434
  - **-i, --input HINT**: Multi-step control with cross-service support and function/field/limit hints (e.g., "ec2:desc-inst:instanceid", "desc-clus", ":arn", "::5")
210
435
  - **--region REGION**: AWS region to use for requests (e.g., us-west-2)
211
436
  - **--profile PROFILE**: AWS profile to use from ~/.aws/credentials
437
+ - **--format FMT**: Output format - `table` (default), `json`, `csv`, `tsv`, `ndjson`
438
+ - **--limit N**: Truncate printed rows to N (independent of the `-i ::N` resource cap)
439
+ - **--docs**: Print the complete agent/LLM reference and exit (no AWS call)
440
+ - **--schema**: Print an operation's input parameters and output fields (no AWS call)
441
+ - **--list-services / --list-actions**: Enumerate services or a service's read-only actions (no AWS call)
442
+ - **--allow-unsafe**: Permit a non-read-only operation without prompting
212
443
 
213
444
  ## Security
214
445
 
@@ -410,8 +641,148 @@ arguments). A service with no curated entry prints its available ReadOnly action
410
641
  and exits non-zero; `awsquery` with no service at all is unchanged — it still lists available
411
642
  services on stdout and exits 0.
412
643
 
644
+ ## Using awsquery with AI Agents and LLMs
645
+
646
+ awsquery is built to be driven by coding agents and LLM tool calls, not just typed by hand. Three
647
+ things make that work: the tool documents itself, it can describe any AWS operation without calling
648
+ AWS, and its output can be made cheap in tokens.
649
+
650
+ ### The tool explains itself
651
+
652
+ ```bash
653
+ awsquery --docs
654
+ ```
655
+
656
+ Prints the complete agent reference - filter grammar, every flag, output formats, exit codes, the
657
+ safety model, recipes and failure modes - as Markdown on stdout, in one call, with no AWS access.
658
+ About 16 KB, sized to drop straight into a context window. This is the one command to give an agent
659
+ that has never seen awsquery before.
660
+
661
+ The same text is mirrored at [`llms-full.txt`](llms-full.txt) with an [`llms.txt`](llms.txt) index
662
+ ([llmstxt.org](https://llmstxt.org/) convention) for agents that fetch from GitHub rather than run
663
+ the binary. [`AGENTS.md`](AGENTS.md) is the separate file for agents working *on* this repository.
664
+
665
+ ### Discovery without credentials
666
+
667
+ These make no AWS API call, need no credentials and no region, and answer in well under a second -
668
+ so an agent can plan a query before it has any access at all:
669
+
670
+ ```bash
671
+ awsquery --list-services # every supported service
672
+ awsquery ec2 --list-actions # that service's read-only operations
673
+ awsquery --schema ec2 describe-instances # inputs, and every field the API can return
674
+ awsquery --schema -j ec2 describe-instances # the same as JSON
675
+ ```
676
+
677
+ `--schema` reads botocore's service model, so it lists all 213 output field paths for
678
+ `ec2 describe-instances` with their types - including fields that happen to be absent from your
679
+ account right now. It also tells you how to turn those paths into column filters.
680
+
681
+ That is the difference from `-k`/`--keys`, which is still there and still useful:
682
+
683
+ | | `--schema` | `-k` / `--keys` |
684
+ | --- | --- | --- |
685
+ | Answers | what the API **can** return | what your account **did** return |
686
+ | AWS call | none | yes |
687
+ | Needs credentials | no | yes |
688
+ | Completeness | every field | only fields populated in existing resources |
689
+
690
+ Use `--schema` to choose columns; use `-k` to inspect real data. `-k` follows `--format` too.
691
+
692
+ ### Token-efficient output
693
+
694
+ Table borders and indented JSON are expensive to read. Measured on 50 rows by 5 columns: grid table
695
+ ~2340 tokens, `--format json` ~2440, `--format csv` ~790.
696
+
697
+ ```bash
698
+ awsquery --format csv --limit 50 ec2 describe-instances prod -- InstanceId Tags.Name State.Name
699
+ ```
700
+
701
+ - `--format table` (default), `json`, `csv`, `tsv`, `ndjson`
702
+ - `-j`/`--json` is equivalent to `--format json`
703
+ - `csv`, `tsv`, `ndjson` and `json` are faithful: values are not truncated, falsy values are
704
+ preserved, native types survive in the JSON formats (csv/tsv cells are text), and one resource
705
+ is always one row. `table` is a display format - it truncates long values, summarises repeats as
706
+ `(+N more)`, renders falsy cells blank and drops all-blank rows, so never parse it
707
+ - An empty result set prints nothing at all under `csv`/`tsv`/`ndjson` (headers come from the
708
+ data); only `json` still returns `{"results": []}`. Exit status is 0 either way
709
+ - `--limit N` truncates the printed resources in any format and notes the truncation on stderr
710
+ - `--limit` is independent of `-i ::N`, which caps resources fed into multi-level resolution
711
+ (note `-i ::0` means unlimited, while `--limit 0` means zero rows)
712
+
713
+ ### Predictable in a tool-call loop
714
+
715
+ ```bash
716
+ export AWSQUERY_NON_INTERACTIVE=1
717
+ ```
718
+
719
+ A non-read-only operation is then refused immediately with exit 2 instead of prompting - awsquery
720
+ never blocks on stdin and never returns a traceback for it. The same applies automatically whenever
721
+ stdin is not a TTY.
722
+
723
+ stdout carries data only; notices and errors go to stderr, so stdout stays parseable.
724
+
725
+ | Exit code | Meaning |
726
+ | --- | --- |
727
+ | 0 | success, including an empty result set |
728
+ | 1 | general or unexpected error |
729
+ | 2 | usage error, unknown service/action, or unsafe operation refused |
730
+ | 3 | AWS API error |
731
+ | 4 | credentials, region or authentication failure |
732
+
733
+ Unknown services and actions are caught offline, before any AWS call, so a typo costs nothing and
734
+ comes back with the command that fixes it. Under `--format json` and `--format ndjson`, errors are
735
+ also emitted to stderr as one compact JSON object:
736
+
737
+ ```json
738
+ {"error": {"code": 2, "type": "UnknownService", "message": "Unknown service 'ec3'",
739
+ "hint": "Run: awsquery --list-services"}}
740
+ ```
741
+
742
+ A successful run with nothing to report uses a `notice` key instead, so branching on the presence
743
+ of `error` is safe.
744
+
745
+ `AWS_REGION` is honoured as a fallback when `AWS_DEFAULT_REGION` is unset, since agents commonly set
746
+ the former and plain boto3 ignores it.
747
+
748
+ ### Recommended agent workflow
749
+
750
+ ```bash
751
+ awsquery --docs # once, to learn the tool
752
+ awsquery --schema -j ec2 describe-instances # pick fields, no credentials needed
753
+ awsquery --format csv --limit 50 \
754
+ ec2 describe-instances prod -- InstanceId Tags.Name State.Name # one narrow query
755
+ ```
756
+
757
+ Combined with `uvx`, an agent needs no install step at all: `uvx awsquery --docs`.
758
+
413
759
  ## Development
414
760
 
761
+ ### Environment setup with uv
762
+
763
+ ```bash
764
+ # Create .venv and install the project plus dev dependencies from uv.lock
765
+ uv sync --extra dev # or: make uv-sync
766
+
767
+ # Run anything inside that environment without activating it
768
+ uv run awsquery ec2 describe-instances # or: make uv-run ARGS="ec2 describe-instances"
769
+ uv run pytest tests/ -v # or: make uv-test
770
+ uv run black src tests
771
+ uv run mypy src
772
+
773
+ # Update the lockfile after changing dependencies in pyproject.toml
774
+ uv lock # or: make uv-lock
775
+
776
+ # Install your working tree as the global awsquery command
777
+ uv tool install --editable . # or: make tool-install
778
+ uv tool uninstall awsquery # or: make tool-uninstall
779
+ ```
780
+
781
+ `uv.lock` is committed, so `uv sync` gives every contributor byte-identical dependency versions.
782
+ Regenerate it with `uv lock` whenever `pyproject.toml` dependencies change and commit the result.
783
+
784
+ The `make` targets below use pip and the system Python; they work unchanged if you prefer that.
785
+
415
786
  ### Running Tests
416
787
 
417
788
  ```bash
@@ -502,9 +873,11 @@ All filters in awsquery use **case-insensitive matching** with optional anchorin
502
873
  - No operators: matches values that CONTAIN the pattern (partial match)
503
874
 
504
875
  #### Value Filters (before `--`)
505
- - Match against ANY field in the response data
876
+ - Match against ANY field in the response data - both the values **and the field names**
506
877
  - ALL specified filters must match (AND logic)
507
878
  - Case-insensitive matching with optional anchoring
879
+ - Because names are searched too, a field name used as a value filter matches every resource
880
+ (`awsquery ec2 describe-instances InstanceId` returns everything). Column names belong after `--`
508
881
 
509
882
  ```bash
510
883
  # "prod" matches: "production", "prod-server", "my-prod-app" (contains)
@@ -527,6 +900,9 @@ awsquery ec2 describe-instances ^prod web$
527
900
  - Match against column/field names in the output
528
901
  - Case-insensitive matching with optional anchoring
529
902
  - Multiple columns can be specified
903
+ - Anchors apply to the full flattened key (`Instances.0.State.Name`), not the displayed header, so
904
+ prefer suffix anchors (`State.Name$`) for nested fields - which is why the curated defaults in
905
+ `default_filters.yaml` are all `$`-anchored
530
906
 
531
907
  ```bash
532
908
  # "Instance" matches: "InstanceId", "InstanceType", "InstanceName" (contains)
@@ -538,8 +914,10 @@ awsquery ec2 describe-instances -- ^Instance
538
914
  # "Name$" matches: "InstanceName", "GroupName", "Tags.Name" (ends with)
539
915
  awsquery ec2 describe-instances -- Name$
540
916
 
541
- # "^State.Name$" matches: only exactly "State.Name" (exact match)
542
- awsquery ec2 describe-instances -- ^State.Name$
917
+ # Anchors apply to the FULL flattened key, which includes list indices
918
+ # (e.g. "Instances.0.State.Name"), so "^State.Name$" matches nothing here.
919
+ # Use a suffix anchor for nested fields:
920
+ awsquery ec2 describe-instances -- State.Name$
543
921
 
544
922
  # Multiple patterns
545
923
  awsquery ec2 describe-instances -- ^Instance Name$ State
@@ -616,7 +994,7 @@ awsquery elbv2 describe-tags -i desc-clus:clusterarn prod
616
994
  # Result limiting - control how many resources are processed (default: 10)
617
995
  awsquery ssm get-parameters -i ::5 # Limit to 5 parameters
618
996
  awsquery ec2 describe-instances -i ::20 # Limit to 20 instances
619
- awsquery s3api list-objects -i ::0 # Unlimited (remove default limit)
997
+ awsquery s3 list-objects-v2 -i ::0 # Unlimited (remove default limit)
620
998
 
621
999
  # Field override without function (uses inferred function)
622
1000
  awsquery ecs describe-tasks -i :clusterarn # Extract ClusterArn field
@@ -690,8 +1068,24 @@ awsquery s3 list-buckets backup -- Name Creation
690
1068
  - Use more specific filters to reduce data volume
691
1069
  - Consider using `--region` to target specific regions
692
1070
 
1071
+ **`awsquery: command not found` after `uv tool install`**
1072
+ - Run `uv tool update-shell` and restart your shell; uv's bin directory (`~/.local/bin`) has to be on `PATH`
1073
+ - `uv tool list` shows what is installed
1074
+
1075
+ **uvx keeps running an old version**
1076
+ - `uvx awsquery` reuses the cached version; use `uvx awsquery@latest` to re-check PyPI
1077
+ - `uv cache clean awsquery` drops the cached build entirely
1078
+ - For an installed tool use `uv tool upgrade awsquery`
1079
+
1080
+ **Tab completion does not work**
1081
+ - Completion needs a real executable on `PATH`: use `uv tool install awsquery`, not a `uvx` alias
1082
+ - See [Enable Shell Autocomplete](#enable-shell-autocomplete)
1083
+
693
1084
  ## Requirements
694
1085
 
1086
+ - Python 3.10 or newer - or just [uv](https://docs.astral.sh/uv/), which supplies its own Python
1087
+ - AWS credentials configured the same way the AWS CLI expects them
1088
+
695
1089
  The package dependencies are:
696
1090
 
697
1091
  - boto3>=1.35.0