crewai-cli 1.15.3.dev20260717__tar.gz → 1.15.4__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 (165) hide show
  1. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/PKG-INFO +2 -2
  2. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/pyproject.toml +1 -1
  3. crewai_cli-1.15.4/src/crewai_cli/__init__.py +1 -0
  4. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/cli.py +9 -21
  5. {crewai_cli-1.15.3.dev20260717/src/crewai_cli/experimental → crewai_cli-1.15.4/src/crewai_cli}/skills/main.py +52 -9
  6. crewai_cli-1.15.4/tests/skills/test_cli_commands.py +63 -0
  7. {crewai_cli-1.15.3.dev20260717/tests/experimental → crewai_cli-1.15.4/tests}/skills/test_main.py +94 -8
  8. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/skills/test_safe_extract.py +1 -1
  9. crewai_cli-1.15.3.dev20260717/src/crewai_cli/__init__.py +0 -1
  10. crewai_cli-1.15.3.dev20260717/tests/experimental/skills/__init__.py +0 -0
  11. crewai_cli-1.15.3.dev20260717/tests/skills/__init__.py +0 -0
  12. crewai_cli-1.15.3.dev20260717/tests/tools/__init__.py +0 -0
  13. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/.gitignore +0 -0
  14. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/README.md +0 -0
  15. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/add_crew_to_flow.py +0 -0
  16. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/authentication/__init__.py +0 -0
  17. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/authentication/constants.py +0 -0
  18. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/authentication/main.py +0 -0
  19. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/authentication/providers/__init__.py +0 -0
  20. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/authentication/providers/auth0.py +0 -0
  21. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/authentication/providers/base_provider.py +0 -0
  22. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/authentication/providers/entra_id.py +0 -0
  23. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/authentication/providers/keycloak.py +0 -0
  24. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/authentication/providers/okta.py +0 -0
  25. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/authentication/providers/workos.py +0 -0
  26. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/authentication/token.py +0 -0
  27. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/authentication/utils.py +0 -0
  28. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/checkpoint_cli.py +0 -0
  29. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/checkpoint_tui.py +0 -0
  30. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/command.py +0 -0
  31. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/config.py +0 -0
  32. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/constants.py +0 -0
  33. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/create_crew.py +0 -0
  34. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/create_flow.py +0 -0
  35. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/create_json_crew.py +0 -0
  36. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/crew_chat.py +0 -0
  37. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/crew_run_tui.py +0 -0
  38. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/deploy/__init__.py +0 -0
  39. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/deploy/archive.py +0 -0
  40. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/deploy/main.py +0 -0
  41. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/deploy/validate.py +0 -0
  42. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/enterprise/__init__.py +0 -0
  43. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/enterprise/main.py +0 -0
  44. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/evaluate_crew.py +0 -0
  45. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/git.py +0 -0
  46. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/input_prompt.py +0 -0
  47. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/install_crew.py +0 -0
  48. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/kickoff_flow.py +0 -0
  49. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/memory_tui.py +0 -0
  50. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/model_catalog.py +0 -0
  51. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/organization/__init__.py +0 -0
  52. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/organization/main.py +0 -0
  53. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/plot_flow.py +0 -0
  54. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/plus_api.py +0 -0
  55. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/provider.py +0 -0
  56. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/py.typed +0 -0
  57. {crewai_cli-1.15.3.dev20260717/src/crewai_cli/experimental → crewai_cli-1.15.4/src/crewai_cli/remote_template}/__init__.py +0 -0
  58. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/remote_template/main.py +0 -0
  59. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/replay_from_task.py +0 -0
  60. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/reset_memories_command.py +0 -0
  61. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/run_crew.py +0 -0
  62. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/run_declarative_flow.py +0 -0
  63. {crewai_cli-1.15.3.dev20260717/src/crewai_cli/experimental/skills → crewai_cli-1.15.4/src/crewai_cli/settings}/__init__.py +0 -0
  64. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/settings/main.py +0 -0
  65. {crewai_cli-1.15.3.dev20260717/src/crewai_cli/remote_template → crewai_cli-1.15.4/src/crewai_cli/shared}/__init__.py +0 -0
  66. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/shared/token_manager.py +0 -0
  67. {crewai_cli-1.15.3.dev20260717/src/crewai_cli/settings → crewai_cli-1.15.4/src/crewai_cli/skills}/__init__.py +0 -0
  68. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/task_outputs.py +0 -0
  69. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/AGENTS.md +0 -0
  70. {crewai_cli-1.15.3.dev20260717/src/crewai_cli/shared → crewai_cli-1.15.4/src/crewai_cli/templates}/__init__.py +0 -0
  71. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/crew/.gitignore +0 -0
  72. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/crew/README.md +0 -0
  73. {crewai_cli-1.15.3.dev20260717/src/crewai_cli/templates → crewai_cli-1.15.4/src/crewai_cli/templates/crew}/__init__.py +0 -0
  74. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/crew/config/agents.yaml +0 -0
  75. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/crew/config/tasks.yaml +0 -0
  76. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/crew/crew.py +0 -0
  77. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/crew/knowledge/user_preference.txt +0 -0
  78. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/crew/main.py +0 -0
  79. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/crew/pyproject.toml +0 -0
  80. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/crew/skills/.gitkeep +0 -0
  81. {crewai_cli-1.15.3.dev20260717/src/crewai_cli/templates/crew → crewai_cli-1.15.4/src/crewai_cli/templates/crew/tools}/__init__.py +0 -0
  82. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/crew/tools/custom_tool.py +0 -0
  83. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/declarative_flow/.gitignore +0 -0
  84. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/declarative_flow/AGENTS.md +0 -0
  85. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/declarative_flow/README.md +0 -0
  86. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/declarative_flow/flow.yaml +0 -0
  87. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/declarative_flow/pyproject.toml +0 -0
  88. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/flow/.gitignore +0 -0
  89. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/flow/README.md +0 -0
  90. {crewai_cli-1.15.3.dev20260717/src/crewai_cli/templates/crew/tools → crewai_cli-1.15.4/src/crewai_cli/templates/flow}/__init__.py +0 -0
  91. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/flow/crews/content_crew/config/agents.yaml +0 -0
  92. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/flow/crews/content_crew/config/tasks.yaml +0 -0
  93. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/flow/crews/content_crew/content_crew.py +0 -0
  94. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/flow/main.py +0 -0
  95. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/flow/pyproject.toml +0 -0
  96. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/flow/skills/.gitkeep +0 -0
  97. {crewai_cli-1.15.3.dev20260717/src/crewai_cli/templates/flow → crewai_cli-1.15.4/src/crewai_cli/templates/flow/tools}/__init__.py +0 -0
  98. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/flow/tools/custom_tool.py +0 -0
  99. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/json_crew/.gitignore +0 -0
  100. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/json_crew/README.md +0 -0
  101. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/json_crew/agent.jsonc +0 -0
  102. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/json_crew/agent_settings.jsonc +0 -0
  103. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/json_crew/crew.jsonc +0 -0
  104. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/json_crew/knowledge/user_preference.txt +0 -0
  105. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/json_crew/pyproject.toml +0 -0
  106. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/json_crew/task.jsonc +0 -0
  107. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/tool/.gitignore +0 -0
  108. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/tool/README.md +0 -0
  109. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/tool/pyproject.toml +0 -0
  110. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/tool/src/{{folder_name}}/__init__.py +0 -0
  111. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/templates/tool/src/{{folder_name}}/tool.py +0 -0
  112. {crewai_cli-1.15.3.dev20260717/src/crewai_cli/templates/flow → crewai_cli-1.15.4/src/crewai_cli}/tools/__init__.py +0 -0
  113. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/tools/main.py +0 -0
  114. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/train_crew.py +0 -0
  115. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/triggers/__init__.py +0 -0
  116. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/triggers/main.py +0 -0
  117. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/tui_picker.py +0 -0
  118. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/update_crew.py +0 -0
  119. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/user_data.py +0 -0
  120. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/utils.py +0 -0
  121. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/src/crewai_cli/version.py +0 -0
  122. {crewai_cli-1.15.3.dev20260717/src/crewai_cli/tools → crewai_cli-1.15.4/tests}/__init__.py +0 -0
  123. {crewai_cli-1.15.3.dev20260717/tests → crewai_cli-1.15.4/tests/authentication}/__init__.py +0 -0
  124. {crewai_cli-1.15.3.dev20260717/tests/authentication → crewai_cli-1.15.4/tests/authentication/providers}/__init__.py +0 -0
  125. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/authentication/providers/test_auth0.py +0 -0
  126. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/authentication/providers/test_entra_id.py +0 -0
  127. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/authentication/providers/test_keycloak.py +0 -0
  128. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/authentication/providers/test_okta.py +0 -0
  129. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/authentication/providers/test_workos.py +0 -0
  130. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/authentication/test_auth_main.py +0 -0
  131. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/authentication/test_utils.py +0 -0
  132. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/deploy/__init__.py +0 -0
  133. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/deploy/test_archive.py +0 -0
  134. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/deploy/test_deploy_main.py +0 -0
  135. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/deploy/test_validate.py +0 -0
  136. {crewai_cli-1.15.3.dev20260717/tests/authentication/providers → crewai_cli-1.15.4/tests/enterprise}/__init__.py +0 -0
  137. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/enterprise/test_main.py +0 -0
  138. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/organization/__init__.py +0 -0
  139. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/organization/test_main.py +0 -0
  140. {crewai_cli-1.15.3.dev20260717/tests/enterprise → crewai_cli-1.15.4/tests/skills}/__init__.py +0 -0
  141. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_cli.py +0 -0
  142. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_click_compatibility.py +0 -0
  143. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_config.py +0 -0
  144. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_constants.py +0 -0
  145. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_create_crew.py +0 -0
  146. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_create_flow.py +0 -0
  147. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_crew_run_tui.py +0 -0
  148. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_crew_test.py +0 -0
  149. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_flow_commands.py +0 -0
  150. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_git.py +0 -0
  151. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_input_prompt.py +0 -0
  152. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_install_crew.py +0 -0
  153. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_kickoff_flow.py +0 -0
  154. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_model_catalog.py +0 -0
  155. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_plus_api.py +0 -0
  156. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_run_crew.py +0 -0
  157. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_run_declarative_flow.py +0 -0
  158. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_settings_command.py +0 -0
  159. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_token_manager.py +0 -0
  160. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_train_crew.py +0 -0
  161. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_utils.py +0 -0
  162. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/test_version.py +0 -0
  163. {crewai_cli-1.15.3.dev20260717/tests/experimental → crewai_cli-1.15.4/tests/tools}/__init__.py +0 -0
  164. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/tools/test_main.py +0 -0
  165. {crewai_cli-1.15.3.dev20260717 → crewai_cli-1.15.4}/tests/triggers/test_main.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crewai-cli
3
- Version: 1.15.3.dev20260717
3
+ Version: 1.15.4
4
4
  Summary: CLI for CrewAI — scaffold, run, deploy and manage AI agent crews.
5
5
  Project-URL: Homepage, https://crewai.com
6
6
  Project-URL: Documentation, https://docs.crewai.com
@@ -10,7 +10,7 @@ Requires-Python: <3.14,>=3.10
10
10
  Requires-Dist: appdirs~=1.4.4
11
11
  Requires-Dist: certifi
12
12
  Requires-Dist: click<9,>=8.1.7
13
- Requires-Dist: crewai-core==1.15.3.dev20260717
13
+ Requires-Dist: crewai-core==1.15.4
14
14
  Requires-Dist: cryptography>=42.0
15
15
  Requires-Dist: httpx~=0.28.1
16
16
  Requires-Dist: packaging>=23.0
@@ -8,7 +8,7 @@ authors = [
8
8
  ]
9
9
  requires-python = ">=3.10, <3.14"
10
10
  dependencies = [
11
- "crewai-core==1.15.3.dev20260717",
11
+ "crewai-core==1.15.4",
12
12
  "click>=8.1.7,<9",
13
13
  "pydantic>=2.11.9,<2.13",
14
14
  "pydantic-settings~=2.10.1",
@@ -0,0 +1 @@
1
+ __version__ = "1.15.4"
@@ -686,20 +686,9 @@ def tool_publish(is_public: bool, force: bool) -> None:
686
686
  tool_cmd.publish(is_public, force)
687
687
 
688
688
 
689
- @crewai.group()
690
- def experimental() -> None:
691
- """Experimental, unstable commands. Subject to change without notice."""
692
- import os
693
-
694
- if os.environ.get("CREWAI_EXPERIMENTAL") != "1":
695
- raise click.UsageError(
696
- "Experimental commands are gated. Set CREWAI_EXPERIMENTAL=1 to enable."
697
- )
698
-
699
-
700
- @experimental.group(name="skill")
689
+ @crewai.group(name="skill")
701
690
  def skill() -> None:
702
- """Skill Repository related commands (experimental)."""
691
+ """Create, publish, and install agent skills."""
703
692
 
704
693
 
705
694
  @skill.command(name="create")
@@ -713,7 +702,7 @@ def skill() -> None:
713
702
  help="Create skill in current dir instead of ./skills/",
714
703
  )
715
704
  def skill_create(name: str, in_project: bool) -> None:
716
- from crewai_cli.experimental.skills.main import SkillCommand
705
+ from crewai_cli.skills.main import SkillCommand
717
706
 
718
707
  skill_cmd = SkillCommand()
719
708
  skill_cmd.create(name, in_project=in_project)
@@ -722,7 +711,7 @@ def skill_create(name: str, in_project: bool) -> None:
722
711
  @skill.command(name="install")
723
712
  @click.argument("ref")
724
713
  def skill_install(ref: str) -> None:
725
- from crewai_cli.experimental.skills.main import SkillCommand
714
+ from crewai_cli.skills.main import SkillCommand
726
715
 
727
716
  skill_cmd = SkillCommand()
728
717
  skill_cmd.install(ref)
@@ -736,20 +725,19 @@ def skill_install(ref: str) -> None:
736
725
  show_default=True,
737
726
  help="Skip git-state validation.",
738
727
  )
739
- @click.option("--public", "is_public", flag_value=True, default=False)
740
- @click.option("--private", "is_public", flag_value=False)
741
728
  @click.option("--org", default=None, help="Organisation slug (overrides settings).")
742
- def skill_publish(is_public: bool, org: str | None, force: bool) -> None:
743
- from crewai_cli.experimental.skills.main import SkillCommand
729
+ def skill_publish(org: str | None, force: bool) -> None:
730
+ """Publish the skill in the current directory, scoped to your organization."""
731
+ from crewai_cli.skills.main import SkillCommand
744
732
 
745
733
  skill_cmd = SkillCommand()
746
- skill_cmd.publish(is_public, org=org, force=force)
734
+ skill_cmd.publish(org=org, force=force)
747
735
 
748
736
 
749
737
  @skill.command(name="list")
750
738
  def skill_list() -> None:
751
739
  """List locally installed skills."""
752
- from crewai_cli.experimental.skills.main import SkillCommand
740
+ from crewai_cli.skills.main import SkillCommand
753
741
 
754
742
  skill_cmd = SkillCommand()
755
743
  skill_cmd.list_cached()
@@ -13,6 +13,7 @@ import zipfile
13
13
  from rich.console import Console
14
14
  from rich.table import Table
15
15
 
16
+ from crewai_cli import git
16
17
  from crewai_cli.command import BaseCommand, PlusAPIMixin
17
18
  from crewai_cli.config import Settings
18
19
  from crewai_cli.constants import DEFAULT_CREWAI_ENTERPRISE_URL
@@ -63,7 +64,7 @@ class SkillCommand(BaseCommand, PlusAPIMixin):
63
64
  (skill_dir / "assets").mkdir()
64
65
 
65
66
  skill_md = skill_dir / "SKILL.md"
66
- skill_md.write_text(_SKILL_MD_TEMPLATE.format(name=name))
67
+ skill_md.write_text(_SKILL_MD_TEMPLATE.format(name=name), encoding="utf-8")
67
68
 
68
69
  console.print(
69
70
  f"[green]Created skill [bold]{name}[/bold] at [bold]{skill_dir}[/bold].[/green]"
@@ -148,7 +149,7 @@ class SkillCommand(BaseCommand, PlusAPIMixin):
148
149
  )
149
150
  else:
150
151
  try:
151
- from crewai.experimental.skills.cache import SkillCacheManager
152
+ from crewai.skills.cache import SkillCacheManager
152
153
 
153
154
  cache = SkillCacheManager()
154
155
  cache.store(org, name, version, archive_bytes)
@@ -170,13 +171,19 @@ class SkillCommand(BaseCommand, PlusAPIMixin):
170
171
  "version": version,
171
172
  "installed_at": datetime.now(tz=timezone.utc).isoformat(),
172
173
  }
173
- (cache_dir / ".crewai_meta.json").write_text(json.dumps(meta, indent=2))
174
+ (cache_dir / ".crewai_meta.json").write_text(
175
+ json.dumps(meta, indent=2), encoding="utf-8"
176
+ )
174
177
  console.print(
175
178
  f"[green]Installed [bold]{ref}[/bold]{' (' + version + ')' if version else ''} to global cache.[/green]"
176
179
  )
177
180
 
178
- def publish(self, is_public: bool, org: str | None, force: bool = False) -> None:
179
- """Publish the skill in the current directory to the registry."""
181
+ def publish(self, org: str | None = None, force: bool = False) -> None:
182
+ """Publish the skill in the current directory to the registry.
183
+
184
+ Skills are always scoped to the publishing organization; there is no
185
+ public visibility option.
186
+ """
180
187
  skill_md = Path("SKILL.md")
181
188
  if not skill_md.exists():
182
189
  console.print(
@@ -185,8 +192,44 @@ class SkillCommand(BaseCommand, PlusAPIMixin):
185
192
  )
186
193
  raise SystemExit(1)
187
194
 
195
+ if not force:
196
+ try:
197
+ repository = git.Repository(fetch=False)
198
+ except ValueError as exc:
199
+ if "not a Git repository" not in str(exc):
200
+ console.print(
201
+ f"[red]Unable to validate git state: {exc}\n"
202
+ "Fix the issue or pass --force to skip this check.[/red]"
203
+ )
204
+ raise SystemExit(1) from exc
205
+ # Standalone skill directories may live outside any git repo;
206
+ # there is no git state to validate in that case.
207
+ repository = None
208
+ if repository is not None:
209
+ try:
210
+ # Refresh remote-tracking refs so is_synced() compares
211
+ # against the actual remote, not stale local state.
212
+ repository.fetch()
213
+ except ValueError as exc:
214
+ console.print(
215
+ f"[red]Unable to validate git state: {exc}\n"
216
+ "Fix the issue or pass --force to skip this check.[/red]"
217
+ )
218
+ raise SystemExit(1) from exc
219
+ if repository is not None and not repository.is_synced():
220
+ console.print(
221
+ "[bold red]Failed to publish skill.[/bold red]\n"
222
+ "Local changes need to be resolved before publishing. Please do the following:\n"
223
+ "* [bold]Commit[/bold] your changes.\n"
224
+ "* [bold]Push[/bold] to sync with the remote.\n"
225
+ "* [bold]Pull[/bold] the latest changes from the remote.\n"
226
+ "\nOnce your repository is up-to-date, retry publishing the skill "
227
+ "(or pass --force to skip this check)."
228
+ )
229
+ raise SystemExit(1)
230
+
188
231
  try:
189
- frontmatter = self._parse_frontmatter(skill_md.read_text())
232
+ frontmatter = self._parse_frontmatter(skill_md.read_text(encoding="utf-8"))
190
233
  except ValueError as exc:
191
234
  console.print(f"[red]Failed to parse SKILL.md frontmatter: {exc}[/red]")
192
235
  raise SystemExit(1) from exc
@@ -233,7 +276,7 @@ class SkillCommand(BaseCommand, PlusAPIMixin):
233
276
  org=effective_org,
234
277
  name=name,
235
278
  version=version,
236
- is_public=is_public,
279
+ is_public=False,
237
280
  description=description,
238
281
  encoded_file=encoded_file,
239
282
  )
@@ -277,7 +320,7 @@ class SkillCommand(BaseCommand, PlusAPIMixin):
277
320
  meta_file = skill_dir / ".crewai_meta.json"
278
321
  if meta_file.exists():
279
322
  try:
280
- meta = json.loads(meta_file.read_text())
323
+ meta = json.loads(meta_file.read_text(encoding="utf-8"))
281
324
  table.add_row(
282
325
  "cache",
283
326
  f"@{meta['org']}/{meta['name']}",
@@ -368,7 +411,7 @@ class SkillCommand(BaseCommand, PlusAPIMixin):
368
411
  def _read_version(self, skill_md: Path) -> str | None:
369
412
  """Read the version from a SKILL.md file's metadata, or None."""
370
413
  try:
371
- fm = self._parse_frontmatter(skill_md.read_text())
414
+ fm = self._parse_frontmatter(skill_md.read_text(encoding="utf-8"))
372
415
  raw_metadata = fm.get("metadata")
373
416
  if isinstance(raw_metadata, dict):
374
417
  return raw_metadata.get("version")
@@ -0,0 +1,63 @@
1
+ """Tests for the top-level `crewai skill` command group.
2
+
3
+ The Skills Repository graduated from the gated `crewai experimental skill`
4
+ group: the commands must be reachable at `crewai skill ...` without
5
+ CREWAI_EXPERIMENTAL set.
6
+ """
7
+
8
+ from unittest import mock
9
+
10
+ from click.testing import CliRunner
11
+ from crewai_cli.cli import crewai
12
+ import pytest
13
+
14
+
15
+ @pytest.fixture
16
+ def runner():
17
+ return CliRunner()
18
+
19
+
20
+ @pytest.fixture
21
+ def no_experimental_env(monkeypatch):
22
+ monkeypatch.delenv("CREWAI_EXPERIMENTAL", raising=False)
23
+
24
+
25
+ class TestSkillGroupIsTopLevel:
26
+ def test_skill_group_registered_at_top_level(self, runner, no_experimental_env):
27
+ result = runner.invoke(crewai, ["skill", "--help"])
28
+ assert result.exit_code == 0, result.output
29
+ for subcommand in ("create", "install", "publish", "list"):
30
+ assert subcommand in result.output
31
+
32
+ def test_skill_group_not_gated_by_experimental_env(
33
+ self, runner, no_experimental_env
34
+ ):
35
+ with mock.patch("crewai_cli.skills.main.SkillCommand") as mock_cmd:
36
+ result = runner.invoke(crewai, ["skill", "create", "my-skill"])
37
+ assert result.exit_code == 0, result.output
38
+ mock_cmd.return_value.create.assert_called_once_with(
39
+ "my-skill", in_project=True
40
+ )
41
+
42
+ def test_skill_create_no_project_flag(self, runner, no_experimental_env):
43
+ with mock.patch("crewai_cli.skills.main.SkillCommand") as mock_cmd:
44
+ result = runner.invoke(crewai, ["skill", "create", "my-skill", "--no-project"])
45
+ assert result.exit_code == 0, result.output
46
+ mock_cmd.return_value.create.assert_called_once_with(
47
+ "my-skill", in_project=False
48
+ )
49
+
50
+
51
+ class TestSkillPublishIsOrgScopedOnly:
52
+ def test_publish_rejects_public_flag(self, runner, no_experimental_env):
53
+ result = runner.invoke(crewai, ["skill", "publish", "--public"])
54
+ assert result.exit_code != 0
55
+ assert "No such option" in result.output
56
+
57
+ def test_publish_passes_org_and_force_only(self, runner, no_experimental_env):
58
+ with mock.patch("crewai_cli.skills.main.SkillCommand") as mock_cmd:
59
+ result = runner.invoke(
60
+ crewai, ["skill", "publish", "--org", "acme", "--force"]
61
+ )
62
+ assert result.exit_code == 0, result.output
63
+ mock_cmd.return_value.publish.assert_called_once_with(org="acme", force=True)
@@ -36,7 +36,7 @@ def skill_command():
36
36
  TokenManager().save_tokens(
37
37
  "test-token", (datetime.now() + timedelta(seconds=36000)).timestamp()
38
38
  )
39
- from crewai_cli.experimental.skills.main import SkillCommand
39
+ from crewai_cli.skills.main import SkillCommand
40
40
  cmd = SkillCommand()
41
41
  yield cmd
42
42
 
@@ -113,7 +113,7 @@ class TestSkillPublish:
113
113
  def test_publish_no_skill_md(self, skill_command):
114
114
  with in_temp_dir():
115
115
  with pytest.raises(SystemExit):
116
- skill_command.publish(is_public=True, org="acme")
116
+ skill_command.publish(org="acme")
117
117
 
118
118
  def test_publish_missing_version(self, skill_command):
119
119
  with in_temp_dir():
@@ -121,7 +121,7 @@ class TestSkillPublish:
121
121
  "---\nname: my-skill\ndescription: Test.\n---\nInstructions."
122
122
  )
123
123
  with pytest.raises(SystemExit):
124
- skill_command.publish(is_public=True, org="acme")
124
+ skill_command.publish(org="acme")
125
125
 
126
126
  def test_publish_missing_name(self, skill_command):
127
127
  with in_temp_dir():
@@ -129,7 +129,7 @@ class TestSkillPublish:
129
129
  "---\ndescription: Test.\nversion: 1.0.0\n---\nInstructions."
130
130
  )
131
131
  with pytest.raises(SystemExit):
132
- skill_command.publish(is_public=True, org="acme")
132
+ skill_command.publish(org="acme")
133
133
 
134
134
  def test_publish_no_org(self, skill_command):
135
135
  with in_temp_dir():
@@ -142,11 +142,11 @@ class TestSkillPublish:
142
142
  mock_resp.status_code = 200
143
143
  mock_resp.json.return_value = {}
144
144
  mock_client.publish_skill.return_value = mock_resp
145
- with patch("crewai_cli.experimental.skills.main.Settings") as mock_settings_cls:
145
+ with patch("crewai_cli.skills.main.Settings") as mock_settings_cls:
146
146
  mock_settings_cls.return_value.org_name = None
147
147
  mock_settings_cls.return_value.enterprise_base_url = None
148
148
  with pytest.raises(SystemExit):
149
- skill_command.publish(is_public=True, org=None)
149
+ skill_command.publish(org=None)
150
150
 
151
151
  def test_publish_calls_api(self, skill_command):
152
152
  with in_temp_dir():
@@ -158,16 +158,102 @@ class TestSkillPublish:
158
158
  mock_resp.status_code = 200
159
159
  mock_resp.json.return_value = {}
160
160
  skill_command.plus_api_client.publish_skill = MagicMock(return_value=mock_resp)
161
- with patch("crewai_cli.experimental.skills.main.Settings") as mock_settings_cls:
161
+ with patch("crewai_cli.skills.main.Settings") as mock_settings_cls:
162
162
  mock_settings_cls.return_value.org_name = "acme"
163
163
  mock_settings_cls.return_value.enterprise_base_url = None
164
164
 
165
- skill_command.publish(is_public=False, org="acme")
165
+ skill_command.publish(org="acme")
166
166
 
167
167
  skill_command.plus_api_client.publish_skill.assert_called_once()
168
168
  call_kwargs = skill_command.plus_api_client.publish_skill.call_args
169
169
  assert call_kwargs.kwargs["name"] == "my-skill"
170
170
  assert call_kwargs.kwargs["version"] == "1.0.0"
171
+ # Skills are always org-scoped; there is no public visibility.
172
+ assert call_kwargs.kwargs["is_public"] is False
173
+
174
+ def test_publish_blocked_when_git_not_synced(self, skill_command):
175
+ with in_temp_dir():
176
+ Path("SKILL.md").write_text(
177
+ "---\nname: my-skill\ndescription: A test skill.\nmetadata:\n version: 1.0.0\n---\nInstructions."
178
+ )
179
+ skill_command.plus_api_client.publish_skill = MagicMock()
180
+ with patch("crewai_cli.skills.main.git.Repository") as mock_repo_cls:
181
+ mock_repo_cls.return_value.is_synced.return_value = False
182
+ with pytest.raises(SystemExit):
183
+ skill_command.publish(org="acme")
184
+ skill_command.plus_api_client.publish_skill.assert_not_called()
185
+
186
+ def test_publish_force_skips_git_check(self, skill_command):
187
+ with in_temp_dir():
188
+ Path("SKILL.md").write_text(
189
+ "---\nname: my-skill\ndescription: A test skill.\nmetadata:\n version: 1.0.0\n---\nInstructions."
190
+ )
191
+ mock_resp = MagicMock()
192
+ mock_resp.is_success = True
193
+ mock_resp.status_code = 200
194
+ mock_resp.json.return_value = {}
195
+ skill_command.plus_api_client.publish_skill = MagicMock(return_value=mock_resp)
196
+ with (
197
+ patch("crewai_cli.skills.main.git.Repository") as mock_repo_cls,
198
+ patch("crewai_cli.skills.main.Settings") as mock_settings_cls,
199
+ ):
200
+ mock_settings_cls.return_value.org_name = "acme"
201
+ mock_settings_cls.return_value.enterprise_base_url = None
202
+ skill_command.publish(org="acme", force=True)
203
+ mock_repo_cls.assert_not_called()
204
+ skill_command.plus_api_client.publish_skill.assert_called_once()
205
+
206
+ def test_publish_blocked_when_fetch_fails(self, skill_command):
207
+ """A failing remote fetch must fail closed, not silently skip syncing."""
208
+ with in_temp_dir():
209
+ Path("SKILL.md").write_text(
210
+ "---\nname: my-skill\ndescription: A test skill.\nmetadata:\n version: 1.0.0\n---\nInstructions."
211
+ )
212
+ skill_command.plus_api_client.publish_skill = MagicMock()
213
+ with patch("crewai_cli.skills.main.git.Repository") as mock_repo_cls:
214
+ mock_repo_cls.return_value.fetch.side_effect = ValueError(
215
+ "Git fetch failed with exit code 128"
216
+ )
217
+ with pytest.raises(SystemExit):
218
+ skill_command.publish(org="acme")
219
+ skill_command.plus_api_client.publish_skill.assert_not_called()
220
+
221
+ def test_publish_blocked_when_git_state_cannot_be_validated(self, skill_command):
222
+ """Git errors other than 'not a repo' must fail closed, not skip the check."""
223
+ with in_temp_dir():
224
+ Path("SKILL.md").write_text(
225
+ "---\nname: my-skill\ndescription: A test skill.\nmetadata:\n version: 1.0.0\n---\nInstructions."
226
+ )
227
+ skill_command.plus_api_client.publish_skill = MagicMock()
228
+ with patch(
229
+ "crewai_cli.skills.main.git.Repository",
230
+ side_effect=ValueError("Git fetch failed with exit code 128"),
231
+ ):
232
+ with pytest.raises(SystemExit):
233
+ skill_command.publish(org="acme")
234
+ skill_command.plus_api_client.publish_skill.assert_not_called()
235
+
236
+ def test_publish_proceeds_outside_git_repo(self, skill_command):
237
+ with in_temp_dir():
238
+ Path("SKILL.md").write_text(
239
+ "---\nname: my-skill\ndescription: A test skill.\nmetadata:\n version: 1.0.0\n---\nInstructions."
240
+ )
241
+ mock_resp = MagicMock()
242
+ mock_resp.is_success = True
243
+ mock_resp.status_code = 200
244
+ mock_resp.json.return_value = {}
245
+ skill_command.plus_api_client.publish_skill = MagicMock(return_value=mock_resp)
246
+ with (
247
+ patch(
248
+ "crewai_cli.skills.main.git.Repository",
249
+ side_effect=ValueError("not a Git repository"),
250
+ ),
251
+ patch("crewai_cli.skills.main.Settings") as mock_settings_cls,
252
+ ):
253
+ mock_settings_cls.return_value.org_name = "acme"
254
+ mock_settings_cls.return_value.enterprise_base_url = None
255
+ skill_command.publish(org="acme")
256
+ skill_command.plus_api_client.publish_skill.assert_called_once()
171
257
 
172
258
 
173
259
  class TestSkillListCached:
@@ -14,7 +14,7 @@ from pathlib import Path
14
14
 
15
15
  import pytest
16
16
 
17
- from crewai_cli.experimental.skills.main import _safe_extractall
17
+ from crewai_cli.skills.main import _safe_extractall
18
18
 
19
19
 
20
20
  def _tar_from_members(build) -> tarfile.TarFile:
@@ -1 +0,0 @@
1
- __version__ = "1.15.3.dev20260717"
File without changes
File without changes