4 Commits

Author SHA1 Message Date
dffa3fae12 feat: 重构工作流体系,将命令模式迁移为技能文档 2026-01-21 15:55:57 +08:00
43e138b19e feat: 新增对话总结命令与浏览器自动化技能
- 本地化命令描述(英文→中文)

- 删除未使用命令文件

- 新增 summarize-conversation 命令

- 更新 AI 模型配置为 DeepSeek

- 新增 agent-browser 技能

- 重构技能目录结构(重命名)
2026-01-15 17:30:39 +08:00
75462f3412 refactor: 删除冗余文档并简化README 2026-01-15 09:38:40 +08:00
5d9efea7ab refactor: 更新配置并删除通知插件 2026-01-15 09:36:05 +08:00
39 changed files with 2154 additions and 2509 deletions

View File

@@ -1,30 +1,14 @@
# OpenCode # OpenCode
## 📊 项目统计
- **15 个 CLI 命令** - 涵盖 Git 和 Gitea 操作
- **7 个开发领域技能库** - Android、iOS、Go、Electron、MQTT 等
- **4 套 CI/CD 工作流模板** - 适配多种项目类型
## 🌟 核心特性
- **智能命令系统** - 自动生成提交信息、管理版本标签、安全地暂存文件
- **可复用技能** - 预定义的开发工作流,如 Git 工作流、Android 开发等
- **安全优先** - 自动过滤敏感文件,防止意外泄露凭证
- **中文友好** - 完整的中文支持和交互提示
## 目录 ## 目录
``` ```
opencode/ opencode/
├── command/ # CLI 命令定义 ├── command/ # CLI 命令定义
│ ├── git-add.md # 智能暂存文件(自动过滤敏感文件)
│ ├── git-commit.md # 自动生成提交信息并提交 │ ├── git-commit.md # 自动生成提交信息并提交
│ ├── git-pull.md # 拉取远程最新变更 │ ├── git-pull.md # 拉取远程最新变更
│ ├── git-push.md # 提交+创建标签+推送(一键完成) │ ├── git-push.md # 提交+创建标签+推送(一键完成)
│ ├── git-push-tags.md # 推送所有标签到远程 │ ├── git-push-tags.md # 推送所有标签到远程
│ ├── git-status.md # 查看仓库状态
│ ├── gitea-config.md # 查看 Gitea 配置和 Runner 状态 │ ├── gitea-config.md # 查看 Gitea 配置和 Runner 状态
│ ├── gitea-create-repo.md # 在 Gitea 创建新仓库 │ ├── gitea-create-repo.md # 在 Gitea 创建新仓库
│ ├── gitea-create-runner.md # 创建并启动 Gitea Actions Runner │ ├── gitea-create-runner.md # 创建并启动 Gitea Actions Runner
@@ -73,13 +57,8 @@ opencode/
│ ├── mqtts-quick-reference.md # 快速参考 │ ├── mqtts-quick-reference.md # 快速参考
│ └── USAGE_EXAMPLES.md # 使用示例 │ └── USAGE_EXAMPLES.md # 使用示例
├── plugin/ # 插件扩展系统
│ └── notification.ts # 通知插件邮件、Slack、钉钉等
├── README.md # 项目说明文档(当前文件) ├── README.md # 项目说明文档(当前文件)
├── AGENTS.md # 全局开发规范和指南 ├── AGENTS.md # 全局开发规范和指南
├── opencode.json # 项目配置文件 ├── opencode.json # 项目配置文件
├── package.json # Node.js 依赖配置
└── .gitignore # Git 忽略文件配置 └── .gitignore # Git 忽略文件配置
``` ```

View File

@@ -1,71 +0,0 @@
---
description: Stage changes with automatic filtering of sensitive files
---
Intelligently stage changes while automatically filtering security-sensitive files.
Please perform the following:
1. **Detect all unstaged changes:**
- Modified files (M)
- Deleted files (D)
- Untracked files (??) - **重要:第一次就显示并提供选项**
2. **Filter sensitive files** - Automatically exclude:
- `.env*` - Environment files
- `*.key`, `*.pem`, `*.p8` - Private keys
- `.aws/*`, `.gcloud/*`, `.ssh/*` - Cloud/SSH credentials
- `credentials.json`, `secrets.json` - Credential files
- `node_modules/`, `vendor/`, `.venv/` - Dependencies
- `dist/`, `build/`, `.next/` - Build artifacts
- `.DS_Store`, `Thumbs.db` - System files
3. **Categorize files:**
- **已跟踪的修改/删除** (tracked modified/deleted)
- **未跟踪的安全文件** (untracked safe files)
- **敏感文件** (sensitive files - filtered)
4. **Display preview in Chinese:**
```
=== 将要暂存的文件 (N) ===
M [tracked modified files]
D [tracked deleted files]
=== 未跟踪的文件 (N) ===
?? [untracked safe files]
=== 敏感文件已过滤 (N) ===
⚠ [sensitive files with reasons]
=== 操作选项 ===
- 输入 "y" 或 "yes" 暂存已修改/已删除的文件(不包括未跟踪文件)
- 输入 "all" 或 "u" 暂存所有安全文件(包括未跟踪文件)✓ 推荐
- 输入 "force" 强制暂存所有文件(包括敏感文件)⚠️ 谨慎使用
- 输入 "no" 或 "cancel" 取消操作
- 输入文件路径 暂存特定文件
```
5. **Wait for user confirmation**
6. **Execute staging based on user choice:**
- `y/yes`: Stage tracked modified/deleted only
- `all/u`: Stage all safe files (including untracked)
- `force`: Show warning, require "confirm" input, then stage everything
- `no/cancel`: Abort
- File path: Stage specific file(s)
7. **Display result in Chinese:**
```
✓ 暂存成功
已暂存 N 个文件:
[列出已暂存的文件]
敏感文件已过滤并排除,保护了你的凭证信息。
下一步:
- 运行 /git-commit 生成提交信息并提交
- 运行 /git-status 查看暂存区状态
```
**重要:第一次运行就显示所有选项,包括未跟踪文件的处理方式,不需要用户多次运行命令。**

View File

@@ -1,52 +0,0 @@
---
description: Commit staged files with auto-generated message and create version tag
---
Auto-generate a commit message for staged files, commit to the local repository, and create a version tag following semantic versioning.
Please follow the git workflow defined in `@skill/git/SKILL.md`:
1. **Check staging area** - Verify files are staged with `git diff --cached --name-only`
- If empty, inform the user and stop
2. **Collect information** - Run these commands in parallel:
- `git status`
- `git diff --cached`
- `git log --oneline -10`
- `git tag --list | sort -V | tail -5`
- Read `@AGENTS.md` if it exists (repository type, version rules, project structure)
3. **Detect repository type** - Polyrepo (tag: `1.2.0`) or Monorepo (tag: `subproject-1.2.0`)
4. **Detect project type and version** - Check for version files:
- iOS: `*.xcodeproj/project.pbxproj``MARKETING_VERSION`
- Node.js: `package.json``version`
- Android: `build.gradle(.kts)``versionName`
- Go: Git tag only
5. **Generate commit message** following Conventional Commits:
- Format: `<type>(<scope>): <subject>`
- Use Chinese for commit messages (macOS/Linux)
- Types: feat, fix, docs, style, refactor, perf, test, chore, ci, build
- For monorepo, use subproject as scope if changes affect single subproject
6. **Update version number** if needed:
- feat: minor +1 (1.2.0 → 1.3.0)
- fix/perf: patch +1 (1.2.3 → 1.2.4)
- Breaking change: major +1 (1.2.3 → 2.0.0)
- Only for user-perceivable changes (feat, fix, perf, breaking)
- Add updated version file to staging
7. **Commit changes** with generated message
8. **Create version tag** if version was updated (unless user specified "skip tag"):
- Polyrepo: `git tag -a "1.2.0" -m "commit message"`
- Monorepo: `git tag -a "subproject-1.2.0" -m "commit message"`
**Options:**
- User can input "skip tag" or "skip" to skip tag creation
**Display result in Chinese:**
```
✓ 提交成功
提交信息:[commit message]
版本标签:[tag] (如果创建了)
要推送到远程仓库,请运行:/git-push
```
**Important:** This command does NOT push to remote. Use `/git-push` to push commits and tags.

View File

@@ -1,23 +0,0 @@
---
description: Pull latest changes from remote repository
---
Pull the latest changes from the remote repository for the current branch.
Please perform the following tasks:
1. **Run `git pull`** to fetch and merge remote changes
2. **Handle merge conflicts if they occur:**
- Check conflict files with `git status`
- Guide me through conflict resolution
- Help stage resolved files with `git add <file>`
- Complete the merge with `git commit`
3. **Show the result** with branch status and changes summary
If there are any errors or conflicts, explain them clearly in Chinese and provide step-by-step guidance for resolution.
Present the final result showing:
- Branch name
- Number of commits pulled
- Files changed
- Any conflicts that need attention

View File

@@ -1,55 +0,0 @@
---
description: Push all local tags to remote repository
---
Push all local tags to the remote repository.
Please perform the following:
1. **List local tags:**
```bash
git tag --list | sort -V
```
2. **Check remote tags:**
```bash
git ls-remote --tags origin
```
3. **Identify unpushed tags** - Compare local and remote to find tags that need to be pushed
4. **Display summary in Chinese:**
```
本地标签总数N 个
远程标签总数M 个
待推送标签K 个
- [list of unpushed tags]
确认推送所有标签到 origin
```
5. **Wait for user confirmation** (or proceed if no confirmation needed)
6. **Push all tags:**
```bash
git push --tags
```
7. **Verify and display result in Chinese:**
```
✓ 已成功推送所有标签到 origin
最近 5 个远程标签:
- [list of recent tags]
```
**Use cases:**
- After creating multiple local tags
- Sync tags with remote repository
- Before triggering CI/CD release workflows
- Share version tags with team
**Notes:**
- Pushes ALL local tags, not just one
- To push a specific tag: `git push origin <tag-name>`
- Safe operation: won't overwrite existing tags (no force push)

View File

@@ -1,55 +0,0 @@
---
description: Commit staged files, create version tag, and push to remote repository
---
Complete workflow: auto-generate commit message, create version tag, commit, and push everything to remote repository.
This is the **all-in-one command** that combines `/git-commit` + push operations.
Please perform the following:
1-7. **Follow the same steps as `/git-commit`:**
- Check staging area (must not be empty)
- Analyze changes and repository type
- Detect project type and version
- Generate commit message (Conventional Commits, Chinese)
- Update version number if needed
- Commit changes
- Create version tag
Refer to `/git-commit` for detailed steps or `@skill/git/SKILL.md` for complete workflow.
8. **Push commit to remote:**
```bash
git push origin $(git branch --show-current)
```
9. **Push tag to remote** (only if tag was created):
- Polyrepo: `git push origin <version>`
- Monorepo: `git push origin <subproject>-<version>`
10. **Display result in Chinese:**
```
✓ 提交并推送成功
分支:[branch]
提交信息:[commit message]
版本标签:[tag] (如果创建了)
已推送到远程仓库origin
- 提交:[commit hash]
- 标签:[tag]
```
**Error handling:**
- If staging area is empty: "暂存区为空,请先使用 `git add` 添加文件。"
- If push fails (e.g., need to pull first): Show error in Chinese with suggested solutions
- If remote rejects tag (already exists): Show error and suggest deleting local tag or updating version
**Options:**
- User can input "skip tag" or "skip" to skip tag creation
**When to use:**
- `/git-commit`: Local only, review before pushing
- `/git-push`: Commit and push immediately
- `/git-push-tags`: Push tags only (no commits)

View File

@@ -1,29 +0,0 @@
---
description: Check git working directory status and file changes
---
Check the current git repository status and display file changes in a clear, organized format.
Please perform the following tasks:
1. **Run `git status`** to show the current state of the working tree
2. **Display current branch** using `git branch --show-current`
3. **List unstaged changes** with `git diff --name-only`
4. **List staged changes** with `git diff --cached --name-only`
Present the information in Chinese with the following structure:
```
当前分支: [branch_name]
暂存区文件 ([count]):
[列出已暂存的文件]
未暂存的修改 ([count]):
[列出未暂存的修改文件]
未跟踪的文件 ([count]):
[列出未跟踪的文件]
```
Use clear formatting and emoji indicators (✓, ⚠️, etc.) to make the output easy to read.

View File

@@ -1,72 +0,0 @@
---
description: View current Gitea configuration and runner status
---
Display the current Gitea configuration and runner status.
## 工作目录
**macOS / Linux:**
```
~/.config/gitea/
```
**Windows:**
```
%USERPROFILE%\.config\gitea\
```
Please perform the following:
1. **Check if configuration exists:**
- Config file:
- macOS/Linux: `~/.config/gitea/config.env`
- Windows: `%USERPROFILE%\.config\gitea\config.env`
- If not exists, prompt user to run `/gitea-reset`
2. **Load and display configuration:**
**macOS / Linux:**
```bash
source ~/.config/gitea/config.env
```
**Windows PowerShell:**
```powershell
Get-Content "$env:USERPROFILE\.config\gitea\config.env" | ForEach-Object {
if ($_ -match '^([^=]+)=(.*)$') {
[Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process')
}
}
```
Show in Chinese:
- Gitea URL
- Default organization (if set)
- Config file path (根据平台显示正确路径)
3. **Validate token and display user info:**
- Call API: `GET ${GITEA_URL}/api/v1/user`
- Header: `Authorization: token ${GITEA_TOKEN}`
- Show: Token status (✓ 有效 / ✗ 无效), username, email
4. **Display runner information:**
- Runners directory:
- macOS/Linux: `~/.config/gitea/runners`
- Windows: `%USERPROFILE%\.config\gitea\runners`
- Count configured runners
- List each runner with status:
- 🟢 运行中 (process running)
- 🔴 已停止 (process not running)
- ⚠️ 配置异常 (config file missing)
5. **Show management commands:**
```
管理命令:
- 重置配置: /gitea-reset
- 切换组织: /gitea-switch-org <org-name>
- 列出 Runners: /gitea-list-runners
- 创建仓库: /create-gitea-repo <repo-name>
```
Use `jq` to parse JSON responses and `pgrep` to check runner process status.

View File

@@ -1,104 +0,0 @@
---
description: Create a new Git repository on Gitea
---
Create a new Git repository on Gitea via API.
## 工作目录
**macOS / Linux:**
```
~/.config/gitea/
```
**Windows:**
```
%USERPROFILE%\.config\gitea\
```
配置文件从该目录加载。
**User input format:**
```
$ARGUMENTS = [<owner>/]<repo> [private|public]
```
**Examples:**
- `my-project` - Private repo under default org or current user
- `ai/my-project` - Private repo under ai organization
- `ai/my-project public` - Public repo under ai organization
- `username/test private` - Private repo under username
Please perform the following:
1. **Load configuration:**
**macOS / Linux:**
```bash
source ~/.config/gitea/config.env
```
**Windows PowerShell:**
```powershell
Get-Content "$env:USERPROFILE\.config\gitea\config.env" | ForEach-Object {
if ($_ -match '^([^=]+)=(.*)$') {
[Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process')
}
}
```
- If not exists: prompt to run `/gitea-reset`
2. **Parse user input from `$ARGUMENTS`:**
- Extract: owner (optional), repo (required), visibility (optional, default: private)
- If no owner specified:
- Use `GITEA_DEFAULT_ORG` if set
- Otherwise get current user from API: `GET /api/v1/user`
- Validate repo name: only letters, numbers, underscores, hyphens, dots
3. **Create repository via API:**
- Try organization API first:
```bash
POST ${GITEA_URL}/api/v1/orgs/${owner}/repos
Body: {
"name": "${repo}",
"private": true/false,
"auto_init": false,
"default_branch": "main"
}
```
- If 404, try user API: `POST /api/v1/user/repos`
- Handle response codes:
- 201: Success
- 409: Repository already exists
- 404: Owner not found or no permission
- Other: API error
4. **Extract repository info from response:**
- `html_url` - Web URL
- `clone_url` - HTTPS URL
- `ssh_url` - SSH URL
5. **Ask user if they want to add remote:**
- Check if current directory is a git repo
- If not, ask to initialize: `git init`
- Check if `origin` remote exists
- Add or update remote: `git remote add/set-url origin <clone_url>`
6. **Display result in Chinese:**
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
仓库创建成功
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
名称: [owner]/[repo]
可见性: [private/public]
Web URL: [html_url]
HTTPS URL: [clone_url]
SSH URL: [ssh_url]
```
**Notes:**
- Requires repo creation permission in token
- Organization and user repositories use different API endpoints
- Default branch is `main` (not `master`)

View File

@@ -1,770 +0,0 @@
---
description: Create and start a Gitea Actions runner (default host mode)
agent: general
subtask: true
---
# 创建并启动 Gitea Actions Runner
你的任务是创建并启动一个 Gitea Actions Runner默认使用 host 模式)。
## 工作目录
**macOS / Linux:**
```
~/.config/gitea/
```
**Windows:**
```
%USERPROFILE%\.config\gitea\
```
所有 Runner 配置、缓存、工作区都存储在该目录的 `runners/` 子目录下。
## 核心功能要求
请按照以下步骤执行:
1. **检查 act_runner 安装**
- 检查 act_runner 是否已安装(使用 `command -v act_runner`
- 如果未安装,使用 Homebrew 自动安装:`brew install act_runner`
- 如果 Homebrew 不存在,提示用户安装 Homebrew
- 验证安装成功后显示版本信息
2. **加载 Gitea 配置**
- 从配置文件加载配置:
- macOS/Linux: `~/.config/gitea/config.env`
- Windows: `%USERPROFILE%\.config\gitea\config.env`
- 如果配置文件不存在,提示用户运行 `/gitea-reset` 初始化
- 验证必需的配置项:`GITEA_URL``GITEA_TOKEN`
- 显示加载成功的配置信息
3. **生成 Runner 名称**
- 如果用户提供了参数 `$ARGUMENTS`,使用该名称
- 否则默认基于主机名生成:`runner-$(hostname -s)`
- 验证名称只包含字母、数字、下划线和连字符
4. **检查 Runner 是否已存在**
- 检查 Runner 目录:
- macOS/Linux: `~/.config/gitea/runners/$runner_name`
- Windows: `%USERPROFILE%\.config\gitea\runners\$runner_name`
- 如果已存在,提示用户可选操作:
- 使用其他名称
- 删除现有 runner使用 `/gitea-delete-runner`
- 查看所有 runners使用 `/gitea-list-runners`
5. **检测系统环境**
- 检测操作系统macOS/Linux
- 检测架构ARM64/x64
- 生成 host 模式的 labels
- `self-hosted:host`
- `{os_label}:host`(如 `macOS:host`
- `{arch_label}:host`(如 `ARM64:host`
- `{combined}:host`(如 `darwin-arm64:host`
6. **创建 Runner 目录结构**
- 创建目录结构:
- macOS/Linux: `~/.config/gitea/runners/$runner_name/{cache,workspace}`
- Windows: `%USERPROFILE%\.config\gitea\runners\$runner_name\{cache,workspace}`
- 验证目录创建成功
7. **生成配置文件**
- 创建 `config.yaml`,使用 host 模式配置
- 从环境变量读取可选配置:
- `GITEA_RUNNER_CAPACITY`(默认 2
- `GITEA_RUNNER_TIMEOUT`(默认 3h
- 配置要点:
- log level: info
- runner.capacity: 并发任务数
- runner.timeout: 任务超时
- cache: 启用缓存
- host.workdir_parent: 工作目录路径
- labels: 使用检测到的系统 labels
8. **获取注册 Token**
- 优先尝试创建全局 Runner需要管理员权限
- API: `GET ${GITEA_URL}/api/v1/admin/runners/registration-token`
- Header: `Authorization: token ${GITEA_TOKEN}`
- 如果返回 403/权限不足,自动降级到组织 Runner
- 使用 `GITEA_DEFAULT_ORG` 作为组织名
- API: `POST ${GITEA_URL}/api/v1/orgs/${org_name}/actions/runners/registration-token`
- 从响应中提取 tokenJSON 格式)
- 记录使用的 runner 级别global 或 organization
9. **注册 Runner**
- 执行命令:
```bash
act_runner register \
--config "$runner_dir/config.yaml" \
--instance "$GITEA_URL" \
--token "$registration_token" \
--name "$runner_name" \
--labels "$labels" \
--no-interactive
```
- 验证 `.runner` 文件是否创建
- 如果失败,提供诊断建议
10. **后台启动 Runner**
- 使用 nohup 后台启动:
```bash
nohup act_runner daemon --config "$runner_dir/config.yaml" \
> "$runner_dir/runner.log" 2>&1 &
```
- 记录进程 PID
- 等待 3 秒初始化
- 验证进程仍在运行
- 如果失败,显示日志的最后 20 行
11. **显示创建摘要**
- Runner 信息名称、级别、模式、状态、PID
- 如果是组织级别,显示组织名
- 配置信息容量、超时、labels
- 目录信息:配置文件、工作目录、缓存目录、日志文件
- 管理命令:查看日志、停止 Runner、查看所有、删除
- 使用示例workflow 中的 runs-on 配置
## 重要配置说明
- **默认模式**Host Mode直接在宿主机执行支持 Android SDK、iOS 构建等原生工具)
- **目录结构**
- macOS/Linux: 所有 runners 位于 `~/.config/gitea/runners/`
- Windows: 所有 runners 位于 `%USERPROFILE%\.config\gitea\runners\`
- **优雅降级**:全局 runner 权限不足时自动降级到组织 runner
- **后台运行**:使用 nohup 后台启动Unix或 Start-ProcessWindows日志输出到文件
- **进程管理**:需要手动管理进程(系统重启后需重新启动)
## 可选参数
- `$ARGUMENTS`: Runner 名称(可选,默认基于主机名生成)
使用示例:
```
/gitea-create-runner
/gitea-create-runner my-custom-runner
```
## 相关命令
- `/gitea-config`: 查看 Gitea 配置
- `/gitea-reset`: 重置/初始化 Gitea 配置
- `/gitea-list-runners`: 列出所有 runners
- `/gitea-delete-runner`: 删除指定 runner
---
## 详细实现步骤(供 AI 参考)
### 1. Check act_runner Installation
**AI 执行**:检查 act_runner 是否已安装,如果没有则自动安装。
```bash
echo "检查 act_runner 安装状态..."
if command -v act_runner &> /dev/null; then
version=$(act_runner --version 2>&1 | head -n1)
echo "✓ act_runner 已安装: $version"
else
echo "⚠️ act_runner 未安装"
echo "正在使用 Homebrew 安装..."
if ! command -v brew &> /dev/null; then
echo "❌ 需要先安装 Homebrew"
echo " 安装命令: /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
exit 1
fi
brew install act_runner
if [ $? -eq 0 ]; then
version=$(act_runner --version 2>&1 | head -n1)
echo "✓ act_runner 安装成功: $version"
else
echo "❌ act_runner 安装失败"
exit 1
fi
fi
echo ""
```
### 2. Load Gitea Configuration
**AI 执行**:加载 Gitea 配置,如果不存在则提示初始化。
```bash
config_file="$HOME/.config/gitea/config.env"
if [ ! -f "$config_file" ]; then
echo "❌ Gitea 配置不存在"
echo ""
echo "请先初始化 Gitea 配置:"
echo " /gitea-reset"
echo ""
echo "或使用以下命令查看配置:"
echo " /gitea-config"
exit 1
fi
source "$config_file"
if [ -z "$GITEA_URL" ] || [ -z "$GITEA_TOKEN" ]; then
echo "❌ Gitea 配置不完整"
echo " 需要 GITEA_URL 和 GITEA_TOKEN"
echo ""
echo "请重新初始化配置:"
echo " /gitea-reset"
exit 1
fi
echo "✓ 已加载 Gitea 配置"
echo " URL: $GITEA_URL"
echo ""
```
### 3. Generate Runner Name
**AI 执行**:生成 runner 名称(基于主机名或用户输入)。
```bash
# Check if runner name provided as argument
# 如果用户提供了名称参数,使用该参数;否则基于主机名生成
if [ -n "$1" ]; then
runner_name="$1"
echo "使用指定的 Runner 名称: $runner_name"
else
hostname=$(hostname -s 2>/dev/null || echo "unknown")
runner_name="runner-$hostname"
echo "生成 Runner 名称: $runner_name"
echo " (基于主机名: $hostname)"
fi
echo ""
# Validate runner name
if [[ ! "$runner_name" =~ ^[a-zA-Z0-9_-]+$ ]]; then
echo "❌ Runner 名称只能包含字母、数字、下划线和连字符"
exit 1
fi
```
### 4. Check Runner Existence
**AI 执行**:检查 runner 是否已存在。
```bash
runners_dir="$HOME/.config/gitea/runners"
runner_dir="$runners_dir/$runner_name"
if [ -d "$runner_dir" ]; then
echo "❌ Runner '$runner_name' 已存在"
echo " 路径: $runner_dir"
echo ""
echo "选项:"
echo " 1. 使用其他名称: /gitea-create-runner <新名称>"
echo " 2. 删除现有 runner: /gitea-delete-runner"
echo " 3. 查看所有 runners: /gitea-list-runners"
exit 1
fi
```
### 5. Detect System Environment
**AI 执行**:智能检测系统环境并生成 labels。
```bash
echo "检测系统环境..."
# Detect OS
OS=$(uname -s)
case "$OS" in
Darwin) os_label="macOS" ;;
Linux) os_label="ubuntu" ;;
*) os_label="unknown" ;;
esac
# Detect architecture
ARCH=$(uname -m)
case "$ARCH" in
arm64|aarch64) arch_label="ARM64" ;;
x86_64) arch_label="x64" ;;
*) arch_label="unknown" ;;
esac
# Generate combined label
combined=$(echo "${OS}-${ARCH}" | tr '[:upper:]' '[:lower:]')
# Generate labels for host mode
labels="self-hosted:host,${os_label}:host,${arch_label}:host,${combined}:host"
echo "✓ 系统信息"
echo " 操作系统: $OS ($os_label)"
echo " 架构: $ARCH ($arch_label)"
echo " 组合标签: $combined"
echo ""
echo "✓ Runner Labels (Host Mode)"
echo " $labels"
echo ""
```
### 6. Create Runner Directory
**AI 执行**:创建 runner 目录结构。
```bash
echo "创建 Runner 目录..."
mkdir -p "$runner_dir"/{cache,workspace}
if [ ! -d "$runner_dir" ]; then
echo "❌ 创建目录失败"
exit 1
fi
echo "✓ 目录创建成功"
echo " 路径: $runner_dir"
echo " - cache/"
echo " - workspace/"
echo ""
```
### 7. Generate Configuration File
**AI 执行**:生成 host 模式配置文件。
```bash
echo "生成配置文件..."
# Get environment-specific settings (with defaults)
runner_capacity="${GITEA_RUNNER_CAPACITY:-2}"
runner_timeout="${GITEA_RUNNER_TIMEOUT:-3h}"
# Generate config.yaml for host mode
cat > "$runner_dir/config.yaml" << EOF
log:
level: info
runner:
file: $runner_dir/.runner
capacity: $runner_capacity
timeout: $runner_timeout
shutdown_timeout: 30s
insecure: false
fetch_timeout: 5s
fetch_interval: 2s
labels:
- "self-hosted:host"
- "${os_label}:host"
- "${arch_label}:host"
- "${combined}:host"
cache:
enabled: true
dir: "$runner_dir/cache"
host: "127.0.0.1"
port: 9000
host:
workdir_parent: "$runner_dir/workspace"
EOF
if [ ! -f "$runner_dir/config.yaml" ]; then
echo "❌ 配置文件生成失败"
exit 1
fi
echo "✓ 配置文件已生成"
echo " 文件: $runner_dir/config.yaml"
echo " 模式: Host Mode (原生执行)"
echo " 容量: $runner_capacity 并发任务"
echo " 超时: $runner_timeout"
echo ""
```
### 8. Get Registration Token
**AI 执行**:获取注册 token优先全局失败则降级到组织
```bash
echo "获取 Runner 注册 Token..."
echo ""
# Try global runner first (requires admin token)
echo "尝试创建全局 Runner可用于所有组织和仓库..."
response=$(curl -s -w "\n%{http_code}" \
-H "Authorization: token $GITEA_TOKEN" \
"${GITEA_URL}/api/v1/admin/runners/registration-token")
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
# Check for admin permission
if [ "$http_code" = "200" ]; then
echo "✓ 使用全局 Runner"
runner_level="global"
registration_token=$(echo "$body" | jq -r '.token')
else
echo "⚠️ 全局 Runner 权限不足 (HTTP $http_code)"
echo " 全局 Runner 需要管理员 Token"
echo ""
echo "降级到组织 Runner..."
runner_level="organization"
if [ -n "$GITEA_DEFAULT_ORG" ]; then
org_name="$GITEA_DEFAULT_ORG"
echo "使用默认组织: $org_name"
else
echo "❌ 未配置默认组织"
echo " 请在配置文件中设置 GITEA_DEFAULT_ORG"
echo " 或重新初始化配置: /gitea-reset"
exit 1
fi
response=$(curl -s -w "\n%{http_code}" -X POST \
-H "Authorization: token $GITEA_TOKEN" \
"${GITEA_URL}/api/v1/orgs/$org_name/actions/runners/registration-token")
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
if [ "$http_code" != "200" ]; then
echo "❌ 获取注册 Token 失败 (HTTP $http_code)"
echo " 响应: $body"
echo ""
echo "可能的原因:"
echo " 1. 组织不存在"
echo " 2. Token 没有组织管理权限"
echo " 3. 网络连接问题"
exit 1
fi
registration_token=$(echo "$body" | jq -r '.token')
echo "✓ 组织 Runner Token 已获取"
fi
if [ -z "$registration_token" ] || [ "$registration_token" = "null" ]; then
echo "❌ 无法解析注册 Token"
exit 1
fi
echo "✓ 注册 Token 已准备"
echo ""
```
### 9. Register Runner
**AI 执行**:注册 runner 到 Gitea 服务器。
```bash
echo "注册 Runner 到 Gitea 服务器..."
act_runner register \
--config "$runner_dir/config.yaml" \
--instance "$GITEA_URL" \
--token "$registration_token" \
--name "$runner_name" \
--labels "$labels" \
--no-interactive
if [ $? -eq 0 ]; then
echo "✓ Runner 注册成功"
else
echo "❌ Runner 注册失败"
echo ""
echo "请检查:"
echo " 1. Token 是否有效"
echo " 2. Gitea 服务器是否可访问"
echo " 3. 配置文件是否正确"
echo ""
echo "查看详细错误,可以手动运行:"
echo " act_runner register --config $runner_dir/config.yaml --instance $GITEA_URL --token <token> --name $runner_name --labels \"$labels\""
exit 1
fi
# Verify .runner file was created
if [ ! -f "$runner_dir/.runner" ]; then
echo "⚠️ 注册文件未创建,但注册可能成功"
echo " 请检查: $runner_dir/.runner"
fi
echo ""
```
### 10. Start Runner
**AI 执行**:后台启动 runner 并验证状态。
```bash
echo "启动 Runner..."
# Start runner in background
nohup act_runner daemon --config "$runner_dir/config.yaml" \
> "$runner_dir/runner.log" 2>&1 &
runner_pid=$!
echo " 进程已启动 (PID: $runner_pid)"
# Wait for runner to initialize
echo " 等待初始化..."
sleep 3
# Check if process is still running
if ps -p $runner_pid > /dev/null 2>&1; then
echo "✓ Runner 运行中"
else
echo "❌ Runner 启动失败"
echo ""
echo "查看日志以诊断问题:"
echo " tail -n 50 $runner_dir/runner.log"
echo ""
tail -n 20 "$runner_dir/runner.log"
exit 1
fi
echo ""
```
### 11. Display Summary
**AI 执行**:显示创建结果和管理命令。
```bash
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "✅ Runner 创建完成!"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "Runner 信息:"
echo " 名称: $runner_name"
echo " 级别: $runner_level"
if [ "$runner_level" = "organization" ]; then
echo " 组织: $org_name"
fi
echo " 模式: Host Mode (原生执行)"
echo " 状态: 🟢 运行中"
echo " PID: $runner_pid"
echo ""
echo "配置:"
echo " 容量: $runner_capacity 并发任务"
echo " 超时: $runner_timeout"
echo " Labels: $labels"
echo ""
echo "目录:"
echo " 配置文件: $runner_dir/config.yaml"
echo " 注册信息: $runner_dir/.runner"
echo " 工作目录: $runner_dir/workspace"
echo " 缓存目录: $runner_dir/cache"
echo " 日志文件: $runner_dir/runner.log"
echo ""
echo "管理命令:"
echo " 查看日志: tail -f $runner_dir/runner.log"
echo " 停止 Runner: pkill -f 'act_runner daemon --config.*$runner_name'"
echo " 查看所有: /gitea-list-runners"
echo " 删除 Runner: /gitea-delete-runner"
echo ""
echo "使用 Runner:"
echo " 在 workflow 中使用以下任一 runs-on 值:"
echo " - runs-on: $combined"
echo " - runs-on: $os_label"
echo " - runs-on: [self-hosted, $os_label, $arch_label]"
echo ""
```
## Output Example
### Example 1: Successful Creation (Global Runner)
```
检查 act_runner 安装状态...
✓ act_runner 已安装: act_runner version 0.2.13
✓ 已加载 Gitea 配置
URL: https://git.digitevents.com
生成 Runner 名称: runner-macbook-pro
(基于主机名: macbook-pro)
检测系统环境...
✓ 系统信息
操作系统: Darwin (macOS)
架构: arm64 (ARM64)
组合标签: darwin-arm64
✓ Runner Labels (Host Mode)
self-hosted:host,macOS:host,ARM64:host,darwin-arm64:host
创建 Runner 目录...
✓ 目录创建成功
路径: /Users/voson/.config/gitea/runners/runner-macbook-pro
- cache/
- workspace/
生成配置文件...
✓ 配置文件已生成
文件: /Users/voson/.config/gitea/runners/runner-macbook-pro/config.yaml
模式: Host Mode (原生执行)
容量: 2 并发任务
超时: 3h
获取 Runner 注册 Token...
尝试创建全局 Runner可用于所有组织和仓库...
✓ 使用全局 Runner
✓ 注册 Token 已准备
注册 Runner 到 Gitea 服务器...
✓ Runner 注册成功
启动 Runner...
进程已启动 (PID: 12345)
等待初始化...
✓ Runner 运行中
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Runner 创建完成!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Runner 信息:
名称: runner-macbook-pro
级别: global
模式: Host Mode (原生执行)
状态: 🟢 运行中
PID: 12345
配置:
容量: 2 并发任务
超时: 3h
Labels: self-hosted:host,macOS:host,ARM64:host,darwin-arm64:host
目录:
配置文件: /Users/voson/.config/gitea/runners/runner-macbook-pro/config.yaml
注册信息: /Users/voson/.config/gitea/runners/runner-macbook-pro/.runner
工作目录: /Users/voson/.config/gitea/runners/runner-macbook-pro/workspace
缓存目录: /Users/voson/.config/gitea/runners/runner-macbook-pro/cache
日志文件: /Users/voson/.config/gitea/runners/runner-macbook-pro/runner.log
管理命令:
查看日志: tail -f /Users/voson/.config/gitea/runners/runner-macbook-pro/runner.log
停止 Runner: pkill -f 'act_runner daemon --config.*runner-macbook-pro'
查看所有: /gitea-list-runners
删除 Runner: /gitea-delete-runner
使用 Runner:
在 workflow 中使用以下任一 runs-on 值:
- runs-on: darwin-arm64
- runs-on: macOS
- runs-on: [self-hosted, macOS, ARM64]
```
### Example 2: Auto-install act_runner
```
检查 act_runner 安装状态...
⚠️ act_runner 未安装
正在使用 Homebrew 安装...
==> Downloading act_runner...
==> Installing act_runner...
✓ act_runner 安装成功: act_runner version 0.2.13
[继续后续步骤...]
```
### Example 3: Downgrade to Organization Runner
```
获取 Runner 注册 Token...
尝试创建全局 Runner可用于所有组织和仓库...
⚠️ 全局 Runner 权限不足 (HTTP 403)
全局 Runner 需要管理员 Token
降级到组织 Runner...
使用默认组织: ai
✓ 组织 Runner Token 已获取
✓ 注册 Token 已准备
[继续后续步骤...]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Runner 创建完成!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Runner 信息:
名称: runner-macbook-pro
级别: organization
组织: ai
模式: Host Mode (原生执行)
[...]
```
### Example 4: Configuration Not Found
```
检查 act_runner 安装状态...
✓ act_runner 已安装: act_runner version 0.2.13
❌ Gitea 配置不存在
请先初始化 Gitea 配置:
/gitea-reset
或使用以下命令查看配置:
/gitea-config
```
### Example 5: Runner Already Exists
```
[前置检查...]
生成 Runner 名称: runner-macbook-pro
(基于主机名: macbook-pro)
❌ Runner 'runner-macbook-pro' 已存在
路径: /Users/voson/.config/gitea/runners/runner-macbook-pro
选项:
1. 使用其他名称: /gitea-create-runner <新名称>
2. 删除现有 runner: /gitea-delete-runner
3. 查看所有 runners: /gitea-list-runners
```
## Technical Notes
- **默认模式**Host Mode支持 Android SDK、iOS 等原生工具)
- **自动安装**:使用 Homebrew 安装 act_runner
- **智能检测**:自动检测 OS 和架构,生成合适的 labels
- **优雅降级**:全局 runner 权限不足时自动降级到组织 runner
- **后台运行**:自动后台启动,日志记录到文件
- **配置环境变量**
- `GITEA_RUNNER_CAPACITY`: 并发任务数(默认 2
- `GITEA_RUNNER_TIMEOUT`: 任务超时时间(默认 3h
- **目录权限**:自动创建,权限继承用户默认权限
- **进程管理**:使用 nohup 后台运行,支持系统重启后手动重启
## Related Commands
- `/gitea-config`: 查看 Gitea 配置
- `/gitea-reset`: 重置/初始化 Gitea 配置
- `/gitea-list-runners`: 列出所有 runners
- `/gitea-delete-runner`: 删除指定 runner
- `/create-gitea-repo`: 创建 Gitea 仓库
## Safety Features
- **配置验证**:检查必需的配置项
- **目录冲突检测**:避免覆盖现有 runner
- **启动验证**:等待并验证进程启动成功
- **错误提示**:清晰的错误信息和解决方案
- **日志记录**:所有输出记录到日志文件
## Version
- **Command Version**: 1.0
- **Last Updated**: 2026-01-12
- **Compatible with**: act_runner 0.2.13+, macOS/Linux

View File

@@ -1,174 +0,0 @@
---
description: Delete a Gitea runner configuration (interactive)
agent: general
subtask: true
---
Delete Gitea runner configuration with interactive selection. This command requires multiple user interactions.
**Important:** This is an interactive command. Wait for user input at each step before proceeding.
## 工作目录
**macOS / Linux:**
```
~/.config/gitea/
```
**Windows:**
```
%USERPROFILE%\.config\gitea\
```
所有 Runner 配置、进程管理都基于此目录。
Please perform the following steps:
## Step 1: Load Configuration and Fetch Runners
1. **Load Gitea configuration:**
**macOS / Linux:**
```bash
source ~/.config/gitea/config.env
```
**Windows PowerShell:**
```powershell
Get-Content "$env:USERPROFILE\.config\gitea\config.env" | ForEach-Object {
if ($_ -match '^([^=]+)=(.*)$') {
[Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process')
}
}
```
- Validate `GITEA_URL` and `GITEA_TOKEN` exist
2. **Fetch global runners from Gitea server:**
- API: `GET ${GITEA_URL}/api/v1/admin/actions/runners`
- Requires admin permissions
- If fails: show error and check token permissions
3. **Display runners list in Chinese:**
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Gitea 全局 Runners (共 N 个)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. [runner-name] [ID: XX] 🟢 在线/🔴 离线
2. [runner-name] [ID: XX] 🟢 在线/🔴 离线
...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
选择要删除的 Runner
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
输入序号: 删除单个 runner
输入 'all': 删除所有 runners
输入 'q' 或 'quit': 取消
```
4. **Wait for user selection** → Do NOT proceed until user responds
## Step 2: Process User Selection
Based on user input:
- If `q` or `quit`: Cancel and exit
- If `all`: Prepare to delete all runners
- If number: Validate and prepare to delete that runner
## Step 3: Display Warning and Wait for Confirmation
Display deletion warning in Chinese:
```
⚠️ 警告: 此操作将执行以下操作:
- 从 Gitea 服务器注销 runner
- 停止本地运行的 runner 进程
- 删除 runner 配置文件
- 删除 cache 和 workspace 目录
- 删除所有相关数据
将删除以下 runners:
- [list of runners to be deleted]
确认删除? 输入 'yes' 继续:
```
**Wait for user confirmation** → Do NOT proceed until user types 'yes'
## Step 4: Execute Deletion
If user confirmed with 'yes', for each selected runner:
### 4.1 Unregister from Gitea Server
```bash
DELETE ${GITEA_URL}/api/v1/admin/actions/runners/${runner_id}
```
- Expected: HTTP 204
- Show: "✓ 已从服务器注销" or "⚠️ 注销失败"
### 4.2 Stop Local Process
1. Find local runner directory by matching ID in `.runner` file
2. Check if process is running: `pgrep -f "act_runner daemon --config ..."`
3. If running:
- Check if runner is busy (executing jobs) via API
- **If busy, wait for user choice:**
```
⚠️ 警告: Runner 正在执行 job
选项:
1. 等待 job 完成后再停止(推荐)
2. 强制立即停止
```
- **Wait for user input** → Proceed based on choice
- If waiting: Poll status every 10 seconds, max 5 minutes
- Stop process: `kill $pid` (graceful), then `kill -9 $pid` if needed (force)
### 4.3 Delete Local Directory
**macOS / Linux:**
```bash
rm -rf ~/.config/gitea/runners/[runner_name]
```
**Windows PowerShell:**
```powershell
Remove-Item -Path "$env:USERPROFILE\.config\gitea\runners\[runner_name]" -Recurse -Force
```
## Step 5: Display Result
Show completion summary in Chinese:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
删除完成
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
成功: N 个
失败: M 个 (if any)
管理命令:
查看剩余 runners: /gitea-list-runners
创建新 runner: /gitea-create-runner
```
---
## Key Points
**Interactive checkpoints (wait for user input):**
1. Step 1: After displaying runners list → Wait for selection
2. Step 3: After displaying warning → Wait for confirmation ('yes')
3. Step 4.2: If runner is busy → Wait for stop choice (1 or 2)
**Safety features:**
- Double confirmation required
- Busy status detection
- Graceful stop before force kill
- Three-step deletion process
- Clear status reporting
**Technical notes:**
- Requires `jq` for JSON parsing
- Requires admin token for global runners
- Uses temporary file `/tmp/gitea_runners.txt` for data passing
- Cleanup temp file after completion

View File

@@ -1,94 +0,0 @@
---
description: List all global runners on Gitea server
---
List all global runners registered on the Gitea server.
## 工作目录
**macOS / Linux:**
```
~/.config/gitea/
```
**Windows:**
```
%USERPROFILE%\.config\gitea\
```
Please perform the following:
1. **Read Gitea configuration:**
- Read from config file:
- macOS/Linux: `~/.config/gitea/config.env`
- Windows: `%USERPROFILE%\.config\gitea\config.env`
- Extract:
- `GITEA_URL`: Gitea server URL
- `GITEA_TOKEN`: API token (admin permission required)
- If config not found: prompt user to run `/gitea-reset` first
2. **Call Gitea API to list runners:**
```bash
curl -s -H "Authorization: token <token>" \
"<server>/api/v1/admin/actions/runners"
```
3. **Parse JSON response and extract information:**
- Response structure:
```json
{
"runners": [...],
"total_count": 1
}
```
- Use `jq` to parse JSON
- For each runner in `runners` array:
- `id`: Runner ID
- `name`: Runner name
- `status`: Runner status ("online"/"offline")
- `busy`: Whether runner is currently busy (true/false)
- `ephemeral`: Whether runner is ephemeral (true/false)
- `labels`: Array of label objects with `name` and `type`
4. **Determine runner status:**
- 🟢 在线 - `status: "online"`
- 🔴 离线 - `status: "offline"`
- ⚠️ 未知 - Unable to determine
5. **Filter global runners:**
- The API endpoint `/api/v1/admin/actions/runners` returns all global runners
- These are runners registered at the instance level (not org or repo specific)
6. **Display summary in Chinese:**
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Gitea 全局 Runners
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
服务器: [server_url]
总计: N 个全局 runner
[runner-name]
状态: 🟢/🔴 [在线/离线]
ID: [id]
忙碌: 是/否
临时: 是/否
标签: [comma-separated labels]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
管理命令
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
查看配置: /gitea-config
创建 runner: /gitea-create-runner
删除 runner: /gitea-delete-runner
```
**Notes:**
- Requires admin API token to list runners
- **Correct API endpoint**: `/api/v1/admin/actions/runners` (not `/api/v1/admin/runners`)
- Only shows global runners (instance-level runners)
- Uses `jq` for JSON parsing
- Response includes: `id`, `name`, `status`, `busy`, `ephemeral`, `labels`
- If API call fails, show error message and suggest checking token permissions
- Tested with Gitea version 1.25.3

View File

@@ -1,132 +0,0 @@
---
description: Reset Gitea configuration with interactive setup wizard
agent: general
subtask: true
---
Launch an interactive configuration wizard to set up or reset Gitea configuration.
## 工作目录
**macOS / Linux:**
```
~/.config/gitea/
```
**Windows:**
```
%USERPROFILE%\.config\gitea\
```
配置文件和 Runner 目录都将存储在此位置。
Please perform the following:
1. **Create configuration directory:**
**macOS / Linux:**
```bash
mkdir -p ~/.config/gitea/runners
```
**Windows PowerShell:**
```powershell
New-Item -Path "$env:USERPROFILE\.config\gitea\runners" -ItemType Directory -Force
```
2. **Interactive input - Gitea URL:**
- Prompt: "请输入 Gitea 实例地址 (例如: https://git.digitevents.com):"
- Validate: Must start with http:// or https://
- Remove trailing slash
3. **Interactive input - Personal Access Token:**
- Prompt: "请输入 Personal Access Token:"
- Before input, show help:
```
提示:获取 Personal Access Token 的步骤:
1. 登录 Gitea
2. 右上角头像 → 设置 → 应用 → 访问令牌
3. 点击 "生成新令牌"
4. 设置令牌名称(如 opencode-cli
5. 选择权限repo, admin:org, write:runner推荐
6. 点击 "生成令牌"
7. 复制生成的 Token
```
- Validate: Not empty
- Use `read -sp` for secure input (password style)
4. **Test connection:**
- API: `GET ${GITEA_URL}/api/v1/user`
- If fails: Show error and possible reasons
- If success: Show username
5. **Validate token permissions:**
- Check `repo`: `GET /api/v1/user/repos` (required)
- Check `admin:org`: `GET /api/v1/user/orgs` (optional, for org runners)
- Check `write:runner`: Try to get registration token (optional, for runners)
- Warn if missing required permissions
6. **Input default organization (optional):**
- Prompt: "请输入默认组织名称 (回车跳过):"
- If provided, validate it exists: `GET /api/v1/orgs/${org_name}`
7. **Save configuration:**
**macOS / Linux** - Save to `~/.config/gitea/config.env`:
```bash
GITEA_URL=...
GITEA_TOKEN=...
GITEA_DEFAULT_ORG=... (if set)
GITEA_RUNNER_CAPACITY=2
GITEA_RUNNER_TIMEOUT=3h
```
- Set permissions: `chmod 600 ~/.config/gitea/config.env`
- Create `.gitignore` to exclude sensitive files
**Windows** - Save to `%USERPROFILE%\.config\gitea\config.env`:
```bash
GITEA_URL=...
GITEA_TOKEN=...
GITEA_DEFAULT_ORG=... (if set)
GITEA_RUNNER_CAPACITY=2
GITEA_RUNNER_TIMEOUT=3h
```
- Set file permissions to restrict access (see setup-guide.md for PowerShell script)
- Create `.gitignore` to exclude sensitive files
8. **Display completion summary in Chinese:**
**macOS / Linux:**
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
配置完成
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
配置文件: ~/.config/gitea/config.env
Runner 目录: ~/.config/gitea/runners
下一步:
- 查看配置: /gitea-config
- 创建 Runner: 告诉 AI '创建一个 runner'
- 创建仓库: /create-gitea-repo <repo-name>
```
**Windows:**
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
配置完成
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
配置文件: %USERPROFILE%\.config\gitea\config.env
Runner 目录: %USERPROFILE%\.config\gitea\runners
下一步:
- 查看配置: /gitea-config
- 创建 Runner: 告诉 AI '创建一个 runner'
- 创建仓库: /create-gitea-repo <repo-name>
```
**Security notes:**
- Config file permissions: 600 (owner read/write only)
- Token is never displayed after initial input
- Sensitive files excluded in .gitignore

View File

@@ -1,82 +0,0 @@
---
description: Switch default Gitea organization
---
Switch the default Gitea organization in configuration.
## 工作目录
**macOS / Linux:**
```
~/.config/gitea/
```
**Windows:**
```
%USERPROFILE%\.config\gitea\
```
**User input format:** `$ARGUMENTS` = organization name
**Example usage:**
```
/gitea-switch-org ai
/gitea-switch-org my-team
```
Please perform the following:
1. **Check configuration exists:**
- Config file:
- macOS/Linux: `~/.config/gitea/config.env`
- Windows: `%USERPROFILE%\.config\gitea\config.env`
- If not exists: prompt user to run `/gitea-reset`
2. **Load configuration:**
**macOS / Linux:**
```bash
source ~/.config/gitea/config.env
```
**Windows PowerShell:**
```powershell
Get-Content "$env:USERPROFILE\.config\gitea\config.env" | ForEach-Object {
if ($_ -match '^([^=]+)=(.*)$') {
[Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process')
}
}
```
3. **Parse user input:**
- Organization name from `$ARGUMENTS`
- If empty: show usage and examples
4. **Validate organization exists:**
- API: `GET ${GITEA_URL}/api/v1/orgs/${org_name}`
- Header: `Authorization: token ${GITEA_TOKEN}`
- If 404: Show error and list available organizations:
```bash
curl -s -H "Authorization: token $GITEA_TOKEN" \
"${GITEA_URL}/api/v1/user/orgs" | jq -r '.[].username'
```
5. **Update configuration file:**
- If `GITEA_DEFAULT_ORG` exists: update the line
- If not exists: add after `GITEA_TOKEN`
- Handle macOS (sed -i '') and Linux (sed -i) differences
6. **Display result in Chinese:**
```
✓ 默认组织已切换到: [org_name]
现在可以:
- 创建仓库: /create-gitea-repo my-project
(将创建到 [org_name]/my-project
- 查看配置: /gitea-config
```
**Notes:**
- Switching organization doesn't affect existing repositories or runners
- Only affects default owner for future repository creation
- Can switch anytime

View File

@@ -1,20 +0,0 @@
---
description: Review code or documentation and provide suggestions
agent: plan
---
Review the code or documentation and provide detailed feedback.
Please perform the following:
1. **Review** the code or documentation mentioned by the user
2. **Identify issues** and areas for improvement
3. **Provide suggestions** with clear explanations
4. **Ask for confirmation** before making modifications
If the user hasn't specified what to review, ask them to provide the code or documentation they want reviewed.
When suggesting changes:
- Explain why each change is needed
- Prioritize suggestions by importance
- Ask if the user wants all changes applied or only specific ones

View File

@@ -1,5 +1,8 @@
{ {
"$schema": "https://opencode.ai/config.json", "$schema": "https://opencode.ai/config.json",
"mcp": {},
"permission": "allow",
"plugin": ["@mohak34/opencode-notifier@latest"],
"provider": { "provider": {
"opencode": { "opencode": {
"models": { "models": {
@@ -10,19 +13,13 @@
"budgetTokens": 16000 "budgetTokens": 16000
} }
} }
}
}
}, },
"claude-sonnet-4-5": { "zhipuai-coding-plan": {
"options": { "options": {
"thinking": { "apiKey": "0f76aea86295476dbfa98724013b0fe8.o2EaJVqcl4Cf7WLP"
"type": "enabled",
"budgetTokens": 16000
} }
} }
} }
}
}
},
"mcp": {
},
"permission": "allow"
} }

View File

@@ -1,72 +0,0 @@
import type { Plugin } from "@opencode-ai/plugin"
/**
* 通知 Plugin
* 在会话完成或发生错误时发送系统通知
*/
export const NotificationPlugin: Plugin = async ({ project, client, $ }) => {
// 检测操作系统
const platform = process.platform
/**
* 发送系统通知
* @param title 通知标题
* @param message 通知内容
* @param isError 是否为错误通知
*/
const sendNotification = async (title: string, message: string, isError: boolean = false) => {
try {
if (platform === "darwin") {
// macOS - 使用 osascript
const sound = isError ? ' sound name "Basso"' : ''
await $`osascript -e 'display notification "${message}" with title "${title}"${sound}'`
} else if (platform === "linux") {
// Linux - 使用 notify-send
const urgency = isError ? "-u critical" : ""
await $`notify-send "${title}" "${message}" ${urgency}`
} else if (platform === "win32") {
// Windows - 使用 PowerShell
const script = `Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('${message}', '${title}')`
await $`powershell -Command "& {${script}}"`
}
// 记录日志
await client.app.log({
service: "notification",
level: "info",
message: `已发送通知: ${title} - ${message}`,
})
} catch (error) {
// 如果通知发送失败,记录错误但不中断流程
await client.app.log({
service: "notification",
level: "error",
message: `发送通知失败: ${error}`,
})
}
}
return {
event: async ({ event }) => {
const projectName = project?.name || "OpenCode"
// 会话完成时发送通知
if (event.type === "session.idle") {
await sendNotification(
projectName,
"会话已完成!",
false
)
}
// 会话错误时发送通知
if (event.type === "session.error") {
await sendNotification(
projectName,
"会话发生错误!",
true
)
}
},
}
}

View File

@@ -0,0 +1,442 @@
---
name: ab
description: 浏览器自动化工具,用于网页测试、表单填写、截图、数据提取等
---
# 浏览器自动化工具 agent-browser
ab是 agent-browser 的缩写,它是一个为 AI 代理设计的无头浏览器自动化 CLI 工具,基于 Rust 和 Playwright 构建。支持快速导航、元素交互、页面截图、数据提取等功能。
注意:必须使用 agent-browser 全称作为命令关键字。
## 快速开始
### 安装检查
agent-browser 默认已安装。如果遇到 "command not found" 错误,请运行以下命令安装:
```bash
# 全局安装
npm install -g agent-browser
# 下载 Chromium 浏览器
agent-browser install
```
### 核心工作流程4步法
```bash
# 使用 agent-browser
1. agent-browser open <url>
2. agent-browser snapshot -i
3. agent-browser click @e1
4. agent-browser fill @e2 "文本"
```
## 核心工作流程详解
### 1. 导航到页面
```bash
agent-browser open https://example.com
```
### 2. 获取页面快照(推荐使用交互模式)
```bash
agent-browser snapshot -i # 仅显示交互元素(按钮、输入框、链接)
```
**输出示例:**
```
- link "Learn more" [ref=e1]
- textbox "Email" [ref=e2]
- button "Submit" [ref=e3]
```
### 3. 使用 Refs 进行交互
快照中的 `[ref=e1]``[ref=e2]` 等是元素的唯一引用标识,**推荐使用 refs 而非 CSS 选择器**
- **确定性**ref 指向快照中的确切元素
- **快速**:无需重新查询 DOM
- **AI 友好**:适合 LLM 处理
### 4. 页面变化后重新快照
页面发生重大变化(导航、表单提交等)后,需要重新获取快照:
```bash
agent-browser snapshot -i # 重新获取新的 refs
```
## 命令参考
### 导航命令
```bash
agent-browser open <url> # 导航到 URLab open <url>
agent-browser back # 后退ab back
agent-browser forward # 前进ab forward
agent-browser reload # 重新加载页面ab reload
agent-browser close # 关闭浏览器ab close
```
### 快照命令(页面分析)
```bash
agent-browser snapshot # 完整可访问性树ab snapshot
agent-browser snapshot -i # 仅交互元素推荐ab snapshot -i
agent-browser snapshot -c # 紧凑输出移除空结构元素ab snapshot -c
agent-browser snapshot -d 3 # 限制深度为 3 级ab snapshot -d 3
agent-browser snapshot -s "#main" # 限定到 CSS 选择器范围ab snapshot -s "#main"
```
### 交互命令(使用 @refs
```bash
# 基础交互
agent-browser click @e1 # 单击
agent-browser dblclick @e1 # 双击
agent-browser fill @e2 "文本" # 清空并填写
agent-browser type @e2 "文本" # 不清空直接输入
agent-browser press Enter # 按键(支持组合键 Control+a
agent-browser hover @e1 # 悬停
agent-browser focus @e1 # 聚焦
# 表单操作
agent-browser check @e1 # 勾选复选框
agent-browser uncheck @e1 # 取消勾选
agent-browser select @e1 "值" # 选择下拉选项
agent-browser upload @e1 file1.jpg # 上传文件
# 滚动
agent-browser scroll down 500 # 向下滚动 500px
agent-browser scrollintoview @e1 # 滚动元素到可见区域
```
### 获取信息
```bash
agent-browser get text @e1 # 获取元素文本
agent-browser get value @e1 # 获取输入框值
agent-browser get html @e1 # 获取 innerHTML
agent-browser get attr @e1 id # 获取属性
agent-browser get title # 获取页面标题
agent-browser get url # 获取当前 URL
agent-browser get count ".item" # 计数匹配元素
agent-browser get box @e1 # 获取边界框
```
### 检查状态
```bash
agent-browser is visible @e1 # 检查是否可见
agent-browser is enabled @e1 # 检查是否启用
agent-browser is checked @e1 # 检查是否勾选
```
### 截图命令
```bash
agent-browser screenshot # 截图到标准输出
agent-browser screenshot page.png # 保存到文件
agent-browser screenshot --full # 完整页面截图
```
### 等待命令
```bash
agent-browser wait @e1 # 等待元素可见
agent-browser wait 2000 # 等待毫秒数
agent-browser wait --text "成功" # 等待文本出现
agent-browser wait --url "*/dashboard" # 等待 URL 模式匹配
agent-browser wait --load networkidle # 等待网络空闲
# 加载状态选项load, domcontentloaded, networkidle
```
### 语义化定位器(替代 refs
```bash
agent-browser find role button click --name "提交"
agent-browser find text "登录" click
agent-browser find label "邮箱" fill "user@test.com"
agent-browser find placeholder "请输入" fill "内容"
agent-browser find first ".item" click
agent-browser find nth 2 "a" text
```
## 认证与状态管理
### 方法1手动登录流程推荐用于首次
```bash
# 导航到登录页面
agent-browser open https://example.com/login
# 填写表单
agent-browser snapshot -i
# 输出显示textbox "邮箱" [ref=e1], textbox "密码" [ref=e2], button "登录" [ref=e3]
agent-browser fill @e1 "user@example.com"
agent-browser fill @e2 "password123"
agent-browser click @e3
# 等待登录成功
agent-browser wait --url "*/dashboard"
# 保存认证状态(重要!)
agent-browser state save auth.json
```
### 方法2加载已保存状态后续使用
```bash
# 加载保存的认证状态
agent-browser state load auth.json
# 直接访问受保护页面
agent-browser open https://example.com/dashboard
```
### 方法3HTTP Headers 认证(跳过登录界面)
```bash
# 为特定域名设置认证头
agent-browser open https://api.example.com --headers '{"Authorization": "Bearer <token>"}'
```
### 方法4Cookies 管理
```bash
# 设置 cookie
agent-browser cookies set session_id "abc123"
# 查看所有 cookies
agent-browser cookies
```
## 高级功能
### 无头/有头模式
```bash
# 默认:无头模式(无界面)
agent-browser open example.com
# 有头模式:显示浏览器窗口(适合调试)
agent-browser --headed open example.com
```
**无头模式特点**
- 后台运行 Chromium
- 不占用屏幕空间
- 更快的执行速度
- 适合自动化测试和 AI Agent 使用
### 会话隔离
```bash
# 创建独立会话
agent-browser --session user1 open site-a.com
agent-browser --session user2 open site-b.com
# 查看活动会话
agent-browser session list
# 每个会话独立:
# - 浏览器实例
# - Cookies 和存储
# - 导航历史
# - 认证状态
```
### JSON 输出(适合机器解析)
```bash
agent-browser snapshot -i --json
agent-browser get text @e1 --json
agent-browser is visible @e2 --json
```
### 自定义浏览器可执行文件
```bash
# 使用自定义 Chromium 路径
agent-browser --executable-path /path/to/chromium open example.com
# 环境变量方式
AGENT_BROWSER_EXECUTABLE_PATH=/path/to/chromium agent-browser open example.com
```
### CDP 模式(连接现有浏览器)
```bash
# 连接通过 Chrome DevTools Protocol 运行的浏览器
agent-browser --cdp 9222 snapshot
# 可控制Electron 应用、启用远程调试的 Chrome、WebView2 等
```
### 调试工具
```bash
agent-browser console # 查看控制台消息
agent-browser errors # 查看页面错误
agent-browser console --clear # 清空控制台
agent-browser errors --clear # 清空错误
agent-browser highlight @e1 # 高亮显示元素
```
## 示例场景
### 示例1表单提交
```bash
# 1. 导航到表单页面
agent-browser open https://example.com/form
# 2. 获取交互元素快照
agent-browser snapshot -i
# 输出textbox "邮箱" [ref=e1], textbox "密码" [ref=e2], button "提交" [ref=e3]
# 3. 填写并提交表单
agent-browser fill @e1 "user@example.com"
agent-browser fill @e2 "password123"
agent-browser click @e3
# 4. 等待结果并验证
agent-browser wait --load networkidle
agent-browser snapshot -i # 检查结果
```
### 示例2带认证的完整流程
```bash
# 首次:登录并保存状态
agent-browser open https://app.example.com/login
agent-browser fill "#email" "username"
agent-browser fill "#password" "password123"
agent-browser click "#submit"
agent-browser wait --url "**/dashboard"
agent-browser state save app-auth.json
# 后续使用:加载状态
agent-browser state load app-auth.json
agent-browser open https://app.example.com/dashboard
# 执行操作
agent-browser snapshot -i
agent-browser click @e1
```
### 示例3数据提取
```bash
# 提取列表数据
agent-browser open https://example.com/products
agent-browser wait --load networkidle
# 获取所有产品标题
for i in $(seq 1 10); do
agent-browser get text "@e$i" --json
done
# 或使用 CSS 选择器
agent-browser get text ".product-title"
```
### 示例4并行测试
```bash
# 会话1用户A
agent-browser --session userA open site.com
agent-browser --session userA fill "#email" "userA@test.com"
agent-browser --session userA fill "#password" "passA123"
# 会话2用户B同时运行
agent-browser --session userB open site.com
agent-browser --session userB fill "#email" "userB@test.com"
agent-browser --session userB fill "#password" "passB123"
```
## 最佳实践
### 1. 优先使用 Refs
-`snapshot -i` 获取 refs
- 使用 `@e1``@e2` 而非 CSS 选择器
- 页面变化后重新快照获取新 refs
### 2. 合理使用等待
- 页面加载:`wait --load networkidle`
- 元素出现:`wait @e1`
- 文本出现:`wait --text "成功"`
- 避免硬编码 sleep使用条件等待
### 3. 状态管理策略
- 首次登录后使用 `state save`
- 后续使用 `state load` 避免重复登录
- 敏感操作使用 `--session` 隔离
### 4. 错误处理
- 检查元素是否存在:`is visible @e1`
- 查看控制台日志:`console`
- 调试时使用 `--headed` 模式
### 5. 性能优化
- 使用 `-i` 参数限制快照输出
- 批量操作使用循环
- 合理使用等待避免超时
## 故障排除
### 常见问题
**1. "command not found: agent-browser" 错误**
```bash
# 错误原因agent-browser 未安装
# 解决方案:运行安装命令
npm install -g agent-browser
agent-browser install
```
**2. "Unsupported token @e1" 错误**
```bash
# 错误原因快照后页面已刷新refs 失效
# 解决方案:重新获取快照
agent-browser snapshot -i
agent-browser click @e1 # 使用新的 ref
```
**3. 元素找不到**
```bash
# 检查元素是否存在
agent-browser is visible @e1
# 等待元素出现
agent-browser wait @e1
# 使用语义化查找
agent-browser find role button click --name "提交"
```
**4. 登录状态丢失**
```bash
# 重新登录并保存状态
agent-browser state save auth.json
# 或设置 cookies
agent-browser cookies set session_id "value"
```
**5. 页面加载缓慢**
```bash
# 增加等待时间
agent-browser wait --load networkidle
agent-browser wait 5000
# 或设置超时
agent-browser set timeout 30000
```
## 平台支持
| 平台 | 原生二进制 | 回退方案 |
|------|-----------|----------|
| macOS ARM64 | ✓ | Node.js |
| macOS x64 | ✓ | Node.js |
| Linux ARM64 | ✓ | Node.js |
| Linux x64 | ✓ | Node.js |
| Windows x64 | ✓ | Node.js |
## 技术架构
agent-browser 采用客户端-守护进程架构:
1. **Rust CLI**(原生二进制)- 解析命令,与守护进程通信
2. **Node.js 守护进程** - 管理 Playwright 浏览器实例
3. **回退方案** - 如果原生二进制不可用,直接使用 Node.js
守护进程在首次命令时自动启动,并在命令间持久化以实现快速后续操作。
**浏览器引擎**:默认使用 Chromium。守护进程也支持通过 Playwright 协议使用 Firefox 和 WebKit。
## 相关资源
- 官方仓库https://github.com/vercel-labs/agent-browser
- 官方文档https://agent-browser.dev
- npm 包https://www.npmjs.com/package/agent-browser
## 许可证
Apache-2.0

View File

@@ -7,6 +7,13 @@ description: Git workflow best practices with commit conventions, tagging, and c
You are an expert in Git version control and repository management. You are an expert in Git version control and repository management.
## 功能文档
| 文档 | 说明 |
|------|------|
| [Commit Workflow](./commit-workflow.md) | 提交暂存文件,自动生成提交信息并创建版本标签 |
| [Push Workflow](./push-workflow.md) | 提交并推送到远程仓库的完整工作流 |
## Core Principles ## Core Principles
1. **Default Main Branch**: Use `main` as the primary branch (not `master`) 1. **Default Main Branch**: Use `main` as the primary branch (not `master`)

View File

@@ -0,0 +1,163 @@
# Git Commit Workflow
提交暂存文件,自动生成提交信息并创建版本标签的完整工作流。
## 概述
此工作流用于:
- 自动分析暂存区变更
- 根据 Conventional Commits 规范生成提交信息
- 检测项目类型并更新版本号
- 创建语义化版本标签
## 执行步骤
### 步骤 1: 检查暂存区
```bash
git diff --cached --name-only
```
- 如果暂存区为空,通知用户并停止
- 如果有文件,继续下一步
### 步骤 2: 收集信息(并行执行)
```bash
# 并行执行以下命令
git status
git diff --cached
git log --oneline -10
git tag --list | sort -V | tail -5
```
同时检查 `AGENTS.md` 文件获取:
- 仓库类型polyrepo/monorepo
- 版本规则
- 项目结构信息
### 步骤 3: 检测仓库类型
**Polyrepo单仓库**
- Tag 格式:`<version>`(如 `1.2.0`
**Monorepo多项目**
- Tag 格式:`<subproject>-<version>`(如 `ios-1.2.0`
- 检测特征:`packages/``apps/``services/` 目录
### 步骤 4: 检测项目类型和版本
| 项目类型 | 版本文件 | 版本字段 |
|---------|---------|---------|
| iOS | `*.xcodeproj/project.pbxproj` | `MARKETING_VERSION` |
| Node.js | `package.json` | `version` |
| Android (Groovy) | `app/build.gradle` | `versionName` |
| Android (Kotlin) | `app/build.gradle.kts` | `versionName` |
| Go | Git tag only | - |
| Python | `pyproject.toml` / `setup.py` | `version` |
| Rust | `Cargo.toml` | `version` |
### 步骤 5: 生成提交信息
遵循 Conventional Commits 格式:
```
<type>(<scope>): <subject>
```
**提交类型**
| Type | 描述 | 版本影响 |
|------|------|---------|
| `feat` | 新功能 | minor +1 |
| `fix` | Bug 修复 | patch +1 |
| `perf` | 性能优化 | patch +1 |
| `BREAKING CHANGE` | 破坏性变更 | major +1 |
| `docs` | 文档更新 | 无 |
| `style` | 代码格式 | 无 |
| `refactor` | 重构 | 无 |
| `test` | 测试 | 无 |
| `chore` | 维护任务 | 无 |
| `ci` | CI/CD 变更 | 无 |
| `build` | 构建配置 | 无 |
**提交语言**
- macOS/Linux使用中文
- Windows使用英文避免编码问题
**Monorepo Scope**
- 单项目变更:`feat(ios): 添加上传功能`
- 多项目变更:`chore: 更新共享依赖`
### 步骤 6: 确定新版本号
根据提交类型计算新版本:
**版本递增规则**
- `feat`minor +1`1.2.0``1.3.0`
- `fix`/`perf`patch +1`1.2.3``1.2.4`
- Breaking changemajor +1`1.2.3``2.0.0`
**不更新版本**
- `docs``test``refactor``style``build``ci``chore`
### 步骤 7: 更新版本文件并暂存
如果需要更新版本(步骤 6 确定了新版本号):
1. **更新版本文件**:将版本号写入对应的版本文件
2. **添加到暂存区**
```bash
git add <version-file>
```
3. **验证暂存**
```bash
git diff --cached --name-only
```
确认版本文件已在暂存区
### 步骤 8: 执行提交
```bash
git commit -m "<commit-message>"
```
### 步骤 9: 创建版本标签
仅在版本更新时创建(除非用户指定 "skip tag"
**Polyrepo**
```bash
git tag -a "1.2.0" -m "<commit-message>"
```
**Monorepo**
```bash
git tag -a "ios-1.2.0" -m "<commit-message>"
```
## 选项
- `skip tag` / `skip`:跳过标签创建
## 输出格式
```
✓ 提交成功
提交信息:[commit message]
版本标签:[tag](如果创建了)
要推送到远程仓库,请运行:/git-push
```
## 注意事项
- 此命令**不会推送**到远程,使用 `/git-push` 推送
- 暂存区为空时会提示用户先 `git add`
- 标签注释使用与提交相同的消息内容
## 相关文档
- [Git Workflow Best Practices](./SKILL.md)
- [Push Workflow](./push-workflow.md)

107
skill/git/push-workflow.md Normal file
View File

@@ -0,0 +1,107 @@
# Git Push Workflow
提交暂存文件,创建版本标签并推送到远程仓库的完整工作流。
## 概述
此工作流是 **All-in-One** 命令,组合了:
- `/git-commit` 的所有功能
- 推送提交到远程
- 推送标签到远程
## 执行步骤
### 步骤 1-9: 与 Commit Workflow 相同
参考 [Commit Workflow](./commit-workflow.md)
1. 检查暂存区(不能为空)
2. 收集变更信息和仓库状态
3. 检测仓库类型polyrepo/monorepo
4. 检测项目类型和版本
5. 生成提交信息Conventional Commits中文
6. 确定新版本号
7. 更新版本文件并添加到暂存区
8. 执行提交
9. 创建版本标签
### 步骤 10: 推送提交到远程
```bash
git push origin $(git branch --show-current)
```
### 步骤 11: 推送标签到远程
仅在创建了标签时执行:
**Polyrepo**
```bash
git push origin <version>
```
**Monorepo**
```bash
git push origin <subproject>-<version>
```
## 选项
- `skip tag` / `skip`:跳过标签创建
## 输出格式
```
✓ 提交并推送成功
分支:[branch]
提交信息:[commit message]
版本标签:[tag](如果创建了)
已推送到远程仓库origin
- 提交:[commit hash]
- 标签:[tag]
```
## 错误处理
### 暂存区为空
```
暂存区为空,请先使用 `git add` 添加文件。
```
### 推送失败
```
❌ 推送失败:[error message]
可能的解决方案:
1. 先拉取远程变更git pull origin <branch>
2. 检查网络连接
3. 检查远程仓库权限
```
### 标签已存在
```
❌ 标签推送失败tag already exists
解决方案:
1. 删除本地标签git tag -d <tag>
2. 更新版本号后重新提交
```
## 使用场景
| 场景 | 推荐命令 |
|------|---------|
| 本地提交,稍后审查 | `/git-commit` |
| 提交并立即推送 | `/git-push` |
| 仅推送已有提交 | `git push origin <branch>` |
| 仅推送标签 | `git push origin <tag>` |
## 相关文档
- [Git Workflow Best Practices](./SKILL.md)
- [Commit Workflow](./commit-workflow.md)

View File

@@ -1,663 +0,0 @@
# Git Quick Reference
Quick reference guide for common Git operations.
## File Changes and Status
### View Changed Files
```bash
# Show working directory status
git status
# Show short status
git status -s
# List changed files only (unstaged)
git diff --name-only
# List changed files only (staged)
git diff --cached --name-only
# or
git diff --staged --name-only
# Show file change statistics
git diff --stat
git diff --cached --stat
```
### View Detailed Changes
```bash
# View unstaged changes
git diff
# View staged changes
git diff --cached
# or
git diff --staged
# View specific file changes
git diff <file-path>
git diff --cached <file-path>
# View changes between commits
git diff <commit1>..<commit2>
git diff HEAD~1..HEAD
# View changes between branches
git diff main..feature-branch
```
## Staging and Committing
### Add Files to Staging
```bash
# Add specific file
git add <file-path>
# Add all files in directory
git add .
# Add all files in repository
git add -A
# Add files interactively
git add -p
# Add only modified files (not new files)
git add -u
```
### Check Staging Area
```bash
# List files in staging area
git diff --cached --name-only
# Show detailed staged changes
git diff --cached
```
### Commit Changes
```bash
# Simple commit
git commit -m "feat: add user authentication"
# Multi-line commit (macOS/Linux)
git commit -m "$(cat <<'EOF'
feat: add user authentication
- Add OAuth2 support
- Implement JWT tokens
- Add login/logout endpoints
EOF
)"
# Multi-line commit (Windows)
git commit -m "feat: add user authentication" \
-m "" \
-m "- Add OAuth2 support" \
-m "- Implement JWT tokens" \
-m "- Add login/logout endpoints"
# Commit with automatic staging
git commit -am "fix: resolve issue"
# Amend last commit (before push only!)
git commit --amend -m "new message"
```
## Tag Management
### Create Tags
```bash
# Create annotated tag
git tag -a "1.2.0" -m "feat: add new feature"
# Create lightweight tag
git tag "1.2.0"
# Create tag with multi-line message
git tag -a "1.2.1" \
-m "fix: resolve connection issue" \
-m "" \
-m "- Increase timeout to 30s" \
-m "- Add retry mechanism"
# Create tag for specific commit
git tag -a "1.2.0" <commit-hash> -m "message"
# Monorepo tag
git tag -a "ios-1.2.0" -m "feat(ios): add feature"
```
### List Tags
```bash
# List all tags
git tag
# List tags with pattern
git tag -l "v1.*"
# List recent tags (sorted)
git tag --list | sort -V | tail -5
# Show tag details
git show <tag-name>
```
### Push Tags
```bash
# Push single tag
git push origin <tag-name>
# Push all tags
git push --tags
# or
git push origin --tags
# Push commit and tag together
git push origin main && git push origin 1.2.0
```
### Delete Tags
```bash
# Delete local tag
git tag -d <tag-name>
# Delete remote tag
git push origin --delete <tag-name>
# or
git push origin :refs/tags/<tag-name>
# Delete multiple tags
git tag -d tag1 tag2 tag3
```
## Branch Operations
### View Branches
```bash
# Show current branch
git branch --show-current
# List local branches
git branch
# List all branches (local + remote)
git branch -a
# List remote branches only
git branch -r
# Show branch with last commit
git branch -v
```
### Create and Switch Branches
```bash
# Create new branch
git branch <branch-name>
# Create and switch to new branch (old way)
git checkout -b <branch-name>
# Create and switch to new branch (modern)
git switch -c <branch-name>
# Switch to existing branch (old way)
git checkout <branch-name>
# Switch to existing branch (modern)
git switch <branch-name>
# Switch to previous branch
git switch -
```
### Delete Branches
```bash
# Delete local branch (safe)
git branch -d <branch-name>
# Delete local branch (force)
git branch -D <branch-name>
# Delete remote branch
git push origin --delete <branch-name>
# or
git push origin :<branch-name>
```
## Pushing and Pulling
### Push Changes
```bash
# Push current branch
git push
# Push to specific remote and branch
git push origin main
# Push current branch to remote
git push origin $(git branch --show-current)
# Push with upstream tracking
git push -u origin <branch-name>
# Push all branches
git push --all
# Push all tags
git push --tags
# Force push (dangerous!)
git push --force
# Better: force push with lease
git push --force-with-lease
```
### Pull Changes
```bash
# Pull from tracked remote
git pull
# Pull from specific remote and branch
git pull origin main
# Pull with rebase
git pull --rebase
# Pull and prune deleted remote branches
git pull --prune
```
### Fetch Changes
```bash
# Fetch from all remotes
git fetch
# Fetch from specific remote
git fetch origin
# Fetch and prune deleted remote branches
git fetch --prune
# Fetch all branches and tags
git fetch --all --tags
```
## History and Logs
### View Commit History
```bash
# View recent commits
git log
# View compact history
git log --oneline
# View recent 10 commits
git log --oneline -10
# View history with graph
git log --graph --oneline --all
# View history with stats
git log --stat
# View history with patches
git log -p
```
### Search History
```bash
# Search commits by message
git log --grep="feature"
# Search by author
git log --author="John"
# Search by date
git log --since="2024-01-01"
git log --after="2 weeks ago"
git log --before="yesterday"
# Search by file
git log -- <file-path>
# Search code changes
git log -S "function_name"
```
### View Commit Details
```bash
# Show specific commit
git show <commit-hash>
# Show specific tag
git show <tag-name>
# Show HEAD commit
git show HEAD
# Show previous commit
git show HEAD~1
git show HEAD^
```
## Undoing Changes
### Discard Changes
```bash
# Discard unstaged changes in file
git checkout -- <file-path>
# or (modern)
git restore <file-path>
# Discard all unstaged changes
git checkout -- .
# or (modern)
git restore .
# Unstage file (keep changes)
git reset HEAD <file-path>
# or (modern)
git restore --staged <file-path>
# Unstage all files
git reset HEAD
# or (modern)
git restore --staged .
```
### Reset Commits
```bash
# Undo last commit, keep changes staged
git reset --soft HEAD~1
# Undo last commit, keep changes unstaged
git reset HEAD~1
# or
git reset --mixed HEAD~1
# Undo last commit, discard changes (dangerous!)
git reset --hard HEAD~1
# Reset to specific commit
git reset --hard <commit-hash>
```
### Revert Commits
```bash
# Create new commit that undoes a commit
git revert <commit-hash>
# Revert without committing
git revert -n <commit-hash>
# Revert multiple commits
git revert <commit1>..<commit2>
```
## Stash Operations
### Save Changes
```bash
# Stash current changes
git stash
# Stash with message
git stash save "work in progress"
# Stash including untracked files
git stash -u
# Stash including untracked and ignored files
git stash -a
```
### Apply Stash
```bash
# Apply most recent stash
git stash apply
# Apply and remove from stash list
git stash pop
# Apply specific stash
git stash apply stash@{2}
```
### Manage Stash
```bash
# List all stashes
git stash list
# Show stash changes
git stash show
git stash show -p
# Drop specific stash
git stash drop stash@{1}
# Clear all stashes
git stash clear
```
## Remote Operations
### View Remotes
```bash
# List remotes
git remote
# List remotes with URLs
git remote -v
# Show remote details
git remote show origin
```
### Manage Remotes
```bash
# Add remote
git remote add <name> <url>
# Remove remote
git remote remove <name>
# Rename remote
git remote rename <old-name> <new-name>
# Change remote URL
git remote set-url <name> <new-url>
```
## Configuration
### View Configuration
```bash
# View all config
git config --list
# View global config
git config --global --list
# View local config
git config --local --list
# View specific config
git config user.name
git config user.email
```
### Set Configuration
```bash
# Set user name
git config --global user.name "Your Name"
# Set user email
git config --global user.email "your.email@example.com"
# Set default branch name
git config --global init.defaultBranch main
# Set default editor
git config --global core.editor "code --wait"
# Set credential helper
git config --global credential.helper store
```
## Workflow Examples
### Standard Commit and Tag Workflow
```bash
# 1. Check status
git status
git diff --cached --name-only
# 2. Stage changes
git add .
# 3. Commit
git commit -m "feat: add user authentication"
# 4. Create tag
git tag -a "1.2.0" -m "feat: add user authentication"
# 5. Push commit and tag
git push origin main
git push origin 1.2.0
```
### Complete Staging to Push Workflow
```bash
# Check what files changed
git status
# View changes
git diff
# Stage specific files
git add src/auth.js src/api.js
# Verify staging
git diff --cached --name-only
# Commit with message
git commit -m "feat: implement OAuth2 authentication"
# Push to remote
git push origin main
```
### Push All Tags Workflow
```bash
# List local tags
git tag
# View recent tags
git tag --list | sort -V | tail -5
# Push all tags to remote
git push --tags
# Verify tags on remote
git ls-remote --tags origin
```
### Quick Status Check
```bash
# Full status
git status
# Changed files only
git diff --name-only
git diff --cached --name-only
# Recent commits and tags
git log --oneline -5
git tag --list | sort -V | tail -5
# Current branch
git branch --show-current
```
## Tips and Tricks
### Aliases
Add to `~/.gitconfig`:
```ini
[alias]
st = status
co = checkout
br = branch
ci = commit
unstage = restore --staged
last = log -1 HEAD
lg = log --graph --oneline --all
tags = tag -l --sort=-v:refname
```
Usage:
```bash
git st
git co main
git lg
```
### Useful One-Liners
```bash
# Delete all merged branches
git branch --merged | grep -v "\*" | xargs -n 1 git branch -d
# View file in specific commit
git show <commit>:<file-path>
# Count commits by author
git shortlog -sn
# Find when a line was changed
git blame <file-path>
# Show what changed in each commit for a file
git log -p <file-path>
# List files in a commit
git diff-tree --no-commit-id --name-only -r <commit>
```

View File

@@ -58,6 +58,7 @@ C:\Users\YourUsername\.config\gitea\
|---------|------|------| |---------|------|------|
| 环境配置 | [setup-guide.md](./setup-guide.md) | 首次使用引导,配置 Gitea URL 和 Token | | 环境配置 | [setup-guide.md](./setup-guide.md) | 首次使用引导,配置 Gitea URL 和 Token |
| Runner 管理 | [runner-management.md](./runner-management.md) | 创建、注册、管理 Gitea Act Runner | | Runner 管理 | [runner-management.md](./runner-management.md) | 创建、注册、管理 Gitea Act Runner |
| 自动创建脚本 | [create-runner.md](./create-runner.md) | 包含完整的 Runner 创建 Bash 脚本 |
| Workflow 生成 | [workflow-generator.md](./workflow-generator.md) | 根据项目类型生成 CI/CD workflow | | Workflow 生成 | [workflow-generator.md](./workflow-generator.md) | 根据项目类型生成 CI/CD workflow |
| 仓库操作 | [repository-operations.md](./repository-operations.md) | 创建和配置 Gitea 仓库 | | 仓库操作 | [repository-operations.md](./repository-operations.md) | 创建和配置 Gitea 仓库 |
| API 参考 | [api-reference.md](./api-reference.md) | Gitea API 常用接口 | | API 参考 | [api-reference.md](./api-reference.md) | Gitea API 常用接口 |

View File

@@ -0,0 +1,416 @@
---
description: 创建并启动 Gitea Actions Runner 的完整脚本
agent: general
---
# Create Runner Script
本文档包含用于创建 Gitea Actions Runner 的完整 Bash 脚本。该脚本支持 Host 模式和 Docker 模式。
## 脚本文件
你可以将以下内容保存为 `create_runner.sh` 并赋予执行权限 (`chmod +x create_runner.sh`)。
```bash
#!/bin/bash
# Gitea Runner Creation Script
# Generated by OpenCode Skill
set -e
# ==========================================
# 1. Choose Mode & Check Dependencies
# ==========================================
echo "请选择 Runner 运行模式:"
echo " 1. Host Mode (直接在宿主机运行,支持 macOS/iOS 原生构建)"
echo " 2. Docker Mode (在容器中运行,环境隔离,适合标准 Linux 构建)"
echo ""
read -p "请输入选项 [1/2] (默认 1): " mode_choice
if [ "$mode_choice" = "2" ]; then
RUNNER_MODE="docker"
echo "✅ 已选择: Docker Mode"
else
RUNNER_MODE="host"
echo "✅ 已选择: Host Mode"
fi
echo ""
# Check dependencies based on mode
if [ "$RUNNER_MODE" = "host" ]; then
echo "检查 act_runner 安装状态..."
if command -v act_runner &> /dev/null; then
version=$(act_runner --version 2>&1 | head -n1)
echo "✓ act_runner 已安装: $version"
else
echo "⚠️ act_runner 未安装"
echo "正在使用 Homebrew 安装..."
if ! command -v brew &> /dev/null; then
echo "❌ 需要先安装 Homebrew"
exit 1
fi
brew install act_runner
if [ $? -eq 0 ]; then
echo "✓ act_runner 安装成功"
else
echo "❌ act_runner 安装失败"
exit 1
fi
fi
else
# Docker mode checks
echo "检查 Docker 环境..."
if command -v docker &> /dev/null; then
if docker info &> /dev/null; then
docker_ver=$(docker --version)
echo "✓ Docker 已安装并运行: $docker_ver"
else
echo "❌ Docker 已安装但未运行"
echo " 请启动 Docker Desktop"
exit 1
fi
else
echo "❌ Docker 未安装"
echo " Docker 模式需要预先安装 Docker"
echo " 请访问 https://www.docker.com/products/docker-desktop/ 下载安装"
exit 1
fi
fi
echo ""
# ==========================================
# 2. Load Gitea Configuration
# ==========================================
config_file="$HOME/.config/gitea/config.env"
if [ ! -f "$config_file" ]; then
echo "❌ Gitea 配置不存在,请先运行 /gitea-reset"
exit 1
fi
source "$config_file"
if [ -z "$GITEA_URL" ] || [ -z "$GITEA_TOKEN" ]; then
echo "❌ Gitea 配置不完整 (缺少 URL 或 TOKEN)"
echo " 请运行 /gitea-reset 重新配置"
exit 1
fi
echo "✓ 已加载 Gitea 配置: $GITEA_URL"
echo ""
# ==========================================
# 3. Generate Runner Name
# ==========================================
if [ -n "$1" ]; then
runner_name="$1"
echo "使用指定的 Runner 名称: $runner_name"
else
hostname=$(hostname -s 2>/dev/null || echo "unknown")
runner_name="runner-$hostname-$RUNNER_MODE"
echo "生成 Runner 名称: $runner_name"
fi
if [[ ! "$runner_name" =~ ^[a-zA-Z0-9_-]+$ ]]; then
echo "❌ Runner 名称无效 (仅限字母、数字、下划线、连字符)"
exit 1
fi
echo ""
# ==========================================
# 4. Check Runner Existence
# ==========================================
runners_dir="$HOME/.config/gitea/runners"
runner_dir="$runners_dir/$runner_name"
if [ "$RUNNER_MODE" = "host" ]; then
if [ -d "$runner_dir" ]; then
echo "❌ Runner 目录已存在: $runner_dir"
echo " 请使用 /gitea-delete-runner 删除旧 Runner 或指定新名称"
exit 1
fi
else
# Docker mode: check directory AND container
if [ -d "$runner_dir" ]; then
echo "❌ Runner 配置目录已存在: $runner_dir"
exit 1
fi
if docker ps -a --format '{{.Names}}' | grep -q "^${runner_name}$"; then
echo "❌ Docker 容器已存在: $runner_name"
echo " 请先删除旧容器: docker rm -f $runner_name"
exit 1
fi
fi
# ==========================================
# 5. Detect System Environment & Labels
# ==========================================
echo "生成 Labels..."
if [ "$RUNNER_MODE" = "host" ]; then
OS=$(uname -s)
case "$OS" in
Darwin) os_label="macOS" ;;
Linux) os_label="ubuntu" ;;
*) os_label="unknown" ;;
esac
ARCH=$(uname -m)
case "$ARCH" in
arm64|aarch64) arch_label="ARM64" ;;
x86_64) arch_label="x64" ;;
*) arch_label="unknown" ;;
esac
combined=$(echo "${OS}-${ARCH}" | tr '[:upper:]' '[:lower:]')
labels="self-hosted:host,${os_label}:host,${arch_label}:host,${combined}:host"
else
# Docker mode uses standard labels mapping to images
# Format: label:docker://image
labels="ubuntu-latest:docker://node:16-bullseye,ubuntu-22.04:docker://node:16-bullseye,ubuntu-20.04:docker://node:16-buster,linux:docker://node:16-bullseye"
fi
echo "✓ Labels ($RUNNER_MODE):"
echo " $labels"
echo ""
# ==========================================
# 6. Create Runner Directory
# ==========================================
echo "创建 Runner 目录..."
mkdir -p "$runner_dir"/{cache,workspace}
if [ "$RUNNER_MODE" = "docker" ]; then
# Docker mode might strictly need data dir mapping
mkdir -p "$runner_dir/data"
fi
echo "✓ 目录: $runner_dir"
echo ""
# ==========================================
# 7. Get Registration Token
# ==========================================
echo "正在获取 Runner 注册 Token..."
# 默认尝试全局 Runner管理员权限
echo "尝试创建全局 Runner可用于所有组织和仓库..."
response=$(curl -s -w "\n%{http_code}" \
-H "Authorization: token $GITEA_TOKEN" \
"${GITEA_URL}/api/v1/admin/runners/registration-token")
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
# 如果全局 Runner 失败(权限不足),降级到组织 Runner
if [ "$http_code" != "200" ]; then
echo "⚠️ 全局 Runner 权限不足 (HTTP $http_code)"
echo " 全局 Runner 需要管理员 Token"
echo ""
echo "降级到组织 Runner..."
runner_level="organization"
if [ -n "$GITEA_DEFAULT_ORG" ]; then
org_name="$GITEA_DEFAULT_ORG"
else
read -p "请输入组织名称: " org_input
if [ -z "$org_input" ]; then
echo "❌ 必须指定组织名称"
exit 1
fi
org_name="$org_input"
fi
echo "使用组织: $org_name"
response=$(curl -s -w "\n%{http_code}" -X POST \
-H "Authorization: token $GITEA_TOKEN" \
"${GITEA_URL}/api/v1/orgs/$org_name/actions/runners/registration-token")
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
else
echo "✓ 使用全局 Runner"
runner_level="global"
fi
if [ "$http_code" != "200" ]; then
echo "❌ 获取注册 Token 失败 (HTTP $http_code)"
echo "$body"
exit 1
fi
# Need jq for parsing json
if ! command -v jq &> /dev/null; then
# Simple grep fallback if jq not available, but jq is better
registration_token=$(echo "$body" | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
else
registration_token=$(echo "$body" | jq -r '.token')
fi
if [ -z "$registration_token" ]; then
echo "❌ 无法解析注册 Token"
exit 1
fi
echo "✓ 注册 Token 已获取"
echo ""
# ==========================================
# 8. Start Runner (Register & Run)
# ==========================================
echo "启动 Runner..."
if [ "$RUNNER_MODE" = "host" ]; then
# Host Mode Config
cat > "$runner_dir/config.yaml" << EOF
log:
level: info
runner:
file: .runner
capacity: 1
timeout: 3h
shutdown_timeout: 30s
insecure: false
fetch_timeout: 5s
fetch_interval: 2s
labels: []
cache:
enabled: true
dir: "$runner_dir/cache"
host: "127.0.0.1"
port: 0
host:
workdir_parent: "$runner_dir/workspace"
EOF
echo "注册 Host Runner..."
act_runner register \
--config "$runner_dir/config.yaml" \
--instance "$GITEA_URL" \
--token "$registration_token" \
--name "$runner_name" \
--labels "$labels" \
--no-interactive
if [ $? -ne 0 ]; then
echo "❌ 注册失败"
exit 1
fi
echo "启动后台进程..."
nohup act_runner daemon --config "$runner_dir/config.yaml" \
> "$runner_dir/runner.log" 2>&1 &
runner_pid=$!
sleep 3
if ps -p $runner_pid > /dev/null 2>&1; then
echo "✓ Host Runner 正在后台运行 (PID: $runner_pid)"
# Save PID
echo $runner_pid > "$runner_dir/pid"
else
echo "❌ 启动失败,请检查日志"
exit 1
fi
else
# Docker Mode
# Strategy: Use environment variables for auto-registration on startup
# This avoids the "Instance Address Empty" issue seen with 'act_runner register' inside containers
cat > "$runner_dir/config.yaml" << EOF
log:
level: info
runner:
file: /data/.runner
capacity: 2
timeout: 3h
shutdown_timeout: 30s
insecure: false
fetch_timeout: 5s
fetch_interval: 2s
labels: []
cache:
enabled: true
dir: "/data/cache"
host: "host.docker.internal"
port: 9040
container:
# 使用 host 网络模式,确保 runner 和 job 容器共处一个网络,以便 cache 能够正常访问
network: "host"
privileged: false
options:
workdir_parent: /data/workspace
valid_volumes: []
docker_host: ""
force_pull: false
host:
workdir_parent: /data/workspace
EOF
echo "启动 Docker 容器 (自动注册)..."
# 使用 host 网络模式,确保 runner 和 job 容器共处一个网络,以便 cache 能够正常访问
docker run -d \
--name "$runner_name" \
--restart always \
--network host \
-v "$runner_dir/config.yaml:/config.yaml" \
-v "$runner_dir/data:/data" \
-v "/var/run/docker.sock:/var/run/docker.sock" \
-e GITEA_INSTANCE_URL="$GITEA_URL" \
-e GITEA_RUNNER_REGISTRATION_TOKEN="$registration_token" \
-e GITEA_RUNNER_NAME="$runner_name" \
-e GITEA_RUNNER_LABELS="$labels" \
gitea/act_runner:latest daemon --config /config.yaml
if [ $? -eq 0 ]; then
echo "✓ Docker Runner 容器已启动: $runner_name"
# 等待容器启动并查看日志
sleep 5
echo "容器日志:"
docker logs "$runner_name" 2>&1 | tail -20
else
echo "❌ 容器启动失败"
exit 1
fi
fi
echo ""
# ==========================================
# 9. Display Summary
# ==========================================
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "✅ Runner 创建成功!"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "基本信息:"
echo " 名称: $runner_name"
echo " 模式: $RUNNER_MODE"
echo " 状态: 🟢 运行中"
if [ "$RUNNER_MODE" = "host" ]; then
echo " PID: $runner_pid"
echo " 日志: $runner_dir/runner.log"
echo " 停止: kill \$(cat $runner_dir/pid)"
else
echo " 容器: $runner_name"
echo " 命令: docker logs -f $runner_name"
echo " docker stop $runner_name"
fi
echo ""
echo "配置文件: $runner_dir/config.yaml"
echo "Labels: $labels"
echo ""
```

View File

@@ -0,0 +1,303 @@
---
description: 交互式批量删除 Gitea Runners 脚本
agent: general
---
# Delete Runner Script
本文档包含用于交互式批量删除 Gitea Actions Runner 的完整 Bash 脚本。
## 功能特点
- **多选支持**:支持输入多个序号(如 `1,3``1 3`)或 `all` 进行批量删除。
- **双重清理**:同时从 Gitea 服务器注销 Runner 和删除本地配置/容器。
- **智能识别**:自动关联远程 Runner 状态与本地 Runner 目录。
- **安全检查**:删除前强制二次确认,防止误删。
## 脚本文件
你可以将以下内容保存为 `delete_runner.sh` 并赋予执行权限 (`chmod +x delete_runner.sh`)。
```bash
#!/bin/bash
# Gitea Runner Deletion Script
# Generated by OpenCode Skill
set -e
# ==========================================
# 1. Setup & Config
# ==========================================
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Config
CONFIG_FILE="$HOME/.config/gitea/config.env"
RUNNERS_BASE_DIR="$HOME/.config/gitea/runners"
if [ ! -f "$CONFIG_FILE" ]; then
echo -e "${RED}❌ 配置文件不存在: $CONFIG_FILE${NC}"
exit 1
fi
source "$CONFIG_FILE"
if [ -z "$GITEA_URL" ] || [ -z "$GITEA_TOKEN" ]; then
echo -e "${RED}❌ 配置无效: 缺少 URL 或 Token${NC}"
exit 1
fi
# Check requirements
if ! command -v jq &> /dev/null; then
echo -e "${RED}❌ 需要安装 jq 工具来解析 JSON${NC}"
exit 1
fi
echo "正在获取 Runner 列表..."
# ==========================================
# 2. Data Collection
# ==========================================
# Temporary files
REMOTE_LIST=$(mktemp)
LOCAL_MAP=$(mktemp)
FINAL_LIST=$(mktemp)
# 2.1 Fetch Remote Runners (Try Admin first, then Org)
# Note: Admin endpoint /api/v1/admin/runners lists all runners
HTTP_CODE=$(curl -s -w "%{http_code}" -o "$REMOTE_LIST" \
-H "Authorization: token $GITEA_TOKEN" \
"${GITEA_URL}/api/v1/admin/runners?page=1&limit=100")
if [ "$HTTP_CODE" != "200" ]; then
# Fallback to Org level if defined
if [ -n "$GITEA_DEFAULT_ORG" ]; then
HTTP_CODE=$(curl -s -w "%{http_code}" -o "$REMOTE_LIST" \
-H "Authorization: token $GITEA_TOKEN" \
"${GITEA_URL}/api/v1/orgs/${GITEA_DEFAULT_ORG}/actions/runners?page=1&limit=100")
fi
fi
if [ "$HTTP_CODE" != "200" ]; then
echo -e "${RED}❌ 无法获取 Runner 列表 (HTTP $HTTP_CODE)${NC}"
cat "$REMOTE_LIST"
rm "$REMOTE_LIST" "$LOCAL_MAP" "$FINAL_LIST"
exit 1
fi
# 2.2 Scan Local Directories to map UUID -> Path
# We need to find which local directory corresponds to which runner ID/UUID
echo "{}" > "$LOCAL_MAP"
if [ -d "$RUNNERS_BASE_DIR" ]; then
for d in "$RUNNERS_BASE_DIR"/*; do
if [ -d "$d" ]; then
# Check Host mode .runner
if [ -f "$d/.runner" ]; then
uuid=$(jq -r '.uuid' "$d/.runner" 2>/dev/null)
if [ -n "$uuid" ] && [ "$uuid" != "null" ]; then
# Add to JSON map
tmp=$(mktemp)
jq --arg uuid "$uuid" --arg path "$d" '.[$uuid] = $path' "$LOCAL_MAP" > "$tmp" && mv "$tmp" "$LOCAL_MAP"
fi
fi
# Check Docker mode data/.runner
if [ -f "$d/data/.runner" ]; then
uuid=$(jq -r '.uuid' "$d/data/.runner" 2>/dev/null)
if [ -n "$uuid" ] && [ "$uuid" != "null" ]; then
tmp=$(mktemp)
jq --arg uuid "$uuid" --arg path "$d" '.[$uuid] = $path' "$LOCAL_MAP" > "$tmp" && mv "$tmp" "$LOCAL_MAP"
fi
fi
fi
done
fi
# ==========================================
# 3. Display Interface
# ==========================================
# Combine Remote and Local info
# Output format: index | id | name | status | local_path
jq -r --slurpfile local "$LOCAL_MAP" '
.runners[] |
[.id, .uuid, .name, .status, ($local[0][.uuid] // "")] |
@tsv
' "$REMOTE_LIST" > "$FINAL_LIST"
count=$(wc -l < "$FINAL_LIST" | tr -d ' ')
if [ "$count" -eq 0 ]; then
echo "没有发现任何 Runners。"
rm "$REMOTE_LIST" "$LOCAL_MAP" "$FINAL_LIST"
exit 0
fi
echo ""
echo -e "${YELLOW}Gitea Runners 列表 (共 $count 个)${NC}"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
printf "%-4s | %-8s | %-20s | %-10s | %-30s\n" "序号" "ID" "名称" "状态" "本地目录"
echo "----------------------------------------------------------------------------"
i=1
declare -a runner_ids
declare -a runner_names
declare -a runner_paths
while IFS=$'\t' read -r id uuid name status local_path; do
status_icon="🔴"
if [ "$status" = "online" ] || [ "$status" = "idle" ] || [ "$status" = "active" ]; then
status_icon="🟢"
fi
local_mark=""
if [ -n "$local_path" ]; then
local_mark="$(basename "$local_path")"
else
local_mark="-"
fi
printf "%-4d | %-8s | %-20s | %s %-8s | %-30s\n" "$i" "$id" "${name:0:20}" "$status_icon" "$status" "$local_mark"
runner_ids[$i]=$id
runner_names[$i]=$name
runner_paths[$i]=$local_path
i=$((i+1))
done < "$FINAL_LIST"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# ==========================================
# 4. User Selection
# ==========================================
echo "请输入要删除的序号:"
echo " - 单个: 1"
echo " - 多选: 1,3,5 或 1 3 5"
echo " - 全部: all"
echo " - 退出: q"
echo ""
read -p "选择 > " selection
if [[ "$selection" =~ ^[qQ] ]]; then
echo "已取消。"
rm "$REMOTE_LIST" "$LOCAL_MAP" "$FINAL_LIST"
exit 0
fi
target_indices=()
if [ "$selection" = "all" ]; then
for ((j=1; j<=count; j++)); do
target_indices+=($j)
done
else
# Replace commas with spaces and iterate
for idx in ${selection//,/ }; do
# Validate number
if [[ "$idx" =~ ^[0-9]+$ ]] && [ "$idx" -ge 1 ] && [ "$idx" -le "$count" ]; then
target_indices+=($idx)
else
echo -e "${YELLOW}⚠️ 忽略无效序号: $idx${NC}"
fi
done
fi
if [ ${#target_indices[@]} -eq 0 ]; then
echo -e "${RED}未选择任何有效 Runner。${NC}"
rm "$REMOTE_LIST" "$LOCAL_MAP" "$FINAL_LIST"
exit 1
fi
# ==========================================
# 5. Confirmation
# ==========================================
echo ""
echo -e "${RED}⚠️ 警告: 即将删除以下 ${#target_indices[@]} 个 Runner:${NC}"
for idx in "${target_indices[@]}"; do
echo " - [${runner_ids[$idx]}] ${runner_names[$idx]}"
if [ -n "${runner_paths[$idx]}" ]; then
echo " └─ 本地目录: ${runner_paths[$idx]}"
fi
done
echo ""
echo "此操作将从服务器注销 Runner 并删除本地文件/容器。"
read -p "确认删除? (输入 yes 继续): " confirm
if [ "$confirm" != "yes" ]; then
echo "操作已取消。"
rm "$REMOTE_LIST" "$LOCAL_MAP" "$FINAL_LIST"
exit 0
fi
# ==========================================
# 6. Execution
# ==========================================
echo ""
echo "开始执行删除..."
for idx in "${target_indices[@]}"; do
r_id="${runner_ids[$idx]}"
r_name="${runner_names[$idx]}"
r_path="${runner_paths[$idx]}"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "正在处理: $r_name (ID: $r_id)"
# 6.1 Delete from Server
echo -n " 1. 从服务器注销... "
del_code=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token $GITEA_TOKEN" \
"${GITEA_URL}/api/v1/admin/actions/runners/${r_id}")
if [ "$del_code" = "204" ] || [ "$del_code" = "404" ]; then
echo -e "${GREEN}成功${NC}"
else
echo -e "${RED}失败 (HTTP $del_code)${NC}"
# Continue cleanup anyway
fi
# 6.2 Cleanup Local
if [ -n "$r_path" ] && [ -d "$r_path" ]; then
dir_name=$(basename "$r_path")
# Stop Docker container if name matches folder name (common convention)
if docker ps -a --format '{{.Names}}' | grep -q "^${dir_name}$"; then
echo -n " 2. 停止并删除 Docker 容器 ($dir_name)... "
docker rm -f "$dir_name" >/dev/null 2>&1
echo -e "${GREEN}完成${NC}"
fi
# Stop Host process (if PID file exists)
if [ -f "$r_path/pid" ]; then
pid=$(cat "$r_path/pid")
echo -n " 2. 停止本地进程 (PID: $pid)... "
kill "$pid" >/dev/null 2>&1 || true
echo -e "${GREEN}完成${NC}"
fi
echo -n " 3. 删除本地目录... "
rm -rf "$r_path"
echo -e "${GREEN}完成${NC}"
else
echo " - 本地目录未找到或已清理"
fi
done
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo -e "${GREEN}✅ 批量删除操作完成${NC}"
# Cleanup temps
rm "$REMOTE_LIST" "$LOCAL_MAP" "$FINAL_LIST"
```

View File

@@ -267,6 +267,8 @@ act_runner --version
7. 获取注册 token优先全局 7. 获取注册 token优先全局
8. 注册并启动 runner 8. 注册并启动 runner
> **提示**:你可以从 [create-runner.md](./create-runner.md) 获取完整的 Bash 脚本。
### 详细创建流程 ### 详细创建流程
当运行 `/gitea-create-runner` 命令时,会执行以下步骤: 当运行 `/gitea-create-runner` 命令时,会执行以下步骤:
@@ -640,23 +642,58 @@ log:
level: info level: info
runner: runner:
file: /path/to/.runner file: /data/.runner # 容器内路径
capacity: 2 capacity: 2
timeout: 3h timeout: 3h
labels: shutdown_timeout: 30s
- "ubuntu-latest:docker://catthehacker/ubuntu:act-latest" insecure: false
fetch_timeout: 5s
fetch_interval: 2s
labels: [] # 通过环境变量设置
cache: cache:
enabled: true enabled: true
dir: "/path/to/cache" dir: "/data/cache" # 容器内缓存目录
host: "192.168.0.103" # 主机 IP非 127.0.0.1 host: "host.docker.internal" # 宿主机地址Docker 特殊 DNS
port: 9000 port: 9040 # 缓存服务端口
container: container:
options: "--platform=linux/amd64" # 容器选项 # 使用 host 网络模式,确保 runner 和 job 容器共处一个网络,以便 cache 能够正常访问
network: "host" # 网络模式 network: "host"
privileged: false
options:
workdir_parent: /data/workspace
valid_volumes: []
docker_host: ""
force_pull: false
host:
workdir_parent: /data/workspace
``` ```
**Docker 容器启动命令**
```bash
docker run -d \
--name "$runner_name" \
--restart always \
--network host \
-v "$runner_dir/config.yaml:/config.yaml" \
-v "$runner_dir/data:/data" \
-v "/var/run/docker.sock:/var/run/docker.sock" \
-e GITEA_INSTANCE_URL="$GITEA_URL" \
-e GITEA_RUNNER_REGISTRATION_TOKEN="$token" \
-e GITEA_RUNNER_NAME="$runner_name" \
-e GITEA_RUNNER_LABELS="ubuntu-latest:docker://node:16-bullseye,ubuntu-22.04:docker://node:16-bullseye,linux:docker://node:16-bullseye" \
gitea/act_runner:latest daemon --config /config.yaml
```
**关键配置说明**
- `--network host`:使用 host 网络模式,确保 runner 和 job 容器共处一个网络,以便 cache 能够正常访问
- `host.docker.internal`Docker 内部 DNS指向宿主机
- 环境变量自动注册:容器启动时自动完成 Runner 注册
- `/var/run/docker.sock`:允许容器内创建兄弟容器执行 jobs
## 多 Runner 缓存共享 ## 多 Runner 缓存共享
### 方案 A: Master-Slave 模式(推荐 2-3 个 runner ### 方案 A: Master-Slave 模式(推荐 2-3 个 runner
@@ -778,6 +815,64 @@ crontab -e
/gitea-list-runners /gitea-list-runners
``` ```
**API 调用详情**
1. **加载配置**
```bash
source ~/.config/gitea/config.env
```
2. **调用 API**
```bash
curl -s -H "Authorization: token $GITEA_TOKEN" \
"${GITEA_URL}/api/v1/admin/actions/runners"
```
3. **响应结构**
```json
{
"runners": [...],
"total_count": 1
}
```
4. **解析每个 Runner**
- `id`: Runner ID
- `name`: Runner 名称
- `status`: 状态("online"/"offline"
- `busy`: 是否忙碌true/false
- `ephemeral`: 是否临时true/false
- `labels`: 标签数组
5. **状态图标**
- 🟢 在线 - `status: "online"`
- 🔴 离线 - `status: "offline"`
- ⚠️ 未知 - 无法确定
6. **输出格式**
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Gitea 全局 Runners
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
服务器: [server_url]
总计: N 个全局 runner
[runner-name]
状态: 🟢/🔴 [在线/离线]
ID: [id]
忙碌: 是/否
临时: 是/否
标签: [comma-separated labels]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
**注意**
- 需要管理员 API Token
- 正确的 API 端点是 `/api/v1/admin/actions/runners`(不是 `/api/v1/admin/runners`
- 使用 `jq` 解析 JSON 响应
### 启动 Runner ### 启动 Runner
```bash ```bash

151
skill/opencode/SKILL.md Normal file
View File

@@ -0,0 +1,151 @@
---
name: opencode
description: Create and manage OpenCode commands and skills with templates and best practices. Use this skill when users ask to create commands or skills.
---
# OpenCode Command and Skill Management
You are an expert in OpenCode configuration and extension development. This skill serves as the entry point for creating and managing OpenCode commands and skills.
**Trigger Phrases**: When users mention any of the following, automatically use this skill:
- "创建command", "创建命令", "make command", "create command"
- "创建skill", "创建技能", "make skill", "create skill"
- "添加command", "添加命令", "add command"
- "添加skill", "添加技能", "add skill"
- "opcode command", "opencode skill"
## Overview
OpenCode extensions are organized into two main types:
- **Commands**: User-invoked prompts for repetitive tasks, defined in `command/` directory
- **Skills**: Reusable behavior definitions for agents, defined in `skill/<name>/SKILL.md`
## Detailed Guides
This skill folder contains comprehensive guides for command and skill creation:
### Command Creation
For detailed command creation guidelines, refer to:
- `skill/opencode/command-creation.md` - Complete guide to creating OpenCode commands
- Includes: file structure, templates, best practices, troubleshooting
### Skill Creation
For detailed skill creation guidelines, refer to:
- `skill/opencode/skill-creation.md` - Complete guide to creating OpenCode skills
- Includes: directory structure, naming rules, templates, testing
## Quick Start
### To Create a Command
1. Determine command name (kebab-case, descriptive)
2. **Default location**: global (`~/.config/opencode/command/`)
3. Create file: `<command-name>.md`
4. Add frontmatter with `description`
5. Write template with `$ARGUMENTS` support
### To Create a Skill
1. Validate skill name (lowercase, hyphens, alphanumeric)
2. **Default location**: global (`~/.config/opencode/skill/<skill-name>/`)
3. Create directory: `skill/<skill-name>/`
4. Create `SKILL.md` with required frontmatter
5. Add structured content: Purpose, Usage, Examples, Troubleshooting
## Automatic Name Generation
When users request command or skill creation, names are automatically generated based on the description to provide a seamless experience.
### For Commands:
1. **Keyword Extraction**: Identify action verbs and target nouns from the description
2. **English Conversion**: Convert Chinese keywords to English equivalents (e.g., "创建" → "create", "总结" → "summarize")
3. **Kebab-case Format**: Combine words with hyphens, all lowercase (e.g., "create-summary")
4. **Conflict Resolution**: Check if name exists in `command/` directory, append numeric suffix if needed
### For Skills:
1. **Function Extraction**: Identify core functionality from the description
2. **Simplified Naming**: Use lowercase, hyphen-separated words describing the skill's purpose
3. **Validation**: Ensure name follows `[a-z0-9-]+` pattern
4. **Conflict Check**: Verify uniqueness in `skill/` directory
### Examples:
- "创建command用于归纳总结当前对话中有价值的内容" → `summarize-conversation`
- "创建skill用于管理git工作流" → `git-workflow`
- "添加命令来处理图片压缩" → `compress-images`
- "创建技能用于代码审查" → `code-review`
### User Override:
If users explicitly provide a name in their request, use the provided name instead of auto-generation.
## Response Guide for Creation Requests
When users ask to create commands or skills, follow this structured approach:
### For "创建command" or "创建命令" requests:
1. **自动生成名称**: 基于用户描述自动生成 kebab-case 命令名称
- 从描述中提取关键词(动词+名词)
- 转换为英文 kebab-case 格式
- 如果名称已存在,添加数字后缀(如 `-2`, `-3`
2. **验证名称**: 确保名称符合 kebab-case 规范
3. **默认位置**: 全局 (`~/.config/opencode/command/`)
4. **创建模板**:
- 生成包含 `description` 的 frontmatter
- 创建支持 `$ARGUMENTS` 的模板
- 包含使用示例
5. **写入文件**: 在默认位置创建命令文件
6. **测试**: 验证文件存在且格式正确
### For "创建skill" or "创建技能" requests:
1. **自动生成名称**: 基于用户描述自动生成 skill 名称
- 从描述中提取核心功能关键词
- 转换为小写字母、连字符格式
- 如果名称已存在,添加数字后缀
2. **验证名称**: 确保名称符合命名规则(小写字母、连字符、字母数字)
3. **默认位置**: 全局 (`~/.config/opencode/skill/<name>/`)
4. **创建目录**: `skill/<name>/`
5. **创建 SKILL.md**:
- 包含 `name``description` 的 frontmatter
- 结构化内容Purpose, Usage, Examples, Best Practices, Troubleshooting
6. **写入文件**: 在默认位置创建完整的 SKILL.md 文件
7. **测试**: 验证技能可正常加载 `skill({ name: "<skill-name>" })`
### Sample Response Format:
```
我将帮你创建 [command/skill]。
基于您的描述,自动生成名称:[generated-name]
**自动命名规则**:
- 从描述中提取关键词(动词+名词)
- 转换为 kebab-case 格式(小写字母、连字符)
- 检查名称冲突,自动添加数字后缀
**文件详情**:
- 名称: [generated-name]
- 用途: [brief-description]
- 位置: 全局 (~/.config/opencode/[command|skill]/)
已创建 [file-path]
```markdown
[complete file content]
```
要测试,请运行:[/command-name] 或 skill({ name: "skill-name" })
```
## Resources
- [OpenCode Skills Documentation](https://opencode.ai/docs/skills)
- [OpenCode Commands Documentation](https://opencode.ai/docs/commands)
- [OpenCode Configuration Guide](https://opencode.ai/docs/config)
- [GitHub Repository](https://github.com/anomalyco/opencode)
## Updates and Maintenance
1. **Regular Review**: Periodically review and update commands/skills
2. **Version Tracking**: Use Git to track changes
3. **Community Sharing**: Share useful commands/skills with community
4. **Feedback Integration**: Incorporate user feedback for improvements
---
*Last updated: 2026-01-15*

View File

@@ -0,0 +1,201 @@
# Command Creation Guide
## Overview
OpenCode commands are user-invoked prompts for repetitive tasks, defined in the `command/` directory.
## File Location
- **Default location (Global)**: `~/.config/opencode/command/<name>.md`
- **Project-specific**: `.opencode/command/<name>.md` (when needed)
## Command Structure
Each command file must contain YAML frontmatter followed by the prompt template.
### Required Frontmatter Fields
- `description`: Brief description shown in TUI (1-2 sentences)
### Optional Frontmatter Fields
- `agent`: Specific agent to execute this command
- `model`: Override default model
- `subtask`: Boolean to force subagent invocation
## Template Features
The command template supports several placeholders:
- `$ARGUMENTS`: All arguments passed to the command
- `$1`, `$2`, `$3`: Individual positional arguments
- `!``command``: Execute bash command and inject output
- `@filename`: Include file content in prompt
## Example Command
Create `~/.config/opencode/command/new-skill.md`:
```markdown
---
description: Create a new OpenCode skill with proper structure
---
Create a new OpenCode skill named "$ARGUMENTS" with comprehensive documentation.
**Skill Requirements:**
1. Directory: `skill/$ARGUMENTS/SKILL.md`
2. Frontmatter with `name` and `description`
3. Clear sections for usage, examples, best practices
4. Follow naming conventions: lowercase, hyphens, alphanumeric
**Steps:**
1. Create directory structure
2. Write SKILL.md with frontmatter
3. Include practical examples
4. Add troubleshooting section
Output the complete SKILL.md content for review.
```
## Best Practices
### Command Design
1. **Clear Purpose**: Each command should have a single, focused purpose
2. **Descriptive Names**: Use verbs that describe the action (e.g., `create-`, `review-`, `analyze-`)
3. **Argument Handling**: Use `$ARGUMENTS` or `$1`, `$2` for flexible input
4. **Error Handling**: Include validation in prompts
5. **Output Format**: Structure responses for easy parsing
### Naming Conventions
- Use kebab-case (lowercase with hyphens)
- Start with verb describing the action
- Keep names concise but descriptive
## Quick Reference
### Command Creation Checklist
- [ ] File name matches command name (kebab-case)
- [ ] Frontmatter includes `description`
- [ ] Template uses appropriate placeholders
- [ ] Includes examples of usage
- [ ] Tested with `/command-name` invocation
### Common Patterns
**Create a new command:**
```bash
# Create command file
touch ~/.config/opencode/command/my-command.md
# Edit with template
cat > ~/.config/opencode/command/my-command.md << 'EOF'
---
description: Description of my command
---
Command template with $ARGUMENTS support.
Example: /my-command argument1 argument2
EOF
```
## Testing and Validation
### Test Command Loading
```bash
# Check if command appears in TUI
# Type "/" in OpenCode TUI and search for your command
```
### Verify Syntax
```bash
# Check YAML frontmatter
head -20 command/my-command.md
```
## Troubleshooting
### Command Not Appearing
1. **Check file location**: Ensure command is in correct `command/` directory
2. **Verify frontmatter**: Must have `description` field
3. **Check permissions**: No restrictive permissions blocking command
4. **Restart OpenCode**: Some changes require restart
### Common Errors
- **"Command not found"**: File not in correct location or missing `.md` extension
- **"Invalid frontmatter"**: Missing required fields or YAML syntax error
## Integration with OpenCode Config
### Permissions Configuration
Add to `opencode.json`:
```json
{
"permission": {
"skill": {
"*": "allow",
"experimental-*": "ask",
"internal-*": "deny"
}
}
}
```
### Agent-Specific Settings
```json
{
"agent": {
"plan": {
"permission": {
"skill": {
"analysis-*": "allow"
}
}
}
}
}
```
## Response Guide for Command Creation Requests
When users ask to create commands, follow this structured approach:
1. **自动生成名称**: 基于用户描述自动生成 kebab-case 命令名称
- 从描述中提取关键词(动词+名词)
- 转换为英文 kebab-case 格式
- 如果名称已存在,添加数字后缀(如 `-2`, `-3`
2. **验证名称**: 确保名称符合 kebab-case 规范
3. **默认位置**: 全局 (`~/.config/opencode/command/`) - commands are created here by default
4. **创建模板**:
- 生成包含 `description` 的 frontmatter
- 创建支持 `$ARGUMENTS` 的模板
- 包含使用示例
5. **写入文件**: 创建命令文件并写入内容
6. **测试**: 验证文件存在且格式正确
### Sample Response Format:
```
我将帮你创建命令。
基于您的描述,自动生成名称:[generated-name]
**自动命名规则**:
- 从描述中提取关键词(动词+名词)
- 转换为 kebab-case 格式(小写字母、连字符)
- 检查名称冲突,自动添加数字后缀
**文件详情**:
- 名称: [generated-name]
- 用途: [brief-description]
- 位置: 全局 (~/.config/opencode/command/)
已创建 [file-path]
```markdown
[complete file content]
```
要测试,请运行:[/command-name]
```
## Resources
- [OpenCode Commands Documentation](https://opencode.ai/docs/commands)
- [OpenCode Configuration Guide](https://opencode.ai/docs/config)
---
*Last updated: 2026-01-15*

View File

@@ -0,0 +1,251 @@
# Skill Creation Guide
## Overview
OpenCode skills are reusable behavior definitions for agents, defined in `skill/<name>/SKILL.md` files.
## Directory Structure
**Default location (Global):**
```
~/.config/opencode/skill/
└── <skill-name>/
└── SKILL.md
```
**Project-specific location (when needed):**
```
.opencode/skill/
└── <skill-name>/
└── SKILL.md
```
## Skill File Requirements
### Frontmatter (Required)
- `name`: Skill name (must match directory name)
- `description`: Concise description (1-1024 characters)
### Frontmatter (Optional)
- `license`: License identifier
- `compatibility`: Compatibility constraints
- `metadata`: Key-value pairs for additional context
## Naming Rules
Skill names must:
- Be 1-64 characters
- Use lowercase alphanumeric with single hyphens
- Not start or end with hyphen
- Not contain consecutive hyphens
- Match regex: `^[a-z0-9]+(-[a-z0-9]+)*$`
## Skill Content Structure
A well-structured skill should include:
1. **Introduction**: Purpose and scope
2. **Usage Instructions**: When and how to use the skill
3. **Examples**: Practical implementation examples
4. **Best Practices**: Recommended approaches
5. **Troubleshooting**: Common issues and solutions
6. **References**: Related documentation
## Example Skill Template
```markdown
---
name: example-skill
description: Brief description of what this skill does
---
# Skill Title
## Purpose
Explain what this skill helps achieve and when to use it.
## Core Concepts
- Key principle 1
- Key principle 2
## Usage
Step-by-step instructions for using this skill.
## Examples
### Basic Example
```bash
# Example code or commands
```
### Advanced Example
Detailed example with explanation.
## Best Practices
1. Recommended approach 1
2. Recommended approach 2
## Troubleshooting
| Issue | Solution |
|-------|----------|
| Common problem | How to fix it |
## References
- [Documentation link](https://opencode.ai/docs)
- Related skills or commands
```
## Best Practices
### Skill Development
1. **Modular Design**: Keep skills focused on specific domains
2. **Comprehensive Documentation**: Include examples and edge cases
3. **Consistent Formatting**: Follow existing skill patterns
4. **Testing**: Verify skill loads correctly with `skill({ name: "skill-name" })`
5. **Version Control**: Track skill changes in Git
### Organization
1. **Default location**: Global (`~/.config/opencode/skill/`) - skills are created here by default for reuse across projects
2. **Naming Conventions**: Use kebab-case for all skill names
3. **Documentation**: Maintain README or index of available skills
4. **Permissions**: Configure access controls in `opencode.json`
## Quick Reference
### Skill Creation Checklist
- [ ] Directory name matches skill name
- [ ] SKILL.md contains required frontmatter
- [ ] Description is 1-1024 characters
- [ ] Name follows naming rules
- [ ] Content includes usage and examples
- [ ] Skill loads without errors
### Common Patterns
**Create a new skill:**
```bash
# Create skill directory
mkdir -p ~/.config/opencode/skill/my-skill
# Create SKILL.md
cat > ~/.config/opencode/skill/my-skill/SKILL.md << 'EOF'
---
name: my-skill
description: Description of my skill
---
# My Skill
## Usage
Instructions here.
## Examples
Example content.
EOF
```
## Testing and Validation
### Test Skill Loading
```bash
# In OpenCode session
skill({ name: "my-skill" })
```
### Verify Syntax
```bash
# Check YAML frontmatter
head -20 skill/my-skill/SKILL.md
# Validate naming
echo "skill-name" | grep -E '^[a-z0-9]+(-[a-z0-9]+)*$'
```
## Troubleshooting
### Skill Not Loading
1. **Directory name**: Must match skill name in frontmatter
2. **File name**: Must be `SKILL.md` (all caps)
3. **Frontmatter**: Requires `name` and `description`
4. **Naming rules**: Verify name follows conventions
5. **Permissions**: Check `opencode.json` permissions
### Common Errors
- **"Skill not found"**: Directory name mismatch or missing SKILL.md
- **"Invalid frontmatter"**: Missing required fields or YAML syntax error
- **"Permission denied"**: Skill blocked by permission configuration
## Integration with OpenCode Config
### Permissions Configuration
Add to `opencode.json`:
```json
{
"permission": {
"skill": {
"*": "allow",
"experimental-*": "ask",
"internal-*": "deny"
}
}
}
```
### Agent-Specific Settings
```json
{
"agent": {
"plan": {
"permission": {
"skill": {
"analysis-*": "allow"
}
}
}
}
}
```
## Response Guide for Skill Creation Requests
When users ask to create skills, follow this structured approach:
1. **自动生成名称**: 基于用户描述自动生成 skill 名称
- 从描述中提取核心功能关键词
- 转换为小写字母、连字符格式
- 如果名称已存在,添加数字后缀
2. **验证名称**: 确保名称符合命名规则(小写字母、连字符、字母数字)
3. **默认位置**: 全局 (`~/.config/opencode/skill/<name>/`) - skills are created here by default
4. **创建 SKILL.md**:
- 包含 `name``description` 的 frontmatter
- 结构化内容Purpose, Usage, Examples, Best Practices, Troubleshooting
5. **写入文件**: 创建完整的 SKILL.md 文件
6. **测试**: 验证技能可正常加载 `skill({ name: "<skill-name>" })`
### Sample Response Format:
```
我将帮你创建技能。
基于您的描述,自动生成名称:[generated-name]
**自动命名规则**:
- 从描述中提取核心功能关键词
- 转换为小写字母、连字符格式
- 检查名称冲突,自动添加数字后缀
**文件详情**:
- 名称: [generated-name]
- 主要功能: [brief-description]
- 位置: 全局 (~/.config/opencode/skill/)
已创建 [file-path]
```markdown
[complete file content]
```
要测试请运行skill({ name: "skill-name" })
```
## Resources
- [OpenCode Skills Documentation](https://opencode.ai/docs/skills)
- [OpenCode Configuration Guide](https://opencode.ai/docs/config)
- [GitHub Repository](https://github.com/anomalyco/opencode)
---
*Last updated: 2026-01-15*