748 lines
30 KiB
Python
748 lines
30 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Skill Seekers - Unified CLI Entry Point
|
|
|
|
Provides a git-style unified command-line interface for all Skill Seekers tools.
|
|
|
|
Usage:
|
|
skill-seekers <command> [options]
|
|
|
|
Commands:
|
|
config Configure GitHub tokens, API keys, and settings
|
|
scrape Scrape documentation website
|
|
github Scrape GitHub repository
|
|
pdf Extract from PDF file
|
|
unified Multi-source scraping (docs + GitHub + PDF)
|
|
analyze Analyze local codebase and extract code knowledge
|
|
enhance AI-powered enhancement (local, no API key)
|
|
enhance-status Check enhancement status (for background/daemon modes)
|
|
package Package skill into .zip file
|
|
upload Upload skill to Claude
|
|
estimate Estimate page count before scraping
|
|
extract-test-examples Extract usage examples from test files
|
|
install-agent Install skill to AI agent directories
|
|
resume Resume interrupted scraping job
|
|
|
|
Examples:
|
|
skill-seekers scrape --config configs/react.json
|
|
skill-seekers github --repo microsoft/TypeScript
|
|
skill-seekers unified --config configs/react_unified.json
|
|
skill-seekers extract-test-examples tests/ --language python
|
|
skill-seekers package output/react/
|
|
skill-seekers install-agent output/react/ --agent cursor
|
|
"""
|
|
|
|
import argparse
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from skill_seekers.cli import __version__
|
|
|
|
|
|
def create_parser() -> argparse.ArgumentParser:
|
|
"""Create the main argument parser with subcommands."""
|
|
parser = argparse.ArgumentParser(
|
|
prog="skill-seekers",
|
|
description="Convert documentation, GitHub repos, and PDFs into Claude AI skills",
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
epilog="""
|
|
Examples:
|
|
# Scrape documentation
|
|
skill-seekers scrape --config configs/react.json
|
|
|
|
# Scrape GitHub repository
|
|
skill-seekers github --repo microsoft/TypeScript --name typescript
|
|
|
|
# Multi-source scraping (unified)
|
|
skill-seekers unified --config configs/react_unified.json
|
|
|
|
# AI-powered enhancement
|
|
skill-seekers enhance output/react/
|
|
|
|
# Package and upload
|
|
skill-seekers package output/react/
|
|
skill-seekers upload output/react.zip
|
|
|
|
For more information: https://github.com/yusufkaraaslan/Skill_Seekers
|
|
""",
|
|
)
|
|
|
|
parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
|
|
|
|
subparsers = parser.add_subparsers(
|
|
dest="command",
|
|
title="commands",
|
|
description="Available Skill Seekers commands",
|
|
help="Command to run",
|
|
)
|
|
|
|
# === config subcommand ===
|
|
config_parser = subparsers.add_parser(
|
|
"config",
|
|
help="Configure GitHub tokens, API keys, and settings",
|
|
description="Interactive configuration wizard",
|
|
)
|
|
config_parser.add_argument(
|
|
"--github", action="store_true", help="Go directly to GitHub token setup"
|
|
)
|
|
config_parser.add_argument(
|
|
"--api-keys", action="store_true", help="Go directly to API keys setup"
|
|
)
|
|
config_parser.add_argument(
|
|
"--show", action="store_true", help="Show current configuration and exit"
|
|
)
|
|
config_parser.add_argument("--test", action="store_true", help="Test connections and exit")
|
|
|
|
# === scrape subcommand ===
|
|
scrape_parser = subparsers.add_parser(
|
|
"scrape",
|
|
help="Scrape documentation website",
|
|
description="Scrape documentation website and generate skill",
|
|
)
|
|
scrape_parser.add_argument("url", nargs="?", help="Documentation URL (positional argument)")
|
|
scrape_parser.add_argument("--config", help="Config JSON file")
|
|
scrape_parser.add_argument("--name", help="Skill name")
|
|
scrape_parser.add_argument("--description", help="Skill description")
|
|
scrape_parser.add_argument(
|
|
"--max-pages", type=int, dest="max_pages", help="Maximum pages to scrape (override config)"
|
|
)
|
|
scrape_parser.add_argument(
|
|
"--skip-scrape", action="store_true", help="Skip scraping, use cached data"
|
|
)
|
|
scrape_parser.add_argument("--enhance", action="store_true", help="AI enhancement (API)")
|
|
scrape_parser.add_argument(
|
|
"--enhance-local", action="store_true", help="AI enhancement (local)"
|
|
)
|
|
scrape_parser.add_argument("--dry-run", action="store_true", help="Dry run mode")
|
|
scrape_parser.add_argument(
|
|
"--async", dest="async_mode", action="store_true", help="Use async scraping"
|
|
)
|
|
scrape_parser.add_argument("--workers", type=int, help="Number of async workers")
|
|
|
|
# === github subcommand ===
|
|
github_parser = subparsers.add_parser(
|
|
"github",
|
|
help="Scrape GitHub repository",
|
|
description="Scrape GitHub repository and generate skill",
|
|
)
|
|
github_parser.add_argument("--config", help="Config JSON file")
|
|
github_parser.add_argument("--repo", help="GitHub repo (owner/repo)")
|
|
github_parser.add_argument("--name", help="Skill name")
|
|
github_parser.add_argument("--description", help="Skill description")
|
|
github_parser.add_argument("--enhance", action="store_true", help="AI enhancement (API)")
|
|
github_parser.add_argument(
|
|
"--enhance-local", action="store_true", help="AI enhancement (local)"
|
|
)
|
|
github_parser.add_argument("--api-key", type=str, help="Anthropic API key for --enhance")
|
|
github_parser.add_argument(
|
|
"--non-interactive",
|
|
action="store_true",
|
|
help="Non-interactive mode (fail fast on rate limits)",
|
|
)
|
|
github_parser.add_argument("--profile", type=str, help="GitHub profile name from config")
|
|
|
|
# === pdf subcommand ===
|
|
pdf_parser = subparsers.add_parser(
|
|
"pdf",
|
|
help="Extract from PDF file",
|
|
description="Extract content from PDF and generate skill",
|
|
)
|
|
pdf_parser.add_argument("--config", help="Config JSON file")
|
|
pdf_parser.add_argument("--pdf", help="PDF file path")
|
|
pdf_parser.add_argument("--name", help="Skill name")
|
|
pdf_parser.add_argument("--description", help="Skill description")
|
|
pdf_parser.add_argument("--from-json", help="Build from extracted JSON")
|
|
|
|
# === unified subcommand ===
|
|
unified_parser = subparsers.add_parser(
|
|
"unified",
|
|
help="Multi-source scraping (docs + GitHub + PDF)",
|
|
description="Combine multiple sources into one skill",
|
|
)
|
|
unified_parser.add_argument("--config", required=True, help="Unified config JSON file")
|
|
unified_parser.add_argument("--merge-mode", help="Merge mode (rule-based, claude-enhanced)")
|
|
unified_parser.add_argument(
|
|
"--fresh", action="store_true", help="Clear existing data and start fresh"
|
|
)
|
|
unified_parser.add_argument("--dry-run", action="store_true", help="Dry run mode")
|
|
|
|
# === enhance subcommand ===
|
|
enhance_parser = subparsers.add_parser(
|
|
"enhance",
|
|
help="AI-powered enhancement (local, no API key)",
|
|
description="Enhance SKILL.md using a local coding agent",
|
|
)
|
|
enhance_parser.add_argument("skill_directory", help="Skill directory path")
|
|
enhance_parser.add_argument(
|
|
"--agent",
|
|
choices=["claude", "codex", "copilot", "opencode", "custom"],
|
|
help="Local coding agent to use (default: claude or SKILL_SEEKER_AGENT)",
|
|
)
|
|
enhance_parser.add_argument(
|
|
"--agent-cmd",
|
|
help="Override agent command template (use {prompt_file} or stdin).",
|
|
)
|
|
enhance_parser.add_argument("--background", action="store_true", help="Run in background")
|
|
enhance_parser.add_argument("--daemon", action="store_true", help="Run as daemon")
|
|
enhance_parser.add_argument(
|
|
"--no-force", action="store_true", help="Disable force mode (enable confirmations)"
|
|
)
|
|
enhance_parser.add_argument("--timeout", type=int, default=600, help="Timeout in seconds")
|
|
|
|
# === enhance-status subcommand ===
|
|
enhance_status_parser = subparsers.add_parser(
|
|
"enhance-status",
|
|
help="Check enhancement status (for background/daemon modes)",
|
|
description="Monitor background enhancement processes",
|
|
)
|
|
enhance_status_parser.add_argument("skill_directory", help="Skill directory path")
|
|
enhance_status_parser.add_argument(
|
|
"--watch", "-w", action="store_true", help="Watch in real-time"
|
|
)
|
|
enhance_status_parser.add_argument("--json", action="store_true", help="JSON output")
|
|
enhance_status_parser.add_argument(
|
|
"--interval", type=int, default=2, help="Watch interval in seconds"
|
|
)
|
|
|
|
# === package subcommand ===
|
|
package_parser = subparsers.add_parser(
|
|
"package",
|
|
help="Package skill into .zip file",
|
|
description="Package skill directory into uploadable .zip",
|
|
)
|
|
package_parser.add_argument("skill_directory", help="Skill directory path")
|
|
package_parser.add_argument("--no-open", action="store_true", help="Don't open output folder")
|
|
package_parser.add_argument("--upload", action="store_true", help="Auto-upload after packaging")
|
|
|
|
# === upload subcommand ===
|
|
upload_parser = subparsers.add_parser(
|
|
"upload",
|
|
help="Upload skill to Claude",
|
|
description="Upload .zip file to Claude via Anthropic API",
|
|
)
|
|
upload_parser.add_argument("zip_file", help=".zip file to upload")
|
|
upload_parser.add_argument("--api-key", help="Anthropic API key")
|
|
|
|
# === estimate subcommand ===
|
|
estimate_parser = subparsers.add_parser(
|
|
"estimate",
|
|
help="Estimate page count before scraping",
|
|
description="Estimate total pages for documentation scraping",
|
|
)
|
|
estimate_parser.add_argument("config", nargs="?", help="Config JSON file")
|
|
estimate_parser.add_argument("--all", action="store_true", help="List all available configs")
|
|
estimate_parser.add_argument("--max-discovery", type=int, help="Max pages to discover")
|
|
|
|
# === extract-test-examples subcommand ===
|
|
test_examples_parser = subparsers.add_parser(
|
|
"extract-test-examples",
|
|
help="Extract usage examples from test files",
|
|
description="Analyze test files to extract real API usage patterns",
|
|
)
|
|
test_examples_parser.add_argument(
|
|
"directory", nargs="?", help="Directory containing test files"
|
|
)
|
|
test_examples_parser.add_argument("--file", help="Single test file to analyze")
|
|
test_examples_parser.add_argument(
|
|
"--language", help="Filter by programming language (python, javascript, etc.)"
|
|
)
|
|
test_examples_parser.add_argument(
|
|
"--min-confidence",
|
|
type=float,
|
|
default=0.5,
|
|
help="Minimum confidence threshold (0.0-1.0, default: 0.5)",
|
|
)
|
|
test_examples_parser.add_argument(
|
|
"--max-per-file", type=int, default=10, help="Maximum examples per file (default: 10)"
|
|
)
|
|
test_examples_parser.add_argument("--json", action="store_true", help="Output JSON format")
|
|
test_examples_parser.add_argument(
|
|
"--markdown", action="store_true", help="Output Markdown format"
|
|
)
|
|
|
|
# === install-agent subcommand ===
|
|
install_agent_parser = subparsers.add_parser(
|
|
"install-agent",
|
|
help="Install skill to AI agent directories",
|
|
description="Copy skill to agent-specific installation directories",
|
|
)
|
|
install_agent_parser.add_argument(
|
|
"skill_directory", help="Skill directory path (e.g., output/react/)"
|
|
)
|
|
install_agent_parser.add_argument(
|
|
"--agent",
|
|
required=True,
|
|
help="Agent name (claude, cursor, vscode, amp, goose, opencode, all)",
|
|
)
|
|
install_agent_parser.add_argument(
|
|
"--force", action="store_true", help="Overwrite existing installation without asking"
|
|
)
|
|
install_agent_parser.add_argument(
|
|
"--dry-run", action="store_true", help="Preview installation without making changes"
|
|
)
|
|
|
|
# === analyze subcommand ===
|
|
analyze_parser = subparsers.add_parser(
|
|
"analyze",
|
|
help="Analyze local codebase and extract code knowledge",
|
|
description="Standalone codebase analysis with C3.x features (patterns, tests, guides)",
|
|
)
|
|
analyze_parser.add_argument("--directory", required=True, help="Directory to analyze")
|
|
analyze_parser.add_argument(
|
|
"--output", default="output/codebase/", help="Output directory (default: output/codebase/)"
|
|
)
|
|
analyze_parser.add_argument(
|
|
"--quick", action="store_true", help="Quick analysis (1-2 min, basic features only)"
|
|
)
|
|
analyze_parser.add_argument(
|
|
"--comprehensive",
|
|
action="store_true",
|
|
help="Comprehensive analysis (20-60 min, all features + AI)",
|
|
)
|
|
analyze_parser.add_argument(
|
|
"--depth",
|
|
choices=["surface", "deep", "full"],
|
|
help="Analysis depth (deprecated - use --quick or --comprehensive instead)",
|
|
)
|
|
analyze_parser.add_argument(
|
|
"--languages", help="Comma-separated languages (e.g., Python,JavaScript,C++)"
|
|
)
|
|
analyze_parser.add_argument("--file-patterns", help="Comma-separated file patterns")
|
|
analyze_parser.add_argument(
|
|
"--enhance",
|
|
action="store_true",
|
|
help="Enable AI enhancement (default level 1 = SKILL.md only)",
|
|
)
|
|
analyze_parser.add_argument(
|
|
"--enhance-level",
|
|
type=int,
|
|
choices=[0, 1, 2, 3],
|
|
default=None,
|
|
help="AI enhancement level: 0=off, 1=SKILL.md only (default), 2=+Architecture+Config, 3=full",
|
|
)
|
|
analyze_parser.add_argument("--skip-api-reference", action="store_true", help="Skip API docs")
|
|
analyze_parser.add_argument(
|
|
"--skip-dependency-graph", action="store_true", help="Skip dep graph"
|
|
)
|
|
analyze_parser.add_argument(
|
|
"--skip-patterns", action="store_true", help="Skip pattern detection"
|
|
)
|
|
analyze_parser.add_argument(
|
|
"--skip-test-examples", action="store_true", help="Skip test examples"
|
|
)
|
|
analyze_parser.add_argument("--skip-how-to-guides", action="store_true", help="Skip guides")
|
|
analyze_parser.add_argument("--skip-config-patterns", action="store_true", help="Skip config")
|
|
analyze_parser.add_argument(
|
|
"--skip-docs", action="store_true", help="Skip project docs (README, docs/)"
|
|
)
|
|
analyze_parser.add_argument("--no-comments", action="store_true", help="Skip comments")
|
|
analyze_parser.add_argument("--verbose", action="store_true", help="Verbose logging")
|
|
|
|
# === install subcommand ===
|
|
install_parser = subparsers.add_parser(
|
|
"install",
|
|
help="Complete workflow: fetch → scrape → enhance → package → upload",
|
|
description="One-command skill installation (AI enhancement MANDATORY)",
|
|
)
|
|
install_parser.add_argument(
|
|
"--config",
|
|
required=True,
|
|
help="Config name (e.g., 'react') or path (e.g., 'configs/custom.json')",
|
|
)
|
|
install_parser.add_argument(
|
|
"--destination", default="output", help="Output directory (default: output/)"
|
|
)
|
|
install_parser.add_argument(
|
|
"--no-upload", action="store_true", help="Skip automatic upload to Claude"
|
|
)
|
|
install_parser.add_argument(
|
|
"--unlimited", action="store_true", help="Remove page limits during scraping"
|
|
)
|
|
install_parser.add_argument(
|
|
"--dry-run", action="store_true", help="Preview workflow without executing"
|
|
)
|
|
|
|
# === resume subcommand ===
|
|
resume_parser = subparsers.add_parser(
|
|
"resume",
|
|
help="Resume interrupted scraping job",
|
|
description="Continue from saved progress checkpoint",
|
|
)
|
|
resume_parser.add_argument(
|
|
"job_id", nargs="?", help="Job ID to resume (or use --list to see available jobs)"
|
|
)
|
|
resume_parser.add_argument("--list", action="store_true", help="List all resumable jobs")
|
|
resume_parser.add_argument("--clean", action="store_true", help="Clean up old progress files")
|
|
|
|
return parser
|
|
|
|
|
|
def main(argv: list[str] | None = None) -> int:
|
|
"""Main entry point for the unified CLI.
|
|
|
|
Args:
|
|
argv: Command-line arguments (defaults to sys.argv)
|
|
|
|
Returns:
|
|
Exit code (0 for success, non-zero for error)
|
|
"""
|
|
parser = create_parser()
|
|
args = parser.parse_args(argv)
|
|
|
|
if not args.command:
|
|
parser.print_help()
|
|
return 1
|
|
|
|
# Delegate to the appropriate tool
|
|
try:
|
|
if args.command == "config":
|
|
from skill_seekers.cli.config_command import main as config_main
|
|
|
|
sys.argv = ["config_command.py"]
|
|
if args.github:
|
|
sys.argv.append("--github")
|
|
if args.api_keys:
|
|
sys.argv.append("--api-keys")
|
|
if args.show:
|
|
sys.argv.append("--show")
|
|
if args.test:
|
|
sys.argv.append("--test")
|
|
return config_main() or 0
|
|
|
|
elif args.command == "scrape":
|
|
from skill_seekers.cli.doc_scraper import main as scrape_main
|
|
|
|
# Convert args namespace to sys.argv format for doc_scraper
|
|
sys.argv = ["doc_scraper.py"]
|
|
# Add positional URL if provided (positional arg has priority)
|
|
if hasattr(args, "url") and args.url:
|
|
sys.argv.append(args.url)
|
|
if args.config:
|
|
sys.argv.extend(["--config", args.config])
|
|
if args.name:
|
|
sys.argv.extend(["--name", args.name])
|
|
if args.description:
|
|
sys.argv.extend(["--description", args.description])
|
|
if hasattr(args, "max_pages") and args.max_pages:
|
|
sys.argv.extend(["--max-pages", str(args.max_pages)])
|
|
if args.skip_scrape:
|
|
sys.argv.append("--skip-scrape")
|
|
if args.enhance:
|
|
sys.argv.append("--enhance")
|
|
if args.enhance_local:
|
|
sys.argv.append("--enhance-local")
|
|
if args.dry_run:
|
|
sys.argv.append("--dry-run")
|
|
if args.async_mode:
|
|
sys.argv.append("--async")
|
|
if args.workers:
|
|
sys.argv.extend(["--workers", str(args.workers)])
|
|
return scrape_main() or 0
|
|
|
|
elif args.command == "github":
|
|
from skill_seekers.cli.github_scraper import main as github_main
|
|
|
|
sys.argv = ["github_scraper.py"]
|
|
if args.config:
|
|
sys.argv.extend(["--config", args.config])
|
|
if args.repo:
|
|
sys.argv.extend(["--repo", args.repo])
|
|
if args.name:
|
|
sys.argv.extend(["--name", args.name])
|
|
if args.description:
|
|
sys.argv.extend(["--description", args.description])
|
|
if args.enhance:
|
|
sys.argv.append("--enhance")
|
|
if args.enhance_local:
|
|
sys.argv.append("--enhance-local")
|
|
if args.api_key:
|
|
sys.argv.extend(["--api-key", args.api_key])
|
|
if args.non_interactive:
|
|
sys.argv.append("--non-interactive")
|
|
if args.profile:
|
|
sys.argv.extend(["--profile", args.profile])
|
|
return github_main() or 0
|
|
|
|
elif args.command == "pdf":
|
|
from skill_seekers.cli.pdf_scraper import main as pdf_main
|
|
|
|
sys.argv = ["pdf_scraper.py"]
|
|
if args.config:
|
|
sys.argv.extend(["--config", args.config])
|
|
if args.pdf:
|
|
sys.argv.extend(["--pdf", args.pdf])
|
|
if args.name:
|
|
sys.argv.extend(["--name", args.name])
|
|
if args.description:
|
|
sys.argv.extend(["--description", args.description])
|
|
if args.from_json:
|
|
sys.argv.extend(["--from-json", args.from_json])
|
|
return pdf_main() or 0
|
|
|
|
elif args.command == "unified":
|
|
from skill_seekers.cli.unified_scraper import main as unified_main
|
|
|
|
sys.argv = ["unified_scraper.py", "--config", args.config]
|
|
if args.merge_mode:
|
|
sys.argv.extend(["--merge-mode", args.merge_mode])
|
|
if args.fresh:
|
|
sys.argv.append("--fresh")
|
|
if args.dry_run:
|
|
sys.argv.append("--dry-run")
|
|
return unified_main() or 0
|
|
|
|
elif args.command == "enhance":
|
|
from skill_seekers.cli.enhance_skill_local import main as enhance_main
|
|
|
|
sys.argv = ["enhance_skill_local.py", args.skill_directory]
|
|
if args.agent:
|
|
sys.argv.extend(["--agent", args.agent])
|
|
if args.agent_cmd:
|
|
sys.argv.extend(["--agent-cmd", args.agent_cmd])
|
|
if args.background:
|
|
sys.argv.append("--background")
|
|
if args.daemon:
|
|
sys.argv.append("--daemon")
|
|
if args.no_force:
|
|
sys.argv.append("--no-force")
|
|
if args.timeout:
|
|
sys.argv.extend(["--timeout", str(args.timeout)])
|
|
return enhance_main() or 0
|
|
|
|
elif args.command == "enhance-status":
|
|
from skill_seekers.cli.enhance_status import main as enhance_status_main
|
|
|
|
sys.argv = ["enhance_status.py", args.skill_directory]
|
|
if args.watch:
|
|
sys.argv.append("--watch")
|
|
if args.json:
|
|
sys.argv.append("--json")
|
|
if args.interval:
|
|
sys.argv.extend(["--interval", str(args.interval)])
|
|
return enhance_status_main() or 0
|
|
|
|
elif args.command == "package":
|
|
from skill_seekers.cli.package_skill import main as package_main
|
|
|
|
sys.argv = ["package_skill.py", args.skill_directory]
|
|
if args.no_open:
|
|
sys.argv.append("--no-open")
|
|
if args.upload:
|
|
sys.argv.append("--upload")
|
|
return package_main() or 0
|
|
|
|
elif args.command == "upload":
|
|
from skill_seekers.cli.upload_skill import main as upload_main
|
|
|
|
sys.argv = ["upload_skill.py", args.zip_file]
|
|
if args.api_key:
|
|
sys.argv.extend(["--api-key", args.api_key])
|
|
return upload_main() or 0
|
|
|
|
elif args.command == "estimate":
|
|
from skill_seekers.cli.estimate_pages import main as estimate_main
|
|
|
|
sys.argv = ["estimate_pages.py"]
|
|
if args.all:
|
|
sys.argv.append("--all")
|
|
elif args.config:
|
|
sys.argv.append(args.config)
|
|
if args.max_discovery:
|
|
sys.argv.extend(["--max-discovery", str(args.max_discovery)])
|
|
return estimate_main() or 0
|
|
|
|
elif args.command == "extract-test-examples":
|
|
from skill_seekers.cli.test_example_extractor import main as test_examples_main
|
|
|
|
sys.argv = ["test_example_extractor.py"]
|
|
if args.directory:
|
|
sys.argv.append(args.directory)
|
|
if args.file:
|
|
sys.argv.extend(["--file", args.file])
|
|
if args.language:
|
|
sys.argv.extend(["--language", args.language])
|
|
if args.min_confidence:
|
|
sys.argv.extend(["--min-confidence", str(args.min_confidence)])
|
|
if args.max_per_file:
|
|
sys.argv.extend(["--max-per-file", str(args.max_per_file)])
|
|
if args.json:
|
|
sys.argv.append("--json")
|
|
if args.markdown:
|
|
sys.argv.append("--markdown")
|
|
return test_examples_main() or 0
|
|
|
|
elif args.command == "analyze":
|
|
from skill_seekers.cli.codebase_scraper import main as analyze_main
|
|
|
|
sys.argv = ["codebase_scraper.py", "--directory", args.directory]
|
|
|
|
if args.output:
|
|
sys.argv.extend(["--output", args.output])
|
|
|
|
# Handle preset flags (depth and features)
|
|
if args.quick:
|
|
# Quick = surface depth + skip advanced features + no AI
|
|
sys.argv.extend(
|
|
[
|
|
"--depth",
|
|
"surface",
|
|
"--skip-patterns",
|
|
"--skip-test-examples",
|
|
"--skip-how-to-guides",
|
|
"--skip-config-patterns",
|
|
]
|
|
)
|
|
elif args.comprehensive:
|
|
# Comprehensive = full depth + all features (AI level is separate)
|
|
sys.argv.extend(["--depth", "full"])
|
|
elif args.depth:
|
|
sys.argv.extend(["--depth", args.depth])
|
|
|
|
# Determine enhance_level (independent of --comprehensive)
|
|
# Priority: explicit --enhance-level > --enhance (uses config default) > --quick (level 0) > 0
|
|
if args.enhance_level is not None:
|
|
enhance_level = args.enhance_level
|
|
elif args.quick:
|
|
enhance_level = 0 # Quick mode disables AI
|
|
elif args.enhance:
|
|
# Use default from config (default: 1)
|
|
try:
|
|
from skill_seekers.cli.config_manager import get_config_manager
|
|
|
|
config = get_config_manager()
|
|
enhance_level = config.get_default_enhance_level()
|
|
except Exception:
|
|
enhance_level = 1 # Fallback to level 1
|
|
else:
|
|
enhance_level = 0 # Default: no AI
|
|
|
|
# Pass enhance_level to codebase_scraper
|
|
sys.argv.extend(["--enhance-level", str(enhance_level)])
|
|
|
|
if args.languages:
|
|
sys.argv.extend(["--languages", args.languages])
|
|
if args.file_patterns:
|
|
sys.argv.extend(["--file-patterns", args.file_patterns])
|
|
|
|
# Pass through skip flags
|
|
if args.skip_api_reference:
|
|
sys.argv.append("--skip-api-reference")
|
|
if args.skip_dependency_graph:
|
|
sys.argv.append("--skip-dependency-graph")
|
|
if args.skip_patterns:
|
|
sys.argv.append("--skip-patterns")
|
|
if args.skip_test_examples:
|
|
sys.argv.append("--skip-test-examples")
|
|
if args.skip_how_to_guides:
|
|
sys.argv.append("--skip-how-to-guides")
|
|
if args.skip_config_patterns:
|
|
sys.argv.append("--skip-config-patterns")
|
|
if args.skip_docs:
|
|
sys.argv.append("--skip-docs")
|
|
if args.no_comments:
|
|
sys.argv.append("--no-comments")
|
|
if args.verbose:
|
|
sys.argv.append("--verbose")
|
|
|
|
result = analyze_main() or 0
|
|
|
|
# Enhance SKILL.md if enhance_level >= 1
|
|
if result == 0 and enhance_level >= 1:
|
|
skill_dir = Path(args.output)
|
|
skill_md = skill_dir / "SKILL.md"
|
|
|
|
if skill_md.exists():
|
|
print("\n" + "=" * 60)
|
|
print(f"ENHANCING SKILL.MD WITH AI (Level {enhance_level})")
|
|
print("=" * 60 + "\n")
|
|
|
|
try:
|
|
from skill_seekers.cli.enhance_skill_local import LocalSkillEnhancer
|
|
|
|
enhancer = LocalSkillEnhancer(str(skill_dir), force=True)
|
|
# Use headless mode (runs claude directly, waits for completion)
|
|
success = enhancer.run(
|
|
headless=True,
|
|
timeout=600, # 10 minute timeout
|
|
)
|
|
|
|
if success:
|
|
print("\n✅ SKILL.md enhancement complete!")
|
|
# Re-read line count
|
|
with open(skill_md) as f:
|
|
lines = len(f.readlines())
|
|
print(f" Enhanced SKILL.md: {lines} lines")
|
|
else:
|
|
print("\n⚠️ SKILL.md enhancement did not complete")
|
|
print(" You can retry with: skill-seekers enhance " + str(skill_dir))
|
|
except Exception as e:
|
|
print(f"\n⚠️ SKILL.md enhancement failed: {e}")
|
|
print(" You can retry with: skill-seekers enhance " + str(skill_dir))
|
|
else:
|
|
print(f"\n⚠️ SKILL.md not found at {skill_md}, skipping enhancement")
|
|
|
|
return result
|
|
|
|
elif args.command == "install-agent":
|
|
from skill_seekers.cli.install_agent import main as install_agent_main
|
|
|
|
sys.argv = ["install_agent.py", args.skill_directory, "--agent", args.agent]
|
|
if args.force:
|
|
sys.argv.append("--force")
|
|
if args.dry_run:
|
|
sys.argv.append("--dry-run")
|
|
return install_agent_main() or 0
|
|
|
|
elif args.command == "install":
|
|
from skill_seekers.cli.install_skill import main as install_main
|
|
|
|
sys.argv = ["install_skill.py"]
|
|
if args.config:
|
|
sys.argv.extend(["--config", args.config])
|
|
if args.destination:
|
|
sys.argv.extend(["--destination", args.destination])
|
|
if args.no_upload:
|
|
sys.argv.append("--no-upload")
|
|
if args.unlimited:
|
|
sys.argv.append("--unlimited")
|
|
if args.dry_run:
|
|
sys.argv.append("--dry-run")
|
|
return install_main() or 0
|
|
|
|
elif args.command == "resume":
|
|
from skill_seekers.cli.resume_command import main as resume_main
|
|
|
|
sys.argv = ["resume_command.py"]
|
|
if args.job_id:
|
|
sys.argv.append(args.job_id)
|
|
if args.list:
|
|
sys.argv.append("--list")
|
|
if args.clean:
|
|
sys.argv.append("--clean")
|
|
return resume_main() or 0
|
|
|
|
else:
|
|
print(f"Error: Unknown command '{args.command}'", file=sys.stderr)
|
|
parser.print_help()
|
|
return 1
|
|
|
|
except KeyboardInterrupt:
|
|
print("\n\nInterrupted by user", file=sys.stderr)
|
|
return 130
|
|
except Exception as e:
|
|
# Provide helpful error message
|
|
error_msg = str(e) if str(e) else f"{type(e).__name__} occurred"
|
|
print(f"Error: {error_msg}", file=sys.stderr)
|
|
|
|
# Show traceback in verbose mode (if -v flag exists in args)
|
|
import traceback
|
|
|
|
if hasattr(args, "verbose") and getattr(args, "verbose", False):
|
|
traceback.print_exc()
|
|
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|