Skip to content

importer

importer

SkillImporter — install ResolvedSkill instances into ~/.openjarvis/skills/.

Steps performed by import_skill:

  1. Parse the source SKILL.md through SkillParser (strict + tolerant).
  2. Translate tool references in the markdown body via ToolTranslator.
  3. Decide on scripts (default-skip; opt-in via with_scripts=True).
  4. Write to disk at ///:
  5. translated SKILL.md
  6. references/, assets/, templates/ (always copied)
  7. scripts/ (only if approved)
  8. .source metadata file
  9. Return ImportResult with status, warnings, translated/missing tools.

Classes

ImportResult dataclass

ImportResult(success: bool = True, skipped: bool = False, target_path: Path | None = None, translated_tools: List[str] = list(), untranslated_tools: List[str] = list(), scripts_imported: bool = False, warnings: List[str] = list(), trust_tier: TrustTier = UNREVIEWED, dangerous_capabilities: List[str] = list(), requires_confirmation: bool = False)

Result of importing a single skill.

SkillImporter

SkillImporter(parser: SkillParser, tool_translator: ToolTranslator, target_root: Path | None = None)

Install resolved skills into the user skills directory.

Source code in src/openjarvis/skills/importer.py
def __init__(
    self,
    parser: SkillParser,
    tool_translator: ToolTranslator,
    target_root: Path | None = None,
) -> None:
    self._parser = parser
    self._translator = tool_translator
    if target_root is None:
        target_root = get_config_dir() / "skills"
    self._target_root = Path(target_root)
Functions
import_skill
import_skill(resolved: ResolvedSkill, *, with_scripts: bool = False, force: bool = False, confirm_dangerous: bool = False) -> ImportResult

Install resolved into <target_root>/<source>/<name>/.

Returns an :class:ImportResult with status, paths, translated tools, untranslated tools, and warnings.

Source code in src/openjarvis/skills/importer.py
def import_skill(
    self,
    resolved: ResolvedSkill,
    *,
    with_scripts: bool = False,
    force: bool = False,
    confirm_dangerous: bool = False,
) -> ImportResult:
    """Install *resolved* into ``<target_root>/<source>/<name>/``.

    Returns an :class:`ImportResult` with status, paths, translated
    tools, untranslated tools, and warnings.
    """
    result = ImportResult()
    target_dir = self._target_root / resolved.source / resolved.name
    result.target_path = target_dir

    # Skip if already installed and force is False
    if target_dir.exists() and not force:
        result.skipped = True
        result.warnings.append(
            f"Skill already installed at {target_dir} (use force=True to overwrite)"
        )
        return result

    # 1. Parse source SKILL.md
    source_md = resolved.path / "SKILL.md"
    if not source_md.exists():
        source_md = resolved.path / "skill.md"
        if not source_md.exists():
            result.success = False
            result.warnings.append(f"No SKILL.md found in {resolved.path}")
            return result

    try:
        frontmatter, body = self._read_skill_md(source_md)
        manifest = self._parser.parse_frontmatter(
            frontmatter, markdown_content=body
        )
    except Exception as exc:
        result.success = False
        result.warnings.append(f"Parse error: {exc}")
        return result

    # 1a. Classify trust and check for dangerous capabilities *before*
    # writing anything to disk. Everything the importer handles comes from
    # an external source (github/hermes/openclaw), so the BUNDLED and
    # WORKSPACE tiers never apply here, and no resolver verifies index
    # membership yet — a signature alone still classifies as UNREVIEWED.
    # Community skills get no special treatment just because they came
    # from a named source.
    result.trust_tier = classify_trust_tier(
        has_signature=bool(manifest.signature),
    )
    result.dangerous_capabilities = has_dangerous_capabilities(manifest)

    if result.dangerous_capabilities and result.trust_tier == TrustTier.UNREVIEWED:
        result.requires_confirmation = True
        if not confirm_dangerous:
            result.success = False
            result.warnings.append(
                "Refusing to install: this unreviewed skill requests "
                f"dangerous capabilities {result.dangerous_capabilities}. "
                "Re-run with confirm_dangerous=True (or `--yes-dangerous` "
                "on the CLI) only if you trust the source and have "
                "reviewed what it does."
            )
            return result
        result.warnings.append(
            "Installed with dangerous capabilities "
            f"{result.dangerous_capabilities} — confirmed by caller. "
            "This skill can run shell commands, open network listeners, "
            "and/or write to the filesystem."
        )

    # 2. Translate tool references
    translated_body, untranslated = self._translator.translate_markdown(body)
    result.untranslated_tools = untranslated
    # Compute the list of translations actually applied
    applied: List[str] = []
    for ext, internal in self._translator._table.items():
        if ext in body and ext not in translated_body:
            applied.append(f"{ext}->{internal}")
    result.translated_tools = applied

    # 3. Write the target directory
    if target_dir.exists():
        shutil.rmtree(target_dir)
    target_dir.mkdir(parents=True)

    # 3a. Translated SKILL.md
    new_md = self._render_skill_md(frontmatter, translated_body)
    (target_dir / "SKILL.md").write_text(new_md, encoding="utf-8")

    # 3b. Always-copied subdirs
    for subdir in COPIED_SUBDIRS:
        src_sub = resolved.path / subdir
        if src_sub.exists():
            shutil.copytree(src_sub, target_dir / subdir)

    # 3c. Scripts (gated by with_scripts)
    scripts_src = resolved.path / "scripts"
    if scripts_src.exists() and with_scripts:
        shutil.copytree(scripts_src, target_dir / "scripts")
        result.scripts_imported = True
    elif scripts_src.exists():
        result.warnings.append(
            "Skipped scripts/ directory (use with_scripts=True to import)"
        )

    # 4. Write .source metadata
    self._write_source_metadata(target_dir, resolved, result)

    return result

Functions