Vandee's Blog

23 Jan 2026

My Agent Skill in OpenCode

TL;DR

虽然我不喜欢 vibe coding,但是 SKILL 是很值得学习的。

一个好的 SKILL 里可以学到工程师的经验、逻辑,以及精炼的 prompt。

Tool 是 LLM 的基础工具,agent 框架是操作系统,MCP 是 USB 接口,SKILL 是专家技能文档。

Agent Skills

简介

agentskills/agentskills 是前段时间 Linux Foundation Announces the Formation of the Agentic AI Foundation (AAIF) Claude 开源的。

在这之前 SKILL 就已经出现了。

Agent Skills are a simple, open format for giving agents new capabilities and expertise.

Skills are folders of instructions, scripts, and resources that agents can discover and use to perform better at specific tasks. Write once, use everywhere.

via: https://github.com/agentskills/agentskills

SKILL 是一个本地文件夹,里面是 SKILL.md、scripts、references、templates,提供 agent 一个专业领域的专业技能。

这样说,听起来还是有点抽象。我也不想展开说明 SKILL 的概念,自己上手是理解它最好的方式。

用 C 极简复现 Claude Skills 里是我之前用 C 实现的简化版的 SKILL 逻辑。

这两个网站里有很多 SKILL 可以探索学习:https://skillsmp.com/https://skills.sh/

SKILL 解决了什么问题

MCP 的工具信息会占用大量的 context 窗口,SKILL 很好的避免了这个问题。

SKILL.md YAML 部分的 description 是对这个 SKILL 的介绍。当 agent 运行的时候,只会预加载这部分内容,当 agent 判断需要使用到的时候,才会加载完整的 SKILL.md

如果说 MCP 是通用工具,那么 SKILL 就是可以高度自定义的 local tool。

编写 SKILL 是在干什么

当遇到一种类型的问题时,把处理它们的方式规范性的固定下来,它就是一个 SKILL 了。

能够把这个问题以及解决问题的办法完整的抽象成一个 SKILL,也变相的说明了自己已经掌握了一种处理问题的方法。

所以,我虽然不喜欢 vibe coding,但是很喜欢看 SKILL。

一个好的 SKILL 里,可以看到优秀工程师对问题处理、抽象的能力。更不用说里面涵盖了 prompt 提示词工程发展到现在的经验和技巧,这么好的学习资源,在以往是付费都很难看到的。

大厂放出来的官方 SKILL 那都是门面啊,还是有很多干货的。

My Agent Conf

下面的每个标题就是我觉得在和 agent 合作的时候比较值得关注的地方,也是我现阶段理解到的一些实践原则。

从 Claude Code 转到 OpenCode,感觉一切良好。

我不是程序员,也不需要高质量的代码。我更喜欢 OpenCode 的一些设计理念,Claude Code 限制太多,也公开表示不让我们用,那就不用好了。

在 OpenCode 里 vibe 一些小玩意还是很够用的。

我虽然不喜欢 vibe,但是需要实现一些原型假设的时候,vibe 还是极好的。

再一个,不了解 vibe 又怎么能说自己不喜欢呢?

Core Rules

Just files and loops!

Provide specific Best Practices, Pros & Cons, Red Flags

Keep it simple!

Maintain a hierarchical codebase map

Your best engineers don’t grep randomly. They have a mental map:

  • What each folder owns
  • What breaks if you touch it wrong
  • Where the real logic lives

via: https://www.railly.dev/blog/intent-layer/

SKILL: intent-layer https://github.com/crafter-station/skills

如果每次新的 session 都让 agent 探索一次项目代码,又不方便,又浪费时间。

给项目代码提供一个持续更新的 codebase map 还是很必要的。

这让 agent 在每次对话的时候在 context 里包含项目的基本信息和架构。

also: https://github.com/affaan-m/everything-claude-code/blob/main/commands/update-codemaps.md

Prepared with clear purpose

SKILL: Onboard https://github.com/ChrisWiles/claude-code-showcase/blob/main/.claude/commands/onboard.md

在开始具体的任务之前,给予 agent 明确的目标以及要涉及到的具体文件。

明确清晰的描述自己的需求非常重要。DO and DONOT.

对于大部分模型,英文 prompt 效果比中文好。

Just files and loops, no more complicated

SKILL: Planning with Files https://github.com/OthmanAdi/planning-with-files

在 agent 执行具体任务的时候,planning with files 这个框架的设计很值得学习。

它用三个文件记录和规划 agent 的 task plan,非常简洁,效果拔群。

结合我在 opencode 里的使用,我加上了 memory 部分:

1. Use the `session-info` tool to retrieve the current conversation's [session-title]
2. Run `date +%Y%m%d-%H%M%S` command to get the [YYYYMMDD-HHMMSS timestamp]
   Create the `session folder`: `mkdir -p $HOME/.MemoryMD/$(basename $(git rev-parse --show-toplevel))/[YYYYMMDD-HHMMSS timestamp]-[session-title]`
3. All generated markdown files should be created in that `session folder`.

没有选择在项目根目录下创建是为了多个 session 和 git-worktree 并行场景下,方便共享。

session-info 是一个很简单的 tool,在 OpenCode 里用来获取当前 session 信息,生成上面提到的文件夹:

tools/session-info.ts :

import { tool } from "@opencode-ai/plugin"
import { execSync } from "child_process"
import { homedir } from "os"

export default tool({
  description: "Get current session information including title",
  args: {},
  async execute(args, context) {
    const { sessionID, agent } = context

    const sessionDir = `${homedir()}/.local/share/opencode/storage/session`

    try {
      const result = execSync(`find ${sessionDir} -name "${sessionID}.json" 2>/dev/null | head -1`, { encoding: "utf-8" })

      if (!result.trim()) {
        throw new Error("Session file not found")
      }

      const sessionFile = result.trim()
      const sessionData = JSON.parse(require("fs").readFileSync(sessionFile, "utf-8"))

      return JSON.stringify({
        sessionID,
        agent,
        title: sessionData.title || null,
        directory: sessionData.directory || null,
        time: sessionData.time || null,
      }, null, 2)
    } catch (error) {
      return JSON.stringify({ error: error.message, sessionID, agent }, null, 2)
    }
  },
})

Handoff when stucked

SKILL: handoff https://github.com/mitsuhiko/agent-stuff/blob/main/commands/handoff.md

有时候 agent 会卡住,陷入死循环,果断 handoff 重开,不用浪费时间。

Maintain memory

我把 planning-with-files 的文档和 Handoff 的文档当作项目的 memory,设计了一个简单的 SKILL 来根据关键字搜索:

现在有许多针对 agent 的 memory 项目,但是我感觉这个概念本身也才刚出来,今年应该有更成熟的实现。

暂时就用这个简单方案过渡一下。

---
name: memory-md
description: Memory management system for storing and retrieving conversation history and context.When user ask anything about project's memory, automatically use this skill.
---

Memory management system for storing and retrieving conversation history and context.


## Parse guide

Parse [quest] as follows:

1. **List command**: If [quest] starts with `-l` or `--list`
   - List recent memory files

2. **Search command**: If [quest] starts with `-s` or `--search`
   - All remaining arguments are search keywords (comma-separated or space-separated)
   - Example: `-s apple,banana` or `-s apple banana` → keywords: ["apple", "banana"]

3. **Default search**: If no flags provided, treat entire [quest] as search keywords
   - Example: `authentication jwt` → keywords: ["authentication", "jwt"]

4. **No results**: If no keywords provided in [quest] after parsing
   - Ask user: "What keywords are you searching for?"

## Memory File Location

Memory files are stored in `$HOME/.MemoryMD/` with the following structure:

```
$HOME/.MemoryMD/
├── [project-name]/                     # Project folders
│   ├── YYYYMMDD-HHMMSS-[session-title]/  # Session folders
│   │   ├── task_plan.md                # Task planning document
│   │   ├── findings.md                 # Research findings
│   │   └── progress.md                 # Progress tracking
└── handoffs/                           # Handoff summaries
    └── YYYYMMDD-HHMMSS-[slug].md      # Session handoff files
```

Examples:
- `agent-conf/20250120-143025-implement-auth/` - Session folder
- `handoffs/20250120-143025-fix-issue-42.md` - Handoff file

## Commands

### --list or -l

List the 20 most recent memory folders/files, sorted by timestamp (newest first).

**Bash command:**
```bash
memory_dir="$HOME/.MemoryMD"

# List session folders grouped by project (sorted newest first)
find "$memory_dir" -maxdepth 2 -type d -name "????????-??????-*" | sort -r | head -20 | awk -F/ '{
    project = $(NF-1)
    foldername = $NF
    timestamp = substr(foldername, 1, 15)
    title = substr(foldername, 17)
    if (project != prev_project) {
        if (prev_project != "") print ""
        print "**" project "**"
        prev_project = project
    }
    print "  [" timestamp "] " title
}'

# List handoff files (sorted newest first)
echo ""
echo "Recent handoffs:"
find "$memory_dir/handoffs" -maxdepth 1 -type f -name "*.md" | sort -r | head -20 | while read file; do
    filename=$(basename "$file")
    title=${filename#*-}
    title=${title%.md}
    echo "$title - $filename"
done
```

**Output format:**
```
**agent-conf:**
  [20250120-143025] implement-auth
  [20250119-091530] fix-issue-42

**another-project:**
  [20250118-1530] api-handler

Recent handoffs:
  fix-issue-42 - 20250120-143025-fix-issue-42.md
  implement-auth - 20250119-091530-implement-auth.md
```

### --search or -s

Search memory files for keywords in both Chinese and English.

Use your Glob and Grep tools first.

First perform exact keyword search. If no results found, search for related similar keywords.

If still no results after all searches, ask user: "What keywords are you searching for?"

**Output Examples:**

```md
Search query: [keywords]

## Found in: agent-conf/20250120-143025-implement-auth/task_plan.md
[summary of your findings]

## Found in: agent-conf/20250120-143025-implement-auth/findings.md
[summary of your findings]
```

Bash commands below serve as auxiliary reference:

**Bash command:**
```bash
memory_dir="$HOME/.MemoryMD"

# Search for keywords in all markdown files
rg -i -t md "$keywords" "$memory_dir" --follow

# Alternative: Search with context (2 lines before and after matches)
rg -i -C 2 -t md "$keywords" "$memory_dir" --follow
```

**Options:**
- `-i`: Case-insensitive search
- `-C N`: Show N lines of context before and after matches
- `-t md`: Search only markdown files
- `--follow`: Follow symbolic links

Maintain useful patterns

SKILL: https://github.com/affaan-m/everything-claude-code/blob/main/commands/learn.md

在解决实际的代码问题的时候,有许多方案是可以固定下来复用的。

根据这个 SKILL,我设计了一个 learned skill。这个 SKILL 实际上是一个索引,在 description 部分加上 learned 的描述信息。

learn skill 会根据当前会话的 session 固定下来有价值的 pattern,生成 skill,自动添加到 learned skill 的 description 部分,这样 agent 在加载的时候就可以知道有哪些 learned skill 了。

不选择把 learned skill 生成单独的 skill 文件夹是因为它们的普遍性不强,也经常要更新和修改,不能完全当作 SKILL 来设计。

Learn skill:

---
name: learn
description: >
  Extract reusable patterns from sessions and create dynamic skills. Use when you need to save learned patterns, error resolutions, debugging techniques, or project-specific knowledge to ~/.config/opencode/skill/learned/.
  Trigger, User asks to extract learning, save patterns, or run /learn command.
  All learned skills in `~/.config/opencode/skill/learned/` are automatically discoverable
  `~/.config/opencode/skill/learned/SKILL.md` is the index off all learned skills
---

# Learn Skill

Dynamically extract and store reusable patterns as skills.

## Quick Start

When user wants to extract learning from current session:

1. Review session context for extractable patterns
2. Identify the most valuable/reusable insight,list them
3. Ask user for confirmation before creating skill file
4. Create `~/.config/opencode/skill/learned/[skill-name].md` - Use [templates/learned-skill-template.md](templates/learned-skill-template.md) as reference
5. Update `~/.config/opencode/skill/learned/SKILL.md` to include the new skill - Use  [templates/SKILL.md](templates/SKILL.md) as reference
6. Run `ls -1 ~/.config/opencode/skill/learned/*.md 2>/dev/null | grep -v SKILL.md | wc -l`, update the total skills number.

## What to Extract

### 1. Error Resolution Patterns
- What error occurred?
- What was the root cause?
- What fixed it?
- Is this reusable for similar errors?

### 2. Debugging Techniques
- Non-obvious debugging steps
- Tool combinations that worked
- Diagnostic patterns

### 3. Workarounds
- Library quirks
- API limitations
- Version-specific fixes

### 4. Project-Specific Patterns
- Codebase conventions discovered
- Architecture decisions made
- Integration patterns

## Quality Guidelines

### DO Extract:
- Error patterns that occur more than once
- Non-obvious debugging techniques
- Workarounds for library quirks
- Architecture decisions and their rationale
- Integration patterns across services/tools

### DO NOT Extract:
- Trivial fixes (typos, simple syntax errors)
- One-time issues (specific API outages, temporary glitches)
- Obvious solutions (standard library usage without special context)
- Information already well-documented elsewhere

### Tips for Quality Skills
1. **Be Specific**: Narrow trigger conditions = better matching
2. **Include Examples**: Code snippets make patterns actionable
3. **Document Why**: Explain the problem, not just the solution
4. **Keep Focused**: One pattern per skill
5. **Use Descriptive Names**: Names should indicate what the skill solves


## Skill File Format

### Individual Skill Files

Use the template file [templates/learned-skill-template.md](templates/learned-skill-template.md) as the base for all learned skills.

Key sections:
- **Frontmatter**: name and description (critical for skill discovery)
- **Problem**: What specific issue this solves
- **Solution**: Actionable steps to implement
- **Example**: Code snippet if applicable
- **When to Use**: Trigger conditions for activation
- **Related Patterns**: Cross-references to other skills

### SKILL.md

Use the template file [templates/SKILL.md](templates/SKILL.md) as the base for maintaining the learned skills index.

Purpose:
- Provides a categorized listing of all learned skills
- Enables easy browsing and discovery of patterns
- Tracks skill count and update timestamp

Update SKILL.md whenever saving a new skill.

## Extraction Process

### Step 1: Review Session Context

Use `session-info` tool to get session details if needed.

Use `memory-md` skill to find relevant memories.

Look for:
- Repeated error fixes
- Non-obvious solutions
- Workarounds discovered
- Best practices learned

### Step 2: Identify Pattern

Ask yourself:
- Is this reusable? (Will save time in future sessions)
- Is this non-trivial? (Not typos or simple syntax errors)
- Is this generalizable? (Not one-time issues)

Prioritize patterns that:
- Solve common problems
- Apply across multiple projects
- Document non-obvious solutions

### Step 3: Draft Skill

Use the skill file format above.

**Naming Convention:**
- Use kebab-case for skill names
- Make names descriptive but concise
- Example: `async-error-handling-pattern`, `docker-volume-permission-fix`

**Frontmatter:**
```yaml
---
name: [skill-name]
description: Use when [trigger conditions]. Covers [specific problem/solution].
---
```

The description is critical - it's what helps the skill system know when to load this skill.

### Step 4: Validate

Before presenting to user:
- Check that the skill has clear trigger conditions
- Ensure the solution is actionable
- Verify code examples are correct
- Confirm the pattern is truly reusable

### Step 5: Present and Save

Show the user:
1. Pattern name
2. Brief description of what was extracted
3. Why it's valuable

Ask: "Save this pattern to learned skills? (y/n)"

If yes, save to `~/.config/opencode/skill/learned/[skill-name].md`

### Step 6: Update `learned/SKILL.md`

1. Update the description of the new learned skill.Append this part: [name of learned skill 1] - [description of learned skill 1]

example YAML of `learned/SKILL.md`:

```md
---
name: learned
description: >
  learned skill is a collection of learned skill user create.It's a index of all learned skills.
  We have these learned skill below:
  [name of learned skill 1] - [description of learned skill 1]
  [name of learned skill 1] - [description of learned skill 2]
---
```

2. Update the new skill to the index section.

## Common Use Cases

### User runs /learn command
```
User: /learn
```
1. Review session for extractable patterns
2. Present candidate patterns to user
3. Ask which to save
4. Save selected patterns

### User asks to extract specific topic
```
User: Extract what we learned about async error handling
```
1. Search session context for async/error patterns
2. Compile findings
3. Generate skill file
4. Present and save

### User wants to capture architecture decision
```
User: Save the event sourcing pattern we used
```
1. Extract the pattern details
2. Document rationale and trade-offs
3. Create skill with example code
4. Present and save

## Integration with Other Skills

This skill works well with:
- **memory-md**: For accessing related patterns from past sessions
- **skill-creator**: For creating more complex, bundled skills

Learnd skill:

---
name: learned
description: >
  learned skill is a collection of learned skill user create.It's a index of all learned skills.
  We have these learned skill below:
  [name of learned skill 1] - [description of learned skill 1]
  [name of learned skill 1] - [description of learned skill 2]
---

# Learned Skills Index

You can read the skill file to load the skill you need.

Treat these skill file below as `learned skill`'s references.

## Error Patterns
- [skill-1.md](skill-1.md)
- [skill-2.md](skill-2.md)

## Debugging Techniques
- [skill-3.md](skill-3.md)

## Workarounds
- [skill-4.md](skill-4.md)

## Project-Specific
- [skill-5.md](skill-5.md)

# Statistics
Total skills: [count]
Last updated: [date]

Maintain code quality and style

SKILL: code-simplifier: https://github.com/anthropics/claude-plugins-official/blob/main/plugins/code-simplifier/agents/code-simplifier.md

LLM 在编写代码的时候,特别是大量代码,复杂代码的时候,很容易犯病,编写重复性的代码,这是因为上下文多了,准确性下降。

在每次 agent 写完代码之后进行代码审查和代码优化。

在 prompt 上,亲测加上:这是别人的代码,效果会更好🤣。LLM 拍马屁的概率大幅下降。

Tags: Coding