with one click
commands
Imported skill commands from langchain
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
Imported skill commands from langchain
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Imported skill init_skill from anthropic
Imported skill node_mcp_server from anthropic
Imported skill readme from anthropic
Imported skill skill from anthropic
Imported skill init_skill from langchain
Imported skill readme from langchain
Based on SOC occupation classification
| description | Imported skill commands from langchain |
| name | commands |
| signature | 47ef5d6732ac044dc5f7d08c3ed5652acd9881e5206ea9056308a8b07317301d |
| source | /a0/tmp/skills_research/langchain/libs/deepagents-cli/deepagents_cli/skills/commands.py |
"""CLI commands for skill management.
These commands are registered with the CLI via cli.py:
import argparse import re from pathlib import Path from typing import Any
from deepagents_cli.config import COLORS, Settings, console from deepagents_cli.skills.load import list_skills
MAX_SKILL_NAME_LENGTH = 64
def _validate_name(name: str) -> tuple[bool, str]: """Validate name per Agent Skills spec.
Requirements (https://agentskills.io/specification):
- Max 64 characters
- Lowercase alphanumeric and hyphens only (a-z, 0-9, -)
- Cannot start or end with hyphen
- No consecutive hyphens
- No path traversal sequences
Args:
name: The name to validate
Returns:
Tuple of (is_valid, error_message). If valid, error_message is empty.
"""
# Check for empty or whitespace-only names
if not name or not name.strip():
return False, "cannot be empty"
# Check length (spec: max 64 chars)
if len(name) > MAX_SKILL_NAME_LENGTH:
return False, "cannot exceed 64 characters"
# Check for path traversal sequences
if ".." in name or "/" in name or "\\" in name:
return False, "cannot contain path components"
# Spec: lowercase alphanumeric and hyphens only
# Pattern ensures: no start/end hyphen, no consecutive hyphens
if not re.match(r"^[a-z0-9]+(-[a-z0-9]+)*$", name):
return (
False,
"must be lowercase letters, numbers, and hyphens only "
"(no uppercase, no underscores, cannot start/end with hyphen)",
)
return True, ""
def _validate_skill_path(skill_dir: Path, base_dir: Path) -> tuple[bool, str]: """Validate that the resolved skill directory is within the base directory.
Args:
skill_dir: The skill directory path to validate
base_dir: The base skills directory that should contain skill_dir
Returns:
Tuple of (is_valid, error_message). If valid, error_message is empty.
"""
try:
# Resolve both paths to their canonical form
resolved_skill = skill_dir.resolve()
resolved_base = base_dir.resolve()
# Check if skill_dir is within base_dir
# Use is_relative_to if available (Python 3.9+), otherwise use string comparison
if hasattr(resolved_skill, "is_relative_to"):
if not resolved_skill.is_relative_to(resolved_base):
return False, f"Skill directory must be within {base_dir}"
else:
# Fallback for older Python versions
try:
resolved_skill.relative_to(resolved_base)
except ValueError:
return False, f"Skill directory must be within {base_dir}"
return True, ""
except (OSError, RuntimeError) as e:
return False, f"Invalid path: {e}"
def _list(agent: str, *, project: bool = False) -> None: """List all available skills for the specified agent.
Args:
agent: Agent identifier for skills (default: agent).
project: If True, show only project skills.
If False, show all skills (user + project).
"""
settings = Settings.from_environment()
user_skills_dir = settings.get_user_skills_dir(agent)
project_skills_dir = settings.get_project_skills_dir()
# If --project flag is used, only show project skills
if project:
if not project_skills_dir:
console.print("[yellow]Not in a project directory.[/yellow]")
console.print(
"[dim]Project skills require a .git directory in the project root.[/dim]",
style=COLORS["dim"],
)
return
if not project_skills_dir.exists() or not any(project_skills_dir.iterdir()):
console.print("[yellow]No project skills found.[/yellow]")
console.print(
f"[dim]Project skills will be created in {project_skills_dir}/ when you add them.[/dim]",
style=COLORS["dim"],
)
console.print(
"\n[dim]Create a project skill:\n deepagents skills create my-skill --project[/dim]",
style=COLORS["dim"],
)
return
skills = list_skills(user_skills_dir=None, project_skills_dir=project_skills_dir)
console.print("\n[bold]Project Skills:[/bold]\n", style=COLORS["primary"])
else:
# Load both user and project skills
skills = list_skills(user_skills_dir=user_skills_dir, project_skills_dir=project_skills_dir)
if not skills:
console.print("[yellow]No skills found.[/yellow]")
console.print(
"[dim]Skills will be created in ~/.deepagents/agent/skills/ when you add them.[/dim]",
style=COLORS["dim"],
)
console.print(
"\n[dim]Create your first skill:\n deepagents skills create my-skill[/dim]",
style=COLORS["dim"],
)
return
console.print("\n[bold]Available Skills:[/bold]\n", style=COLORS["primary"])
# Group skills by source
user_skills = [s for s in skills if s["source"] == "user"]
project_skills_list = [s for s in skills if s["source"] == "project"]
# Show user skills
if user_skills and not project:
console.print("[bold cyan]User Skills:[/bold cyan]", style=COLORS["primary"])
for skill in user_skills:
skill_path = Path(skill["path"])
console.print(f" • [bold]{skill['name']}[/bold]", style=COLORS["primary"])
console.print(f" {skill['description']}", style=COLORS["dim"])
console.print(f" Location: {skill_path.parent}/", style=COLORS["dim"])
console.print()
# Show project skills
if project_skills_list:
if not project and user_skills:
console.print()
console.print("[bold green]Project Skills:[/bold green]", style=COLORS["primary"])
for skill in project_skills_list:
skill_path = Path(skill["path"])
console.print(f" • [bold]{skill['name']}[/bold]", style=COLORS["primary"])
console.print(f" {skill['description']}", style=COLORS["dim"])
console.print(f" Location: {skill_path.parent}/", style=COLORS["dim"])
console.print()
def _create(skill_name: str, agent: str, project: bool = False) -> None: """Create a new skill with a template SKILL.md file.
Args:
skill_name: Name of the skill to create.
agent: Agent identifier for skills
project: If True, create in project skills directory.
If False, create in user skills directory.
"""
# Validate skill name first (per Agent Skills spec)
is_valid, error_msg = _validate_name(skill_name)
if not is_valid:
console.print(f"[bold red]Error:[/bold red] Invalid skill name: {error_msg}")
console.print(
"[dim]Per Agent Skills spec: names must be lowercase alphanumeric with hyphens only.\n"
"Examples: web-research, code-review, data-analysis[/dim]",
style=COLORS["dim"],
)
return
# Determine target directory
settings = Settings.from_environment()
if project:
if not settings.project_root:
console.print("[bold red]Error:[/bold red] Not in a project directory.")
console.print(
"[dim]Project skills require a .git directory in the project root.[/dim]",
style=COLORS["dim"],
)
return
skills_dir = settings.ensure_project_skills_dir()
else:
skills_dir = settings.ensure_user_skills_dir(agent)
skill_dir = skills_dir / skill_name
# Validate the resolved path is within skills_dir
is_valid_path, path_error = _validate_skill_path(skill_dir, skills_dir)
if not is_valid_path:
console.print(f"[bold red]Error:[/bold red] {path_error}")
return
if skill_dir.exists():
console.print(
f"[bold red]Error:[/bold red] Skill '{skill_name}' already exists at {skill_dir}"
)
return
# Create skill directory
skill_dir.mkdir(parents=True, exist_ok=True)
# Create template SKILL.md (per Agent Skills spec: https://agentskills.io/specification)
template = f"""---
name: {skill_name} description: Brief description of what this skill does and when to use it.
[Provide a detailed explanation of what this skill does and when it should be used]
[Explain what to do first]
[Explain what to do next]
[Explain how to complete the task]
This skill directory can include supporting files referenced in the instructions:
helper.py - Python scripts for automationconfig.json - Configuration filesreference.md - Additional reference documentationUser Request: "[Example user request]"
Approach:
User Request: "[Another example]"
Approach:
[Additional tips, warnings, or context]
[Known limitations or edge cases]
[Links to external resources if helpful] """
skill_md = skill_dir / "SKILL.md" skill_md.write_text(template)
console.print(f"✓ Skill '{skill_name}' created successfully!", style=COLORS["primary"]) console.print(f"Location: {skill_dir}\n", style=COLORS["dim"]) console.print( "[dim]Edit the SKILL.md file to customize:\n" " 1. Update the description in YAML frontmatter\n" " 2. Fill in the instructions and examples\n" " 3. Add any supporting files (scripts, configs, etc.)\n" "\n" f" nano {skill_md}\n" "\n" "💡 See examples/skills/ in the deepagents repo for example skills:\n" " - web-research: Structured research workflow\n" " - langgraph-docs: LangGraph documentation lookup\n" "\n" " Copy an example: cp -r examples/skills/web-research ~/.deepagents/agent/skills/\n", style=COLORS["dim"], )
def _info(skill_name: str, *, agent: str = "agent", project: bool = False) -> None: """Show detailed information about a specific skill.
Args:
skill_name: Name of the skill to show info for.
agent: Agent identifier for skills (default: agent).
project: If True, only search in project skills. If False, search in both user and project skills.
"""
settings = Settings.from_environment()
user_skills_dir = settings.get_user_skills_dir(agent)
project_skills_dir = settings.get_project_skills_dir()
# Load skills based on --project flag
if project:
if not project_skills_dir:
console.print("[bold red]Error:[/bold red] Not in a project directory.")
return
skills = list_skills(user_skills_dir=None, project_skills_dir=project_skills_dir)
else:
skills = list_skills(user_skills_dir=user_skills_dir, project_skills_dir=project_skills_dir)
# Find the skill
skill = next((s for s in skills if s["name"] == skill_name), None)
if not skill:
console.print(f"[bold red]Error:[/bold red] Skill '{skill_name}' not found.")
console.print("\n[dim]Available skills:[/dim]", style=COLORS["dim"])
for s in skills:
console.print(f" - {s['name']}", style=COLORS["dim"])
return
# Read the full SKILL.md file
skill_path = Path(skill["path"])
skill_content = skill_path.read_text()
# Determine source label
source_label = "Project Skill" if skill["source"] == "project" else "User Skill"
source_color = "green" if skill["source"] == "project" else "cyan"
console.print(
f"\n[bold]Skill: {skill['name']}[/bold] [bold {source_color}]({source_label})[/bold {source_color}]\n",
style=COLORS["primary"],
)
console.print(f"[bold]Description:[/bold] {skill['description']}\n", style=COLORS["dim"])
console.print(f"[bold]Location:[/bold] {skill_path.parent}/\n", style=COLORS["dim"])
# List supporting files
skill_dir = skill_path.parent
supporting_files = [f for f in skill_dir.iterdir() if f.name != "SKILL.md"]
if supporting_files:
console.print("[bold]Supporting Files:[/bold]", style=COLORS["dim"])
for file in supporting_files:
console.print(f" - {file.name}", style=COLORS["dim"])
console.print()
# Show the full SKILL.md content
console.print("[bold]Full SKILL.md Content:[/bold]\n", style=COLORS["primary"])
console.print(skill_content, style=COLORS["dim"])
console.print()
def setup_skills_parser( subparsers: Any, ) -> argparse.ArgumentParser: """Setup the skills subcommand parser with all its subcommands.""" skills_parser = subparsers.add_parser( "skills", help="Manage agent skills", description="Manage agent skills - create, list, and view skill information", ) skills_subparsers = skills_parser.add_subparsers(dest="skills_command", help="Skills command")
# Skills list
list_parser = skills_subparsers.add_parser(
"list", help="List all available skills", description="List all available skills"
)
list_parser.add_argument(
"--agent",
default="agent",
help="Agent identifier for skills (default: agent)",
)
list_parser.add_argument(
"--project",
action="store_true",
help="Show only project-level skills",
)
# Skills create
create_parser = skills_subparsers.add_parser(
"create",
help="Create a new skill",
description="Create a new skill with a template SKILL.md file",
)
create_parser.add_argument("name", help="Name of the skill to create (e.g., web-research)")
create_parser.add_argument(
"--agent",
default="agent",
help="Agent identifier for skills (default: agent)",
)
create_parser.add_argument(
"--project",
action="store_true",
help="Create skill in project directory instead of user directory",
)
# Skills info
info_parser = skills_subparsers.add_parser(
"info",
help="Show detailed information about a skill",
description="Show detailed information about a specific skill",
)
info_parser.add_argument("name", help="Name of the skill to show info for")
info_parser.add_argument(
"--agent",
default="agent",
help="Agent identifier for skills (default: agent)",
)
info_parser.add_argument(
"--project",
action="store_true",
help="Search only in project skills",
)
return skills_parser
def execute_skills_command(args: argparse.Namespace) -> None: """Execute skills subcommands based on parsed arguments.
Args:
args: Parsed command line arguments with skills_command attribute
"""
# validate agent argument
if args.agent:
is_valid, error_msg = _validate_name(args.agent)
if not is_valid:
console.print(f"[bold red]Error:[/bold red] Invalid agent name: {error_msg}")
console.print(
"[dim]Agent names must only contain letters, numbers, hyphens, and underscores.[/dim]",
style=COLORS["dim"],
)
return
if args.skills_command == "list":
_list(agent=args.agent, project=args.project)
elif args.skills_command == "create":
_create(args.name, agent=args.agent, project=args.project)
elif args.skills_command == "info":
_info(args.name, agent=args.agent, project=args.project)
else:
# No subcommand provided, show help
console.print("[yellow]Please specify a skills subcommand: list, create, or info[/yellow]")
console.print("\n[bold]Usage:[/bold]", style=COLORS["primary"])
console.print(" deepagents skills <command> [options]\n")
console.print("[bold]Available commands:[/bold]", style=COLORS["primary"])
console.print(" list List all available skills")
console.print(" create <name> Create a new skill")
console.print(" info <name> Show detailed information about a skill")
console.print("\n[bold]Examples:[/bold]", style=COLORS["primary"])
console.print(" deepagents skills list")
console.print(" deepagents skills create web-research")
console.print(" deepagents skills info web-research")
console.print("\n[dim]For more help on a specific command:[/dim]", style=COLORS["dim"])
console.print(" deepagents skills <command> --help", style=COLORS["dim"])
all = [ "execute_skills_command", "setup_skills_parser", ]