通过宝塔 (aaPanel/BT Panel) API 远程管理服务器 — 部署项目、更新已有站点、上传/下载/读写文件、执行 shell、操作 MySQL 数据库。当用户提到宝塔、更新线上、部署到服务器、`/www/wwwroot`、或给出宝塔面板地址 + API 密钥时触发。
75
93%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
一套通过宝塔面板 HTTP API 完成部署 / 运维 / 数据库变更的 Python 工具集。 无需 SSH、无需 rsync、无需本地装 vercel/docker — 只要一个面板地址和 API 密钥。
自动触发(魔尊未显式点名时也应主动调用):
https://IP:port 形式的宝塔面板地址和一串 32 位 API 密钥/www/wwwroot/ / /www/server/ 下不触发:
本 skill 不假设特定版本 — bt_client.py 首次调用 test() 时会自动探测
面板的 OS / 变体 / 主版本,缓存到 client.panel_info,后续所有方法都据此选择接口。
| 面板 | panel_info 识别 | 状态 | 说明 |
|---|---|---|---|
| 宝塔 Linux v11+ | {os:linux, variant:bt, major:11} | ✅ 已实测 | Debian 12 + v11.6.0,主验证环境 |
| 宝塔 Linux v7/v8/v9/v10 | {major:7-10} | ✅ 支持 | exec_shell 自动走老接口 ExecShellMsg;sql_execute 先试面板 SqlExecute API |
| aaPanel(英文国际版) | {os:linux, variant:aapanel} | ✅ 支持 | API 与宝塔 Linux 完全一致,仅错误消息是英文;write_file 兜底已识别中英双语 |
| 宝塔 Windows 面板 | {os:windows} | ⚠️ 实验 | 文件 / shell / SQL 可用;bt_deploy.py(依赖本地 tar)仅在宝塔 Linux 下完整 |
| 1Panel(飞致云) | — | ❌ 不覆盖 | 完全不同的 REST API,不要用本 skill 操作 1Panel |
| 宝塔企业版 | 同 v11+ | ✅ 预期兼容 | 未实测但 API 同源 |
ExecShell;v7–v10 → ExecShellMsg;均失败自动回退另一个/www/server/mysql/bin/mysql → /www/server/mariadb/bin/mysql → /usr/local/mysql/bin/mysql → $(command -v mysql) → mysql"不存在"/"权限" ∪ 英文 "not exist"/"Permission denied"type 重定向(cmd 不支持 heredoc)python3 bt_client.py test
# 返回里附带:
# "_skill_detected": {"os": "linux", "variant": "bt", "major": 11, "shell": "bash"}Claude 收到 _skill_detected 后应据此决定:
major < 11 + variant=bt → 可以直接用 SQL API(可能更快)variant=aapanel → 错误消息会是英文,别困惑os=windows → 重启命令要改成 Windows 等价(net stop nginx 代替 systemctl restart nginx)major=0 → 探测失败,面板返回不标准 → 跑 test 时把原始 JSON 给魔尊看request_token = md5(request_time + md5(api_key)),每次请求带 request_time 和 request_tokenSaveFileBody 在 /tmp 下可能报 FILE_SAVE_ERR Permission denied,write_file 已自动 delete+recreate 兜底~/.claude/skills/ccg/bt-panel/
├── SKILL.md # 本文件(给你用的指南)
├── bt_client.py # 核心 API 客户端 + 通用 CLI(test/sites/ls/cat/put/exec/sql …)
├── bt_deploy.py # 一键部署器(tar→upload→extract→sql→restart→cleanup)
├── sites.example.json # 站点别名配置示例(复制为 sites.json 使用)
└── references/
├── api-reference.md # 宝塔 v11 API 接口速查(踩过的坑都在这)
└── recipes.md # 实战食谱:更新前端 / PHP / Node / 回滚 …# 环境变量(一次性)
export BT_URL="https://panel.example.com:8888"
export BT_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# 或 CLI 参数:--panel ... --key ...
# 或 ~/.claude/skills/ccg/bt-panel/sites.json 里配置别名,然后 --alias <name>python3 ~/.claude/skills/ccg/bt-panel/bt_client.py test
# → 返回 {version, system, cpuNum, memTotal, ...}python3 ~/.claude/skills/ccg/bt-panel/bt_deploy.py \
--local ~/projects/myapp \
--remote /www/wwwroot/myapp.example.com \
--exclude node_modules --exclude .git --exclude '*.log' \
--backup \
--restart 'cd /www/wwwroot/myapp.example.com && pm2 restart myapp'部署器会:连通测试 → 备份远端 → 本地 tar.gz → 上传 → 解压 → chown → SQL → 重启 → 清理。
# 通用客户端 — bt_client.py
python3 bt_client.py test # 系统信息
python3 bt_client.py sites # 站点列表
python3 bt_client.py dbs # 数据库列表
python3 bt_client.py ls /www/wwwroot # 列目录
python3 bt_client.py cat /www/wwwroot/app/.env
python3 bt_client.py write /www/wwwroot/app/config.json '{"a":1}'
python3 bt_client.py put ./local.js /www/wwwroot/app/
python3 bt_client.py get /www/wwwroot/app/log.txt ./log.txt
python3 bt_client.py mkdir /www/wwwroot/app/cache
python3 bt_client.py rm /www/wwwroot/app/old.js
python3 bt_client.py exec "cd /www/wwwroot/app && pm2 restart app" --cwd /www/wwwroot/app
python3 bt_client.py sql mydb "SELECT COUNT(*) FROM users"
python3 bt_client.py sql mydb --from-file migration.sql
# 一键部署 — bt_deploy.py
python3 bt_deploy.py --alias myapp # 用别名
python3 bt_deploy.py --alias myapp --dry-run # 预览不执行
python3 bt_deploy.py --alias myapp --clean # 清空目标再部署(慎用)
python3 bt_deploy.py --local DIR --remote DIR ... # 无别名import os
import sys
sys.path.insert(0, os.path.expanduser('~/.claude/skills/ccg/bt-panel'))
from bt_client import BtClient
c = BtClient('https://1.2.3.4:8888', 'API_KEY')
c.test() # 系统信息
c.get_sites() # 站点
c.exec_shell('pm2 restart all', cwd='/root') # 远程执行
c.sql_execute('mydb', 'UPDATE users SET ...') # SQL
c.upload('./dist.tar.gz', '/tmp/') # 上传
c.write_file('/www/wwwroot/app/.env', 'KEY=1') # 写文件触发场景:用户发来形如 https://1.2.3.4:8888 <32位API密钥> 更新一下 xxx 的指令。
bt_client.py test 确认密钥有效、面板可达bt_client.py sites 列出站点、ls /www/wwwroot 找到目标bt_deploy.py --clean(前端资源需要完整替换)bt_deploy.py + 重启服务bt_client.py put 或 writebt_client.py sql ... --from-filebt_client.py exec "pm2 restart xxx"--dry-run 预览给魔尊确认,无歧义直接干exec 'curl -I <url>' 或 cat .env 之类读回确认rm -rf 删除 /www/wwwroot/*,先 --backup 再 --clean.gitignore)--dry-rundb_backup(db_id) 或 exec "mysqldump ... > backup.sql"见 references/recipes.md → 故障排查章节。常见问题:
签名校验失败 → API 密钥错 / 客户端时间漂移(差 >60s)IP 未在白名单 → 宝塔面板 → 设置 → API 接口 → 添加本机公网 IP指定参数无效 → 接口字段名版本差异,参考 api-reference.mdFILE_SAVE_ERR Permission denied → sticky bit 冲突,客户端已自动兜底FILE_SHELL_EMPTY → 首轮轮询太快,exec_shell 已延后首次 pollfba314b
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.