Auto commit: 2026-03-28 16:17:35
This commit is contained in:
+312
@@ -0,0 +1,312 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
MODE="all"
|
||||
RESTART_GATEWAY=0
|
||||
SKILLS_PREF="default"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--cli-only)
|
||||
MODE="cli"
|
||||
shift
|
||||
;;
|
||||
--skill-only)
|
||||
MODE="skill"
|
||||
shift
|
||||
;;
|
||||
--plugin-only)
|
||||
MODE="plugin"
|
||||
shift
|
||||
;;
|
||||
--restart-gateway)
|
||||
RESTART_GATEWAY=1
|
||||
shift
|
||||
;;
|
||||
--no-skills)
|
||||
SKILLS_PREF="off"
|
||||
shift
|
||||
;;
|
||||
--with-skills)
|
||||
SKILLS_PREF="on"
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
cat <<'USAGE'
|
||||
Usage: install.sh [--cli-only|--skill-only|--plugin-only] [--no-skills|--with-skills] [--restart-gateway]
|
||||
|
||||
Installs the skillhub CLI.
|
||||
Default mode installs CLI + workspace skill (find-skill style).
|
||||
Use --plugin-only only when you explicitly want legacy plugin injection.
|
||||
Use --no-skills to skip installing workspace skills and persist this preference
|
||||
for OTA self-upgrade migrations.
|
||||
USAGE
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Error: unknown argument: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# Supports two archive layouts:
|
||||
# 1) install.sh at kit root: ./install.sh + ./cli + ./plugin + ./skill
|
||||
# 2) install.sh inside cli folder: ./cli/install.sh + ./cli/plugin + ./cli/skill + cli files
|
||||
if [[ -d "${SCRIPT_DIR}/cli" ]]; then
|
||||
CLI_SRC_DIR="${SCRIPT_DIR}/cli"
|
||||
PLUGIN_SRC_DIR="${SCRIPT_DIR}/plugin"
|
||||
SKILL_SRC_DIR="${SCRIPT_DIR}/skill"
|
||||
else
|
||||
CLI_SRC_DIR="${SCRIPT_DIR}"
|
||||
PLUGIN_SRC_DIR="${SCRIPT_DIR}/plugin"
|
||||
SKILL_SRC_DIR="${SCRIPT_DIR}/skill"
|
||||
fi
|
||||
|
||||
INSTALL_BASE="${HOME}/.skillhub"
|
||||
BIN_DIR="${HOME}/.local/bin"
|
||||
CLI_TARGET="${INSTALL_BASE}/skills_store_cli.py"
|
||||
UPGRADE_MODULE_TARGET="${INSTALL_BASE}/skills_upgrade.py"
|
||||
VERSION_TARGET="${INSTALL_BASE}/version.json"
|
||||
METADATA_TARGET="${INSTALL_BASE}/metadata.json"
|
||||
INDEX_TARGET="${INSTALL_BASE}/skills_index.local.json"
|
||||
CONFIG_TARGET="${INSTALL_BASE}/config.json"
|
||||
WRAPPER_TARGET="${BIN_DIR}/skillhub"
|
||||
LEGACY_WRAPPER_TARGET="${BIN_DIR}/oc-skills"
|
||||
|
||||
PLUGIN_TARGET_DIR="${HOME}/.openclaw/extensions/skillhub"
|
||||
FIND_SKILL_TARGET_DIR="${HOME}/.openclaw/workspace/skills/find-skills"
|
||||
PREFERENCE_SKILL_TARGET_DIR="${HOME}/.openclaw/workspace/skills/skillhub-preference"
|
||||
|
||||
find_openclaw_bin() {
|
||||
if command -v openclaw >/dev/null 2>&1; then
|
||||
command -v openclaw
|
||||
return 0
|
||||
fi
|
||||
if [[ -x "${HOME}/.local/share/pnpm/openclaw" ]]; then
|
||||
echo "${HOME}/.local/share/pnpm/openclaw"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
install_cli() {
|
||||
if ! command -v python3 >/dev/null 2>&1; then
|
||||
echo "Error: python3 is required for skillhub." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "${INSTALL_BASE}" "${BIN_DIR}"
|
||||
cp "${CLI_SRC_DIR}/skills_store_cli.py" "${CLI_TARGET}"
|
||||
cp "${CLI_SRC_DIR}/skills_upgrade.py" "${UPGRADE_MODULE_TARGET}"
|
||||
cp "${CLI_SRC_DIR}/version.json" "${VERSION_TARGET}"
|
||||
cp "${CLI_SRC_DIR}/metadata.json" "${METADATA_TARGET}"
|
||||
if [[ -f "${CLI_SRC_DIR}/skills_index.local.json" ]]; then
|
||||
cp "${CLI_SRC_DIR}/skills_index.local.json" "${INDEX_TARGET}"
|
||||
fi
|
||||
chmod +x "${CLI_TARGET}"
|
||||
|
||||
if [[ ! -f "${CONFIG_TARGET}" ]]; then
|
||||
cat > "${CONFIG_TARGET}" <<'JSON'
|
||||
{
|
||||
"self_update_url": "https://skillhub-1388575217.cos.ap-guangzhou.myqcloud.com/version.json"
|
||||
}
|
||||
JSON
|
||||
fi
|
||||
|
||||
cat > "${WRAPPER_TARGET}" <<'WRAPPER'
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
BASE="${HOME}/.skillhub"
|
||||
CLI="${BASE}/skills_store_cli.py"
|
||||
|
||||
if [[ ! -f "${CLI}" ]]; then
|
||||
echo "Error: CLI not found at ${CLI}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec python3 "${CLI}" "$@"
|
||||
WRAPPER
|
||||
|
||||
chmod +x "${WRAPPER_TARGET}"
|
||||
|
||||
cat > "${LEGACY_WRAPPER_TARGET}" <<'WRAPPER'
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
exec "${HOME}/.local/bin/skillhub" "$@"
|
||||
WRAPPER
|
||||
|
||||
chmod +x "${LEGACY_WRAPPER_TARGET}"
|
||||
}
|
||||
|
||||
set_workspace_skills_preference() {
|
||||
local enabled="$1"
|
||||
if ! command -v python3 >/dev/null 2>&1; then
|
||||
echo "Warn: python3 not found; cannot persist skills preference." >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
python3 - "$CONFIG_TARGET" "$enabled" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
config_path = Path(sys.argv[1]).expanduser()
|
||||
enabled = sys.argv[2].strip().lower() == "true"
|
||||
default_update_url = "https://skillhub-1388575217.cos.ap-guangzhou.myqcloud.com/version.json"
|
||||
|
||||
raw = {}
|
||||
if config_path.exists():
|
||||
try:
|
||||
loaded = json.loads(config_path.read_text(encoding="utf-8"))
|
||||
if isinstance(loaded, dict):
|
||||
raw = loaded
|
||||
except Exception:
|
||||
raw = {}
|
||||
|
||||
if not isinstance(raw.get("self_update_url"), str) or not raw["self_update_url"].strip():
|
||||
raw["self_update_url"] = default_update_url
|
||||
raw["install_workspace_skills"] = enabled
|
||||
|
||||
config_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
config_path.write_text(json.dumps(raw, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
||||
PY
|
||||
}
|
||||
|
||||
install_plugin() {
|
||||
mkdir -p "${PLUGIN_TARGET_DIR}"
|
||||
cp "${PLUGIN_SRC_DIR}/index.ts" "${PLUGIN_TARGET_DIR}/index.ts"
|
||||
cp "${PLUGIN_SRC_DIR}/openclaw.plugin.json" "${PLUGIN_TARGET_DIR}/openclaw.plugin.json"
|
||||
}
|
||||
|
||||
install_skill() {
|
||||
local find_skill_src="${SKILL_SRC_DIR}/SKILL.md"
|
||||
local preference_skill_src="${SKILL_SRC_DIR}/SKILL.skillhub-preference.md"
|
||||
local installed=0
|
||||
|
||||
if [[ -f "${find_skill_src}" ]]; then
|
||||
mkdir -p "${FIND_SKILL_TARGET_DIR}"
|
||||
cp "${find_skill_src}" "${FIND_SKILL_TARGET_DIR}/SKILL.md"
|
||||
installed=1
|
||||
else
|
||||
echo "Warn: find-skills source not found at ${find_skill_src}; skipped." >&2
|
||||
fi
|
||||
|
||||
if [[ -f "${preference_skill_src}" ]]; then
|
||||
mkdir -p "${PREFERENCE_SKILL_TARGET_DIR}"
|
||||
cp "${preference_skill_src}" "${PREFERENCE_SKILL_TARGET_DIR}/SKILL.md"
|
||||
installed=1
|
||||
else
|
||||
echo "Warn: skillhub-preference source not found at ${preference_skill_src}; skipped." >&2
|
||||
fi
|
||||
|
||||
if [[ "${installed}" -ne 1 ]]; then
|
||||
echo "Warn: no skill templates installed." >&2
|
||||
fi
|
||||
}
|
||||
|
||||
configure_plugin() {
|
||||
local openclaw_bin
|
||||
if ! openclaw_bin="$(find_openclaw_bin)"; then
|
||||
echo "Warn: openclaw not found on PATH; skipped plugin config." >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
"${openclaw_bin}" config set plugins.entries.skillhub.enabled true
|
||||
"${openclaw_bin}" config set plugins.entries.skillhub.config.primaryCli 'skillhub'
|
||||
"${openclaw_bin}" config set plugins.entries.skillhub.config.fallbackCli 'clawhub'
|
||||
"${openclaw_bin}" config set plugins.entries.skillhub.config.primaryLabel 'cn-optimized'
|
||||
"${openclaw_bin}" config set plugins.entries.skillhub.config.fallbackLabel 'public-registry'
|
||||
}
|
||||
|
||||
disable_plugin_if_present() {
|
||||
local openclaw_bin
|
||||
if ! openclaw_bin="$(find_openclaw_bin)"; then
|
||||
echo "Warn: openclaw not found on PATH; skipped plugin disable." >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Remove the whole config entry to avoid OpenClaw warning:
|
||||
# "plugin disabled (not in allowlist) but config is present".
|
||||
if ! "${openclaw_bin}" config unset plugins.entries.skillhub >/dev/null 2>&1; then
|
||||
echo "Info: skillhub plugin config entry not found or already removed; skip disable."
|
||||
fi
|
||||
}
|
||||
|
||||
restart_gateway_if_needed() {
|
||||
if [[ "${RESTART_GATEWAY}" -ne 1 ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local openclaw_bin
|
||||
if ! openclaw_bin="$(find_openclaw_bin)"; then
|
||||
echo "Warn: openclaw not found on PATH; skipped gateway restart." >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
nohup "${openclaw_bin}" gateway run --bind loopback --port 18789 --force >/tmp/openclaw-gateway.log 2>&1 &
|
||||
}
|
||||
|
||||
if [[ "${MODE}" == "all" || "${MODE}" == "cli" ]]; then
|
||||
install_cli
|
||||
fi
|
||||
|
||||
if [[ "${SKILLS_PREF}" == "off" ]]; then
|
||||
set_workspace_skills_preference false
|
||||
elif [[ "${SKILLS_PREF}" == "on" ]]; then
|
||||
set_workspace_skills_preference true
|
||||
fi
|
||||
|
||||
if [[ "${MODE}" == "all" || "${MODE}" == "skill" ]]; then
|
||||
if [[ "${SKILLS_PREF}" != "off" ]]; then
|
||||
install_skill
|
||||
else
|
||||
echo "Info: skipped workspace skills installation by --no-skills."
|
||||
fi
|
||||
disable_plugin_if_present
|
||||
fi
|
||||
|
||||
if [[ "${MODE}" == "plugin" ]]; then
|
||||
install_plugin
|
||||
configure_plugin
|
||||
fi
|
||||
|
||||
restart_gateway_if_needed
|
||||
|
||||
echo "Install complete."
|
||||
echo " mode: ${MODE}"
|
||||
if [[ "${MODE}" == "all" || "${MODE}" == "cli" ]]; then
|
||||
echo " cli: ${WRAPPER_TARGET}"
|
||||
if [[ -f "${INDEX_TARGET}" ]]; then
|
||||
echo " index: ${INDEX_TARGET}"
|
||||
fi
|
||||
fi
|
||||
if [[ "${MODE}" == "all" || "${MODE}" == "skill" ]]; then
|
||||
if [[ "${SKILLS_PREF}" != "off" ]]; then
|
||||
echo " skill: ${FIND_SKILL_TARGET_DIR}/SKILL.md"
|
||||
echo " skill: ${PREFERENCE_SKILL_TARGET_DIR}/SKILL.md"
|
||||
else
|
||||
echo " skill: skipped (--no-skills)"
|
||||
fi
|
||||
fi
|
||||
if [[ "${MODE}" == "plugin" ]]; then
|
||||
echo " plugin: ${PLUGIN_TARGET_DIR}"
|
||||
fi
|
||||
echo
|
||||
echo "Quick check:"
|
||||
if [[ "${MODE}" == "all" || "${MODE}" == "cli" ]]; then
|
||||
echo " skillhub search calendar"
|
||||
fi
|
||||
if [[ "${MODE}" == "all" || "${MODE}" == "skill" ]]; then
|
||||
if [[ "${SKILLS_PREF}" != "off" ]]; then
|
||||
echo " test -f ${FIND_SKILL_TARGET_DIR}/SKILL.md && echo find-skills-installed"
|
||||
echo " test -f ${PREFERENCE_SKILL_TARGET_DIR}/SKILL.md && echo skillhub-preference-installed"
|
||||
else
|
||||
echo " skills install skipped by --no-skills"
|
||||
fi
|
||||
fi
|
||||
if [[ "${MODE}" == "plugin" ]]; then
|
||||
echo " If you use OpenClaw: openclaw plugins list | grep skillhub"
|
||||
fi
|
||||
Reference in New Issue
Block a user