mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-08-10 08:21:54 +00:00
feat(skills)!: promote Skills Repository out of experimental (#6579)
* feat(skills)!: promote Skills Repository out of experimental The registry-backed Skills Repository (crewai skill create/publish/ install/list, @org/name refs, global cache) is now mainline: - CLI: `crewai skill ...` is a top-level group; the CREWAI_EXPERIMENTAL gate and the now-empty `crewai experimental` group are removed. - Runtime: registry.py, cache.py, and events.py move from crewai.experimental.skills into crewai.skills next to the loader; the require_experimental_skills() gate is gone. crewai.experimental.skills remains as a deprecated re-export shim. - Docs: concepts/skills now leads with the CLI workflow and documents the create -> publish -> install lifecycle. Linear: n/a (requested promotion) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(skills): org-scoped publish only + docs in all languages Skills are always scoped to the publishing organization, like tools: drop the --public/--private flags from `crewai skill publish` and always send is_public=False to the registry. CLI tests assert the flag is rejected and the API never receives a public publish. Translate the new CLI-first Quick Start and the create -> publish -> install lifecycle section into ar, pt-BR, and ko concepts/skills docs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(skills): address review comments on the promotion PR - Back-compat shim now aliases the old submodules in sys.modules so `crewai.experimental.skills.registry/cache/events` imports (and patch targets) resolve to the real crewai.skills modules, not just the package-root re-exports. - `crewai skill publish` actually enforces the git-state check that --force claims to skip: unsynced repos block publishing (mirroring tool publish); standalone skill dirs outside any git repo publish without a check. - Explicit UTF-8 encoding on SKILL.md and cache-metadata reads/writes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(skills): fail closed when git state cannot be validated on publish Follow deploy's pattern: construct git.Repository(fetch=False) and only treat "not a Git repository" as skippable — any other git error (fetch/auth/misconfiguration) now blocks publish with a --force escape hatch instead of silently bypassing the sync check. Also single-style imports in the shim test (CodeQL) with the dotted shim import covered via importlib. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(skills): fetch before sync check on publish; bump mcp past advisories Publish now refreshes remote-tracking refs (repository.fetch()) before is_synced(), so ahead/behind is judged against the actual remote rather than stale local refs; a failing fetch blocks publish with the --force escape hatch. Adds a fail-closed test for fetch errors. Raise mcp to >=1.28.1,<2 (locks 1.28.1): the ~=1.26.0 pin blocked GHSA-hvrp-rf83-w775 / GHSA-jpw9-pfvf-9f58 (fixed 1.27.2) and GHSA-vj7q-gjh5-988w (fixed 1.28.1), which were failing pip-audit on this PR. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Vinicius Brasil <vini@hey.com>
This commit is contained in:
@@ -686,20 +686,9 @@ def tool_publish(is_public: bool, force: bool) -> None:
|
||||
tool_cmd.publish(is_public, force)
|
||||
|
||||
|
||||
@crewai.group()
|
||||
def experimental() -> None:
|
||||
"""Experimental, unstable commands. Subject to change without notice."""
|
||||
import os
|
||||
|
||||
if os.environ.get("CREWAI_EXPERIMENTAL") != "1":
|
||||
raise click.UsageError(
|
||||
"Experimental commands are gated. Set CREWAI_EXPERIMENTAL=1 to enable."
|
||||
)
|
||||
|
||||
|
||||
@experimental.group(name="skill")
|
||||
@crewai.group(name="skill")
|
||||
def skill() -> None:
|
||||
"""Skill Repository related commands (experimental)."""
|
||||
"""Create, publish, and install agent skills."""
|
||||
|
||||
|
||||
@skill.command(name="create")
|
||||
@@ -713,7 +702,7 @@ def skill() -> None:
|
||||
help="Create skill in current dir instead of ./skills/",
|
||||
)
|
||||
def skill_create(name: str, in_project: bool) -> None:
|
||||
from crewai_cli.experimental.skills.main import SkillCommand
|
||||
from crewai_cli.skills.main import SkillCommand
|
||||
|
||||
skill_cmd = SkillCommand()
|
||||
skill_cmd.create(name, in_project=in_project)
|
||||
@@ -722,7 +711,7 @@ def skill_create(name: str, in_project: bool) -> None:
|
||||
@skill.command(name="install")
|
||||
@click.argument("ref")
|
||||
def skill_install(ref: str) -> None:
|
||||
from crewai_cli.experimental.skills.main import SkillCommand
|
||||
from crewai_cli.skills.main import SkillCommand
|
||||
|
||||
skill_cmd = SkillCommand()
|
||||
skill_cmd.install(ref)
|
||||
@@ -736,20 +725,19 @@ def skill_install(ref: str) -> None:
|
||||
show_default=True,
|
||||
help="Skip git-state validation.",
|
||||
)
|
||||
@click.option("--public", "is_public", flag_value=True, default=False)
|
||||
@click.option("--private", "is_public", flag_value=False)
|
||||
@click.option("--org", default=None, help="Organisation slug (overrides settings).")
|
||||
def skill_publish(is_public: bool, org: str | None, force: bool) -> None:
|
||||
from crewai_cli.experimental.skills.main import SkillCommand
|
||||
def skill_publish(org: str | None, force: bool) -> None:
|
||||
"""Publish the skill in the current directory, scoped to your organization."""
|
||||
from crewai_cli.skills.main import SkillCommand
|
||||
|
||||
skill_cmd = SkillCommand()
|
||||
skill_cmd.publish(is_public, org=org, force=force)
|
||||
skill_cmd.publish(org=org, force=force)
|
||||
|
||||
|
||||
@skill.command(name="list")
|
||||
def skill_list() -> None:
|
||||
"""List locally installed skills."""
|
||||
from crewai_cli.experimental.skills.main import SkillCommand
|
||||
from crewai_cli.skills.main import SkillCommand
|
||||
|
||||
skill_cmd = SkillCommand()
|
||||
skill_cmd.list_cached()
|
||||
|
||||
Reference in New Issue
Block a user