# Open

> 用系统编辑器打开文件。无参数时打开上一次对话产生或修改的文件；带参数时打开指定文件。编辑器优先级：subl > atom > zed > geditor > ghostwriter > glow > micro > nano > pico > marktext > typora > nvim > vim。

- Skill: `orangeviolin/open` (Agent Skill)
- Install (CLI): `npx skillmds@latest add orangeviolin/open`
- Raw SKILL.md: https://api.skillmd.com/api/skills/orangeviolin/open/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: OrangeViolin (https://skillmd.com/u/orangeviolin)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/orangeviolin/open

---


# /open — 用编辑器打开文件

## 调用方式

| 调用 | 说明 |
|------|------|
| `/open` | 打开上一次对话中产生或修改的文件 |
| `/open <路径>` | 打开指定文件（支持相对路径、绝对路径、模糊描述） |

## 步骤 1 · 检测可用编辑器

优先读取缓存，缓存未命中时才遍历候选列表：

```bash
CACHE_FILE="$HOME/.cache/claude_open_editor"

if [ -f "$CACHE_FILE" ]; then
  EDITOR_CMD=$(cat "$CACHE_FILE")
else
  _detect_editor() {
    for candidate in subl atom zed geditor ghostwriter glow micro nano pico marktext typora nvim vim ; do
      [ -z "$candidate" ] && continue
      if command -v "$candidate" &>/dev/null; then
        echo "$candidate"; return
      fi
    done
    echo ""
  }
  EDITOR_CMD=$(_detect_editor)
  [ -n "$EDITOR_CMD" ] && mkdir -p "$HOME/.cache" && echo "$EDITOR_CMD" > "$CACHE_FILE"
fi
```

若没有找到任何可用编辑器，向用户报告并退出。

缓存刷新：若用户在参数中指定了编辑器（如 `use subl`），以指定值为准并更新缓存：

```bash
echo "$EDITOR_CMD" > "$CACHE_FILE"
```

## 步骤 2 · 确定要打开的文件

### 无参数模式

回顾**当前对话**中自己使用过的工具调用历史，找出最近一次通过 `Edit`、`Write`、`NotebookEdit` 工具操作的文件路径，即为目标文件。

- 只看当前对话，不看 git 状态
- 取最后一次操作的文件（时间上最近的那个）
- 若当前对话中没有编辑过任何文件，告知用户并退出

若找到多个候选（同一对话中编辑了多个文件），展示列表让用户选择，默认选最后一个并告知用户。

### 带参数模式

参数可以是：
- **明确路径**（绝对或相对）：直接使用
- **文件名片段**（如 `config`、`SKILL`）：在当前目录递归搜索
  ```bash
  find . -not -path '*/.git/*' -name "*${PARAM}*" -type f | head -10
  ```
- **模糊描述**（如 `grow phase 6 summary`、`上次改的 wiki 页面`）：按以下顺序搜索，任一命中则停止

  **1. 全局文件名匹配**：用 `find` 递归搜索当前 wiki repo
  ```bash
  FOUND=$(find . -not -path '*/.git/*' -type f -iname "*${PARAM}*" 2>/dev/null | head -20)
  ```

  **2. 多关键词组合**：若参数含空格/连字符，分词后逐词过滤
  ```bash
  if [ -z "$FOUND" ]; then
    WORDS=$(echo "$PARAM" | sed 's/[-_]/ /g')
    # 从全文件列表开始，逐词缩小范围
    CANDIDATES=$(find . -not -path '*/.git/*' -type f 2>/dev/null)
    for w in $WORDS; do
      [ ${#w} -le 2 ] && continue  # 忽略太短的词
      CANDIDATES=$(echo "$CANDIDATES" | grep -i "$w")
    done
    FOUND=$(echo "$CANDIDATES" | head -20)
  fi
  ```

  **3. 按修改时间排序**（最近修改优先）
  ```bash
  if [ -n "$FOUND" ]; then
    FOUND=$(echo "$FOUND" | xargs -r stat -c '%Y %n' 2>/dev/null | sort -rn | head -10 | cut -d' ' -f2-)
  fi
  ```

  **4. 兜底搜索 $MEMEX_ROOT**：当前 repo 未搜到时
  ```bash
  if [ -z "$FOUND" ] && [ -n "$MEMEX_ROOT" ]; then
    FOUND=$(find "$MEMEX_ROOT" -not -path '*/.git/*' -type f -iname "*${PARAM}*" 2>/dev/null | head -20)
  fi
  ```

  **5. 结果处理**：
  - 命中 1 个 → 直接打开
  - 命中多个 → 列出前 10 个，询问用户选择
  - 零结果 → 告知"未找到匹配文件"，建议更精确的关键词

## 步骤 3 · 打开文件

确定文件路径后，用检测到的编辑器打开：

```bash
"$EDITOR_CMD" "$FILE_PATH"
```

- 对于 GUI 编辑器（`cursor`、`code`、`gedit`）：后台启动，不等待进程退出
- 对于终端编辑器（`nvim`、`vim`、`nano`）：前台运行，等待用户退出

**判断是否为 GUI 编辑器：**

```bash
case "$EDITOR_CMD" in
  cursor|code|gedit|subl|atom)
    "$EDITOR_CMD" "$FILE_PATH" &
    echo "已用 $EDITOR_CMD 打开：$FILE_PATH"
    ;;
  *)
    "$EDITOR_CMD" "$FILE_PATH"
    ;;
esac
```

## 输出

向用户报告：
1. 使用的编辑器
2. 打开的文件路径
3. 若为无参数模式，说明是从哪个来源（暂存区 / 最近 commit / 文件系统）找到的

## 铁律

- **不修改任何文件**：只负责打开，不写入
- **不猜测内容**：若无法确定文件，向用户列出候选，让用户决定
- **不打开目录**：确保打开的是文件，不是目录

