xsoar-cli 2.1.1__tar.gz → 2.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 (168) hide show
  1. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/CHANGELOG.md +26 -1
  2. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/CLAUDE.md +1 -3
  3. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/CONTRIBUTING.md +5 -30
  4. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/PKG-INFO +2 -1
  5. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/_version.py +2 -2
  6. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/pyproject.toml +1 -1
  7. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/cli.py +23 -7
  8. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/case/commands.py +14 -7
  9. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/completions/commands.py +2 -1
  10. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/config/README.md +18 -0
  11. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/config/commands.py +26 -6
  12. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/content/commands.py +9 -9
  13. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/graph/commands.py +4 -3
  14. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/integration/commands.py +8 -8
  15. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/manifest/commands.py +6 -5
  16. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/pack/commands.py +4 -4
  17. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/plugins/README.md +13 -2
  18. xsoar_cli-2.2.0/src/xsoar_cli/commands/plugins/commands.py +257 -0
  19. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/rbac/commands.py +8 -8
  20. xsoar_cli-2.2.0/src/xsoar_cli/plugins/README.md +45 -0
  21. xsoar_cli-2.2.0/src/xsoar_cli/plugins/__init__.py +48 -0
  22. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/plugins/manager.py +59 -73
  23. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/utilities/validators.py +19 -26
  24. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/artifact_providers/azure.py +4 -0
  25. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/artifact_providers/s3.py +3 -3
  26. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/content.py +3 -2
  27. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/cli/conftest.py +48 -14
  28. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/cli/test_config.py +39 -0
  29. xsoar_cli-2.2.0/tests/cli/test_plugins.py +244 -0
  30. xsoar_cli-2.2.0/tests/unit/test_plugin_manager.py +319 -0
  31. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_validators.py +4 -4
  32. xsoar_cli-2.1.1/src/xsoar_cli/commands/plugins/commands.py +0 -184
  33. xsoar_cli-2.1.1/src/xsoar_cli/plugins/README.md +0 -53
  34. xsoar_cli-2.1.1/src/xsoar_cli/plugins/__init__.py +0 -62
  35. xsoar_cli-2.1.1/tests/cli/test_plugins.py +0 -104
  36. xsoar_cli-2.1.1/tests/unit/test_plugin_manager.py +0 -213
  37. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/.github/workflows/main.yml +0 -0
  38. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/.github/workflows/pull-request-open.yml +0 -0
  39. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/.github/workflows/release.yml +0 -0
  40. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/.github/workflows/update-changelog.yml +0 -0
  41. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/.gitignore +0 -0
  42. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/LICENSE.txt +0 -0
  43. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/README.md +0 -0
  44. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/__init__.py +0 -0
  45. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/__init__.py +0 -0
  46. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/case/README.md +0 -0
  47. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/case/__init__.py +0 -0
  48. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/completions/README.md +0 -0
  49. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/completions/__init__.py +0 -0
  50. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/config/__init__.py +0 -0
  51. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/content/README.md +0 -0
  52. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/content/__init__.py +0 -0
  53. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/graph/README.md +0 -0
  54. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/graph/__init__.py +0 -0
  55. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/integration/README.md +0 -0
  56. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/integration/__init__.py +0 -0
  57. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/manifest/README.md +0 -0
  58. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/manifest/__init__.py +0 -0
  59. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/pack/README.md +0 -0
  60. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/pack/__init__.py +0 -0
  61. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/plugins/__init__.py +0 -0
  62. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/rbac/README.md +0 -0
  63. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/rbac/__init__.py +0 -0
  64. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/configuration.py +0 -0
  65. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/error_handling/__init__.py +0 -0
  66. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/error_handling/connection.py +0 -0
  67. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/error_handling/http.py +0 -0
  68. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/log.py +0 -0
  69. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/utilities/__init__.py +0 -0
  70. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/utilities/config_file.py +0 -0
  71. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/utilities/content.py +0 -0
  72. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/utilities/download_content_handlers.py +0 -0
  73. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/utilities/manifest.py +0 -0
  74. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/utilities/version_check.py +0 -0
  75. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/__init__.py +0 -0
  76. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/artifact_providers/__init__.py +0 -0
  77. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/artifact_providers/base.py +0 -0
  78. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/cases.py +0 -0
  79. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/client.py +0 -0
  80. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/constants.py +0 -0
  81. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/integrations.py +0 -0
  82. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/packs.py +0 -0
  83. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/rbac.py +0 -0
  84. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/__init__.py +0 -0
  85. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/cli/__init__.py +0 -0
  86. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/cli/test_base.py +0 -0
  87. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/cli/test_case.py +0 -0
  88. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/cli/test_completions.py +0 -0
  89. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/cli/test_content.py +0 -0
  90. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/cli/test_graph.py +0 -0
  91. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/cli/test_manifest.py +0 -0
  92. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/cli/test_pack.py +0 -0
  93. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/conftest.py +0 -0
  94. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/cases/create.json +0 -0
  95. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/cases/get.json +0 -0
  96. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/content/automation_search.json +0 -0
  97. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/content/playbook_search.json +0 -0
  98. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/content/user_commands.json +0 -0
  99. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/integrations/instances.json +0 -0
  100. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/manifest/manifest_base.json +0 -0
  101. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/manifest/manifest_invalid.json +0 -0
  102. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/manifest/manifest_with_pack_not_on_server.json +0 -0
  103. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/manifest/server_base_response.json +0 -0
  104. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/manifest/server_base_response_missing_one_pack.json +0 -0
  105. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/manifest/server_base_response_with_updates.json +0 -0
  106. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/manifest/server_base_response_with_updates_and_one_extra.json +0 -0
  107. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/packs/installed.json +0 -0
  108. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/packs/installed_expired.json +0 -0
  109. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/rbac/roles.json +0 -0
  110. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/rbac/user_groups.json +0 -0
  111. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/fixtures/rbac/users.json +0 -0
  112. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Download/playbook-empty.yml +0 -0
  113. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/.pack-ignore +0 -0
  114. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/.secrets-ignore +0 -0
  115. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/Author_image.png +0 -0
  116. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/Playbooks/GenericPlaybook.yml +0 -0
  117. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/README.md +0 -0
  118. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/pack_metadata.json +0 -0
  119. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonScripts/.pack-ignore +0 -0
  120. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonScripts/.secrets-ignore +0 -0
  121. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonScripts/Author_image.png +0 -0
  122. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonScripts/README.md +0 -0
  123. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonScripts/Scripts/GenericScript/GenericScript.py +0 -0
  124. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonScripts/Scripts/GenericScript/GenericScript.yml +0 -0
  125. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonScripts/Scripts/GenericScript/README.md +0 -0
  126. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonScripts/pack_metadata.json +0 -0
  127. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/.pack-ignore +0 -0
  128. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/.secrets-ignore +0 -0
  129. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Author_image.png +0 -0
  130. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Playbooks/EDR_InitialTriage.yml +0 -0
  131. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/README.md +0 -0
  132. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_FetchFile/EDR_FetchFile.py +0 -0
  133. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_FetchFile/EDR_FetchFile.yml +0 -0
  134. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_FetchFile/README.md +0 -0
  135. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_Triage/EDR_Triage.py +0 -0
  136. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_Triage/EDR_Triage.yml +0 -0
  137. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_Triage/README.md +0 -0
  138. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/LegacyItem/LegacyItem.py +0 -0
  139. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/LegacyItem/LegacyItem.yml +0 -0
  140. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/LegacyItem/README.md +0 -0
  141. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/LegacyItem/test_data/basescript-dummy.json +0 -0
  142. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/pack_metadata.json +0 -0
  143. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_Layouts/.pack-ignore +0 -0
  144. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_Layouts/.secrets-ignore +0 -0
  145. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_Layouts/Author_image.png +0 -0
  146. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_Layouts/Layouts/layoutscontainer-GenericLayout.json +0 -0
  147. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_Layouts/README.md +0 -0
  148. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_Layouts/pack_metadata.json +0 -0
  149. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/mock_content/Packs/Not_applicable/Playbooks/Empty.yml +0 -0
  150. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/__init__.py +0 -0
  151. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/conftest.py +0 -0
  152. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_artifact_azure.py +0 -0
  153. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_artifact_base.py +0 -0
  154. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_artifact_s3.py +0 -0
  155. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_cases.py +0 -0
  156. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_client.py +0 -0
  157. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_config_file.py +0 -0
  158. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_content_domain.py +0 -0
  159. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_content_filters.py +0 -0
  160. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_content_handlers.py +0 -0
  161. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_error_handling.py +0 -0
  162. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_integrations.py +0 -0
  163. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_main.py +0 -0
  164. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_manifest_utils.py +0 -0
  165. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_packs.py +0 -0
  166. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_rbac.py +0 -0
  167. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/tests/unit/test_version_check.py +0 -0
  168. {xsoar_cli-2.1.1 → xsoar_cli-2.2.0}/uv.lock +0 -0
@@ -6,6 +6,31 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ### Added
10
+
11
+ - `config set-version-check` command to enable or disable the version update check on CLI startup. Accepts `--enable` or `--disable`.
12
+ - `plugins init` command to create the plugins directory and generate an example plugin.
13
+
14
+ ### Changed
15
+
16
+ - **Breaking:** Plugins must explicitly import `XSOARPlugin` (`from xsoar_cli.plugins import XSOARPlugin`). The base class is no longer injected automatically and so old plugins require modification. See the [plugin README](src/xsoar_cli/plugins/README.md) for details.
17
+ - Plugin commands (`list`, `info`, `validate`) now report a clear error when the plugins directory has not been initialized.
18
+ - Plugin registration failures no longer prevent remaining plugins from loading.
19
+ - `content get-detached --type` is now required. The `all` choice has been removed; specify `scripts` or `playbooks` explicitly.
20
+ - `integration dump`, `rbac getroles`, `rbac getusers`, and `rbac getusergroups` no longer emit a trailing blank line after JSON output.
21
+ - `config show` now uses `click.echo()` instead of `print()`, improving behavior when piping output to other tools.
22
+
23
+ ### Removed
24
+
25
+ - The plugins directory is no longer automatically created on CLI startup. Run `xsoar-cli plugins init` to create it explicitly.
26
+
27
+ ### Fixed
28
+
29
+ - `content get-detached` no longer fails when invoked without `--type` due to a stale default value that referenced the removed `all` choice.
30
+ - Content bundle download (`get_content_bundle`) now raises on HTTP errors instead of silently proceeding and failing with a confusing `tarfile` error.
31
+
32
+ ## [2.1.1] - 2026-04-08
33
+
9
34
  ### Changed
10
35
 
11
36
  - `manifest generate` now uses an `--output-dir` option (default: current directory) instead of a positional path argument. The output file is always named `xsoar_config.json`. Prompts for confirmation if the file already exists.
@@ -83,4 +108,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
83
108
 
84
109
  ### Removed
85
110
 
86
- - `config validate --stacktrace` option. Use `--verbose` / `-v` instead.
111
+ - `config validate --stacktrace` option. Use `--verbose` / `-v` instead.
@@ -64,6 +64,7 @@ src/xsoar_cli/ # Main package (src layout)
64
64
  azure.py # AzureArtifactProvider (Azure Blob Storage)
65
65
  commands/ # CLI command groups
66
66
  case/ # Case operations command group
67
+ completions/ # Shell autocompletion command group
67
68
  config/ # Config management command group
68
69
  content/ # Content download/list command group
69
70
  graph/ # Dependency graph command group
@@ -124,9 +125,6 @@ Always use `--no-pager` when running git commands (e.g. `git --no-pager log`, `g
124
125
  ```sh
125
126
  # Install dependencies
126
127
  uv sync
127
- uv pip install -r requirements.txt
128
- uv pip install -r requirements_dev.txt
129
- uv pip install -e .
130
128
 
131
129
  # Run all tests
132
130
  uv run pytest
@@ -44,40 +44,16 @@ For other platforms and installation options, see the [uv installation docs](htt
44
44
 
45
45
  ### 3. Set Up Development Environment
46
46
 
47
- **Recommended: uv**
48
-
49
- You may find that you will need to make modifications in [xsoar-client](https://github.com/tlium/xsoar-client) and/or [xsoar-dependency-graph](https://github.com/tlium/xsoar-dependency-graph) in order
50
- to fix bugs or add new features to `xsoar-cli`. If you need to work on `xsoar-client` or `xsoar-dependency-graph`, install them in editable mode from your local Git clones:
51
-
52
- ```bash
53
- uv pip install -e /path/to/your/xsoar-client
54
- uv pip install -e /path/to/your/xsoar-dependency-graph
55
- ```
56
-
57
47
  ```bash
58
48
  # Install dependencies and xsoar-cli in editable mode
59
49
  uv sync
60
50
  uv pip install -e .
61
51
  ```
62
- **Alternative: pip/venv**
63
52
 
64
- ```bash
65
- # Create and activate a virtual environment
66
- python -m venv venv
67
- source venv/bin/activate
68
-
69
- # Install development dependencies
70
- pip install -r requirements_dev.txt
71
-
72
- # Install xsoar-cli in editable mode
73
- pip install -e .
74
- ```
75
-
76
- If you need to work on the supporting libraries, install them in editable mode as well:
53
+ You may need to make modifications in [xsoar-dependency-graph](https://github.com/tlium/xsoar-dependency-graph) to fix bugs or add new features to `xsoar-cli`. If so, install it in editable mode from your local Git clone:
77
54
 
78
55
  ```bash
79
- pip install -e /path/to/your/xsoar-client
80
- pip install -e /path/to/your/xsoar-dependency-graph
56
+ uv pip install -e /path/to/your/xsoar-dependency-graph
81
57
  ```
82
58
 
83
59
  ## Development Workflow
@@ -115,16 +91,15 @@ pip install -e /path/to/your/xsoar-dependency-graph
115
91
 
116
92
  #### Lazy imports
117
93
 
118
- Heavy third-party packages like `xsoar_client`, `xsoar_dependency_graph` and `demisto_client` pull in large dependency trees (boto3, azure-storage-blob, matplotlib, networkx, etc.) that are expensive to load. To keep everyday invocations like `--help` and `--version` fast, these imports are placed inside the functions that need them rather than at the top of the file. Each lazy import is marked with the comment `# Lazy import for performance reasons`.
94
+ Heavy third-party packages like `xsoar_dependency_graph` and `demisto_client` pull in large dependency trees (boto3, azure-storage-blob, matplotlib, networkx, etc.) that are expensive to load. To keep everyday invocations like `--help` and `--version` fast, these imports are placed inside the functions that need them rather than at the top of the file. Each lazy import is marked with the comment `# Lazy import for performance reasons`.
119
95
 
120
- Type hints for the deferred types still appear in function signatures. To avoid quoting them as strings, modules that use this pattern include `from __future__ import annotations` and a `TYPE_CHECKING` block at the top:
96
+ Type hints for the deferred types still appear in function signatures. To keep them clean, use a `TYPE_CHECKING` block at the top of the module:
121
97
 
122
98
  ```python
123
- from __future__ import annotations
124
99
  from typing import TYPE_CHECKING
125
100
 
126
101
  if TYPE_CHECKING:
127
- from xsoar_client.xsoar_client import Client
102
+ from xsoar_cli.xsoar_client.client import Client
128
103
  ```
129
104
 
130
105
  See `configuration.py` for a complete example.
@@ -1,6 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xsoar-cli
3
- Version: 2.1.1
3
+ Version: 2.2.0
4
+ Summary: A command-line interface for managing Palo Alto Networks XSOAR (Cortex XSOAR)
4
5
  Project-URL: Documentation, https://github.com/tlium/xsoar-cli#readme
5
6
  Project-URL: Issues, https://github.com/tlium/xsoar-cli/issues
6
7
  Project-URL: Source, https://github.com/tlium/xsoar-cli
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '2.1.1'
22
- __version_tuple__ = version_tuple = (2, 1, 1)
21
+ __version__ = version = '2.2.0'
22
+ __version_tuple__ = version_tuple = (2, 2, 0)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
5
5
  [project]
6
6
  name = "xsoar-cli"
7
7
  dynamic = ["version"]
8
- description = ''
8
+ description = 'A command-line interface for managing Palo Alto Networks XSOAR (Cortex XSOAR)'
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
11
11
  license = "MIT"
@@ -83,13 +83,29 @@ def _load_plugins() -> tuple[list[str], PluginManager]:
83
83
  """Captures core command names, then loads and registers plugins. Returns both."""
84
84
  core_commands = list(cli.commands.keys())
85
85
  manager = PluginManager()
86
- try:
87
- manager.load_all_plugins(ignore_errors=True)
88
- for plugin_name, error in manager.get_failed_plugins().items():
89
- click.echo(f"Warning: plugin '{plugin_name}' failed to load: {error}", err=True)
90
- manager.register_plugin_commands(cli)
91
- except Exception as e:
92
- click.echo(f"Warning: failed to register plugin commands: {e}", err=True)
86
+
87
+ if not manager.plugins_dir_exists:
88
+ logging.getLogger(__name__).debug("Plugins directory not found, skipping plugin loading")
89
+ return core_commands, manager
90
+
91
+ manager.load_all_plugins(ignore_errors=True)
92
+
93
+ # Report load failures on stderr. These warnings run at module level before
94
+ # logging is configured, so logger.warning would be invisible. Plugin load
95
+ # failures are important enough to surface unconditionally.
96
+ load_failures = set(manager.get_failed_plugins().keys())
97
+ for plugin_name, error in manager.get_failed_plugins().items():
98
+ click.echo(f"Warning: plugin '{plugin_name}' failed to load: {error}", err=True)
99
+
100
+ manager.register_plugin_commands(cli)
101
+
102
+ # Registration failures are recorded in failed_plugins by the manager
103
+ # (skip-and-record pattern). Report only the new ones added during registration.
104
+ for plugin_name, error in manager.get_failed_plugins().items():
105
+ if plugin_name in load_failures:
106
+ continue # Already reported above
107
+ click.echo(f"Warning: plugin '{plugin_name}' failed to register: {error}", err=True)
108
+
93
109
  return core_commands, manager
94
110
 
95
111
 
@@ -8,7 +8,10 @@ from requests.exceptions import HTTPError
8
8
  from xsoar_cli.error_handling.connection import ConnectionErrorHandler
9
9
  from xsoar_cli.error_handling.http import HTTPErrorHandler
10
10
  from xsoar_cli.utilities.config_file import get_xsoar_config, load_config
11
- from xsoar_cli.utilities.validators import validate_environments
11
+ from xsoar_cli.utilities.validators import validate_environments, validate_xsoar_connectivity
12
+
13
+ if TYPE_CHECKING:
14
+ from xsoar_cli.xsoar_client.client import Client
12
15
 
13
16
  logger = logging.getLogger(__name__)
14
17
 
@@ -22,12 +25,9 @@ def parse_string_to_dict(input_string: str | None, delimiter: str) -> dict:
22
25
  return {key.strip(): value.strip() for key, value in valid_pairs}
23
26
 
24
27
 
25
- if TYPE_CHECKING:
26
- from xsoar_cli.xsoar_client.client import Client
27
-
28
-
29
- @click.group(help="Create, retrieve, and clone cases")
28
+ @click.group()
30
29
  def case() -> None:
30
+ """Create, retrieve, and clone cases"""
31
31
  pass
32
32
 
33
33
 
@@ -36,6 +36,7 @@ def case() -> None:
36
36
  @click.option("--environment", default=None, help="Default environment set in config file.")
37
37
  @click.pass_context
38
38
  @load_config
39
+ @validate_xsoar_connectivity
39
40
  def get(ctx: click.Context, casenumber: int, environment: str | None) -> None:
40
41
  """Retrieve and display a single case.
41
42
 
@@ -82,7 +83,12 @@ def clone(ctx: click.Context, casenumber: int, source: str, dest: str) -> None:
82
83
  click.echo(f"Error: cannot find environments {source} and/or {dest} in config")
83
84
  ctx.exit(1)
84
85
 
85
- # Test connectivity to both environments before proceeding
86
+ # Test connectivity to both environments before proceeding. This is the only function that does
87
+ # explicit connectivity testing and error handling due to the fact that it is the only function
88
+ # that operates on multiple environments. If later a new command or sub-command is added to
89
+ # xsoar-cli that operates on multiple environments, then a new decorator should be created to
90
+ # handle connectivity testing for multiple environments (@validate_xsoar_connectivity only tests
91
+ # a single environment)
86
92
  config = get_xsoar_config(ctx)
87
93
  for env_name in (source, dest):
88
94
  logger.debug("Testing XSOAR connectivity for environment '%s'", env_name)
@@ -159,6 +165,7 @@ def clone(ctx: click.Context, casenumber: int, source: str, dest: str) -> None:
159
165
  @click.argument("name", type=str, default="Test case created from xsoar-cli")
160
166
  @click.pass_context
161
167
  @load_config
168
+ @validate_xsoar_connectivity
162
169
  def create( # noqa: PLR0913
163
170
  ctx: click.Context,
164
171
  environment: str | None,
@@ -73,8 +73,9 @@ def _resolve_shell(shell_name: str | None) -> str:
73
73
  return detected
74
74
 
75
75
 
76
- @click.group(help="Install and manage shell completion for xsoar-cli.")
76
+ @click.group()
77
77
  def completions() -> None:
78
+ """Install and manage shell completion for xsoar-cli"""
78
79
  pass
79
80
 
80
81
 
@@ -101,3 +101,21 @@ Set the Azure Blob Storage SAS token for an environment in the configuration fil
101
101
  xsoar-cli config set-azure-token my-sas-token
102
102
  xsoar-cli config set-azure-token --environment prod my-sas-token
103
103
  ```
104
+
105
+ ## Set Version Check
106
+
107
+ Enable or disable the version update check on CLI startup. When enabled, the CLI checks PyPI for newer versions and prints a notice to stderr.
108
+
109
+ **Syntax:** `xsoar-cli config set-version-check [OPTIONS]`
110
+
111
+ **Options:**
112
+ - `--enable` - Enable the version update check
113
+ - `--disable` - Disable the version update check
114
+
115
+ One of `--enable` or `--disable` must be provided.
116
+
117
+ **Examples:**
118
+ ```
119
+ xsoar-cli config set-version-check --enable
120
+ xsoar-cli config set-version-check --disable
121
+ ```
@@ -5,9 +5,6 @@ from typing import TYPE_CHECKING
5
5
 
6
6
  import click
7
7
 
8
- if TYPE_CHECKING:
9
- from xsoar_cli.xsoar_client.client import Client
10
-
11
8
  from xsoar_cli.utilities.config_file import (
12
9
  get_config_file_contents,
13
10
  get_config_file_path,
@@ -15,6 +12,9 @@ from xsoar_cli.utilities.config_file import (
15
12
  load_config,
16
13
  )
17
14
 
15
+ if TYPE_CHECKING:
16
+ from xsoar_cli.xsoar_client.client import Client
17
+
18
18
  logger = logging.getLogger(__name__)
19
19
 
20
20
 
@@ -47,8 +47,9 @@ def get_config_file_template_contents() -> dict:
47
47
  }
48
48
 
49
49
 
50
- @click.group(help="Create, validate, and manage CLI configuration")
50
+ @click.group()
51
51
  def config() -> None:
52
+ """Create, validate, and manage CLI configuration"""
52
53
  pass
53
54
 
54
55
 
@@ -67,8 +68,7 @@ def show(ctx: click.Context, masked: bool) -> None:
67
68
  if "azure_storage_access_token" in config["server_config"][key]:
68
69
  config["server_config"][key]["azure_storage_access_token"] = "*****" # noqa: S105
69
70
 
70
- print(json.dumps(config, indent=4))
71
- ctx.exit()
71
+ click.echo(json.dumps(config, indent=4))
72
72
 
73
73
 
74
74
  @click.command()
@@ -203,8 +203,28 @@ def set_azure_token(ctx: click.Context, environment: str, sastoken: str) -> None
203
203
  logger.info("Azure SAS token updated for environment '%s'", environment)
204
204
 
205
205
 
206
+ @click.command()
207
+ @click.option("--enable", "action", flag_value="enable", help="Enable the version update check on CLI startup.")
208
+ @click.option("--disable", "action", flag_value="disable", help="Disable the version update check on CLI startup.")
209
+ @click.pass_context
210
+ @load_config
211
+ def set_version_check(ctx: click.Context, action: str | None) -> None: # noqa: ARG001
212
+ """Enable or disable the version update check on CLI startup."""
213
+ if action is None:
214
+ raise click.UsageError("Specify either --enable or --disable.")
215
+ config_file = get_config_file_path()
216
+ config_data = json.loads(config_file.read_text())
217
+ # skip_version_check is the inverse: enabling the check means skip=False.
218
+ config_data["skip_version_check"] = action == "disable"
219
+ config_file.write_text(json.dumps(config_data, indent=4))
220
+ state = "enabled" if action == "enable" else "disabled"
221
+ logger.info("Version check %s", state)
222
+ click.echo(f"Version check {state}.")
223
+
224
+
206
225
  config.add_command(create)
207
226
  config.add_command(validate)
208
227
  config.add_command(show)
209
228
  config.add_command(set_credentials)
210
229
  config.add_command(set_azure_token)
230
+ config.add_command(set_version_check)
@@ -19,7 +19,8 @@ logger = logging.getLogger(__name__)
19
19
 
20
20
  @click.group()
21
21
  def content() -> None:
22
- """Inspect and manage content items."""
22
+ """Inspect and manage content items"""
23
+ pass
23
24
 
24
25
 
25
26
  @click.command()
@@ -27,21 +28,20 @@ def content() -> None:
27
28
  @click.option(
28
29
  "--type",
29
30
  "content_type",
30
- type=click.Choice(["scripts", "playbooks", "all"], case_sensitive=False),
31
- default="all",
32
- show_default=True,
31
+ type=click.Choice(["scripts", "playbooks"], case_sensitive=False),
32
+ required=True,
33
33
  help="Type of content items to retrieve.",
34
34
  )
35
35
  @click.pass_context
36
36
  @load_config
37
- @validate_xsoar_connectivity()
37
+ @validate_xsoar_connectivity
38
38
  def get_detached(ctx: click.Context, environment: str | None, content_type: str) -> None:
39
39
  """List detached content items."""
40
40
  config = get_xsoar_config(ctx)
41
41
  xsoar_client: Client = config.get_client(environment)
42
42
  response = xsoar_client.content.get_detached(content_type)
43
- click.echo(json.dumps(response.json(), indent=4))
44
- click.echo(f"Getting detached content items ({content_type=})")
43
+ data = json.loads(response)
44
+ click.echo(json.dumps(data, indent=4))
45
45
 
46
46
 
47
47
  # We name the command in the decorator here to avoid shadowing the builtin list.
@@ -59,7 +59,7 @@ def get_detached(ctx: click.Context, environment: str | None, content_type: str)
59
59
  @click.option("--verbose", is_flag=True, default=False, help="Output the full unfiltered response.")
60
60
  @click.pass_context
61
61
  @load_config
62
- @validate_xsoar_connectivity()
62
+ @validate_xsoar_connectivity
63
63
  def list_content(ctx: click.Context, environment: str | None, content_type: str, detail: bool, verbose: bool) -> None:
64
64
  """
65
65
  List detached content items. The purpose of this function is to list out available commands,
@@ -98,7 +98,7 @@ def list_content(ctx: click.Context, environment: str | None, content_type: str,
98
98
  @click.argument("name", type=str)
99
99
  @click.pass_context
100
100
  @load_config
101
- @validate_xsoar_connectivity()
101
+ @validate_xsoar_connectivity
102
102
  def download(ctx: click.Context, environment: str | None, content_type: str, output_path: str | None, name: str) -> None:
103
103
  """Download a content item by name.
104
104
 
@@ -67,8 +67,9 @@ def _build_content_graph(
67
67
  return cg
68
68
 
69
69
 
70
- @click.group(help="(BETA) Create dependency graphs from one or more content packs")
70
+ @click.group()
71
71
  def graph() -> None:
72
+ """(BETA) Create dependency graphs from one or more content packs"""
72
73
  pass
73
74
 
74
75
 
@@ -76,7 +77,7 @@ def graph() -> None:
76
77
  @click.command()
77
78
  @click.pass_context
78
79
  @load_config
79
- @validate_xsoar_connectivity()
80
+ @validate_xsoar_connectivity
80
81
  def generate(ctx: click.Context, packs: tuple[Path], repo_path: str, upstream_repo_path: str, environment: str | None) -> None:
81
82
  """BETA
82
83
 
@@ -99,7 +100,7 @@ def generate(ctx: click.Context, packs: tuple[Path], repo_path: str, upstream_re
99
100
  @_common_graph_options
100
101
  @click.pass_context
101
102
  @load_config
102
- @validate_xsoar_connectivity()
103
+ @validate_xsoar_connectivity
103
104
  def export(
104
105
  ctx: click.Context,
105
106
  packs: tuple[Path],
@@ -14,25 +14,25 @@ logger = logging.getLogger(__name__)
14
14
 
15
15
 
16
16
  @click.group()
17
- @click.pass_context
18
- def integration(ctx: click.Context) -> None:
17
+ def integration() -> None:
19
18
  """(BETA) Save/load integration configuration for an integration instance."""
19
+ pass
20
20
 
21
21
 
22
22
  @click.command()
23
23
  @click.option("--environment", default=None, help="Default environment set in config file.")
24
- @click.option("--all", is_flag=True, default=False)
24
+ @click.option("--all", "all_integrations", is_flag=True, default=False, help="Dump all integrations")
25
25
  @click.argument("name", type=str, required=False, default=None)
26
26
  @click.pass_context
27
27
  @load_config
28
- @validate_xsoar_connectivity()
29
- def dump(ctx: click.Context, environment: str | None, name: str | None, all: bool) -> None:
28
+ @validate_xsoar_connectivity
29
+ def dump(ctx: click.Context, environment: str | None, name: str | None, all_integrations: bool) -> None:
30
30
  """Dump integration instance configuration to stdout as JSON."""
31
31
  config = get_xsoar_config(ctx)
32
32
  xsoar_client: Client = config.get_client(environment)
33
33
  logger.debug("Dumping integration config (environment: '%s')", environment or config.default_environment)
34
34
  integrations = xsoar_client.integrations.get_instances()
35
- if all:
35
+ if all_integrations:
36
36
  logger.debug("Fetching config for all integrations (environment: '%s')", environment or config.default_environment)
37
37
  integration_data = integrations
38
38
  else:
@@ -41,11 +41,11 @@ def dump(ctx: click.Context, environment: str | None, name: str | None, all: boo
41
41
  if not integration_data:
42
42
  click.echo(f"Cannot find integration instance '{name}'")
43
43
  ctx.exit(1)
44
- click.echo(json.dumps(integration_data, sort_keys=True, indent=4) + "\n")
44
+ click.echo(json.dumps(integration_data, sort_keys=True, indent=4))
45
45
 
46
46
 
47
47
  @click.command()
48
- def load(ctx: click.Context) -> None:
48
+ def load() -> None:
49
49
  """Load integration instance configuration into XSOAR from a JSON file. Not yet implemented."""
50
50
  logger.debug("integration loadconfig command not implemented")
51
51
  click.echo("Command not implemented")
@@ -116,6 +116,7 @@ def _check_pack_availability(
116
116
  @click.group()
117
117
  def manifest() -> None:
118
118
  """Various commands to interact/update/deploy content packs defined in the xsoar_config.json manifest."""
119
+ pass
119
120
 
120
121
 
121
122
  MANIFEST_FILENAME = "xsoar_config.json"
@@ -132,7 +133,7 @@ MANIFEST_FILENAME = "xsoar_config.json"
132
133
  )
133
134
  @click.pass_context
134
135
  @load_config
135
- @validate_xsoar_connectivity()
136
+ @validate_xsoar_connectivity
136
137
  def generate(ctx: click.Context, environment: str | None, output_dir: str) -> None:
137
138
  """Generate a new xsoar_config.json manifest from installed content packs.
138
139
 
@@ -168,7 +169,7 @@ def generate(ctx: click.Context, environment: str | None, output_dir: str) -> No
168
169
  @click.pass_context
169
170
  @load_config
170
171
  @validate_artifacts_provider
171
- @validate_xsoar_connectivity()
172
+ @validate_xsoar_connectivity
172
173
  def update(ctx: click.Context, environment: str | None, manifest: str) -> None:
173
174
  """Update manifest on disk with latest available content pack versions."""
174
175
  # Lazy import for performance reasons
@@ -256,7 +257,7 @@ def update(ctx: click.Context, environment: str | None, manifest: str) -> None:
256
257
  @click.pass_context
257
258
  @load_config
258
259
  @validate_artifacts_provider
259
- @validate_xsoar_connectivity()
260
+ @validate_xsoar_connectivity
260
261
  def validate(ctx: click.Context, environment: str | None, mode: str, manifest: str) -> None:
261
262
  """Validate manifest JSON and content pack availability.
262
263
 
@@ -320,7 +321,7 @@ def validate(ctx: click.Context, environment: str | None, mode: str, manifest: s
320
321
  @click.argument("manifest", type=click.Path(exists=True))
321
322
  @click.pass_context
322
323
  @load_config
323
- @validate_xsoar_connectivity()
324
+ @validate_xsoar_connectivity
324
325
  def diff(ctx: click.Context, manifest: str, environment: str | None) -> None:
325
326
  """Prints out the differences (if any) between what is defined in the xsoar_config.json manifest and what is actually
326
327
  installed on the XSOAR server."""
@@ -379,7 +380,7 @@ def diff(ctx: click.Context, manifest: str, environment: str | None) -> None:
379
380
  @click.pass_context
380
381
  @load_config
381
382
  @validate_artifacts_provider
382
- @validate_xsoar_connectivity()
383
+ @validate_xsoar_connectivity
383
384
  def deploy(ctx: click.Context, environment: str | None, manifest: str, verbose: bool, yes: bool) -> None: # noqa: FBT001
384
385
  """Deploy content packs to the server as defined in the xsoar_config.json manifest.
385
386
 
@@ -13,9 +13,9 @@ logger = logging.getLogger(__name__)
13
13
 
14
14
 
15
15
  @click.group()
16
- @click.pass_context
17
- def pack(ctx: click.Context) -> None:
16
+ def pack() -> None:
18
17
  """Various content pack related commands."""
18
+ pass
19
19
 
20
20
 
21
21
  @click.command()
@@ -23,7 +23,7 @@ def pack(ctx: click.Context) -> None:
23
23
  @click.argument("pack_id", type=str)
24
24
  @click.pass_context
25
25
  @load_config
26
- @validate_xsoar_connectivity()
26
+ @validate_xsoar_connectivity
27
27
  def delete(ctx: click.Context, environment: str | None, pack_id: str) -> None:
28
28
  """Delete a content pack from the server."""
29
29
  config = get_xsoar_config(ctx)
@@ -45,7 +45,7 @@ def delete(ctx: click.Context, environment: str | None, pack_id: str) -> None:
45
45
  @click.pass_context
46
46
  @load_config
47
47
  @validate_artifacts_provider
48
- @validate_xsoar_connectivity()
48
+ @validate_xsoar_connectivity
49
49
  def get_outdated(ctx: click.Context, environment: str | None) -> None:
50
50
  """Print a list of outdated content packs."""
51
51
  config = get_xsoar_config(ctx)
@@ -2,6 +2,19 @@
2
2
 
3
3
  Manage plugins loaded into the CLI.
4
4
 
5
+ ## Init
6
+
7
+ Initialize the plugins directory and generate an example plugin.
8
+
9
+ **Syntax:** `xsoar-cli plugins init`
10
+
11
+ Creates `~/.local/xsoar-cli/plugins/` (if it does not exist) and writes an example `hello.py` plugin. If the example file already exists, prompts for confirmation before overwriting.
12
+
13
+ **Examples:**
14
+ ```
15
+ xsoar-cli plugins init
16
+ ```
17
+
5
18
  ## List
6
19
 
7
20
  List all available and loaded plugins.
@@ -41,5 +54,3 @@ Validate all plugins in the plugins directory. Checks that each plugin can load
41
54
  ```
42
55
  xsoar-cli plugins validate
43
56
  ```
44
-
45
-