From 1bf528acc87cdbcd2d9e1c199e2975a29018259e Mon Sep 17 00:00:00 2001
From: arch3rPro
Date: Tue, 24 Mar 2026 19:00:47 +0800
Subject: [PATCH] feat: add AI-powered 1Panel app builder skill
- Add skill configuration for generating 1Panel app configs via AI
- Include templates for data.yml and docker-compose.yml
- Add utility scripts for app generation, icon download, and validation
- Provide reference examples and usage documentation
- Update .gitignore to exclude .trae directory
- Update README.md with skill usage instructions
---
.gitignore | 2 +
README.md | 80 +++--
skills/README.md | 200 ++++++++++++
skills/SKILL.md | 404 +++++++++++++++++++++++
skills/evals/evals.json | 23 ++
skills/examples/example-usage.md | 237 ++++++++++++++
skills/references/1panel-examples.md | 394 ++++++++++++++++++++++
skills/scripts/download-icon.sh | 195 +++++++++++
skills/scripts/generate-app.sh | 416 ++++++++++++++++++++++++
skills/scripts/validate-app.sh | 257 +++++++++++++++
skills/templates/data.yml.tpl | 33 ++
skills/templates/docker-compose.yml.tpl | 20 ++
12 files changed, 2241 insertions(+), 20 deletions(-)
create mode 100644 skills/README.md
create mode 100644 skills/SKILL.md
create mode 100644 skills/evals/evals.json
create mode 100644 skills/examples/example-usage.md
create mode 100644 skills/references/1panel-examples.md
create mode 100644 skills/scripts/download-icon.sh
create mode 100644 skills/scripts/generate-app.sh
create mode 100644 skills/scripts/validate-app.sh
create mode 100644 skills/templates/data.yml.tpl
create mode 100644 skills/templates/docker-compose.yml.tpl
diff --git a/.gitignore b/.gitignore
index 1209cd0..1c15d8b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,5 @@
# Update
/update
+# Skills
+.trae
\ No newline at end of file
diff --git a/README.md b/README.md
index 51a59d8..ee5ef4e 100644
--- a/README.md
+++ b/README.md
@@ -18,16 +18,15 @@
### 📖 仓库介绍
- - 本仓库包含多个适用于 1Panel 的应用,旨在为用户提供简单、快速的安装与更新体验。应用均为开源项目,支持通过 1Panel 的计划任务功能自动化安装和更新。通过仓库提供的脚本,可以轻松地将应用集成到 1Panel 系统中。
- - 仓库主打优质应用合集,不追求大而全(很多基本用不上的应用会干扰检索查看),有推荐的应用可以在issue中进行提交
+
+- 本仓库包含多个适用于 1Panel 的应用,旨在为用户提供简单、快速的安装与更新体验。应用均为开源项目,支持通过 1Panel 的计划任务功能自动化安装和更新。通过仓库提供的脚本,可以轻松地将应用集成到 1Panel 系统中。
+- 仓库主打优质应用合集,不追求大而全(很多基本用不上的应用会干扰检索查看),有推荐的应用可以在issue中进行提交
### ⚠️ 仓库申明
-
- 非官方,第三方应用商店
- 不对任何原始镜像的有效性做出任何明示或暗示的保证或声明,安全性和风险自查
-- 个人仓库,可以Fork后自行更新,但是严禁未经授权,私自删除个人信息后合并发布
-
+- 个人仓库,可以Fork后自行更新,但是严禁未经授权,私自删除个人信息后合并发布
### 📱 应用列表
@@ -36,14 +35,10 @@
#### 🤖LLM免费API接口
- 支持一键部署AI免费API接口,使用方式请参考应用内**README介绍**
-
- **Free-API系列应用已下架,原项目由于供应链投毒,被植入恶意代码,请及时停止运行并删除这些服务!!!**
-
- 经过几天的排查和重构,已重新上架[GLM-Free-API](https://github.com/xiaoY233/GLM-Free-API)、[MiniMax-Free-API](https://github.com/xiaoY233/MiniMax-Free-API)、[Qwen-Free-API](https://github.com/xiaoY233/Qwen-Free-API)、[Kimi-Free-API](https://github.com/xiaoY233/Kimi-Free-API),[DeepSeek-Free-API](https://github.com/xiaoY233/DeepSeek-Free-API),欢迎各位对源码进行审查,如果不放心,建议还是暂停使用!
-
- 其他的Free-API系列看情况再搞了,后续主要更新上述几个Free-API兼容Gemini-cli和Claude的API接入。
-
@@ -103,8 +98,8 @@
- Jimeng-Free-API
-
+
+Jimeng-Free-API
🚀 即梦3.0逆向API【特长:图像生成顶流】
@@ -115,8 +110,8 @@
- Spark-Free-API
-
+
+Spark-Free-API
🚀 讯飞星火大模型逆向API【特长:办公助手】
@@ -144,8 +139,8 @@
- Step-Free-API
-
+
+Step-Free-API
🚀 阶跃星辰跃问Step 多模态大模型逆向API【特长:超强多模态】
@@ -156,8 +151,8 @@
- Metaso-Free-API
-
+
+Metaso-Free-API
🚀 秘塔AI搜索逆向API【特长:超强检索超长输出】
@@ -208,7 +203,6 @@
|
-
#### 📝 文档与内容管理
@@ -1222,8 +1216,54 @@ rm -rf /tmp/appstore_merge
echo "应用商店数据已更新"
```
+### 🤖 使用 AI 快速生成应用配置
+
+本仓库提供了 Skill 配置,支持在 Cursor、Windsurf、Claude Code 等 AI 客户端中快速生成 1Panel 应用配置。
+
+#### 📁 Skills 目录结构
+
+```
+skills/
+├── SKILL.md # 1Panel App Builder 技能定义
+├── README.md # 使用文档
+├── templates/ # 配置模板
+│ ├── data.yml.tpl # 应用元数据模板
+│ └── docker-compose.yml.tpl # 编排文件模板
+├── scripts/ # 工具脚本
+│ ├── generate-app.sh # 主生成脚本
+│ ├── download-icon.sh # 图标下载工具
+│ └── validate-app.sh # 配置验证工具
+├── references/ # 参考示例
+│ └── 1panel-examples.md
+└── examples/ # 使用示例
+ └── example-usage.md
+```
+
+#### 💡 使用示例
+
+只需向 AI 提供以下任一信息,即可自动生成完整的应用配置:
+
+```
+# GitHub 项目
+添加应用 AList https://github.com/alist-org/alist
+
+# docker-compose 文件
+根据这个 docker-compose.yml 生成 1Panel 应用配置
+
+# docker run 命令
+将这个 docker run 命令转换为 1Panel 应用:
+docker run -d --name=nginx -p 80:80 nginx:latest
+```
+
+#### ✨ AI 生成的配置包含
+
+- `data.yml` - 应用元数据(顶层)
+- `version/data.yml` - 参数定义(表单字段)
+- `docker-compose.yml` - Docker 编排文件
+- `README.md` - 中文文档
+- `README_en.md` - 英文文档
+- `logo.png` - 应用图标
-
-
+!\[Copyright-arch3rPro]\(https\://img.shields.io/badge/Copyright-arch3rPro-ff9800?style=flat\&logo=github\&logoColor=white null)
diff --git a/skills/README.md b/skills/README.md
new file mode 100644
index 0000000..03d794c
--- /dev/null
+++ b/skills/README.md
@@ -0,0 +1,200 @@
+# 1Panel App Builder
+
+快速生成符合 1Panel 本地应用商店规范的 APP 配置文件。
+
+## 功能特性
+
+- ✅ 支持多种输入源(GitHub、docker-compose、docker run、本地文件)
+- ✅ 自动抽取应用信息并生成标准化配置
+- ✅ 自动下载应用图标(支持多个图标源)
+- ✅ 生成中英文 README
+- ✅ 符合 1Panel 应用商店规范
+
+## 目录结构
+
+```
+1panel-app-builder/
+├── SKILL.md # 技能定义文件
+├── README.md # 使用文档
+├── templates/ # 配置模板
+│ ├── data.yml.tpl # 应用元数据模板
+│ └── docker-compose.yml.tpl # 编排文件模板
+├── scripts/ # 工具脚本
+│ ├── generate-app.sh # 主生成脚本
+│ └── download-icon.sh # 图标下载工具
+└── examples/ # 使用示例
+ └── example-usage.md
+```
+
+## 快速开始
+
+### 1. 基本用法
+
+```bash
+# GitHub 项目
+./scripts/generate-app.sh https://github.com/alist-org/alist
+
+# docker-compose 文件链接
+./scripts/generate-app.sh https://raw.githubusercontent.com/.../docker-compose.yml
+
+# docker run 命令
+./scripts/generate-app.sh "docker run -d --name=alist -p 5244:5244 xhofe/alist:v3.45.0"
+
+# 本地文件
+./scripts/generate-app.sh ./my-docker-compose.yml
+```
+
+### 2. 输出示例
+
+```
+./apps/alist/v3.45.0/
+├── data.yml # 应用元数据
+├── docker-compose.yml # 编排文件
+├── logo.png # 应用图标
+├── README.md # 中文简介
+└── README_en.md # 英文简介
+```
+
+### 3. 生成的配置文件
+
+#### data.yml 示例
+
+```yaml
+name: AList
+tags:
+ - 实用工具
+ - 云存储
+title: 支持多存储的文件列表程序和私人网盘
+description: 支持多存储的文件列表程序和私人网盘
+additionalProperties:
+ key: alist
+ name: AList
+ tags:
+ - Storage
+ - Tool
+ shortDescZh: 支持多存储的文件列表程序和私人网盘
+ shortDescEn: Supporting multi-storage file listing program
+ website: https://alist.nn.ci/
+ github: https://github.com/alist-org/alist
+ architectures:
+ - amd64
+ - arm64
+```
+
+#### docker-compose.yml 示例
+
+```yaml
+services:
+ alist:
+ container_name: ${CONTAINER_NAME}
+ restart: always
+ networks:
+ - 1panel-network
+ ports:
+ - "${PANEL_APP_PORT_HTTP}:5244"
+ volumes:
+ - ./data/data:/opt/alist/data
+ environment:
+ - PUID=0
+ - PGID=0
+ - UMASK=022
+ image: xhofe/alist:v3.45.0
+ labels:
+ createdBy: "Apps"
+networks:
+ 1panel-network:
+ external: true
+```
+
+## 高级用法
+
+### 指定输出目录
+
+```bash
+./scripts/generate-app.sh https://github.com/alist-org/alist ./my-apps
+```
+
+### 单独下载图标
+
+```bash
+./scripts/download-icon.sh alist ./logo.png 200
+```
+
+### 图标源优先级
+
+1. [Dashboard Icons](https://dashboardicons.com/icons)
+2. [Simple Icons](https://simpleicons.org/)
+3. [selfh.st Icons](https://selfh.st/icons/)
+
+## 依赖工具
+
+必需:
+- `bash` - 脚本执行环境
+- `curl` - HTTP 请求
+- `jq` - JSON 解析
+- `yq` - YAML 解析(可选,用于高级解析)
+
+可选:
+- `ImageMagick` (convert) - 图标尺寸调整
+- `sips` (macOS) - 图标尺寸调整
+- `tree` - 目录树显示
+
+## 配置模板说明
+
+### data.yml 模板变量
+
+| 变量 | 说明 | 示例 |
+|------|------|------|
+| `${APP_NAME}` | 应用名称 | AList |
+| `${APP_KEY}` | 应用键名 | alist |
+| `${TITLE_ZH}` | 中文标题 | 文件列表程序 |
+| `${DESC_ZH}` | 中文描述 | 支持多存储... |
+| `${TAG_1}` | 标签1 | 实用工具 |
+| `${WEBSITE}` | 官网 | https://alist.nn.ci/ |
+| `${GITHUB}` | GitHub | https://github.com/alist-org/alist |
+
+### docker-compose.yml 模板变量
+
+| 变量 | 说明 | 示例 |
+|------|------|------|
+| `${SERVICE_NAME}` | 服务名 | alist |
+| `${IMAGE}` | 镜像名 | xhofe/alist |
+| `${TAG}` | 镜像标签 | v3.45.0 |
+| `${PORT}` | 端口 | 5244 |
+
+## 下一步操作
+
+生成配置后:
+
+1. ✅ 检查 `data.yml` 中的应用信息是否准确
+2. ✅ 补充完善应用描述和标签
+3. ✅ 替换 `logo.png` 为合适的应用图标
+4. ✅ 测试 `docker-compose.yml` 是否正常工作
+5. ✅ 提交到 1Panel 应用商店仓库
+
+## 常见问题
+
+### Q: 图标下载失败怎么办?
+
+A: 手动从以下网站下载图标:
+- https://dashboardicons.com/icons?q=<应用名>
+- https://simpleicons.org/?q=<应用名>
+- https://selfh.st/icons/
+
+### Q: 如何处理多服务应用?
+
+A: 生成后手动编辑 `docker-compose.yml`,添加其他服务。
+
+### Q: 版本号如何确定?
+
+A: 默认从镜像标签提取,也可手动指定。
+
+## 参考资源
+
+- [1Panel 官方文档](https://1panel.cn/docs/)
+- [1Panel 应用商店仓库](https://github.com/1Panel-dev/appstore)
+- [Docker Compose 文档](https://docs.docker.com/compose/)
+
+## 许可证
+
+MIT License
diff --git a/skills/SKILL.md b/skills/SKILL.md
new file mode 100644
index 0000000..d06696b
--- /dev/null
+++ b/skills/SKILL.md
@@ -0,0 +1,404 @@
+---
+name: 1panel-app-builder
+description: >
+ Build 1Panel local app store configurations from Docker deployments. Use when:
+ - User provides a GitHub project link and wants to add it to 1Panel app store
+ - User has a docker-compose.yml or docker run command and needs 1Panel app format
+ - User wants to create a local app for 1Panel panel
+ - User mentions "1Panel app", "1Panel 应用商店", "本地应用", "app store", or similar
+
+ Supports: GitHub repos, Docker Hub images, docker-compose files, docker run commands.
+ Output: Complete app folder with data.yml, docker-compose.yml, logo.png, README.md
+
+ Always use this skill for 1Panel app packaging - it knows the exact directory structure,
+ variable naming conventions (PANEL_APP_PORT_HTTP, CONTAINER_NAME), and 1panel-network
+ requirements that are easy to get wrong without guidance.
+---
+
+# 1Panel App Store Builder
+
+Transform Docker deployments into 1Panel-compatible local app store packages.
+
+## Understanding 1Panel App Structure
+
+A valid 1Panel app follows this directory structure:
+
+```
+app-key/ # App identifier (lowercase, hyphenated)
+├── logo.png # App icon (64x64 or 128x128 recommended)
+├── data.yml # App metadata (top-level)
+├── README.md # Chinese documentation
+├── README_en.md # English documentation (optional)
+└── 1.0.0/ # Version directory (semver or "latest")
+ ├── data.yml # Parameter definitions (form fields)
+ ├── docker-compose.yml # Compose file with variable substitution
+ ├── data/ # Persistent data directory
+ └── scripts/ # Optional scripts
+ └── upgrade.sh # Upgrade script
+```
+
+## Step-by-Step Workflow
+
+### Step 1: Gather Source Information
+
+Based on user input type, extract Docker deployment details:
+
+**From GitHub Link:**
+1. Fetch the GitHub repository README.md
+2. Look for Docker installation instructions (docker run, docker-compose)
+3. Extract: image name, ports, volumes, environment variables
+4. Note: project name, description, official website, supported architectures
+
+**From docker-compose.yml:**
+1. Parse all services defined
+2. Extract: image versions, port mappings, volume mounts, environment variables
+3. Identify the main service (typically the one with web UI)
+
+**From docker run command:**
+1. Parse flags: `-p` (ports), `-v` (volumes), `-e` (env vars), `--name`
+2. Extract the image name and tag
+3. Identify exposed ports and data directories
+
+### Step 2: Generate App Key and Metadata
+
+**App Key Rules:**
+- Lowercase only
+- Use hyphens for multi-word names
+- Keep it short but descriptive
+- Examples: `alist`, `it-tools`, `n8n-zh`, `lobe-chat-data`
+
+**Required Metadata (top-level data.yml):**
+```yaml
+name: AppName # Display name (can have capitals)
+tags: # Chinese tags for categorization
+ - 开发工具
+ - 实用工具
+title: Brief Chinese description
+description: Same as title
+additionalProperties:
+ key: app-key # Must match directory name
+ name: AppName # Same as name above
+ tags: # English tags
+ - DevTool
+ - Utility
+ shortDescZh: Chinese description
+ shortDescEn: English description
+ description:
+ en: Full English description
+ zh: Full Chinese description
+ # Add more languages if available: ja, ko, ru, pt-br, ms, zh-Hant
+ type: website # or "runtime" for databases, "tool" for CLI tools
+ crossVersionUpdate: true # Usually true
+ limit: 0 # 0 = unlimited instances
+ recommend: 0 # 0-100, higher = more recommended
+ website: https://example.com # Official website
+ github: https://github.com/org/repo
+ document: https://docs.example.com
+ architectures: # Supported CPU architectures
+ - amd64
+ - arm64
+ # Add: arm/v7, arm/v6, s390x if supported
+```
+
+### Step 3: Define Parameters (version/data.yml)
+
+Parameters become UI form fields in 1Panel. Define user-configurable values:
+
+```yaml
+additionalProperties:
+ formFields:
+ # Port parameter example
+ - default: 8080
+ edit: true
+ envKey: PANEL_APP_PORT_HTTP # Variable name used in docker-compose
+ labelEn: Web Port
+ labelZh: Web端口
+ required: true
+ rule: paramPort # Validation rule
+ type: number # Field type
+ label: # Multi-language labels
+ en: Web Port
+ zh: Web端口
+ ja: Webポート
+ ko: Web 포트
+
+ # Text parameter example (for API keys, passwords, etc.)
+ - default: ""
+ edit: true
+ envKey: API_KEY
+ labelEn: API Key
+ labelZh: API密钥
+ required: false
+ rule: paramCommon
+ type: text
+
+ # Password parameter example
+ - default: "changeme"
+ edit: true
+ envKey: ADMIN_PASSWORD
+ labelEn: Admin Password
+ labelZh: 管理员密码
+ required: true
+ rule: paramCommon
+ type: password
+
+ # Select parameter example
+ - default: "sqlite"
+ edit: true
+ envKey: DATABASE_TYPE
+ labelEn: Database Type
+ labelZh: 数据库类型
+ required: true
+ type: select
+ values:
+ - label: SQLite
+ value: sqlite
+ - label: PostgreSQL
+ value: postgres
+```
+
+**Parameter Types:**
+- `number`: For ports, counts
+- `text`: For API keys, URLs, names
+- `password`: For secrets (masked input)
+- `select`: For dropdown choices
+- `boolean`: For toggle switches
+
+**Validation Rules:**
+- `paramPort`: Valid port number (1-65535)
+- `paramCommon`: Non-empty string
+- `paramExtUrl`: Valid URL format
+- Empty string: No validation
+
+### Step 4: Create docker-compose.yml
+
+Convert the original Docker deployment to use variable substitution:
+
+```yaml
+services:
+ app-name:
+ container_name: ${CONTAINER_NAME}
+ restart: always
+ networks:
+ - 1panel-network
+ ports:
+ - "${PANEL_APP_PORT_HTTP}:8080"
+ volumes:
+ - ./data:/app/data
+ environment:
+ - TZ=Asia/Shanghai
+ image: org/image:tag
+ labels:
+ createdBy: "Apps"
+networks:
+ 1panel-network:
+ external: true
+```
+
+**Critical Rules:**
+1. Always use `${CONTAINER_NAME}` for container_name
+2. Always use `restart: always`
+3. Always connect to `1panel-network` (external network)
+4. Port mapping uses `PANEL_APP_PORT_*` variables from data.yml
+5. Volume paths use relative `./data/` for persistence
+6. Add `labels: createdBy: "Apps"`
+7. Keep original environment variables but use defaults
+
+### Step 5: Create README Files
+
+**README.md (Chinese):**
+```markdown
+# AppName
+
+简短描述应用的功能和特点。
+
+## 功能特点
+
+- 特点1
+- 特点2
+- 特点3
+
+## 使用说明
+
+### 默认端口
+
+- Web界面: 8080
+
+### 默认账号密码
+
+- 用户名: admin
+- 密码: changeme (请在部署后立即修改)
+
+### 数据目录
+
+应用数据存储在 `./data` 目录。
+
+## 相关链接
+
+- 官方网站: https://example.com
+- GitHub: https://github.com/org/repo
+- 文档: https://docs.example.com
+```
+
+**README_en.md (English, optional):**
+```markdown
+# AppName
+
+Brief description of the application.
+
+## Features
+
+- Feature 1
+- Feature 2
+- Feature 3
+
+## Usage
+
+### Default Port
+
+- Web UI: 8080
+
+### Default Credentials
+
+- Username: admin
+- Password: changeme (change after deployment)
+
+## Links
+
+- Website: https://example.com
+- GitHub: https://github.com/org/repo
+```
+
+### Step 6: Download App Icon
+
+Search and download the app logo from these sources (in order):
+
+1. **Dashboard Icons**: https://dashboardicons.com/icons?q={app-name}
+2. **Simple Icons**: https://simpleicons.org/?q={app-name}
+3. **Selfh.st Icons**: https://selfh.st/icons/
+
+Save as `logo.png` in the app root directory.
+
+### Step 7: Create Data Directory Structure
+
+Create the `data/` directory inside the version folder:
+```bash
+mkdir -p app-key/version/data
+```
+
+This directory will be mounted as a volume for persistent data.
+
+## Quality Checklist
+
+Before delivering the app package, verify:
+
+- [ ] App key is lowercase with hyphens only
+- [ ] All required fields in top-level data.yml are present
+- [ ] Version data.yml has proper parameter definitions
+- [ ] docker-compose.yml uses variable substitution correctly
+- [ ] `1panel-network` is defined as external network
+- [ ] Volume paths use relative `./data/` format
+- [ ] README files are created with proper documentation
+- [ ] Logo file exists (logo.png)
+- [ ] Version directory follows semver or uses "latest"
+
+## Common Patterns
+
+### Database Applications
+```yaml
+# For apps that need a database (PostgreSQL, MySQL, etc.)
+# Include database as a separate service in docker-compose
+services:
+ app:
+ depends_on:
+ - db
+ db:
+ image: postgres:15
+ volumes:
+ - ./data/db:/var/lib/postgresql/data
+ environment:
+ - POSTGRES_DB=appdb
+ - POSTGRES_USER=appuser
+ - POSTGRES_PASSWORD=${DB_PASSWORD}
+```
+
+### Multi-Service Applications
+```yaml
+# For apps with multiple services (frontend + backend, etc.)
+services:
+ frontend:
+ image: org/frontend:tag
+ ports:
+ - "${PANEL_APP_PORT_HTTP}:80"
+ backend:
+ image: org/backend:tag
+ ports:
+ - "${PANEL_APP_PORT_API}:8080"
+```
+
+### Applications with Reverse Proxy
+```yaml
+# For apps that don't expose ports directly
+services:
+ app:
+ # No ports section - accessed through 1Panel's reverse proxy
+ expose:
+ - "8080"
+ networks:
+ - 1panel-network
+```
+
+## Automation Scripts
+
+Use the provided scripts for faster workflow:
+
+### generate-app.sh - 自动生成应用配置
+
+```bash
+# GitHub 项目
+./scripts/generate-app.sh https://github.com/alist-org/alist
+
+# docker-compose 文件
+./scripts/generate-app.sh ./docker-compose.yml
+
+# docker run 命令
+./scripts/generate-app.sh "docker run -d --name=nginx -p 80:80 nginx:latest"
+```
+
+### download-icon.sh - 下载应用图标
+
+```bash
+./scripts/download-icon.sh redis ./logo.png 200
+```
+
+### validate-app.sh - 验证配置完整性
+
+```bash
+./scripts/validate-app.sh ./apps/myapp
+```
+
+## Reference Files
+
+- `references/1panel-examples.md` - 完整的真实应用配置示例(AList、NocoDB等)
+- `examples/example-usage.md` - 使用示例和工作流程
+
+## Troubleshooting
+
+**Issue**: App won't start
+- Check if ports are already in use
+- Verify volume permissions
+- Check container logs: `docker logs ${CONTAINER_NAME}`
+
+**Issue**: Data not persisting
+- Ensure volumes are correctly mapped to `./data/`
+- Check directory permissions
+
+**Issue**: Environment variables not working
+- Verify variable names match between data.yml and docker-compose.yml
+- Check default values are appropriate
+
+**Issue**: 图标下载失败
+- 从以下网站手动下载:
+ - https://dashboardicons.com/icons?q={app-name}
+ - https://simpleicons.org/?q={app-name}
+ - https://selfh.st/icons/
diff --git a/skills/evals/evals.json b/skills/evals/evals.json
new file mode 100644
index 0000000..232ca5b
--- /dev/null
+++ b/skills/evals/evals.json
@@ -0,0 +1,23 @@
+{
+ "skill_name": "1panel-app-builder",
+ "evals": [
+ {
+ "id": 1,
+ "prompt": "帮我把这个项目打包成1Panel本地应用:https://github.com/0xJacky/nginx-ui 这是一个Nginx配置管理工具,用docker部署,默认端口是9000",
+ "expected_output": "Create a complete 1Panel app package for nginx-ui with proper directory structure, data.yml metadata, docker-compose.yml with variable substitution, README files, and placeholder logo",
+ "files": []
+ },
+ {
+ "id": 2,
+ "prompt": "我有一个docker-compose.yml文件,内容如下:\n```yaml\nversion: '3'\nservices:\n memos:\n image: neosmemo/memos:latest\n container_name: memos\n ports:\n - \"5230:5230\"\n volumes:\n - ./memos_data:/var/opt/memos\n restart: always\n```\n帮我生成1Panel应用商店的配置",
+ "expected_output": "Parse the docker-compose file and generate 1Panel app package for memos with converted docker-compose.yml using PANEL_APP_PORT_HTTP variable, proper data.yml with port parameter definition, and supporting files",
+ "files": []
+ },
+ {
+ "id": 3,
+ "prompt": "docker run -d --name umami -p 3000:3000 -e DATABASE_URL=postgresql://user:pass@db:5432/umami ghcr.io/umami-software/umami:postgresql-latest\n请帮我把这个umami网站统计工具做成1Panel应用",
+ "expected_output": "Parse the docker run command, extract port 3000, environment variable DATABASE_URL, and generate 1Panel app package with appropriate parameter fields for database URL configuration",
+ "files": []
+ }
+ ]
+}
diff --git a/skills/examples/example-usage.md b/skills/examples/example-usage.md
new file mode 100644
index 0000000..eaf530b
--- /dev/null
+++ b/skills/examples/example-usage.md
@@ -0,0 +1,237 @@
+# 使用示例
+
+## 示例 1:从 GitHub 项目生成
+
+```bash
+# 输入
+./scripts/generate-app.sh https://github.com/alist-org/alist
+
+# 输出
+./apps/alist/v3.45.0/
+├── data.yml
+├── docker-compose.yml
+├── logo.png
+├── README.md
+└── README_en.md
+```
+
+### 生成的 data.yml
+
+```yaml
+name: AList
+tags:
+ - 实用工具
+ - 云存储
+title: AList - 文件列表程序
+description: 支持多存储的文件列表程序和私人网盘
+additionalProperties:
+ key: alist
+ name: AList
+ tags:
+ - Storage
+ - Tool
+ shortDescZh: 支持多存储的文件列表程序和私人网盘
+ shortDescEn: Supporting multi-storage file listing program
+ website: https://alist.nn.ci/
+ github: https://github.com/alist-org/alist
+```
+
+### 生成的 docker-compose.yml
+
+```yaml
+services:
+ alist:
+ container_name: ${CONTAINER_NAME}
+ restart: always
+ networks:
+ - 1panel-network
+ ports:
+ - "${PANEL_APP_PORT_HTTP}:5244"
+ volumes:
+ - ./data/data:/opt/alist/data
+ environment:
+ - PUID=0
+ - PGID=0
+ - UMASK=022
+ image: xhofe/alist:v3.45.0
+ labels:
+ createdBy: "Apps"
+networks:
+ 1panel-network:
+ external: true
+```
+
+---
+
+## 示例 2:从 docker run 命令生成
+
+```bash
+# 输入
+./scripts/generate-app.sh "docker run -d --name=nginx -p 80:80 nginx:latest"
+
+# 输出
+./apps/nginx/latest/
+├── data.yml
+├── docker-compose.yml
+├── logo.png
+├── README.md
+└── README_en.md
+```
+
+### 生成的 docker-compose.yml
+
+```yaml
+services:
+ nginx:
+ container_name: ${CONTAINER_NAME}
+ restart: always
+ networks:
+ - 1panel-network
+ ports:
+ - "${PANEL_APP_PORT_HTTP}:80"
+ volumes:
+ - ./data/data:/app/data
+ environment:
+ - PUID=0
+ - PGID=0
+ - UMASK=022
+ image: nginx:latest
+ labels:
+ createdBy: "Apps"
+networks:
+ 1panel-network:
+ external: true
+```
+
+---
+
+## 示例 3:从 docker-compose 文件链接生成
+
+```bash
+# 输入
+./scripts/generate-app.sh https://raw.githubusercontent.com/portainer/portainer/develop/docker-compose.yml
+
+# 输出
+./apps/portainer/latest/
+├── data.yml
+├── docker-compose.yml
+├── logo.png
+├── README.md
+└── README_en.md
+```
+
+---
+
+## 示例 4:从本地文件生成
+
+```bash
+# 创建测试文件
+cat > /tmp/test-compose.yml << 'EOF'
+version: '3'
+services:
+ redis:
+ image: redis:7-alpine
+ ports:
+ - "6379:6379"
+ volumes:
+ - redis-data:/data
+
+volumes:
+ redis-data:
+EOF
+
+# 运行脚本
+./scripts/generate-app.sh /tmp/test-compose.yml ./my-apps
+
+# 输出
+./my-apps/redis/7-alpine/
+├── data.yml
+├── docker-compose.yml
+├── logo.png
+├── README.md
+└── README_en.md
+```
+
+---
+
+## 示例 5:单独下载图标
+
+```bash
+# 下载 Redis 图标
+./scripts/download-icon.sh redis ./redis-logo.png 200
+
+# 输出
+✓ 从 Simple Icons 下载成功
+✓ 图标下载完成: ./redis-logo.png
+```
+
+---
+
+## 示例 6:自定义输出目录
+
+```bash
+# 输出到指定目录
+./scripts/generate-app.sh https://github.com/portainer/portainer ~/my-1panel-apps
+
+# 输出
+/Users/username/my-1panel-apps/portainer/latest/
+├── data.yml
+├── docker-compose.yml
+├── logo.png
+├── README.md
+└── README_en.md
+```
+
+---
+
+## 完整工作流程示例
+
+```bash
+# 1. 生成应用配置
+./scripts/generate-app.sh https://github.com/alist-org/alist
+
+# 2. 查看生成的文件
+cd ./apps/alist/v3.45.0
+cat data.yml
+cat docker-compose.yml
+
+# 3. 手动优化配置
+# - 补充应用描述
+# - 添加合适的标签
+# - 替换 logo.png
+
+# 4. 测试 docker-compose
+docker-compose up -d
+
+# 5. 确认无误后,提交到应用商店
+git add .
+git commit -m "feat: add alist app"
+git push
+```
+
+---
+
+## 故障排除
+
+### 问题:图标下载失败
+
+```bash
+# 手动下载图标
+# 访问:https://dashboardicons.com/icons?q=alist
+# 下载后保存为 logo.png
+```
+
+### 问题:端口冲突
+
+```bash
+# 修改 docker-compose.yml 中的端口映射
+ports:
+ - "${PANEL_APP_PORT_HTTP}:5244" # 修改此处
+```
+
+### 问题:镜像版本不对
+
+```bash
+# 手动编辑 docker-compose.yml
+image: xhofe/alist:v3.45.0 # 修改版本号
+```
diff --git a/skills/references/1panel-examples.md b/skills/references/1panel-examples.md
new file mode 100644
index 0000000..d96d5a6
--- /dev/null
+++ b/skills/references/1panel-examples.md
@@ -0,0 +1,394 @@
+# 1Panel 应用商店参考示例
+
+本文件包含从 1Panel-Appstore 和 appstore 官方仓库提取的实际应用配置示例。
+
+## 目录
+
+1. [简单单服务应用](#简单单服务应用)
+2. [带数据库的应用](#带数据库的应用)
+3. [多端口应用](#多端口应用)
+4. [多服务应用](#多服务应用)
+5. [常见标签分类](#常见标签分类)
+
+---
+
+## 简单单服务应用
+
+### 示例:AList
+
+**目录结构:**
+```
+alist/
+├── logo.png
+├── data.yml # 顶层元数据
+├── README.md
+├── README_en.md
+└── 3.45.0/ # 版本目录
+ ├── data.yml # 参数定义
+ ├── docker-compose.yml
+ └── data/ # 数据目录
+```
+
+**顶层 data.yml:**
+```yaml
+name: AList
+tags:
+ - 实用工具
+ - 云存储
+title: 支持多存储的文件列表程序和私人网盘
+description: 支持多存储的文件列表程序和私人网盘
+additionalProperties:
+ key: alist
+ name: AList
+ tags:
+ - Storage
+ - Tool
+ shortDescZh: 支持多存储的文件列表程序和私人网盘
+ shortDescEn: Supporting multi-storage file listing program and private cloud storage
+ description:
+ en: Supporting multi-storage file listing program and private cloud storage
+ ja: 複数ストレージのファイルリスト表示プログラムとプライベートクラウドストレージのサポート
+ ms: Menyokong program senarai fail multi-penyimpanan dan penyimpanan awan peribadi
+ pt-br: Suporte para programa de listagem de arquivos em múltiplos armazenamentos e armazenamento em nuvem privado
+ ru: Поддержка программы отображения файлов в нескольких хранилищах и частного облачного хранилища
+ ko: 다중 저장소 파일 목록 프로그램 및 개인 클라우드 저장소 지원
+ zh-Hant: 支援多存儲檔案列出程序和私人雲端空間
+ zh: 支持多存储文件列出程序和私有云存储
+ type: website
+ crossVersionUpdate: true
+ limit: 0
+ recommend: 65
+ website: https://alist.nn.ci/
+ github: https://github.com/alist-org/alist
+ document: https://alist.nn.ci/zh/guide/
+ architectures:
+ - amd64
+ - arm64
+ - arm/v7
+ - arm/v6
+ - s390x
+```
+
+**版本 data.yml(参数定义):**
+```yaml
+additionalProperties:
+ formFields:
+ - default: 5244
+ edit: true
+ envKey: PANEL_APP_PORT_HTTP
+ labelEn: WebUI Port
+ labelZh: 网页端口
+ required: true
+ rule: paramPort
+ type: number
+ label:
+ en: WebUI Port
+ ja: WebUI ポート
+ ms: Port WebUI
+ pt-br: Porta WebUI
+ ru: Порт WebUI
+ ko: WebUI 포트
+ zh-Hant: WebUI 埠
+ zh: WebUI 端口
+ - default: 5426
+ edit: true
+ envKey: PANEL_APP_PORT_S3
+ labelEn: S3 Port
+ labelZh: S3 端口
+ required: true
+ rule: paramPort
+ type: number
+ label:
+ en: S3 Port
+ ja: S3 ポート
+ ms: Port S3
+ pt-br: Porta S3
+ ru: Порт S3
+ ko: S3 포트
+ zh-Hant: S3 埠
+ zh: S3 端口
+```
+
+**docker-compose.yml:**
+```yaml
+services:
+ alist:
+ container_name: ${CONTAINER_NAME}
+ restart: always
+ networks:
+ - 1panel-network
+ ports:
+ - "${PANEL_APP_PORT_HTTP}:5244"
+ - "${PANEL_APP_PORT_S3}:5426"
+ volumes:
+ - ./data/data:/opt/alist/data
+ - ./data/mnt:/mnt/data
+ environment:
+ - PUID=0
+ - PGID=0
+ - UMASK=022
+ image: xhofe/alist:v3.45.0
+ labels:
+ createdBy: "Apps"
+networks:
+ 1panel-network:
+ external: true
+```
+
+---
+
+## 带数据库的应用
+
+### 示例:NocoDB(PostgreSQL)
+
+**docker-compose.yml:**
+```yaml
+services:
+ nocodb:
+ container_name: ${CONTAINER_NAME}
+ restart: always
+ networks:
+ - 1panel-network
+ ports:
+ - "${PANEL_APP_PORT_HTTP}:8080"
+ volumes:
+ - ./data/nocodb:/usr/app/data
+ environment:
+ - NC_DB=pg://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
+ - NC_AUTH_JWT_SECRET=${JWT_SECRET}
+ depends_on:
+ db:
+ condition: service_healthy
+ image: nocodb/nocodb:0.258.2
+ labels:
+ createdBy: "Apps"
+ db:
+ image: postgres:16-alpine
+ restart: always
+ networks:
+ - 1panel-network
+ volumes:
+ - ./data/postgres:/var/lib/postgresql/data
+ environment:
+ - POSTGRES_DB=${DB_NAME}
+ - POSTGRES_USER=${DB_USER}
+ - POSTGRES_PASSWORD=${DB_PASSWORD}
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
+ interval: 5s
+ timeout: 5s
+ retries: 5
+networks:
+ 1panel-network:
+ external: true
+```
+
+**参数定义:**
+```yaml
+- default: 8080
+ edit: true
+ envKey: PANEL_APP_PORT_HTTP
+ labelEn: Web Port
+ labelZh: Web端口
+ required: true
+ rule: paramPort
+ type: number
+- default: nocodb
+ edit: true
+ envKey: DB_NAME
+ labelEn: Database Name
+ labelZh: 数据库名称
+ required: true
+ rule: paramCommon
+ type: text
+- default: nocodb
+ edit: true
+ envKey: DB_USER
+ labelEn: Database User
+ labelZh: 数据库用户
+ required: true
+ rule: paramCommon
+ type: text
+- default: nocodb_password
+ edit: true
+ envKey: DB_PASSWORD
+ labelEn: Database Password
+ labelZh: 数据库密码
+ required: true
+ rule: paramCommon
+ type: password
+```
+
+---
+
+## 多端口应用
+
+### 示例:Nginx Proxy Manager
+
+**参数定义:**
+```yaml
+formFields:
+ - default: 81
+ edit: true
+ envKey: PANEL_APP_PORT_HTTP
+ labelEn: Admin Port
+ labelZh: 管理端口
+ required: true
+ rule: paramPort
+ type: number
+ - default: 80
+ edit: true
+ envKey: PANEL_APP_PORT_NGINX_HTTP
+ labelEn: HTTP Port
+ labelZh: HTTP端口
+ required: true
+ rule: paramPort
+ type: number
+ - default: 443
+ edit: true
+ envKey: PANEL_APP_PORT_NGINX_HTTPS
+ labelEn: HTTPS Port
+ labelZh: HTTPS端口
+ required: true
+ rule: paramPort
+ type: number
+```
+
+**docker-compose.yml:**
+```yaml
+services:
+ app:
+ container_name: ${CONTAINER_NAME}
+ restart: always
+ networks:
+ - 1panel-network
+ ports:
+ - "${PANEL_APP_PORT_HTTP}:81"
+ - "${PANEL_APP_PORT_NGINX_HTTP}:80"
+ - "${PANEL_APP_PORT_NGINX_HTTPS}:443"
+ volumes:
+ - ./data/data:/data
+ - ./data/letsencrypt:/etc/letsencrypt
+ image: jc21/nginx-proxy-manager:latest
+ labels:
+ createdBy: "Apps"
+networks:
+ 1panel-network:
+ external: true
+```
+
+---
+
+## 多服务应用
+
+### 示例:Dify(完整栈)
+
+**docker-compose.yml:**
+```yaml
+services:
+ api:
+ container_name: ${CONTAINER_NAME}
+ restart: always
+ networks:
+ - 1panel-network
+ ports:
+ - "${PANEL_APP_PORT_HTTP}:80"
+ volumes:
+ - ./data/storage:/app/api/storage
+ environment:
+ - MODE=api
+ - SECRET_KEY=${SECRET_KEY}
+ depends_on:
+ - db
+ - redis
+ image: langgenius/dify-api:latest
+ labels:
+ createdBy: "Apps"
+ worker:
+ restart: always
+ networks:
+ - 1panel-network
+ environment:
+ - MODE=worker
+ - SECRET_KEY=${SECRET_KEY}
+ depends_on:
+ - db
+ - redis
+ image: langgenius/dify-api:latest
+ db:
+ image: postgres:15-alpine
+ restart: always
+ networks:
+ - 1panel-network
+ volumes:
+ - ./data/postgres:/var/lib/postgresql/data
+ environment:
+ - POSTGRES_USER=${DB_USER}
+ - POSTGRES_PASSWORD=${DB_PASSWORD}
+ - POSTGRES_DB=${DB_NAME}
+ redis:
+ image: redis:7-alpine
+ restart: always
+ networks:
+ - 1panel-network
+ volumes:
+ - ./data/redis:/data
+networks:
+ 1panel-network:
+ external: true
+```
+
+---
+
+## 常见标签分类
+
+### 中文标签(tags)
+
+| 分类 | 标签 |
+|------|------|
+| 开发工具 | 开发工具 |
+| 实用工具 | 实用工具 |
+| 文档与笔记 | 文档与笔记 |
+| 云存储 | 云存储 |
+| 数据库 | 数据库 |
+| 监控运维 | 监控运维 |
+| 安全工具 | 安全工具 |
+| 网络工具 | 网络工具 |
+| 建站工具 | 建站工具 |
+| AI/LLM | AI/LLM |
+| 容器管理 | 容器管理 |
+
+### 英文标签(additionalProperties.tags)
+
+| 分类 | 标签 |
+|------|------|
+| 开发工具 | DevTool |
+| 实用工具 | Utility |
+| 文档与笔记 | Note |
+| 云存储 | Storage |
+| 数据库 | Database |
+| 监控运维 | Monitor |
+| 安全工具 | Security |
+| 网络工具 | Network |
+| 建站工具 | Website |
+| AI/LLM | AI |
+| 容器管理 | Container |
+
+### 应用类型(type)
+
+| 类型 | 说明 |
+|------|------|
+| website | Web应用(默认) |
+| runtime | 运行时环境(数据库等) |
+| tool | 命令行工具 |
+
+---
+
+## 最佳实践
+
+1. **版本号**:使用实际的镜像标签版本,如 `v3.45.0`,而非 `latest`
+2. **推荐值**:优质应用设置 recommend: 60-80,一般应用 30-50
+3. **架构支持**:至少支持 amd64 和 arm64
+4. **多语言**:至少提供中英文描述,推荐添加日韩俄等语言
+5. **数据持久化**:使用 `./data/` 目录,避免绝对路径
+6. **环境变量**:敏感信息使用 password 类型参数
diff --git a/skills/scripts/download-icon.sh b/skills/scripts/download-icon.sh
new file mode 100644
index 0000000..64cbfd6
--- /dev/null
+++ b/skills/scripts/download-icon.sh
@@ -0,0 +1,195 @@
+#!/usr/bin/env bash
+
+# =============================================================================
+# Icon Downloader - 从多个图标源下载应用图标
+# 支持的源:dashboardicons、simpleicons、selfh.st
+# =============================================================================
+
+set -euo pipefail
+
+# 颜色定义
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m'
+
+# 图标源配置
+DASHBOARD_ICONS="https://dashboardicons.com/icons"
+SIMPLE_ICONS="https://cdn.simpleicons.org"
+SELFHST_ICONS="https://selfh.st/icons"
+
+# 默认输出尺寸
+DEFAULT_SIZE=200
+
+# 打印帮助
+print_help() {
+ cat << EOF
+${BLUE}Icon Downloader${NC} - 从多个图标源下载应用图标
+
+${YELLOW}用法:${NC}
+ $0 <应用名称> [输出文件] [尺寸]
+
+${YELLOW}参数:${NC}
+ 应用名称 - 应用的名称(如 alist, nginx, redis)
+ 输出文件 - 图标保存路径(默认: ./logo.png)
+ 尺寸 - 图标尺寸(默认: 200x200)
+
+${YELLOW}图标源优先级:${NC}
+ 1. Dashboard Icons (dashboardicons.com)
+ 2. Simple Icons (simpleicons.org)
+ 3. selfh.st Icons (selfh.st)
+
+${YELLOW}示例:${NC}
+ $0 alist ./logo.png 200
+ $0 nginx /tmp/nginx-icon.png
+ $0 redis
+EOF
+}
+
+# 日志函数
+log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
+log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
+log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
+
+# 下载并调整图标尺寸
+download_and_resize() {
+ local url="$1"
+ local output="$2"
+ local size="$3"
+
+ if curl -sSL -o "$output" "$url" 2>/dev/null && [[ -s "$output" ]]; then
+ # 检查是否安装了 ImageMagick 或 sips (macOS)
+ if command -v convert &>/dev/null; then
+ convert "$output" -resize "${size}x${size}" "$output" 2>/dev/null || true
+ elif command -v sips &>/dev/null; then
+ sips -z "$size" "$size" "$output" &>/dev/null || true
+ fi
+ return 0
+ fi
+ return 1
+}
+
+# 尝试从各图标源下载
+try_download_icon() {
+ local app_name="$1"
+ local output="$2"
+ local size="$3"
+
+ local name_lower
+ name_lower=$(echo "$app_name" | tr '[:upper:]' '[:lower:]' | tr -d ' ')
+
+ log_info "尝试下载图标: $app_name"
+
+ # 1. Dashboard Icons
+ log_info "尝试 Dashboard Icons..."
+ local dashboard_url="${DASHBOARD_ICONS}/${name_lower}.png"
+ if download_and_resize "$dashboard_url" "$output" "$size"; then
+ log_info "✓ 从 Dashboard Icons 下载成功"
+ return 0
+ fi
+
+ # 尝试带 -dark 后缀
+ if download_and_resize "${DASHBOARD_ICONS}/${name_lower}-dark.png" "$output" "$size"; then
+ log_info "✓ 从 Dashboard Icons (dark) 下载成功"
+ return 0
+ fi
+
+ # 2. Simple Icons
+ log_info "尝试 Simple Icons..."
+ local simple_url="${SIMPLE_ICONS}/${name_lower}"
+ if download_and_resize "$simple_url" "$output" "$size"; then
+ log_info "✓ 从 Simple Icons 下载成功"
+ return 0
+ fi
+
+ # Simple Icons 也支持 SVG
+ if curl -sSL -o "${output%.png}.svg" "${SIMPLE_ICONS}/${name_lower}" 2>/dev/null && [[ -s "${output%.png}.svg" ]]; then
+ log_info "✓ 从 Simple Icons 下载 SVG 成功"
+ # 如果有 SVG,尝试转换
+ if command -v convert &>/dev/null; then
+ convert "${output%.png}.svg" -resize "${size}x${size}" "$output" 2>/dev/null || true
+ if [[ -s "$output" ]]; then
+ rm -f "${output%.png}.svg"
+ return 0
+ fi
+ fi
+ fi
+
+ # 3. selfh.st Icons
+ log_info "尝试 selfh.st Icons..."
+ local selfhst_url="${SELFHST_ICONS}/${name_lower}.png"
+ if download_and_resize "$selfhst_url" "$output" "$size"; then
+ log_info "✓ 从 selfh.st Icons 下载成功"
+ return 0
+ fi
+
+ return 1
+}
+
+# 创建占位图标
+create_placeholder() {
+ local output="$1"
+ local size="$2"
+
+ log_warn "创建占位图标"
+
+ # 使用 ImageMagick 创建简单的占位图标
+ if command -v convert &>/dev/null; then
+ convert -size "${size}x${size}" xc:'#4A90E2' \
+ -gravity center \
+ -pointsize 48 \
+ -fill white \
+ -annotate 0 "?" \
+ "$output" 2>/dev/null
+ return $?
+ fi
+
+ # macOS sips 方式
+ if command -v sips &>/dev/null; then
+ # 创建一个简单的 1x1 像素 PNG 然后放大
+ local temp_file="/tmp/placeholder_${RANDOM}.png"
+ echo -n "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" | base64 -d > "$temp_file"
+ sips -z "$size" "$size" "$temp_file" --out "$output" &>/dev/null
+ rm -f "$temp_file"
+ return $?
+ fi
+
+ # 最简单的占位符
+ echo -n "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" | base64 -d > "$output"
+}
+
+# 主函数
+main() {
+ local app_name="${1:-}"
+ local output="${2:-./logo.png}"
+ local size="${3:-$DEFAULT_SIZE}"
+
+ # 参数检查
+ if [[ -z "$app_name" ]] || [[ "$app_name" == "-h" ]] || [[ "$app_name" == "--help" ]]; then
+ print_help
+ exit 0
+ fi
+
+ # 确保输出目录存在
+ local output_dir
+ output_dir=$(dirname "$output")
+ mkdir -p "$output_dir"
+
+ # 尝试下载
+ if try_download_icon "$app_name" "$output" "$size"; then
+ log_info "${GREEN}✓ 图标下载完成: $output${NC}"
+ exit 0
+ fi
+
+ # 下载失败,创建占位符
+ create_placeholder "$output" "$size"
+ log_warn "未找到图标,已创建占位符: $output"
+ log_info "请手动从以下网站下载合适的图标:"
+ echo " - https://dashboardicons.com/icons?q=${app_name}"
+ echo " - https://simpleicons.org/?q=${app_name}"
+ echo " - https://selfh.st/icons/"
+}
+
+# 执行主函数
+main "$@"
diff --git a/skills/scripts/generate-app.sh b/skills/scripts/generate-app.sh
new file mode 100644
index 0000000..5bd3e89
--- /dev/null
+++ b/skills/scripts/generate-app.sh
@@ -0,0 +1,416 @@
+#!/usr/bin/env bash
+
+# =============================================================================
+# 1Panel App Builder - 主生成脚本
+# 功能:从 GitHub 项目、docker-compose、docker run 命令生成 1Panel APP 配置
+# 用法:./generate-app.sh <输入源> [输出目录]
+# =============================================================================
+
+set -euo pipefail
+
+# 颜色定义
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m' # No Color
+
+# 默认配置
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+TEMPLATE_DIR="${SCRIPT_DIR}/../templates"
+OUTPUT_BASE="${2:-./apps}"
+ICON_SOURCES=(
+ "https://dashboardicons.com/icons"
+ "https://simpleicons.org/icons"
+ "https://selfh.st/icons"
+)
+
+# 打印帮助
+print_help() {
+ cat << EOF
+${BLUE}1Panel App Builder${NC} - 快速生成 1Panel 应用配置
+
+${YELLOW}用法:${NC}
+ $0 <输入源> [输出目录]
+
+${YELLOW}输入源支持:${NC}
+ 1. GitHub 项目链接
+ 例如: https://github.com/alist-org/alist
+
+ 2. docker-compose.yml 文件链接
+ 例如: https://raw.githubusercontent.com/alist-org/alist/master/docker-compose.yml
+
+ 3. docker run 命令
+ 例如: "docker run -d --name=alist -p 5244:5244 xhofe/alist:v3.45.0"
+
+ 4. 本地文件路径
+ 例如: ./myapp/docker-compose.yml
+
+${YELLOW}输出:${NC}
+ 在指定目录(默认 ./apps)下生成:
+ //
+ ├── data.yml # 应用元数据
+ ├── docker-compose.yml # 编排文件
+ ├── logo.png # 应用图标
+ ├── README.md # 中文简介
+ └── README_en.md # 英文简介
+
+${YELLOW}示例:${NC}
+ $0 https://github.com/alist-org/alist
+ $0 ./my-docker-compose.yml ./my-apps
+ $0 "docker run -d --name nginx -p 80:80 nginx:latest"
+EOF
+}
+
+# 日志函数
+log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
+log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
+log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
+
+# 检测输入类型
+detect_input_type() {
+ local input="$1"
+
+ # GitHub 项目链接
+ if [[ "$input" =~ ^https?://github\.com/[^/]+/[^/]+ ]]; then
+ echo "github"
+ return 0
+ fi
+
+ # docker-compose 文件链接
+ if [[ "$input" =~ ^https?://.*\.ya?ml$ ]] || [[ "$input" =~ docker-compose ]]; then
+ echo "compose_url"
+ return 0
+ fi
+
+ # docker run 命令
+ if [[ "$input" =~ ^docker\ run ]] || [[ "$input" =~ ^docker\ run$ ]]; then
+ echo "docker_run"
+ return 0
+ fi
+
+ # 本地文件
+ if [[ -f "$input" ]]; then
+ if [[ "$input" =~ \.ya?ml$ ]]; then
+ echo "compose_file"
+ return 0
+ fi
+ fi
+
+ echo "unknown"
+}
+
+# 从 GitHub 项目提取信息
+extract_from_github() {
+ local github_url="$1"
+ local api_url temp_dir
+
+ log_info "正在从 GitHub 项目提取信息: $github_url"
+
+ # 转换为 API URL
+ # https://github.com/owner/repo -> https://api.github.com/repos/owner/repo
+ api_url="${github_url/github\.com/api.github.com\/repos}"
+
+ # 获取项目信息
+ local repo_info
+ repo_info=$(curl -s "$api_url" 2>/dev/null || echo "{}")
+
+ # 提取字段
+ APP_NAME=$(echo "$repo_info" | jq -r '.name // empty')
+ APP_KEY=$(echo "$APP_NAME" | tr '[:upper:]' '[:lower:]')
+ DESCRIPTION=$(echo "$repo_info" | jq -r '.description // empty')
+ GITHUB="$github_url"
+ WEBSITE=$(echo "$repo_info" | jq -r '.homepage // empty')
+ if [[ -z "$WEBSITE" ]]; then
+ WEBSITE="$github_url"
+ fi
+
+ # 尝试查找 docker-compose.yml
+ local owner_repo
+ owner_repo=$(echo "$github_url" | sed -E 's|https?://github.com/||')
+ COMPOSE_URL="https://raw.githubusercontent.com/${owner_repo}/main/docker-compose.yml"
+
+ log_info "应用名称: $APP_NAME"
+ log_info "描述: $DESCRIPTION"
+}
+
+# 从 docker-compose 提取信息
+extract_from_compose() {
+ local compose_content="$1"
+
+ log_info "正在解析 docker-compose 内容"
+
+ # 提取服务名
+ SERVICE_NAME=$(echo "$compose_content" | yq '.services | keys | .[0]' 2>/dev/null || echo "")
+
+ # 提取镜像
+ local image
+ image=$(echo "$compose_content" | yq ".services.${SERVICE_NAME}.image" 2>/dev/null || echo "")
+
+ # 解析镜像名和标签
+ if [[ "$image" =~ ^([^:]+):(.+)$ ]]; then
+ IMAGE="${BASH_REMATCH[1]}"
+ TAG="${BASH_REMATCH[2]}"
+ else
+ IMAGE="$image"
+ TAG="latest"
+ fi
+
+ # 提取端口
+ PORT=$(echo "$compose_content" | yq ".services.${SERVICE_NAME}.ports[0]" 2>/dev/null | grep -oE '[0-9]+$' || echo "8080")
+
+ log_info "服务名: $SERVICE_NAME"
+ log_info "镜像: $IMAGE:$TAG"
+ log_info "端口: $PORT"
+}
+
+# 从 docker run 命令提取信息
+extract_from_docker_run() {
+ local cmd="$1"
+
+ log_info "正在解析 docker run 命令"
+
+ # 提取镜像
+ IMAGE=$(echo "$cmd" | grep -oE '[^ ]+:[^ ]+$' | cut -d':' -f1 || echo "")
+ TAG=$(echo "$cmd" | grep -oE '[^ ]+:[^ ]+$' | cut -d':' -f2 || echo "latest")
+
+ # 提取容器名
+ SERVICE_NAME=$(echo "$cmd" | grep -oE '\-\-name[= ]+[^ ]+' | awk '{print $NF}' || echo "app")
+
+ # 提取端口
+ PORT=$(echo "$cmd" | grep -oE '\-p[= ]+[0-9]+:[0-9]+' | grep -oE '[0-9]+$' || echo "8080")
+
+ APP_NAME="$SERVICE_NAME"
+ APP_KEY=$(echo "$SERVICE_NAME" | tr '[:upper:]' '[:lower:]')
+
+ log_info "应用名称: $APP_NAME"
+ log_info "镜像: $IMAGE:$TAG"
+ log_info "端口: $PORT"
+}
+
+# 生成 data.yml
+generate_data_yml() {
+ local output_file="$1"
+
+ log_info "生成 data.yml: $output_file"
+
+ cat > "$output_file" << EOF
+name: ${APP_NAME:-MyApp}
+tags:
+ - 实用工具
+ - 容器
+title: ${APP_NAME:-MyApp} - 容器应用
+description: ${DESCRIPTION:-自动生成的应用配置}
+additionalProperties:
+ key: ${APP_KEY:-myapp}
+ name: ${APP_NAME:-MyApp}
+ tags:
+ - Tool
+ - Container
+ shortDescZh: ${DESCRIPTION:-自动生成的应用配置}
+ shortDescEn: ${DESCRIPTION:-Auto-generated application configuration}
+ description:
+ en: ${DESCRIPTION:-Auto-generated application configuration}
+ ja: ${DESCRIPTION:-Auto-generated application configuration}
+ ms: ${DESCRIPTION:-Auto-generated application configuration}
+ pt-br: ${DESCRIPTION:-Auto-generated application configuration}
+ ru: ${DESCRIPTION:-Auto-generated application configuration}
+ ko: ${DESCRIPTION:-Auto-generated application configuration}
+ zh-Hant: ${DESCRIPTION:-Auto-generated application configuration}
+ zh: ${DESCRIPTION:-自动生成的应用配置}
+ type: website
+ crossVersionUpdate: true
+ limit: 0
+ recommend: 50
+ website: ${WEBSITE:-https://example.com}
+ github: ${GITHUB:-https://github.com}
+ document: ${GITHUB:-https://github.com}
+ architectures:
+ - amd64
+ - arm64
+EOF
+}
+
+# 生成 docker-compose.yml
+generate_docker_compose() {
+ local output_file="$1"
+
+ log_info "生成 docker-compose.yml: $output_file"
+
+ cat > "$output_file" << EOF
+services:
+ ${SERVICE_NAME:-app}:
+ container_name: \${CONTAINER_NAME}
+ restart: always
+ networks:
+ - 1panel-network
+ ports:
+ - "\${PANEL_APP_PORT_HTTP}:${PORT:-8080}"
+ volumes:
+ - ./data/data:/app/data
+ environment:
+ - PUID=0
+ - PGID=0
+ - UMASK=022
+ image: ${IMAGE:-app}:${TAG:-latest}
+ labels:
+ createdBy: "Apps"
+networks:
+ 1panel-network:
+ external: true
+EOF
+}
+
+# 生成 README
+generate_readme() {
+ local output_dir="$1"
+
+ log_info "生成 README 文件"
+
+ cat > "${output_dir}/README.md" << EOF
+# ${APP_NAME:-MyApp}
+
+## 简介
+
+${DESCRIPTION:-这是一个自动生成的应用配置。}
+
+## 使用说明
+
+1. 在 1Panel 应用商店中安装此应用
+2. 配置相关参数
+3. 启动应用
+
+## 更多信息
+
+- 官网: ${WEBSITE:-https://example.com}
+- GitHub: ${GITHUB:-https://github.com}
+- 文档: ${GITHUB:-https://github.com}
+EOF
+
+ cat > "${output_dir}/README_en.md" << EOF
+# ${APP_NAME:-MyApp}
+
+## Introduction
+
+${DESCRIPTION:-This is an auto-generated application configuration.}
+
+## Usage
+
+1. Install this app from 1Panel App Store
+2. Configure parameters
+3. Start the application
+
+## More Information
+
+- Website: ${WEBSITE:-https://example.com}
+- GitHub: ${GITHUB:-https://github.com}
+- Documentation: ${GITHUB:-https://github.com}
+EOF
+}
+
+# 下载图标
+download_icon() {
+ local app_name="$1"
+ local output_file="$2"
+ local icon_name
+
+ icon_name=$(echo "$app_name" | tr '[:upper:]' '[:lower:]')
+
+ log_info "尝试下载图标: $app_name"
+
+ # 尝试各个图标源
+ for source in "${ICON_SOURCES[@]}"; do
+ local icon_url="${source}/${icon_name}.png"
+ if curl -sSL -o "$output_file" "$icon_url" 2>/dev/null && [[ -s "$output_file" ]]; then
+ log_info "图标下载成功: $icon_url"
+ return 0
+ fi
+ done
+
+ log_warn "未找到图标,使用占位符"
+ # 创建简单的占位图标(1x1 像素 PNG)
+ echo -n "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" | base64 -d > "$output_file"
+}
+
+# 主函数
+main() {
+ local input="$1"
+ local input_type
+
+ # 参数检查
+ if [[ -z "$input" ]] || [[ "$input" == "-h" ]] || [[ "$input" == "--help" ]]; then
+ print_help
+ exit 0
+ fi
+
+ log_info "开始处理: $input"
+
+ # 检测输入类型
+ input_type=$(detect_input_type "$input")
+ log_info "检测到输入类型: $input_type"
+
+ # 根据类型提取信息
+ case "$input_type" in
+ github)
+ extract_from_github "$input"
+ COMPOSE_CONTENT=$(curl -s "$COMPOSE_URL" 2>/dev/null || echo "")
+ if [[ -n "$COMPOSE_CONTENT" ]]; then
+ extract_from_compose "$COMPOSE_CONTENT"
+ fi
+ ;;
+ compose_url)
+ COMPOSE_CONTENT=$(curl -s "$input" 2>/dev/null)
+ extract_from_compose "$COMPOSE_CONTENT"
+ APP_NAME="$SERVICE_NAME"
+ APP_KEY=$(echo "$SERVICE_NAME" | tr '[:upper:]' '[:lower:]')
+ ;;
+ compose_file)
+ COMPOSE_CONTENT=$(cat "$input")
+ extract_from_compose "$COMPOSE_CONTENT"
+ APP_NAME="$SERVICE_NAME"
+ APP_KEY=$(echo "$SERVICE_NAME" | tr '[:upper:]' '[:lower:]')
+ ;;
+ docker_run)
+ extract_from_docker_run "$input"
+ ;;
+ *)
+ log_error "无法识别的输入类型: $input"
+ exit 1
+ ;;
+ esac
+
+ # 创建输出目录
+ local output_dir="${OUTPUT_BASE}/${APP_KEY}/${TAG:-latest}"
+ mkdir -p "$output_dir"
+
+ log_info "输出目录: $output_dir"
+
+ # 生成文件
+ generate_data_yml "${output_dir}/data.yml"
+ generate_docker_compose "${output_dir}/docker-compose.yml"
+ generate_readme "$output_dir"
+ download_icon "$APP_NAME" "${output_dir}/logo.png"
+
+ # 生成上级目录的 data.yml
+ generate_data_yml "${OUTPUT_BASE}/${APP_KEY}/data.yml"
+ cp "${output_dir}/logo.png" "${OUTPUT_BASE}/${APP_KEY}/logo.png" 2>/dev/null || true
+ cp "${output_dir}/README.md" "${OUTPUT_BASE}/${APP_KEY}/README.md" 2>/dev/null || true
+ cp "${output_dir}/README_en.md" "${OUTPUT_BASE}/${APP_KEY}/README_en.md" 2>/dev/null || true
+
+ # 输出结果
+ echo ""
+ log_info "${GREEN}✓ 生成完成!${NC}"
+ echo ""
+ echo "目录结构:"
+ tree "${OUTPUT_BASE}/${APP_KEY}" 2>/dev/null || find "${OUTPUT_BASE}/${APP_KEY}" -type f
+ echo ""
+ log_info "下一步:"
+ echo " 1. 检查生成的配置文件"
+ echo " 2. 补充完善应用描述和标签"
+ echo " 3. 替换 logo.png 为合适的应用图标"
+ echo " 4. 测试 docker-compose.yml"
+ echo " 5. 提交到应用商店仓库"
+}
+
+# 执行主函数
+main "$@"
diff --git a/skills/scripts/validate-app.sh b/skills/scripts/validate-app.sh
new file mode 100644
index 0000000..05995cb
--- /dev/null
+++ b/skills/scripts/validate-app.sh
@@ -0,0 +1,257 @@
+#!/usr/bin/env bash
+
+# =============================================================================
+# 1Panel App Validator - 验证生成的配置是否符合规范
+# 用法:./validate-app.sh
+# =============================================================================
+
+set -euo pipefail
+
+# 颜色定义
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m'
+
+# 计数器
+ERRORS=0
+WARNINGS=0
+
+# 打印帮助
+print_help() {
+ cat << EOF
+${BLUE}1Panel App Validator${NC} - 验证应用配置是否符合规范
+
+${YELLOW}用法:${NC}
+ $0
+
+${YELLOW}检查项目:${NC}
+ - 目录结构完整性
+ - data.yml 格式正确性
+ - docker-compose.yml 变量使用
+ - logo.png 是否存在
+ - README 文件是否存在
+
+${YELLOW}示例:${NC}
+ $0 ./apps/alist
+EOF
+}
+
+# 日志函数
+log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
+log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; ((WARNINGS++)); }
+log_error() { echo -e "${RED}[ERROR]${NC} $1"; ((ERRORS++)); }
+
+# 检查目录结构
+check_directory_structure() {
+ local app_dir="$1"
+ local app_name
+ app_name=$(basename "$app_dir")
+
+ log_info "检查目录结构: $app_name"
+
+ # 检查必需文件
+ if [[ ! -f "$app_dir/data.yml" ]]; then
+ log_error "缺少顶层 data.yml"
+ fi
+
+ if [[ ! -f "$app_dir/logo.png" ]]; then
+ log_error "缺少 logo.png"
+ fi
+
+ if [[ ! -f "$app_dir/README.md" ]]; then
+ log_warn "缺少 README.md(推荐)"
+ fi
+
+ # 查找版本目录
+ local version_dirs
+ version_dirs=$(find "$app_dir" -maxdepth 1 -type d -name "v*" -o -name "latest" -o -name "[0-9]*" 2>/dev/null || echo "")
+
+ if [[ -z "$version_dirs" ]]; then
+ log_error "未找到版本目录(如 1.0.0/, v1.0.0/, latest/)"
+ return 1
+ fi
+
+ # 检查每个版本目录
+ for version_dir in $version_dirs; do
+ log_info "检查版本目录: $(basename "$version_dir")"
+
+ if [[ ! -f "$version_dir/data.yml" ]]; then
+ log_error "版本目录缺少 data.yml: $version_dir"
+ fi
+
+ if [[ ! -f "$version_dir/docker-compose.yml" ]]; then
+ log_error "版本目录缺少 docker-compose.yml: $version_dir"
+ fi
+ done
+}
+
+# 验证顶层 data.yml
+validate_top_data_yml() {
+ local data_file="$1"
+
+ log_info "验证顶层 data.yml"
+
+ if [[ ! -f "$data_file" ]]; then
+ return 1
+ fi
+
+ # 检查必需字段
+ local required_fields=("name" "title" "description")
+ for field in "${required_fields[@]}"; do
+ if ! grep -q "^${field}:" "$data_file"; then
+ log_error "data.yml 缺少必需字段: $field"
+ fi
+ done
+
+ # 检查 additionalProperties
+ if ! grep -q "additionalProperties:" "$data_file"; then
+ log_error "data.yml 缺少 additionalProperties"
+ fi
+
+ # 检查 key
+ if ! grep -q "key:" "$data_file"; then
+ log_error "data.yml 缺少 additionalProperties.key"
+ fi
+
+ # 检查 tags
+ if ! grep -q "tags:" "$data_file"; then
+ log_warn "data.yml 缺少 tags(推荐)"
+ fi
+
+ # 检查 architectures
+ if ! grep -q "architectures:" "$data_file"; then
+ log_warn "data.yml 缺少 architectures(推荐)"
+ fi
+}
+
+# 验证版本 data.yml
+validate_version_data_yml() {
+ local data_file="$1"
+
+ log_info "验证版本 data.yml"
+
+ if [[ ! -f "$data_file" ]]; then
+ return 1
+ fi
+
+ # 检查 formFields
+ if ! grep -q "formFields:" "$data_file"; then
+ log_warn "版本 data.yml 缺少 formFields(如果无可配置参数则忽略)"
+ return 0
+ fi
+
+ # 检查每个参数是否有 envKey
+ local param_count
+ param_count=$(grep -c "envKey:" "$data_file" 2>/dev/null || echo "0")
+
+ if [[ "$param_count" -eq 0 ]]; then
+ log_warn "formFields 中未找到 envKey 定义"
+ else
+ log_info "找到 $param_count 个可配置参数"
+ fi
+}
+
+# 验证 docker-compose.yml
+validate_docker_compose() {
+ local compose_file="$1"
+
+ log_info "验证 docker-compose.yml"
+
+ if [[ ! -f "$compose_file" ]]; then
+ return 1
+ fi
+
+ # 检查 container_name 使用变量
+ if grep -q "container_name:" "$compose_file"; then
+ if ! grep -q 'container_name:.*\${CONTAINER_NAME}' "$compose_file"; then
+ log_error "container_name 必须使用 \${CONTAINER_NAME} 变量"
+ fi
+ fi
+
+ # 检查 networks
+ if ! grep -q "1panel-network:" "$compose_file"; then
+ log_error "docker-compose.yml 缺少 1panel-network"
+ fi
+
+ if ! grep -q "external: true" "$compose_file"; then
+ log_error "1panel-network 必须设置为 external: true"
+ fi
+
+ # 检查 restart
+ if ! grep -q "restart: always" "$compose_file"; then
+ log_warn "建议设置 restart: always"
+ fi
+
+ # 检查 labels
+ if ! grep -q 'createdBy: "Apps"' "$compose_file"; then
+ log_warn "建议添加 labels: createdBy: \"Apps\""
+ fi
+
+ # 检查端口映射使用变量
+ if grep -q "ports:" "$compose_file"; then
+ if ! grep -q 'PANEL_APP_PORT_' "$compose_file"; then
+ log_warn "端口映射建议使用 PANEL_APP_PORT_* 变量"
+ fi
+ fi
+
+ # 检查数据卷路径
+ if grep -q "volumes:" "$compose_file"; then
+ if grep -qE '^\s+- /[a-zA-Z]' "$compose_file"; then
+ log_warn "检测到绝对路径的数据卷,建议使用 ./data/ 相对路径"
+ fi
+ fi
+}
+
+# 主函数
+main() {
+ local app_dir="${1:-}"
+
+ # 参数检查
+ if [[ -z "$app_dir" ]] || [[ "$app_dir" == "-h" ]] || [[ "$app_dir" == "--help" ]]; then
+ print_help
+ exit 0
+ fi
+
+ if [[ ! -d "$app_dir" ]]; then
+ log_error "目录不存在: $app_dir"
+ exit 1
+ fi
+
+ echo ""
+ echo -e "${BLUE}=== 1Panel App Validator ===${NC}"
+ echo ""
+
+ # 执行检查
+ check_directory_structure "$app_dir"
+ validate_top_data_yml "$app_dir/data.yml"
+
+ # 查找并验证版本目录
+ local version_dirs
+ version_dirs=$(find "$app_dir" -maxdepth 1 -type d \( -name "v*" -o -name "latest" -o -name "[0-9]*" \) 2>/dev/null || echo "")
+
+ for version_dir in $version_dirs; do
+ validate_version_data_yml "$version_dir/data.yml"
+ validate_docker_compose "$version_dir/docker-compose.yml"
+ done
+
+ # 输出结果
+ echo ""
+ echo -e "${BLUE}=== 验证结果 ===${NC}"
+ echo ""
+
+ if [[ $ERRORS -eq 0 ]] && [[ $WARNINGS -eq 0 ]]; then
+ echo -e "${GREEN}✓ 验证通过!未发现问题。${NC}"
+ exit 0
+ elif [[ $ERRORS -eq 0 ]]; then
+ echo -e "${YELLOW}⚠ 验证通过,但有 $WARNINGS 个警告。${NC}"
+ exit 0
+ else
+ echo -e "${RED}✗ 验证失败!发现 $ERRORS 个错误和 $WARNINGS 个警告。${NC}"
+ exit 1
+ fi
+}
+
+# 执行主函数
+main "$@"
diff --git a/skills/templates/data.yml.tpl b/skills/templates/data.yml.tpl
new file mode 100644
index 0000000..91bf9a7
--- /dev/null
+++ b/skills/templates/data.yml.tpl
@@ -0,0 +1,33 @@
+name: ${APP_NAME}
+tags:
+ - ${TAG_1}
+ - ${TAG_2}
+title: ${TITLE_ZH}
+description: ${DESC_ZH}
+additionalProperties:
+ key: ${APP_KEY}
+ name: ${APP_NAME}
+ tags:
+ - ${TAG_EN_1}
+ - ${TAG_EN_2}
+ shortDescZh: ${SHORT_DESC_ZH}
+ shortDescEn: ${SHORT_DESC_EN}
+ description:
+ en: ${DESC_EN}
+ ja: ${DESC_JA:-Supporting multi-storage file listing program and private cloud storage}
+ ms: ${DESC_MS:-Supporting multi-storage file listing program and private cloud storage}
+ pt-br: ${DESC_PT_BR:-Supporting multi-storage file listing program and private cloud storage}
+ ru: ${DESC_RU:-Supporting multi-storage file listing program and private cloud storage}
+ ko: ${DESC_KO:-Supporting multi-storage file listing program and private cloud storage}
+ zh-Hant: ${DESC_ZH_HANT:-支援多存儲檔案列出程序和私人雲端空間}
+ zh: ${DESC_ZH}
+ type: ${APP_TYPE}
+ crossVersionUpdate: ${CROSS_VERSION_UPDATE:-true}
+ limit: ${LIMIT:-0}
+ recommend: ${RECOMMEND:-50}
+ website: ${WEBSITE}
+ github: ${GITHUB}
+ document: ${DOCUMENT:-}
+ architectures:
+ - amd64
+ - arm64
diff --git a/skills/templates/docker-compose.yml.tpl b/skills/templates/docker-compose.yml.tpl
new file mode 100644
index 0000000..bdc2823
--- /dev/null
+++ b/skills/templates/docker-compose.yml.tpl
@@ -0,0 +1,20 @@
+services:
+ ${SERVICE_NAME}:
+ container_name: \${CONTAINER_NAME}
+ restart: always
+ networks:
+ - 1panel-network
+ ports:
+ - "\${PANEL_APP_PORT_HTTP}:${PORT}"
+ volumes:
+ - ./data/data:/app/data
+ environment:
+ - PUID=0
+ - PGID=0
+ - UMASK=022
+ image: ${IMAGE}:${TAG}
+ labels:
+ createdBy: "Apps"
+networks:
+ 1panel-network:
+ external: true