diff --git a/scripts/create-cloudbird-agent-app.html b/scripts/create-cloudbird-agent-app.html
new file mode 100644
index 0000000..a8ad505
--- /dev/null
+++ b/scripts/create-cloudbird-agent-app.html
@@ -0,0 +1,26 @@
+
+
+
+
+ 创建 cloudbird-agent GitHub App
+
+
+ 正在跳转到 GitHub 创建 cloudbird-agent App……
+ (浏览器需已登录 Cloudbird-Software 组织 owner 账号;表单已按最小权限预填,确认后点 Create GitHub App。)
+
+
+
diff --git a/scripts/gh-app-token.sh b/scripts/gh-app-token.sh
new file mode 100755
index 0000000..b92a482
--- /dev/null
+++ b/scripts/gh-app-token.sh
@@ -0,0 +1,70 @@
+#!/usr/bin/env bash
+# gh-app-token.sh —— 用 cloudbird-agent App 私钥换取 1 小时有效的安装令牌
+#
+# 这是 agent 与 GitHub 交互的唯一推荐认证方式:
+# - 权限最小:Contents / Pull requests / Issues 读写,无 admin、无 Workflows 改动权
+# - 令牌 1 小时自动过期,磁盘上不落任何长期凭据(私钥妥善保管即可)
+# - 所有操作以 cloudbird-agent[bot] 身份进入审计日志,与人类账号区分
+# - ruleset 照样生效:App 不能直推 main,必须走 PR 过 gate
+#
+# 依赖:bash curl openssl jq(无需任何 GitHub SDK)
+#
+# 用法:
+# export CB_APP_ID=123456 # App 详情页的 App ID
+# export CB_APP_KEY_FILE=~/.config/cloudbird/cloudbird-agent.pem
+# # CI / secret 场景改用字面量: export CB_APP_KEY=""
+#
+# GH_TOKEN=$(bash gh-app-token.sh) # 作用域=安装的全部仓库
+# GH_TOKEN=$(REPO=template-service bash gh-app-token.sh) # 作用域=单仓库(推荐)
+# gh api user # 验证:应显示 cloudbird-agent[bot]
+set -euo pipefail
+
+API="${CB_GITHUB_API:-https://api.github.com}"
+ORG="${ORG:-Cloudbird-Software}"
+APP_ID="${CB_APP_ID:?需要环境变量 CB_APP_ID(GitHub App 设置页的 App ID)}"
+
+# 私钥:优先文件,其次字面量(CI secret 里通常存 PEM 全文)
+if [[ -n "${CB_APP_KEY_FILE:-}" && -f "$CB_APP_KEY_FILE" ]]; then
+ KEY=$(cat "$CB_APP_KEY_FILE")
+elif [[ -n "${CB_APP_KEY:-}" ]]; then
+ KEY="$CB_APP_KEY"
+else
+ echo "错误:需要 CB_APP_KEY_FILE(私钥文件路径)或 CB_APP_KEY(PEM 内容)" >&2
+ exit 1
+fi
+
+b64url() { openssl base64 -A | tr '+/' '-_' | tr -d '=\n'; }
+
+# 1) 生成 App JWT(RS256 签名,9 分钟有效,容忍时钟偏差)
+now=$(date +%s)
+header=$(printf '{"alg":"RS256","typ":"JWT"}' | b64url)
+payload=$(printf '{"iat":%d,"exp":%d,"iss":"%s"}' "$((now - 60))" "$((now + 480))" "$APP_ID" | b64url)
+signature=$(printf '%s.%s' "$header" "$payload" | openssl dgst -sha256 -sign <(printf '%s\n' "$KEY") | b64url)
+JWT="$header.$payload.$signature"
+
+gh_api() { curl -sS -H "Authorization: Bearer $JWT" -H "Accept: application/vnd.github+json" "$@"; }
+
+# 2) 定位组织内的 installation id
+INSTALL_ID=$(gh_api "$API/app/installations?per_page=100" \
+ | jq -r --arg org "$ORG" '.[] | select((.account.login | ascii_downcase) == ($org | ascii_downcase)) | .id' | head -1)
+if [[ -z "$INSTALL_ID" ]]; then
+ echo "错误:找不到 $ORG 的 installation。请先安装 App:Settings → Applications → cloudbird-agent → Configure" >&2
+ exit 1
+fi
+
+# 3) JWT 换安装令牌;REPO 非空时把令牌限定到单仓库(最小权限)
+BODY='{}'
+[[ -n "${REPO:-}" ]] && BODY=$(jq -nc --arg r "$REPO" '{repositories: [$r]}')
+RESP=$(curl -sS -X POST \
+ -H "Authorization: Bearer $JWT" \
+ -H "Accept: application/vnd.github+json" \
+ -d "$BODY" "$API/app/installations/$INSTALL_ID/access_tokens")
+
+TOKEN=$(jq -r '.token // empty' <<<"$RESP")
+if [[ -z "$TOKEN" ]]; then
+ echo "错误:换令牌失败:$RESP" >&2
+ exit 1
+fi
+
+echo "令牌有效至 $(jq -r .expires_at <<<"$RESP")(作用域:${REPO:-全部已安装仓库},身份 cloudbird-agent[bot])" >&2
+echo "$TOKEN"