Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion setup_codex.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import subprocess
from pathlib import Path

from utils import adapt_instructions_file, ensure_https, get_gateway_host, get_npm_version
from utils import adapt_instructions_file, ensure_https, get_gateway_host, get_npm_version, mirror_claude_skills

# Set HOME if not properly set
if not os.environ.get("HOME") or os.environ["HOME"] == "/":
Expand Down Expand Up @@ -93,6 +93,9 @@
codex_dir = home / ".codex"
codex_dir.mkdir(exist_ok=True)

# Mirror Claude skills into ~/.codex/skills so Codex sees the same skill content
mirror_claude_skills(codex_dir / "skills", "Codex")

# Copy bundled Databricks model catalog into ~/.codex so it can be referenced
# by relative path in config.toml (codex resolves relatives against CODEX_HOME).
catalog_src = Path(__file__).parent / ".codex" / "databricks-models.json"
Expand Down
5 changes: 4 additions & 1 deletion setup_hermes.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import subprocess
from pathlib import Path

from utils import adapt_instructions_file, ensure_https, get_gateway_host
from utils import adapt_instructions_file, ensure_https, get_gateway_host, mirror_claude_skills

# Opt-out: allow operators to disable Hermes bundling without removing the file.
if os.environ.get("ENABLE_HERMES", "true").strip().lower() in ("false", "0", "no"):
Expand Down Expand Up @@ -58,6 +58,9 @@
local_bin.mkdir(parents=True, exist_ok=True)
hermes_home.mkdir(parents=True, exist_ok=True)

# Mirror Claude skills into ~/.hermes/skills so Hermes sees the same skill content
mirror_claude_skills(hermes_home / "skills", "Hermes")


def _run(cmd, **kwargs):
"""Run a subprocess command and return (rc, stdout, stderr)."""
Expand Down
5 changes: 4 additions & 1 deletion setup_opencode.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import subprocess
from pathlib import Path

from utils import ensure_https, get_gateway_host, get_npm_version
from utils import ensure_https, get_gateway_host, get_npm_version, mirror_claude_skills

# content-filter proxy local proxy — sanitizes empty content blocks before reaching Databricks
# (see https://github.com/sst/opencode/issues/5028)
Expand Down Expand Up @@ -278,6 +278,9 @@
opencode_data_dir = home / ".local" / "share" / "opencode"
opencode_data_dir.mkdir(parents=True, exist_ok=True)

# Mirror Claude skills into ~/.local/share/opencode/skills so OpenCode sees them
mirror_claude_skills(opencode_data_dir / "skills", "OpenCode")

if gateway_host:
auth_data = {
"databricks": {
Expand Down
19 changes: 19 additions & 0 deletions utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,29 @@

import os
import re
import shutil
import subprocess
from pathlib import Path


def mirror_claude_skills(target_dir: Path, agent_name: str) -> None:
"""Mirror ~/.claude/skills into ``target_dir`` so non-Claude agents see them.

Replaces ``target_dir`` if it already exists (idempotent across restarts).
Resolves the Claude skills directory via ``HOME``, falling back to a no-op
if nothing is there (the same shape `setup_gemini.py` uses for Gemini).
"""
home = Path(os.environ.get("HOME", "/app/python/source_code"))
claude_skills_dir = home / ".claude" / "skills"
if not claude_skills_dir.exists():
print(f"No Claude skills at {claude_skills_dir}, skipping {agent_name} mirror")
return
if target_dir.exists():
shutil.rmtree(target_dir)
shutil.copytree(claude_skills_dir, target_dir)
print(f"Skills mirrored: {claude_skills_dir} -> {target_dir}")


def get_npm_version(package_name):
"""Resolve the latest stable version of an npm package.

Expand Down