diff --git a/conftest.py b/conftest.py index 1cce71c26..d4f10048a 100644 --- a/conftest.py +++ b/conftest.py @@ -12,6 +12,7 @@ from dotenv import load_dotenv import pytest from vcr.request import Request # type: ignore[import-untyped] + try: import vcr.stubs.httpx_stubs as httpx_stubs # type: ignore[import-untyped] except ModuleNotFoundError: @@ -225,7 +226,7 @@ def vcr_cassette_dir(request: Any) -> str: for parent in test_file.parents: if ( - parent.name in ("crewai", "crewai-tools", "crewai-files") + parent.name in ("crewai", "crewai-tools", "crewai-files", "cli") and parent.parent.name == "lib" ): package_root = parent diff --git a/lib/cli/README.md b/lib/cli/README.md new file mode 100644 index 000000000..9fe7e42f0 --- /dev/null +++ b/lib/cli/README.md @@ -0,0 +1,15 @@ +# crewai-cli + +CLI for CrewAI - scaffold, run, deploy and manage AI agent crews without installing the full framework. + +## Installation + +```bash +pip install crewai-cli +``` + +Or install alongside the full framework: + +```bash +pip install crewai[cli] +``` diff --git a/lib/cli/pyproject.toml b/lib/cli/pyproject.toml new file mode 100644 index 000000000..bcddda21a --- /dev/null +++ b/lib/cli/pyproject.toml @@ -0,0 +1,39 @@ +[project] +name = "crewai-cli" +version = "1.10.0" +description = "CLI for CrewAI - scaffold, run, deploy and manage AI agent crews without installing the full framework." +readme = "README.md" +authors = [ + { name = "Joao Moura", email = "joao@crewai.com" } +] +requires-python = ">=3.10, <3.14" +dependencies = [ + "click~=8.1.7", + "pydantic~=2.11.9", + "pydantic-settings~=2.10.1", + "appdirs~=1.4.4", + "httpx~=0.28.1", + "pyjwt>=2.9.0,<3", + "rich>=13.7.1", + "tomli~=2.0.2", + "tomli-w~=1.1.0", + "packaging>=23.0", + "python-dotenv~=1.1.1", + "uv~=0.9.13", + "portalocker~=2.7.0", +] + +[project.urls] +Homepage = "https://crewai.com" +Documentation = "https://docs.crewai.com" +Repository = "https://github.com/crewAIInc/crewAI" + +[project.scripts] +crewai = "crewai_cli.cli:crewai" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.build.targets.wheel] +packages = ["src/crewai_cli"] diff --git a/lib/cli/src/crewai_cli/__init__.py b/lib/cli/src/crewai_cli/__init__.py new file mode 100644 index 000000000..fcfdf3836 --- /dev/null +++ b/lib/cli/src/crewai_cli/__init__.py @@ -0,0 +1 @@ +__version__ = "1.10.0" diff --git a/pyproject.toml b/pyproject.toml index 657c15eaa..f74928366 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,8 +36,10 @@ dev = [ src = ["lib/*"] extend-exclude = [ "lib/crewai/src/crewai/cli/templates", + "lib/cli/src/crewai_cli/templates", "lib/crewai/tests/", "lib/crewai-tools/tests/", + "lib/cli/tests/", ] respect-gitignore = true force-exclude = true @@ -106,6 +108,7 @@ ignore-decorators = ["typing.overload"] "lib/crewai/tests/**/*.py" = ["S101", "RET504", "S105", "S106"] # Allow assert statements, unnecessary assignments, and hardcoded passwords in tests "lib/crewai-tools/tests/**/*.py" = ["S101", "RET504", "S105", "S106", "RUF012", "N818", "E402", "RUF043", "S110", "B017"] # Allow various test-specific patterns "lib/crewai-files/tests/**/*.py" = ["S101", "RET504", "S105", "S106", "B017", "F841"] # Allow assert statements and blind exception assertions in tests +"lib/cli/tests/**/*.py" = ["S101", "RET504", "S105", "S106"] # Allow assert statements in tests [tool.mypy] @@ -118,12 +121,12 @@ warn_return_any = true show_error_codes = true warn_unused_ignores = true python_version = "3.12" -exclude = "(?x)(^lib/crewai/src/crewai/cli/templates/|^lib/crewai/tests/|^lib/crewai-tools/tests/|^lib/crewai-files/tests/)" +exclude = "(?x)(^lib/crewai/src/crewai/cli/templates/|^lib/cli/src/crewai_cli/templates/|^lib/crewai/tests/|^lib/crewai-tools/tests/|^lib/crewai-files/tests/|^lib/cli/tests/)" plugins = ["pydantic.mypy"] [tool.bandit] -exclude_dirs = ["lib/crewai/src/crewai/cli/templates"] +exclude_dirs = ["lib/crewai/src/crewai/cli/templates", "lib/cli/src/crewai_cli/templates"] [tool.pytest.ini_options] @@ -134,6 +137,7 @@ testpaths = [ "lib/crewai/tests", "lib/crewai-tools/tests", "lib/crewai-files/tests", + "lib/cli/tests", ] asyncio_mode = "strict" asyncio_default_fixture_loop_scope = "function" @@ -157,6 +161,7 @@ members = [ "lib/crewai-tools", "lib/devtools", "lib/crewai-files", + "lib/cli", ] @@ -165,3 +170,4 @@ crewai = { workspace = true } crewai-tools = { workspace = true } crewai-devtools = { workspace = true } crewai-files = { workspace = true } +crewai-cli = { workspace = true } diff --git a/uv.lock b/uv.lock index dba6ab30c..0b65ae1cb 100644 --- a/uv.lock +++ b/uv.lock @@ -15,6 +15,7 @@ resolution-markers = [ [manifest] members = [ "crewai", + "crewai-cli", "crewai-devtools", "crewai-files", "crewai-tools", @@ -1233,6 +1234,43 @@ requires-dist = [ ] provides-extras = ["a2a", "anthropic", "aws", "azure-ai-inference", "bedrock", "docling", "embeddings", "file-processing", "google-genai", "litellm", "mem0", "openpyxl", "pandas", "qdrant", "tools", "voyageai", "watson"] +[[package]] +name = "crewai-cli" +version = "1.10.0" +source = { editable = "lib/cli" } +dependencies = [ + { name = "appdirs" }, + { name = "click" }, + { name = "httpx" }, + { name = "packaging" }, + { name = "portalocker" }, + { name = "pydantic" }, + { name = "pydantic-settings" }, + { name = "pyjwt" }, + { name = "python-dotenv" }, + { name = "rich" }, + { name = "tomli" }, + { name = "tomli-w" }, + { name = "uv" }, +] + +[package.metadata] +requires-dist = [ + { name = "appdirs", specifier = "~=1.4.4" }, + { name = "click", specifier = "~=8.1.7" }, + { name = "httpx", specifier = "~=0.28.1" }, + { name = "packaging", specifier = ">=23.0" }, + { name = "portalocker", specifier = "~=2.7.0" }, + { name = "pydantic", specifier = "~=2.11.9" }, + { name = "pydantic-settings", specifier = "~=2.10.1" }, + { name = "pyjwt", specifier = ">=2.9.0,<3" }, + { name = "python-dotenv", specifier = "~=1.1.1" }, + { name = "rich", specifier = ">=13.7.1" }, + { name = "tomli", specifier = "~=2.0.2" }, + { name = "tomli-w", specifier = "~=1.1.0" }, + { name = "uv", specifier = "~=0.9.13" }, +] + [[package]] name = "crewai-devtools" source = { editable = "lib/devtools" } @@ -7769,6 +7807,11 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0f/8b/4b61d6e13f7108f36910df9ab4b58fd389cc2520d54d81b88660804aad99/torch-2.10.0-2-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:418997cb02d0a0f1497cf6a09f63166f9f5df9f3e16c8a716ab76a72127c714f", size = 79423467, upload-time = "2026-02-10T21:44:48.711Z" }, { url = "https://files.pythonhosted.org/packages/d3/54/a2ba279afcca44bbd320d4e73675b282fcee3d81400ea1b53934efca6462/torch-2.10.0-2-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:13ec4add8c3faaed8d13e0574f5cd4a323c11655546f91fbe6afa77b57423574", size = 79498202, upload-time = "2026-02-10T21:44:52.603Z" }, { url = "https://files.pythonhosted.org/packages/ec/23/2c9fe0c9c27f7f6cb865abcea8a4568f29f00acaeadfc6a37f6801f84cb4/torch-2.10.0-2-cp313-none-macosx_11_0_arm64.whl", hash = "sha256:e521c9f030a3774ed770a9c011751fb47c4d12029a3d6522116e48431f2ff89e", size = 79498254, upload-time = "2026-02-10T21:44:44.095Z" }, + { url = "https://files.pythonhosted.org/packages/16/ee/efbd56687be60ef9af0c9c0ebe106964c07400eade5b0af8902a1d8cd58c/torch-2.10.0-3-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a1ff626b884f8c4e897c4c33782bdacdff842a165fee79817b1dd549fdda1321", size = 915510070, upload-time = "2026-03-11T14:16:39.386Z" }, + { url = "https://files.pythonhosted.org/packages/36/ab/7b562f1808d3f65414cd80a4f7d4bb00979d9355616c034c171249e1a303/torch-2.10.0-3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:ac5bdcbb074384c66fa160c15b1ead77839e3fe7ed117d667249afce0acabfac", size = 915518691, upload-time = "2026-03-11T14:15:43.147Z" }, + { url = "https://files.pythonhosted.org/packages/b3/7a/abada41517ce0011775f0f4eacc79659bc9bc6c361e6bfe6f7052a6b9363/torch-2.10.0-3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:98c01b8bb5e3240426dcde1446eed6f40c778091c8544767ef1168fc663a05a6", size = 915622781, upload-time = "2026-03-11T14:17:11.354Z" }, + { url = "https://files.pythonhosted.org/packages/ab/c6/4dfe238342ffdcec5aef1c96c457548762d33c40b45a1ab7033bb26d2ff2/torch-2.10.0-3-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:80b1b5bfe38eb0e9f5ff09f206dcac0a87aadd084230d4a36eea5ec5232c115b", size = 915627275, upload-time = "2026-03-11T14:16:11.325Z" }, + { url = "https://files.pythonhosted.org/packages/d8/f0/72bf18847f58f877a6a8acf60614b14935e2f156d942483af1ffc081aea0/torch-2.10.0-3-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:46b3574d93a2a8134b3f5475cfb98e2eb46771794c57015f6ad1fb795ec25e49", size = 915523474, upload-time = "2026-03-11T14:17:44.422Z" }, { url = "https://files.pythonhosted.org/packages/0c/1a/c61f36cfd446170ec27b3a4984f072fd06dab6b5d7ce27e11adb35d6c838/torch-2.10.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:5276fa790a666ee8becaffff8acb711922252521b28fbce5db7db5cf9cb2026d", size = 145992962, upload-time = "2026-01-21T16:24:14.04Z" }, { url = "https://files.pythonhosted.org/packages/b5/60/6662535354191e2d1555296045b63e4279e5a9dbad49acf55a5d38655a39/torch-2.10.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:aaf663927bcd490ae971469a624c322202a2a1e68936eb952535ca4cd3b90444", size = 915599237, upload-time = "2026-01-21T16:23:25.497Z" }, { url = "https://files.pythonhosted.org/packages/40/b8/66bbe96f0d79be2b5c697b2e0b187ed792a15c6c4b8904613454651db848/torch-2.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:a4be6a2a190b32ff5c8002a0977a25ea60e64f7ba46b1be37093c141d9c49aeb", size = 113720931, upload-time = "2026-01-21T16:24:23.743Z" },