bt-cli 0.4.28__tar.gz → 0.4.29__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 (174) hide show
  1. {bt_cli-0.4.28 → bt_cli-0.4.29}/CLAUDE.md +1 -1
  2. {bt_cli-0.4.28 → bt_cli-0.4.29}/PKG-INFO +1 -1
  3. {bt_cli-0.4.28 → bt_cli-0.4.29}/pyproject.toml +1 -1
  4. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/__init__.py +1 -1
  5. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/commands/configure.py +218 -2
  6. {bt_cli-0.4.28 → bt_cli-0.4.29}/.claude/skills/bt/SKILL.md +0 -0
  7. {bt_cli-0.4.28 → bt_cli-0.4.29}/.claude/skills/entitle/SKILL.md +0 -0
  8. {bt_cli-0.4.28 → bt_cli-0.4.29}/.claude/skills/epmw/SKILL.md +0 -0
  9. {bt_cli-0.4.28 → bt_cli-0.4.29}/.claude/skills/pra/SKILL.md +0 -0
  10. {bt_cli-0.4.28 → bt_cli-0.4.29}/.claude/skills/pws/SKILL.md +0 -0
  11. {bt_cli-0.4.28 → bt_cli-0.4.29}/.env.example +0 -0
  12. {bt_cli-0.4.28 → bt_cli-0.4.29}/.github/workflows/ci.yml +0 -0
  13. {bt_cli-0.4.28 → bt_cli-0.4.29}/.github/workflows/release.yml +0 -0
  14. {bt_cli-0.4.28 → bt_cli-0.4.29}/.gitignore +0 -0
  15. {bt_cli-0.4.28 → bt_cli-0.4.29}/README.md +0 -0
  16. {bt_cli-0.4.28 → bt_cli-0.4.29}/assets/cli-help.png +0 -0
  17. {bt_cli-0.4.28 → bt_cli-0.4.29}/assets/cli-output.png +0 -0
  18. {bt_cli-0.4.28 → bt_cli-0.4.29}/bt-cli.spec +0 -0
  19. {bt_cli-0.4.28 → bt_cli-0.4.29}/bt_entry.py +0 -0
  20. {bt_cli-0.4.28 → bt_cli-0.4.29}/scripts/bt_entry.py +0 -0
  21. {bt_cli-0.4.28 → bt_cli-0.4.29}/scripts/sync-package-data.sh +0 -0
  22. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/cli.py +0 -0
  23. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/commands/__init__.py +0 -0
  24. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/commands/learn.py +0 -0
  25. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/commands/quick.py +0 -0
  26. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/__init__.py +0 -0
  27. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/auth.py +0 -0
  28. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/client.py +0 -0
  29. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/config.py +0 -0
  30. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/config_file.py +0 -0
  31. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/csv_utils.py +0 -0
  32. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/errors.py +0 -0
  33. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/output.py +0 -0
  34. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/prompts.py +0 -0
  35. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/rest_debug.py +0 -0
  36. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/data/CLAUDE.md +0 -0
  37. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/data/__init__.py +0 -0
  38. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/data/skills/bt/SKILL.md +0 -0
  39. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/data/skills/entitle/SKILL.md +0 -0
  40. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/data/skills/epmw/SKILL.md +0 -0
  41. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/data/skills/pra/SKILL.md +0 -0
  42. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/data/skills/pws/SKILL.md +0 -0
  43. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/__init__.py +0 -0
  44. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/client/__init__.py +0 -0
  45. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/client/base.py +0 -0
  46. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/__init__.py +0 -0
  47. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/accounts.py +0 -0
  48. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/applications.py +0 -0
  49. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/auth.py +0 -0
  50. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/bundles.py +0 -0
  51. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/integrations.py +0 -0
  52. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/permissions.py +0 -0
  53. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/policies.py +0 -0
  54. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/resources.py +0 -0
  55. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/roles.py +0 -0
  56. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/users.py +0 -0
  57. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/workflows.py +0 -0
  58. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/__init__.py +0 -0
  59. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/bundle.py +0 -0
  60. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/common.py +0 -0
  61. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/integration.py +0 -0
  62. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/permission.py +0 -0
  63. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/policy.py +0 -0
  64. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/resource.py +0 -0
  65. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/role.py +0 -0
  66. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/user.py +0 -0
  67. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/workflow.py +0 -0
  68. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/__init__.py +0 -0
  69. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/client/__init__.py +0 -0
  70. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/client/base.py +0 -0
  71. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/__init__.py +0 -0
  72. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/audits.py +0 -0
  73. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/auth.py +0 -0
  74. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/computers.py +0 -0
  75. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/events.py +0 -0
  76. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/groups.py +0 -0
  77. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/policies.py +0 -0
  78. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/quick.py +0 -0
  79. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/requests.py +0 -0
  80. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/roles.py +0 -0
  81. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/tasks.py +0 -0
  82. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/users.py +0 -0
  83. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/models/__init__.py +0 -0
  84. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/__init__.py +0 -0
  85. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/client/__init__.py +0 -0
  86. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/client/base.py +0 -0
  87. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/__init__.py +0 -0
  88. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/auth.py +0 -0
  89. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/import_export.py +0 -0
  90. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/jump_clients.py +0 -0
  91. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/jump_groups.py +0 -0
  92. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/jump_items.py +0 -0
  93. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/jumpoints.py +0 -0
  94. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/policies.py +0 -0
  95. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/quick.py +0 -0
  96. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/teams.py +0 -0
  97. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/users.py +0 -0
  98. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/vault.py +0 -0
  99. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/__init__.py +0 -0
  100. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/common.py +0 -0
  101. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/jump_client.py +0 -0
  102. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/jump_group.py +0 -0
  103. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/jump_item.py +0 -0
  104. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/jumpoint.py +0 -0
  105. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/team.py +0 -0
  106. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/user.py +0 -0
  107. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/vault.py +0 -0
  108. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/__init__.py +0 -0
  109. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/client/__init__.py +0 -0
  110. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/client/base.py +0 -0
  111. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/client/beyondinsight.py +0 -0
  112. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/client/passwordsafe.py +0 -0
  113. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/__init__.py +0 -0
  114. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/accounts.py +0 -0
  115. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/assets.py +0 -0
  116. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/attributes.py +0 -0
  117. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/auth.py +0 -0
  118. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/clouds.py +0 -0
  119. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/config.py +0 -0
  120. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/credentials.py +0 -0
  121. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/databases.py +0 -0
  122. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/directories.py +0 -0
  123. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/functional.py +0 -0
  124. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/import_export.py +0 -0
  125. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/platforms.py +0 -0
  126. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/quick.py +0 -0
  127. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/search.py +0 -0
  128. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/secrets.py +0 -0
  129. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/systems.py +0 -0
  130. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/users.py +0 -0
  131. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/workgroups.py +0 -0
  132. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/config.py +0 -0
  133. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/models/__init__.py +0 -0
  134. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/models/account.py +0 -0
  135. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/models/asset.py +0 -0
  136. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/models/common.py +0 -0
  137. {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/models/system.py +0 -0
  138. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/__init__.py +0 -0
  139. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/conftest.py +0 -0
  140. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/core/__init__.py +0 -0
  141. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/core/test_auth.py +0 -0
  142. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/core/test_config.py +0 -0
  143. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/core/test_errors.py +0 -0
  144. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/core/test_rest_debug.py +0 -0
  145. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/entitle/__init__.py +0 -0
  146. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/entitle/test_client.py +0 -0
  147. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/entitle/test_commands.py +0 -0
  148. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/entitle-smoke-test.sh +0 -0
  149. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/epmw/__init__.py +0 -0
  150. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/epmw/test_client.py +0 -0
  151. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/epmw/test_commands.py +0 -0
  152. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/epmw-quick-test-plan.md +0 -0
  153. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/fixtures/__init__.py +0 -0
  154. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/fixtures/responses.py +0 -0
  155. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/__init__.py +0 -0
  156. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/conftest.py +0 -0
  157. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/helpers.py +0 -0
  158. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/test_entitle_integration.py +0 -0
  159. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/test_epmw_integration.py +0 -0
  160. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/test_epmw_lifecycle.py +0 -0
  161. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/test_pra_integration.py +0 -0
  162. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/test_pra_lifecycle.py +0 -0
  163. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/test_pws_integration.py +0 -0
  164. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/test_pws_lifecycle.py +0 -0
  165. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pra/__init__.py +0 -0
  166. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pra/test_client.py +0 -0
  167. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pra/test_commands.py +0 -0
  168. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pra-smoke-test.sh +0 -0
  169. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pra-test-plan.md +0 -0
  170. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pws/__init__.py +0 -0
  171. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pws/test_client.py +0 -0
  172. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pws/test_commands.py +0 -0
  173. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pws-quick-test-plan.md +0 -0
  174. {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pws-smoke-test.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  # BT-CLI
2
2
 
3
- BeyondTrust Platform CLI for Password Safe, Entitle, PRA, and EPM Windows. **Version: 0.4.28**
3
+ BeyondTrust Platform CLI for Password Safe, Entitle, PRA, and EPM Windows. **Version: 0.4.29**
4
4
 
5
5
  ## Setup
6
6
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bt-cli
3
- Version: 0.4.28
3
+ Version: 0.4.29
4
4
  Summary: BeyondTrust Platform CLI (unofficial) - Password Safe, Entitle, PRA, EPM
5
5
  Author-email: Dave Grendysz <dgrendysz@beyondtrust.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "bt-cli"
7
- version = "0.4.28"
7
+ version = "0.4.29"
8
8
  description = "BeyondTrust Platform CLI (unofficial) - Password Safe, Entitle, PRA, EPM"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1,3 +1,3 @@
1
1
  """BeyondTrust Unified Admin CLI."""
2
2
 
3
- __version__ = "0.4.28"
3
+ __version__ = "0.4.29"
@@ -298,11 +298,21 @@ def show_config(
298
298
  profile: Optional[str] = typer.Option(None, "--profile", help="Profile to show"),
299
299
  show_secrets: bool = typer.Option(False, "--show-secrets", help="Show secret values"),
300
300
  ) -> None:
301
- """Show current configuration."""
301
+ """Show configuration from config file.
302
+
303
+ Note: This only shows profiles saved to ~/.bt-cli/config.yaml.
304
+ If you're using environment variables or .env file, use:
305
+
306
+ bt configure effective
307
+
308
+ to see the actual configuration in use.
309
+ """
302
310
  config = load_config_file()
303
311
 
304
312
  if not config.profiles:
305
- print_warning("No configuration found. Run 'bt configure' to set up.")
313
+ print_warning("No profiles in config file. Run 'bt configure' to set up.")
314
+ console.print("\n[dim]Tip: If using .env or environment variables, run:[/dim]")
315
+ console.print("[cyan] bt configure effective[/cyan]")
306
316
  raise typer.Exit(0)
307
317
 
308
318
  profiles_to_show = [profile] if profile else config.list_profiles()
@@ -413,3 +423,209 @@ def show_path() -> None:
413
423
  console.print("[green]Config file exists[/green]")
414
424
  else:
415
425
  console.print("[yellow]Config file does not exist yet[/yellow]")
426
+
427
+
428
+ @app.command("import-env")
429
+ def import_from_env(
430
+ profile: str = typer.Option("default", "--profile", "-p", help="Profile name to save as"),
431
+ force: bool = typer.Option(False, "--force", "-f", help="Overwrite existing profile"),
432
+ ) -> None:
433
+ """Import configuration from environment variables into a profile.
434
+
435
+ This saves the current BT_* environment variables (including .env file)
436
+ into a named profile in the config file. Useful for:
437
+
438
+ - Converting .env setup to profile-based config
439
+ - Creating profiles from existing environment
440
+ - Backing up current config to file
441
+
442
+ Example:
443
+ bt configure import-env --profile production
444
+ """
445
+ import os
446
+ from dotenv import load_dotenv, find_dotenv
447
+ from rich.prompt import Confirm
448
+
449
+ # Load .env if present
450
+ env_file = find_dotenv()
451
+ if env_file:
452
+ load_dotenv(env_file)
453
+ console.print(f"[dim]Loaded .env from: {env_file}[/dim]\n")
454
+
455
+ config = load_config_file()
456
+
457
+ # Check if profile exists
458
+ if profile in config.profiles and not force:
459
+ if not Confirm.ask(f"Profile '{profile}' exists. Overwrite?", default=False):
460
+ print_info("Cancelled")
461
+ raise typer.Exit(0)
462
+
463
+ # Product environment variable mappings
464
+ env_mappings = {
465
+ "pws": {
466
+ "api_url": "BT_PWS_API_URL",
467
+ "api_key": "BT_PWS_API_KEY",
468
+ "client_id": "BT_PWS_CLIENT_ID",
469
+ "client_secret": "BT_PWS_CLIENT_SECRET",
470
+ "run_as": "BT_PWS_RUN_AS",
471
+ "verify_ssl": "BT_PWS_VERIFY_SSL",
472
+ "timeout": "BT_PWS_TIMEOUT",
473
+ },
474
+ "pra": {
475
+ "api_url": "BT_PRA_API_URL",
476
+ "client_id": "BT_PRA_CLIENT_ID",
477
+ "client_secret": "BT_PRA_CLIENT_SECRET",
478
+ "verify_ssl": "BT_PRA_VERIFY_SSL",
479
+ "timeout": "BT_PRA_TIMEOUT",
480
+ },
481
+ "entitle": {
482
+ "api_url": "BT_ENTITLE_API_URL",
483
+ "api_key": "BT_ENTITLE_API_KEY",
484
+ "verify_ssl": "BT_ENTITLE_VERIFY_SSL",
485
+ "timeout": "BT_ENTITLE_TIMEOUT",
486
+ },
487
+ "epmw": {
488
+ "api_url": "BT_EPM_API_URL",
489
+ "client_id": "BT_EPM_CLIENT_ID",
490
+ "client_secret": "BT_EPM_CLIENT_SECRET",
491
+ "verify_ssl": "BT_EPM_VERIFY_SSL",
492
+ "timeout": "BT_EPM_TIMEOUT",
493
+ },
494
+ }
495
+
496
+ imported = []
497
+ for product, env_vars in env_mappings.items():
498
+ product_config = {}
499
+ for setting, env_var in env_vars.items():
500
+ value = os.getenv(env_var)
501
+ if value:
502
+ # Convert types
503
+ if setting == "verify_ssl":
504
+ product_config[setting] = value.lower() not in ("false", "0", "no")
505
+ elif setting == "timeout":
506
+ try:
507
+ product_config[setting] = float(value)
508
+ except ValueError:
509
+ product_config[setting] = 30.0
510
+ else:
511
+ product_config[setting] = value
512
+
513
+ if product_config.get("api_url"):
514
+ # Infer auth_method for PWS
515
+ if product == "pws":
516
+ if product_config.get("api_key"):
517
+ product_config["auth_method"] = "apikey"
518
+ elif product_config.get("client_id"):
519
+ product_config["auth_method"] = "oauth"
520
+
521
+ config.set_product_config(product, product_config, profile)
522
+ imported.append(product)
523
+
524
+ if imported:
525
+ if not config.default_profile or profile == "default":
526
+ config.default_profile = profile
527
+ save_config_file(config)
528
+ print_success(f"Imported {', '.join(imported)} into profile '{profile}'")
529
+ console.print(f"[dim]Config saved to: {CONFIG_FILE}[/dim]")
530
+ else:
531
+ print_warning("No configuration found in environment variables")
532
+
533
+
534
+ @app.command("effective")
535
+ def show_effective_config(
536
+ show_secrets: bool = typer.Option(False, "--show-secrets", help="Show secret values"),
537
+ ) -> None:
538
+ """Show effective configuration from all sources.
539
+
540
+ Shows what configuration is actually in use, combining:
541
+ - Environment variables (BT_PWS_*, BT_PRA_*, etc.)
542
+ - .env file (if present)
543
+ - Config file profiles (~/.bt-cli/config.yaml)
544
+
545
+ This is useful for debugging why the CLI connects successfully
546
+ but 'bt configure show' appears empty.
547
+ """
548
+ import os
549
+ from dotenv import load_dotenv, find_dotenv
550
+
551
+ # Load .env if present
552
+ env_file = find_dotenv()
553
+ if env_file:
554
+ load_dotenv(env_file)
555
+ console.print(f"[dim]Loaded .env from: {env_file}[/dim]\n")
556
+
557
+ def mask_secret(key: str, value: str) -> str:
558
+ if not value:
559
+ return "[dim]not set[/dim]"
560
+ if not show_secrets and any(s in key.lower() for s in ["secret", "key", "password"]):
561
+ return "****" + value[-4:] if len(value) > 4 else "****"
562
+ return value
563
+
564
+ # Product environment variable mappings
565
+ products = {
566
+ "Password Safe": {
567
+ "api_url": "BT_PWS_API_URL",
568
+ "api_key": "BT_PWS_API_KEY",
569
+ "client_id": "BT_PWS_CLIENT_ID",
570
+ "client_secret": "BT_PWS_CLIENT_SECRET",
571
+ "run_as": "BT_PWS_RUN_AS",
572
+ "verify_ssl": "BT_PWS_VERIFY_SSL",
573
+ "timeout": "BT_PWS_TIMEOUT",
574
+ },
575
+ "PRA": {
576
+ "api_url": "BT_PRA_API_URL",
577
+ "client_id": "BT_PRA_CLIENT_ID",
578
+ "client_secret": "BT_PRA_CLIENT_SECRET",
579
+ "verify_ssl": "BT_PRA_VERIFY_SSL",
580
+ "timeout": "BT_PRA_TIMEOUT",
581
+ },
582
+ "Entitle": {
583
+ "api_url": "BT_ENTITLE_API_URL",
584
+ "api_key": "BT_ENTITLE_API_KEY",
585
+ "verify_ssl": "BT_ENTITLE_VERIFY_SSL",
586
+ "timeout": "BT_ENTITLE_TIMEOUT",
587
+ },
588
+ "EPM Windows": {
589
+ "api_url": "BT_EPM_API_URL",
590
+ "client_id": "BT_EPM_CLIENT_ID",
591
+ "client_secret": "BT_EPM_CLIENT_SECRET",
592
+ "verify_ssl": "BT_EPM_VERIFY_SSL",
593
+ "timeout": "BT_EPM_TIMEOUT",
594
+ },
595
+ }
596
+
597
+ # Check active profile
598
+ active_profile = os.getenv("BT_PROFILE", "default")
599
+ console.print(f"[bold]Active Profile:[/bold] {active_profile}\n")
600
+
601
+ # Show effective config for each product
602
+ for product_name, env_vars in products.items():
603
+ table = Table(title=product_name, show_header=True, title_style="bold cyan")
604
+ table.add_column("Setting", style="green")
605
+ table.add_column("Env Var", style="dim")
606
+ table.add_column("Value")
607
+ table.add_column("Source", style="dim")
608
+
609
+ has_config = False
610
+ for setting, env_var in env_vars.items():
611
+ value = os.getenv(env_var, "")
612
+ if value:
613
+ has_config = True
614
+ source = ".env" if env_file else "environment"
615
+ table.add_row(setting, env_var, mask_secret(setting, value), source)
616
+
617
+ if has_config:
618
+ console.print(table)
619
+ console.print()
620
+ else:
621
+ console.print(f"[dim]{product_name}: not configured[/dim]\n")
622
+
623
+ # Also show config file info
624
+ config = load_config_file()
625
+ if config.profiles:
626
+ console.print("[bold]Config File Profiles:[/bold]")
627
+ for profile_name in config.list_profiles():
628
+ products_list = list(config.profiles[profile_name].keys())
629
+ is_default = " (default)" if profile_name == config.default_profile else ""
630
+ console.print(f" {profile_name}{is_default}: {', '.join(products_list)}")
631
+ console.print(f"\n[dim]Note: Environment variables override config file settings[/dim]")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes