mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-08-12 09:18:04 +00:00
feat(cli): unify scaffolding under crewai create <resource> (#6821)
* feat(cli): add canonical `crewai create tool` command Unify tool scaffolding under the create verb and deprecate `crewai tool create` with a yellow warning while keeping backward compatibility. * feat(cli): add canonical `crewai create skill` command Unify skill scaffolding under the create verb and deprecate `crewai skill create` with a yellow warning while keeping backward compatibility. * feat(cli): add canonical `crewai create template` command Unify template scaffolding under the create verb and deprecate `crewai template add` with a yellow warning while keeping backward compatibility. * docs: document unified `crewai create` scaffolding commands Document canonical create forms for tool, skill, and template projects, note deprecated aliases, and update skills and agents-md guides. * feat(cli): extend create picker and DMN guidance for all types Show tool, skill, and template in the interactive create picker and list every supported type in the CREWAI_DMN usage error. * fix(cli): allow create tool/skill/template in CREWAI_DMN mode Only set skip_provider in DMN mode for crew creation, since tool, skill, and template paths reject that flag as a crew-only option. * test(cli): patch TemplateCommand at cli lookup site in DMN test create() resolves TemplateCommand from crewai_cli.cli, not from remote_template.main directly.
This commit is contained in:
@@ -19,6 +19,7 @@ from crewai_cli.utils import (
|
||||
enable_prompt_line_editing,
|
||||
is_dmn_mode_enabled,
|
||||
read_toml,
|
||||
warn_deprecated_command,
|
||||
)
|
||||
|
||||
|
||||
@@ -137,7 +138,10 @@ def uv(uv_args: tuple[str, ...]) -> None:
|
||||
|
||||
@crewai.command()
|
||||
@click.argument(
|
||||
"type", required=False, default=None, type=click.Choice(["crew", "flow"])
|
||||
"type",
|
||||
required=False,
|
||||
default=None,
|
||||
type=click.Choice(["crew", "flow", "tool", "skill", "template"]),
|
||||
)
|
||||
@click.argument("name", required=False, default=None)
|
||||
@click.option("--provider", type=str, help="The provider to use for the crew")
|
||||
@@ -152,6 +156,21 @@ def uv(uv_args: tuple[str, ...]) -> None:
|
||||
is_flag=True,
|
||||
help="Create a declarative Flow project instead of a Python Flow project",
|
||||
)
|
||||
@click.option(
|
||||
"--no-project",
|
||||
"in_project",
|
||||
is_flag=True,
|
||||
default=True,
|
||||
flag_value=False,
|
||||
help="Skill only: create in current dir instead of ./skills/",
|
||||
)
|
||||
@click.option(
|
||||
"-o",
|
||||
"--output-dir",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Template only: directory name for the template (defaults to template name)",
|
||||
)
|
||||
def create(
|
||||
type: str | None,
|
||||
name: str | None,
|
||||
@@ -159,14 +178,17 @@ def create(
|
||||
skip_provider: bool = False,
|
||||
classic: bool = False,
|
||||
declarative: bool = False,
|
||||
in_project: bool = True,
|
||||
output_dir: str | None = None,
|
||||
) -> None:
|
||||
"""Create a new crew, or flow."""
|
||||
"""Create a new crew, flow, tool, skill, or template."""
|
||||
dmn_mode = is_dmn_mode_enabled()
|
||||
if not type:
|
||||
if dmn_mode:
|
||||
raise click.UsageError(
|
||||
"TYPE is required when CREWAI_DMN is set. "
|
||||
"Use `crewai create crew <name>` or `crewai create flow <name>`."
|
||||
"Use `crewai create <type> <name>` where type is one of: "
|
||||
"crew, flow, tool, skill, template."
|
||||
)
|
||||
from crewai_cli.tui_picker import pick
|
||||
|
||||
@@ -176,6 +198,9 @@ def create(
|
||||
"flow",
|
||||
"A deterministic workflow with full control over agents and crews",
|
||||
),
|
||||
("tool", "A custom tool for the CrewAI Tool Repository"),
|
||||
("skill", "An agent skill with instructions and optional assets"),
|
||||
("template", "A remote project template from the CrewAI gallery"),
|
||||
]
|
||||
type = pick("What would you like to create?", options)
|
||||
if type is None:
|
||||
@@ -189,9 +214,36 @@ def create(
|
||||
click.style(f" Name of your {type}", fg="cyan", bold=True),
|
||||
prompt_suffix=click.style(" › ", fg="bright_white"), # noqa: RUF001
|
||||
)
|
||||
if dmn_mode:
|
||||
if dmn_mode and type == "crew":
|
||||
skip_provider = True
|
||||
if type == "crew":
|
||||
if not in_project and type != "skill":
|
||||
raise click.UsageError("--no-project can only be used with skill projects.")
|
||||
if output_dir is not None and type != "template":
|
||||
raise click.UsageError("--output-dir can only be used with template projects.")
|
||||
if type == "tool":
|
||||
if declarative or classic or provider is not None or skip_provider:
|
||||
raise click.UsageError(
|
||||
"Crew and flow options cannot be used with tool projects."
|
||||
)
|
||||
from crewai_cli.tools.main import ToolCommand
|
||||
|
||||
ToolCommand().create(name)
|
||||
elif type == "skill":
|
||||
if declarative or classic or provider is not None or skip_provider:
|
||||
raise click.UsageError(
|
||||
"Crew and flow options cannot be used with skill projects."
|
||||
)
|
||||
from crewai_cli.skills.main import SkillCommand
|
||||
|
||||
SkillCommand().create(name, in_project=in_project)
|
||||
elif type == "template":
|
||||
if declarative or classic or provider is not None or skip_provider:
|
||||
raise click.UsageError(
|
||||
"Crew and flow options cannot be used with template projects."
|
||||
)
|
||||
template_cmd = TemplateCommand()
|
||||
template_cmd.add_template(name, output_dir)
|
||||
elif type == "crew":
|
||||
if declarative:
|
||||
raise click.UsageError("--declarative can only be used with flow projects")
|
||||
if classic:
|
||||
@@ -207,7 +259,10 @@ def create(
|
||||
|
||||
create_flow(name, declarative=declarative)
|
||||
else:
|
||||
click.secho("Error: Invalid type. Must be 'crew' or 'flow'.", fg="red")
|
||||
click.secho(
|
||||
"Error: Invalid type. Must be 'crew', 'flow', 'tool', 'skill', or 'template'.",
|
||||
fg="red",
|
||||
)
|
||||
|
||||
|
||||
@crewai.command()
|
||||
@@ -652,6 +707,8 @@ def tool() -> None:
|
||||
@tool.command(name="create")
|
||||
@click.argument("handle")
|
||||
def tool_create(handle: str) -> None:
|
||||
"""[Deprecated: use `crewai create tool`] Create a custom tool project."""
|
||||
warn_deprecated_command(old="crewai tool create", new="crewai create tool")
|
||||
from crewai_cli.tools.main import ToolCommand
|
||||
|
||||
tool_cmd = ToolCommand()
|
||||
@@ -702,6 +759,8 @@ def skill() -> None:
|
||||
help="Create skill in current dir instead of ./skills/",
|
||||
)
|
||||
def skill_create(name: str, in_project: bool) -> None:
|
||||
"""[Deprecated: use `crewai create skill`] Create a new agent skill."""
|
||||
warn_deprecated_command(old="crewai skill create", new="crewai create skill")
|
||||
from crewai_cli.skills.main import SkillCommand
|
||||
|
||||
skill_cmd = SkillCommand()
|
||||
@@ -765,7 +824,8 @@ def template_list() -> None:
|
||||
help="Directory name for the template (defaults to template name)",
|
||||
)
|
||||
def template_add(name: str, output_dir: str | None) -> None:
|
||||
"""Add a template to the current directory."""
|
||||
"""[Deprecated: use `crewai create template`] Add a template to the current directory."""
|
||||
warn_deprecated_command(old="crewai template add", new="crewai create template")
|
||||
template_cmd = TemplateCommand()
|
||||
template_cmd.add_template(name, output_dir)
|
||||
|
||||
|
||||
@@ -44,10 +44,19 @@ __all__ = [
|
||||
"render_template",
|
||||
"tree_copy",
|
||||
"tree_find_and_replace",
|
||||
"warn_deprecated_command",
|
||||
"write_env_file",
|
||||
]
|
||||
|
||||
|
||||
def warn_deprecated_command(*, old: str, new: str) -> None:
|
||||
"""Print a yellow deprecation warning for a legacy CLI command path."""
|
||||
click.secho(
|
||||
f"Warning: The command '{old}' is deprecated. Use '{new}' instead.",
|
||||
fg="yellow",
|
||||
)
|
||||
|
||||
|
||||
console = Console()
|
||||
_TEMPLATE_TOKEN_RE = re.compile(r"{{([a-zA-Z_][a-zA-Z0-9_]*)}}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user