---
name: skill-installer
description: 从 GitHub 仓库、子树链接或本地目录安装、更新、卸载 Akashic 技能（SKILL.md），无需编写插件即可热生效。当用户要求"安装这个 skill"、"给我装个技能"、"从 GitHub 安装技能"、"卸载某个 skill"、"怎么安装 skill"时使用。触发词：安装技能, 安装 skill, install skill, 装个 skill, 更新 skill, 删除 skill, 卸载 skill, skill 目录。
metadata: {"akashic": {"always": false, "requires": {"bins": ["git"]}}}
---

# 安装、更新与卸载 Akashic 技能（Skill）

Akashic 的 `skills` 插件按四层来源热扫描技能，**普通技能不需要编写或安装插件**，把含 `SKILL.md` 的目录放入本地技能目录即可立即被 `load_skill` 热读取。

## 1. 四层来源与优先级（高 → 低）

| 优先级 | 来源 (`source`) | 目录路径 | 适用场景 |
| --- | --- | --- | --- |
| 1（最高） | `workspace` | `$AKASHIC_WORKSPACE/skills/<skill-name>/SKILL.md` | **默认安装位置**。随工作区持久化，容器/服务重启后不丢失 |
| 2 | `user` | `~/.akashic/skills/<skill-name>/SKILL.md` | 宿主用户级共享技能（注意容器部署时需确认 `HOME` 是否挂载） |
| 3 | `builtin` | `<Core 根>/skills/<skill-name>/SKILL.md` | 随 Akashic Core 仓库发布的内置通用技能 |
| 4（最低） | `plugin` | 插件 `INSTALLED_ASSETS.register` 声明的 `skills/` | 与特定插件工具强绑定的随包技能（需走 `plugin-system` 安装） |

- **同名覆盖**：高层同名技能静默覆盖低层；目录名 `<skill-name>` 即技能的唯一标识（对应 `load_skill(skill="<skill-name>")`）。
- **热加载机制**：`SkillCatalogParser` 按目录项与 `SKILL.md` 的 `(mtime, size)` 自动失效缓存。复制或修改文件后，**无需重启服务或重装插件**，当轮即可直接调用 `load_skill(skill="<skill-name>")` 验证。

## 2. 确定工作区技能目录

优先使用环境变量 `$AKASHIC_WORKSPACE/skills`；若当前 Shell 未注入该变量，从提示词的「工作区 → 根目录」或运行进程参数 `--workspace` 取得准确路径并设置变量。无法确定时先询问，不猜测其他实例的目录：

```sh
: "${AKASHIC_WORKSPACE:?请先确认当前工作区并设置 AKASHIC_WORKSPACE}"
SKILL_ROOT="$AKASHIC_WORKSPACE/skills"
mkdir -p "$SKILL_ROOT"
```

## 3. 从 GitHub 仓库或本地路径安装

外部技能仓库通常有两种目录形态（兼容 Claude Code / Codex / OpenClaw 等常见 SKILL.md 仓库）：
- **单技能仓库**：仓库根目录下直接是 `SKILL.md`
- **多技能集合仓库**：`skills/<skill-name>/SKILL.md` 或 `<skill-name>/SKILL.md`（例如 `https://github.com/<owner>/<repo>/tree/<branch>/skills/<skill-name>`）

### 标准安装步骤

1. **克隆到隔离临时目录**（不要直接 clone 到 `skills/` 根目录，避免残留 `.git` 或嵌套层级错误）：
   ```sh
   TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/akashic-skill.XXXXXX")"
   git clone --depth 1 https://github.com/<owner>/<repo>.git "$TMP_DIR/repo"
   ```
2. **定位 `SKILL.md` 所在的技能目录并检查内容**：
   - 找到目标 `<skill-dir>/SKILL.md`，确认 frontmatter 至少包含 `name` 和 `description`。
   - 若外部 `SKILL.md` 带有 `metadata` 字段，注意 Akashic 解析规则：当 `metadata` 为字符串时必须能被 `json.loads` 解析为 JSON 对象（或直接写成 YAML 映射对象）；若原文件使用了非 JSON 的自由文本 `metadata`，安装后需用 `edit_file` 修正或移除该字段，否则解析会报错。
   - 检查 `metadata.akashic.requires`（或 `metadata.requires`）中的 `bins` / `env` 在本机是否满足。
3. **先准备完整副本，再替换目标目录**。核对 `<skill-name>` 是单个目录名，且目标在当前 `SKILL_ROOT` 内。先在同一文件系统、扫描目录外复制；复制失败时旧技能保持原样：
   ```sh
   RECOVERY_DIR="$(mktemp -d "$AKASHIC_WORKSPACE/.skill-install.XXXXXX")"
   cp -R "$TMP_DIR/repo/skills/<skill-name>" "$RECOVERY_DIR/new" &&
     test -s "$RECOVERY_DIR/new/SKILL.md"
   ```
   仅在上述命令成功后继续。检查新副本内的 `.git`、链接与资源路径；不要把仓库元数据或指向临时目录的链接带入安装目录。目标已存在时，将整个旧目录移到 `$RECOVERY_DIR/previous`，保留用户改动和资源；再把 `$RECOVERY_DIR/new` 移到 `$SKILL_ROOT/<skill-name>`。发布失败就把 `previous` 移回原处。备份不能放在 `skills/` 内，否则会被当成第二个技能扫描。
4. **调用 `load_skill` 验证后再清理本次临时 clone**。验证失败时保留失败副本并恢复 `previous`，重新加载确认旧技能可用。向用户报告恢复点；不自动删除旧技能副本。启用 `shell_restore` 时按其实际移动行为核对清理结果，只处理本次创建的临时目录。

## 4. 立即验证（必做）

文件落盘后，**必须在当轮直接调用 `load_skill` 工具**核对：

```json
{"skill": "<skill-name>"}
```

- 返回 `status="success"` 且包含 `base_directory` 与 `instructions` 正文 → 安装成功且当前可用。
- 返回 `技能不可用：...；缺少依赖：CLI: xxx / ENV: xxx` → 如实告知用户缺少哪个二进制或环境变量，或按授权安装依赖后再验。
- 返回 `技能不存在` → 检查目录层级是否为 `$SKILL_ROOT/<skill-name>/SKILL.md`（不能多套一层父目录）。

## 5. 更新与卸载

- **更新**：按上述准备、替换和恢复流程操作，保留原目录中的用户改动供核对，再调用 `load_skill(skill="<skill-name>")` 核对新正文。
- **卸载**：用户明确要求卸载后，将准确的目标目录移到 `skills/` 外的恢复点并核对扫描结果；若 `builtin` 或 `plugin` 层存在同名技能，会回退到低层版本。永久删除恢复点需要单独确认。
