← Back to Skills Marketplace
heigher

App Packager

by Heigher · GitHub ↗ · v1.0.0 · MIT-0
cross-platform ✓ Security Clean
164
Downloads
0
Stars
1
Active Installs
1
Versions
Install in OpenClaw
/install app-packager
Description
自动切换 Git 分支并执行 APP 打包脚本。支持指定分支、平台、构建类型、版本号、上传选项、API_KEY和更新说明。 打包完成后会自动通知用户结果。 Use when: 用户需要打包 APP、切换分支打包、构建应用、生成安装包。 NOT for: 代码合并、代码提交、单元测试、代码检查。
README (SKILL.md)

APP 打包助手(带完成通知)

执行方式

方式一:命令行调用(推荐)

~/.openclaw/workspace/skills/app-packager/scripts/app-packager --branch develop --platform android --upload --api-key 你的API_KEY --desc "更新说明"

重要:所有打包都必须使用此脚本,不要手动执行 pgyer_all.sh

参数选项:

参数 简写 说明 默认值
--branch -b Git 分支 develop
--platform -p 平台 (android/ios/all) all (双端打包)
--type - 构建类型 (debug/adhoc/release) debug
--upload -u 上传到蒲公英
--api-key --key 蒲公英 API_KEY -
--desc -d 更新说明 -

方式二:自然语言触发

直接对我说:"在 develop 分支打包 Android" 或 "打包 iOS release 版"

When to Run

  • 用户说“打包 APP”“生成安装包”“构建应用”
  • 用户说“在 xx 分支上打包”“切到 xx 分支打包”
  • 用户指定平台如“打包 iOS”“打安卓包”
  • 用户指定类型如“打 debug 包”“打 release 包”
  • 用户指定版本如“版本 1.2.3 打包”
  • 用户指定 API_KEY 如“api_key: xxxxx”
  • 用户说“打渠道包”

Pre-flight Check(执行前检查)

  1. 确认项目路径:/Users/nuoyun/Desktop/package/NYLiveUser 是否存在
  2. 确认打包脚本:./pgyer_all.sh 是否有执行权限
  3. 确认 Git 命令可用

Workflow

第一步:解析用户意图

从用户输入中提取所有参数,使用以下规则:

参数提取规则

  • 分支 (branch): 匹配 在\s*([\w\-_\./]+)\s*分支切到\s*([\w\-_\./]+)\s*分支分支[::]\s*([\w\-_\./]+)
  • 版本号 (version): 匹配 版本[::]?\s*([\d\.]+)version[::]?\s*([\d\.]+)
  • 构建类型 (build_type): 匹配 debug|测试包|测试版本debug; adhoc|验收包|验收版本adhoc; release|发布包|发布版本|商店包release
  • 平台 (platform): 匹配 iOS|苹果|iphoneios; 安卓|androidandroid; 渠道包|多渠道channel; 未指定时 → ``(双端打包)
  • 是否上传 (upload): 匹配 上传|需要上传|要上传yes; 不上传|不需要上传|不用上传no
  • API_KEY (api_key): 匹配 api_key[::]\s*([a-zA-Z0-9_\-]+)API密钥[::]\s*([a-zA-Z0-9_\-]+)蒲公英密钥[::]\s*([a-zA-Z0-9_\-]+)
  • 更新说明 (desc): 匹配 说明[::]\s*(.+?)(?=\.|$|,|。)描述[::]\s*(.+?)(?=\.|$|,|。)更新内容[::]\s*(.+?)(?=\.|$|,|。)

特殊判断

  • 渠道包:如果 platformchannel,设置 is_channel_package=true

第二步:参数处理规则

基本原则:每个参数独立判断,用户指定就用指定的值,否则用脚本默认值。

脚本提示 参数变量 用户指定时的映射 默认行为
版本号 version 直接填入用户输入的版本号 直接回车(脚本读取 pubspec.yaml)
构建类型 build_type debug1, adhoc2, release3 直接回车(脚本默认)
平台选择 platform ios1, android2, 渠道包→3 直接回车(脚本默认:双端打包)
是否上传 upload yes1, no2 直接回车(默认:不上传)
API_KEY api_key 直接填入用户输入的 API_KEY 直接回车(用脚本默认值)
更新说明 desc 直接填入用户输入的说明 直接回车(空字符串)

第三步:执行打包流程

# 进入项目目录
cd /Users/nuoyun/Desktop/package/NYLiveUser/ || { 
    reply "❌ 错误:项目路径 /Users/nuoyun/Desktop/package/NYLiveUser/ 不存在"
    exit 1
}

# 检查脚本权限
if [ ! -x "./pgyer_all.sh" ]; then
    reply "❌ 错误:打包脚本 pgyer_all.sh 无执行权限,请执行:chmod +x pgyer_all.sh"
    exit 1
fi

# 切换分支(如果指定了分支)
branch_status=""
if [ -n "$branch" ]; then
    reply "🔄 正在切换到分支: $branch ..."
    
    # 先拉取最新代码
    git fetch --all
    
    # 检查分支是否存在
    if git show-ref --verify --quiet refs/heads/"$branch"; then
        # 本地分支存在
        git checkout "$branch"
        git pull origin "$branch"
        branch_status="✅ 已切换到本地分支: $branch"
    elif git ls-remote --exit-code --heads origin "$branch"; then
        # 远程分支存在,创建本地分支并跟踪
        git checkout -b "$branch" origin/"$branch"
        branch_status="✅ 已切换到远程分支: $branch"
    else
        # 分支不存在
        reply "❌ 错误:分支 '$branch' 不存在"
        exit 1
    fi
else
    current_branch=$(git branch --show-current)
    branch_status="📌 保持当前分支: $current_branch"
fi

# 显示当前分支状态
git status -sb

# 记录开始时间
start_time=$(date +%s)

# 告知用户开始打包
reply "🚀 开始打包,预计需要3-5分钟,完成后我会通知您~"

# 构建输入序列
inputs=()

# 1. 版本号
if [ -n "$version" ]; then
    inputs+=("$version")
else
    inputs+=("")
fi

# 2. 构建类型
if [ "$build_type" = "debug" ]; then
    inputs+=("1")
elif [ "$build_type" = "adhoc" ]; then
    inputs+=("2")
elif [ "$build_type" = "release" ]; then
    inputs+=("3")
else
    inputs+=("")
fi

# 3. 平台选择
if [ "$is_channel_package" = "true" ]; then
    inputs+=("3")
else
    if [ "$platform" = "ios" ]; then
        inputs+=("1")
    elif [ "$platform" = "android" ]; then
        inputs+=("2")
    else
        inputs+=("")
    fi
fi

# 4. 如果不是渠道包,才需要后续三个参数
if [ "$is_channel_package" != "true" ]; then
    # 4.1 是否上传
    if [ "$upload" = "yes" ]; then
        inputs+=("1")
    elif [ "$upload" = "no" ]; then
        inputs+=("2")
    else
        inputs+=("2")  # 默认不上传(对应脚本中的选项2)
    fi
    
    # 4.2 API_KEY - 接收用户输入,没有指定时用默认
    if [ -n "$api_key" ]; then
        inputs+=("$api_key")
    else
        inputs+=("")  # 回车,使用脚本默认值
    fi
    
    # 4.3 更新说明
    if [ -n "$desc" ]; then
        inputs+=("$desc")
    else
        inputs+=("")
    fi
fi

# 执行打包并捕获输出
temp_output=$(mktemp)
temp_error=$(mktemp)

# 构建输入字符串
input_string=""
for item in "${inputs[@]}"; do
    input_string+="$item\
"
done

# 执行打包命令
echo -e "$input_string" | ./pgyer_all.sh > "$temp_output" 2> "$temp_error"
exit_code=$?

# 计算耗时
end_time=$(date +%s)
duration=$((end_time - start_time))
minutes=$((duration / 60))
seconds=$((duration % 60))
time_str="${minutes}分${seconds}秒"

# 读取输出内容
output_content=$(cat "$temp_output")
error_content=$(cat "$temp_error")

# 清理临时文件
rm -f "$temp_output" "$temp_error"

# 分析打包结果并生成反馈
if [ $exit_code -eq 0 ]; then
    # 打包成功,提取生成的文件信息
    apk_files=$(find /Users/nuoyun/Desktop/package/NYLiveUser/build -name "*.apk" -type f -mmin -5 2>/dev/null | head -3)
    ipa_files=$(find /Users/nuoyun/Desktop/package/NYLiveUser/build -name "*.ipa" -type f -mmin -5 2>/dev/null | head -3)
    
    # 提取蒲公英链接
    pgyer_links=$(echo "$output_content" | grep -E "https?://[a-zA-Z0-9./-]+(pgyer|蒲公英)" | head -3)
    
    # 构建成功消息
    feedback="✅ 打包完成!\
\
"
    feedback+="📂 分支信息:$branch_status\
"
    feedback+="⏱️ 打包耗时:$time_str\
\
"
    feedback+="📦 打包参数:\
"
    
    # 版本号
    if [ -n "$version" ]; then
        feedback+="• 版本号:$version\
"
    else
        feedback+="• 版本号:默认(取自pubspec.yaml)\
"
    fi
    
    # 构建类型
    if [ -n "$build_type" ]; then
        feedback+="• 构建类型:$build_type\
"
    else
        feedback+="• 构建类型:默认(iOS debug/Android release)\
"
    fi
    
    # 平台
    if [ "$is_channel_package" = "true" ]; then
        feedback+="• 平台:渠道包(Android多渠道)\
"
    elif [ -n "$platform" ]; then
        feedback+="• 平台:$platform\
"
    else
        feedback+="• 平台:双端(iOS+Android)\
"
    fi
    
    # 上传
    if [ "$is_channel_package" = "true" ]; then
        feedback+="• 上传蒲公英:不适用(渠道包自动跳过)\
"
    elif [ -n "$upload" ]; then
        if [ "$upload" = "yes" ]; then
            feedback+="• 上传蒲公英:是\
"
        else
            feedback+="• 上传蒲公英:否\
"
        fi
    else
        feedback+="• 上传蒲公英:否(默认)\
"
    fi
    
    # API_KEY(只在用户指定或上传为是时显示)
    if [ "$is_channel_package" != "true" ] && [ "$upload" = "yes" ]; then
        if [ -n "$api_key" ]; then
            feedback+="• API_KEY:$api_key\
"
        else
            feedback+="• API_KEY:使用默认值\
"
        fi
    fi
    
    # 更新说明
    if [ "$is_channel_package" = "true" ]; then
        feedback+="• 更新说明:不适用\
"
    elif [ -n "$desc" ]; then
        feedback+="• 更新说明:$desc\
"
    else
        feedback+="• 更新说明:无\
"
    fi
    
    feedback+="\
📁 生成文件:\
"
    
    # 添加APK文件
    if [ -n "$apk_files" ]; then
        while IFS= read -r apk; do
            feedback+="📱 Android: \`$apk\`\
"
        done \x3C\x3C\x3C "$apk_files"
    fi
    
    # 添加IPA文件
    if [ -n "$ipa_files" ]; then
        while IFS= read -r ipa; do
            feedback+="🍎 iOS: \`$ipa\`\
"
        done \x3C\x3C\x3C "$ipa_files"
    fi
    
    # 添加蒲公英链接
    if [ -n "$pgyer_links" ] && [ "$upload" = "yes" ]; then
        feedback+="\
📎 下载链接:\
"
        while IFS= read -r link; do
            feedback+="$link\
"
        done \x3C\x3C\x3C "$pgyer_links"
    fi
    
    feedback+="\
💡 提示:文件保存在 build 目录下,可通过 Finder 访问。"
else
    # 构建失败消息
    error_summary=$(echo "$error_content" | tail -20)
    
    feedback="❌ 打包失败\
\
"
    feedback+="📂 分支信息:$branch_status\
"
    feedback+="⏱️ 耗时:$time_str\
\
"
    feedback+="❌ 错误信息:\
\`\`\`\
"
    feedback+="$error_summary\
"
    feedback+="\`\`\`\
\
"
    feedback+="🔍 可能的原因:\
"
    feedback+="1. 代码编译错误 - 检查 Flutter 环境\
"
    feedback+="2. 依赖问题 - 尝试执行 \`flutter pub get\`\
"
    feedback+="3. iOS 证书问题 - 检查证书配置\
"
    feedback+="4. Android 签名问题 - 检查 keystore 配置\
\
"
    feedback+="📋 完整日志:请查看项目目录下的 build.log 文件"
fi

# 发送反馈消息
reply "$feedback"
Usage Guidance
This skill will run git commands and execute a packaging script inside a specific project path. Before using it: 1) Confirm the hard-coded project path matches your project or update the instructions; 2) Ensure you have no uncommitted changes (the flow may checkout and pull, which can overwrite/complicate local changes); 3) Inspect the project's ./pgyer_all.sh (and any wrapper scripts) to verify they are safe and do what you expect, especially before supplying an API_KEY for uploads; 4) Prefer running it first in a disposable clone or branch to observe behavior; 5) If you need it to operate on a different path, modify the SKILL.md or provide a safe configuration mechanism. These steps reduce risk from accidental repo state changes or unintended uploads.
Capability Analysis
Type: OpenClaw Skill Name: app-packager Version: 1.0.0 The skill bundle is a legitimate automation tool for packaging and deploying mobile applications to the Pgyer platform. It handles Git branch switching, parameter parsing (version, build type, API keys), and executes a local build script (`pgyer_all.sh`) while providing status updates to the user. Although it contains a hardcoded local path (`/Users/nuoyun/Desktop/package/NYLiveUser`) and relies on an external script not included in the bundle, its logic is transparent, well-documented, and strictly aligned with its stated purpose without any signs of malicious intent or data exfiltration.
Capability Assessment
Purpose & Capability
The skill's name and description (switch git branch and run packaging/upload) match the SKILL.md actions (git fetch/checkout/pull, run packaging script, optionally upload). There is no unrelated credential request. Minor inconsistency: the README example calls a wrapper at ~/.openclaw/.../scripts/app-packager, yet the runtime flow directly runs ./pgyer_all.sh inside the project — this mismatch should be clarified.
Instruction Scope
The instructions perform destructive/side-effect operations on a local repository: fetch, checkout (possibly creating a local branch tracking origin), pull, and run an arbitrary packaging script from the project. They assume a hard-coded absolute project path (/Users/nuoyun/Desktop/package/NYLiveUser) and call ./pgyer_all.sh. The skill does not stash or protect uncommitted changes before checkout/pull, so running it may alter working tree state. The flow captures output and scans for URLs to report back — which is expected — but users should be aware the skill will access the filesystem, run shell commands, and communicate build/upload results.
Install Mechanism
Instruction-only skill with no install spec or code files — lowest install risk. Nothing is downloaded or written to disk by the skill itself (the script executed is expected to be in the project).
Credentials
No required environment variables or primary credentials are declared. The skill supports an optional API_KEY provided by the user for uploading (expected for a pgyer upload). No extraneous secrets are requested.
Persistence & Privilege
always is false and model invocation is allowed (platform default). The skill does not request persistent system-wide configuration or to modify other skills. It does execute commands in the user's workspace when invoked, which is expected for this functionality.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install app-packager
  3. After installation, invoke the skill by name or use /app-packager
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.0
Initial release of app-packager skill: - Automatically switches Git branches and executes app packaging scripts based on user requests. - Supports parameters for branch, platform (android/ios/all), build type (debug/adhoc/release), version, upload options, API_KEY, and update descriptions. - Provides CLI and natural language triggers for invocation; parses user intent and maps to script parameters. - Performs pre-flight checks for project path, script permissions, and Git availability. - Notifies user about packaging progress and returns detailed results, including generated files and download links. - Designed specifically for app packaging scenarios—does not support merging, committing, unit testing, or code checking.
Metadata
Slug app-packager
Version 1.0.0
License MIT-0
All-time Installs 1
Active Installs 1
Total Versions 1
Frequently Asked Questions

What is App Packager?

自动切换 Git 分支并执行 APP 打包脚本。支持指定分支、平台、构建类型、版本号、上传选项、API_KEY和更新说明。 打包完成后会自动通知用户结果。 Use when: 用户需要打包 APP、切换分支打包、构建应用、生成安装包。 NOT for: 代码合并、代码提交、单元测试、代码检查。 It is an AI Agent Skill for Claude Code / OpenClaw, with 164 downloads so far.

How do I install App Packager?

Run "/install app-packager" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is App Packager free?

Yes, App Packager is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does App Packager support?

App Packager is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created App Packager?

It is built and maintained by Heigher (@heigher); the current version is v1.0.0.

💬 Comments