AIUsage

英文名称: AIUsage-main

类型: Skill | 原作者: admin | 发布者/贡献者: HAOSkill 管理员 | 协同共创极客: | 配置完整度: 100%

Skill 描述

一个统一的仪表盘,用于追踪和管理多个AI提供商的配额、成本和账户,并内置Claude Code、Codex和OpenCode的代理功能。

Skill 内容

name: Release Build

on:
  push:
    tags:
      - "v*.*.*"
  workflow_dispatch:

permissions:
  contents: write

concurrency:
  group: release-${{ github.ref }}
  cancel-in-progress: true

jobs:
  build-release:
    runs-on: macos-15

    steps:
      - name: Checkout
        uses: actions/checkout@v5
        with:
          fetch-depth: 0

      - name: Resolve version
        id: version
        shell: bash
        run: |
          if [[ "${GITHUB_REF_TYPE:-}" == "tag" ]]; then
            VERSION="${GITHUB_REF_NAME#v}"
          else
            VERSION="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' AIUsage/Info.plist)"
          fi

          echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
          echo "Resolved version: ${VERSION}"

      - name: Validate version matches project
        shell: bash
        run: |
          PLIST_SHORT="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' AIUsage/Info.plist)"
          PLIST_BUILD="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' AIUsage/Info.plist)"
          PBXPROJ_VERSION="$(grep 'MARKETING_VERSION = ' AIUsage.xcodeproj/project.pbxproj | head -1 | sed 's/.*= *//;s/ *;.*//')"
          TAG_VERSION="${{ steps.version.outputs.version }}"

          echo "Tag:                     $TAG_VERSION"
          echo "ShortVersionString:      $PLIST_SHORT"
          echo "BundleVersion:           $PLIST_BUILD"
          echo "MARKETING_VERSION:       $PBXPROJ_VERSION"

          FAIL=0
          if [[ "$PLIST_SHORT" != "$TAG_VERSION" ]]; then echo "MISMATCH: CFBundleShortVersionString"; FAIL=1; fi
          if [[ "$PLIST_BUILD" != "$TAG_VERSION" ]]; then echo "MISMATCH: CFBundleVersion"; FAIL=1; fi
          if [[ "$PBXPROJ_VERSION" != "$TAG_VERSION" ]]; then echo "MISMATCH: MARKETING_VERSION"; FAIL=1; fi
          if [[ $FAIL -ne 0 ]]; then exit 1; fi

      - name: Resolve SPM dependencies
        shell: bash
        run: |
          xcodebuild -project AIUsage.xcodeproj -scheme AIUsage \
            -destination "platform=macOS" \
            -resolvePackageDependencies \
            -derivedDataPath build/DerivedData

      - name: Build macOS release artifacts
        shell: bash
        env:
          SPARKLE_EDDSA_PRIVATE_KEY: ${{ secrets.SPARKLE_EDDSA_PRIVATE_KEY }}
          REQUIRE_SPARKLE_SIGNING: "1"
        run: |
          SPARKLE_TOOL="$(find build/DerivedData/SourcePackages/artifacts -name sign_update -path '*/bin/sign_update' | head -1)"
          export SPARKLE_SIGN_TOOL="${SPARKLE_TOOL}"
          ./scripts/package-release.sh "${{ steps.version.outputs.version }}"

      - name: Upload build artifacts
        uses: actions/upload-artifact@v6
        with:
          name: AIUsage-${{ steps.version.outputs.version }}-macOS
          path: |
            dist/AIUsage-${{ steps.version.outputs.version }}-macOS.zip
            dist/AIUsage-${{ steps.version.outputs.version }}-macOS.dmg
          if-no-files-found: error

      - name: Publish GitHub Release
        if: startsWith(github.ref, 'refs/tags/')
        uses: softprops/action-gh-release@v3
        with:
          tag_name: ${{ github.ref_name }}
          generate_release_notes: true
          files: |
            dist/AIUsage-${{ steps.version.outputs.version }}-macOS.zip
            dist/AIUsage-${{ steps.version.outputs.version }}-macOS.dmg

      - name: Update appcast.xml in repository
        if: startsWith(github.ref, 'refs/tags/') && hashFiles('dist/appcast.xml') != ''
        shell: bash
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
          git fetch origin main --depth=1
          git checkout FETCH_HEAD
          cp dist/appcast.xml appcast.xml
          git add appcast.xml
          git diff --cached --quiet && { echo "No appcast changes"; exit 0; }
          git commit -m "Update appcast.xml for ${{ github.ref_name }}"
          git push origin HEAD:main

      - name: Verify appcast version
        if: startsWith(github.ref, 'refs/tags/') && hashFiles('dist/appcast.xml') != ''
        shell: bash
        run: |
          EXPECTED="${{ steps.version.outputs.version }}"
          grep -q "<sparkle:shortVersionString>${EXPECTED}</sparkle:shortVersionString>" dist/appcast.xml
          grep -q "<sparkle:version>${EXPECTED}</sparkle:version>" dist/appcast.xml
          echo "Appcast verified: version ${EXPECTED}"

补充内容

name: Release Build

on:
  push:
    tags:
      - "v*.*.*"
  workflow_dispatch:

permissions:
  contents: write

concurrency:
  group: release-${{ github.ref }}
  cancel-in-progress: true

jobs:
  build-release:
    runs-on: macos-15

    steps:
      - name: Checkout
        uses: actions/checkout@v5
        with:
          fetch-depth: 0

      - name: Resolve version
        id: version
        shell: bash
        run: |
          if [[ "${GITHUB_REF_TYPE:-}" == "tag" ]]; then
            VERSION="${GITHUB_REF_NAME#v}"
          else
            VERSION="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' AIUsage/Info.plist)"
          fi

          echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
          echo "Resolved version: ${VERSION}"

      - name: Validate version matches project
        shell: bash
        run: |
          PLIST_SHORT="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' AIUsage/Info.plist)"
          PLIST_BUILD="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' AIUsage/Info.plist)"
          PBXPROJ_VERSION="$(grep 'MARKETING_VERSION = ' AIUsage.xcodeproj/project.pbxproj | head -1 | sed 's/.*= *//;s/ *;.*//')"
          TAG_VERSION="${{ steps.version.outputs.version }}"

          echo "Tag:                     $TAG_VERSION"
          echo "ShortVersionString:      $PLIST_SHORT"
          echo "BundleVersion:           $PLIST_BUILD"
          echo "MARKETING_VERSION:       $PBXPROJ_VERSION"

          FAIL=0
          if [[ "$PLIST_SHORT" != "$TAG_VERSION" ]]; then echo "MISMATCH: CFBundleShortVersionString"; FAIL=1; fi
          if [[ "$PLIST_BUILD" != "$TAG_VERSION" ]]; then echo "MISMATCH: CFBundleVersion"; FAIL=1; fi
          if [[ "$PBXPROJ_VERSION" != "$TAG_VERSION" ]]; then echo "MISMATCH: MARKETING_VERSION"; FAIL=1; fi
          if [[ $FAIL -ne 0 ]]; then exit 1; fi

      - name: Resolve SPM dependencies
        shell: bash
        run: |
          xcodebuild -project AIUsage.xcodeproj -scheme AIUsage \
            -destination "platform=macOS" \
            -resolvePackageDependencies \
            -derivedDataPath build/DerivedData

      - name: Build macOS release artifacts
        shell: bash
        env:
          SPARKLE_EDDSA_PRIVATE_KEY: ${{ secrets.SPARKLE_EDDSA_PRIVATE_KEY }}
          REQUIRE_SPARKLE_SIGNING: "1"
        run: |
          SPARKLE_TOOL="$(find build/DerivedData/SourcePackages/artifacts -name sign_update -path '*/bin/sign_update' | head -1)"
          export SPARKLE_SIGN_TOOL="${SPARKLE_TOOL}"
          ./scripts/package-release.sh "${{ steps.version.outputs.version }}"

      - name: Upload build artifacts
        uses: actions/upload-artifact@v6
        with:
          name: AIUsage-${{ steps.version.outputs.version }}-macOS
          path: |
            dist/AIUsage-${{ steps.version.outputs.version }}-macOS.zip
            dist/AIUsage-${{ steps.version.outputs.version }}-macOS.dmg
          if-no-files-found: error

      - name: Publish GitHub Release
        if: startsWith(github.ref, 'refs/tags/')
        uses: softprops/action-gh-release@v3
        with:
          tag_name: ${{ github.ref_name }}
          generate_release_notes: true
          files: |
            dist/AIUsage-${{ steps.version.outputs.version }}-macOS.zip
            dist/AIUsage-${{ steps.version.outputs.version }}-macOS.dmg

      - name: Update appcast.xml in repository
        if: startsWith(github.ref, 'refs/tags/') && hashFiles('dist/appcast.xml') != ''
        shell: bash
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
          git fetch origin main --depth=1
          git checkout FETCH_HEAD
          cp dist/appcast.xml appcast.xml
          git add appcast.xml
          git diff --cached --quiet && { echo "No appcast changes"; exit 0; }
          git commit -m "Update appcast.xml for ${{ github.ref_name }}"
          git push origin HEAD:main

      - name: Verify appcast version
        if: startsWith(github.ref, 'refs/tags/') && hashFiles('dist/appcast.xml') != ''
        shell: bash
        run: |
          EXPECTED="${{ steps.version.outputs.version }}"
          grep -q "<sparkle:shortVersionString>${EXPECTED}</sparkle:shortVersionString>" dist/appcast.xml
          grep -q "<sparkle:version>${EXPECTED}</sparkle:version>" dist/appcast.xml
          echo "Appcast verified: version ${EXPECTED}"

使用指南与最佳实践

<p align="center"> <img src="docs/images/app-icon.png" alt="AIUsage icon" width="128"> </p> <h1 align="center">AIUsage</h1> <h4 align="center">一个管理所有AI订阅的仪表盘</h4> <p align="center"> 追踪10+ AI提供商的配额、成本和账户。<br> 内置Claude Code、Codex和OpenCode的代理——兼容任何OpenAI兼容模型。 </p> <p align="center"> <a href="README.zh-CN.md">中文说明</a> · <strong>English</strong> </p> <p align="center"> <a href="https://github.com/sylearn/AIUsage/releases"><img alt="macOS 14+" src="https://img.shields.io/badge/macOS-14%2B-111827?style=flat-square&logo=apple&logoColor=white"></a> <img alt="SwiftUI" src="https://img.shields.io/badge/SwiftUI-Native-f97316?style=flat-square&logo=swift&logoColor=white"> <a href="https://github.com/sylearn/AIUsage/releases/latest"><img alt="Release" src="https://img.shields.io/github/v/release/sylearn/AIUsage?style=flat-square&color=22c55e&label=release"></a> <a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-Apache%202.0-0ea5e9?style=flat-square"></a> <a href="https://github.com/sylearn/AIUsage/stargazers"><img alt="Stars" src="https://img.shields.io/github/stars/sylearn/AIUsage?style=flat-square&color=f59e0b"></a> <a href="https://github.com/sylearn/AIUsage/releases"><img alt="Downloads" src="https://img.shields.io/github/downloads/sylearn/AIUsage/total?style=flat-square&color=6366f1&label=downloads"></a> </p> <p align="center"> <sup>赞助商</sup><br> <a href="https://sucloud.vip"> <img src="docs/images/sucloud-logo.png" alt="Sucloud" width="180"> </a><br> <sub>500+ AI模型 · 文本、图像、视频和音频 · 包含顶级模型 · 按需付费</sub> </p> <p align="center"> <img src="docs/images/dashboard-overview_en.png" alt="AIUsage dashboard" width="100%"> </p> --- ## 目录 - [功能特性](#功能特性) - [预览](#预览) - [安装](#安装) - [代理](#代理) - [调用分析](#调用分析) - [致谢](#致谢) - [赞助商](#赞助商) - [支持作者](#支持作者) - [许可证](#许可证) ## 功能特性 | 功能 | 描述 | | --- | --- | | **12+ AI提供商** | Codex, Copilot, Cursor, Antigravity, Kiro, Warp, Gemini CLI, Droid, Claude Code, OpenCode, Kimi, MiniMax — 一个仪表盘 | | **多账户** | 每个提供商多个账户,独立刷新,一键CLI切换 | | **用量统计** | 来自Claude/Codex代理存档的统一成本和Token分解,仅Token的非代理Codex会话,以及OpenCode的本地会话账本 — 按模型趋势、时间段分析、源感知聚合 | | **Claude Code代理** | 使用DeepSeek、GPT、Ollama或任何OpenAI兼容模型运行Claude Code;Anthropic直通用于用量记录 | | **Codex代理** | 将Codex CLI指向任何OpenAI兼容上游;跨订阅账户和API节点的统一切换器,精确的`config.toml`合并 | | **OpenCode代理** | 通过受管理的`opencode.json`块跨上游切换OpenCode — OpenAI兼容、Anthropic和Responses协议,按节点用量归属,按模型定价和可选的请求记录 | | **调用分析** | 从本地会话日志中统计Claude Code、Codex和OpenCode的MCP/技能/工具调用 — Top-N排名、每日趋势和按应用零调用(“僵尸”技能/MCP)检测;只读,零检测 | | **菜单栏** | 多账户状态栏图标,配额/成本指标,按代理节点切换器,快速查看弹出窗口,彩色进度条 | | **凭证保管库** | macOS钥匙串存储所有管理的凭证 | ## 预览 <table> <tr> <td width="50%"><img src="docs/images/dashboard-overview_en.png" alt="Dashboard"></td> <td width="50%"><img src="docs/images/provider-monitoring_en.png" alt="Provider monitoring"></td> </tr> <tr> <td align="center"><strong>仪表盘</strong></td> <td align="center"><strong>提供商和多账户监控</strong></td> </tr> <tr> <td width="50%"><img src="docs/images/Claude-Code-Proxy-1_en.png" alt="Claude Code proxy node management"></td> <td width="50%"><img src="docs/images/Claude-Code-Proxy-2_en.png" alt="Claude Code proxy configuration"></td> </tr> <tr> <td align="center"><strong>Claude Code代理 · 节点管理</strong></td> <td align="center"><strong>Claude Code代理 · 配置</strong></td> </tr> <tr> <td width="50%"><img src="docs/images/Codex-Proxy-stats_en.png" alt="Codex proxy"></td> <td width="50%"><img src="docs/images/Opencode-Proxy-stats_en.png" alt="OpenCode proxy"></td> </tr> <tr> <td align="center"><strong>Codex代理 · 节点和订阅</strong></td> <td align="center"><strong>OpenCode代理 · 节点和统计</strong></td> </tr> <tr> <td width="50%"><img src="docs/images/proxy-stats_en.png" alt="Usage stats"></td> <td width="50%"><img src="docs/images/menu_bar_en.png" alt="Menu bar"></td> </tr> <tr> <td align="center"><strong>用量统计(Claude、Codex和OpenCode)</strong></td> <td align="center"><strong>菜单栏</strong></td> </tr> <tr> <td colspan="2"><img src="docs/images/Call_analytics_en.png" alt="Call Analytics"></td> </tr> <tr> <td colspan="2" align="center"><strong>调用分析 · MCP/技能/工具使用</strong></td> </tr> </table> ## 安装 从[发布页面](https://github.com/sylearn/AIUsage/releases)下载`.dmg`或`.zip`文件。 ## 代理 AIUsage附带三个独立的代理 — 用于**Claude Code**、**Codex (Codex CLI)**和**OpenCode** — 每个都带有节点管理、用量记录和统一切换器。 ### Claude Code代理 使用任何OpenAI兼容模型运行Claude Code CLI,或透明记录Anthropic API用量。 | 模式 | 功能 | |------|-------------| | **OpenAI代理** | 将Claude API转换为OpenAI格式。适用于DeepSeek、GPT、Azure、Ollama等。 | | **Anthropic直通** | 按原样转发请求,记录输入/输出/缓存Token以进行成本追踪 | **快速开始:** 打开AIUsage → Claude Code代理 → 新建节点 → 配置 → 激活。设置会自动写入`~/.claude/settings.json`。 ### Codex代理 将Codex CLI指向任何OpenAI兼容上游(Responses API),并从一处切换**订阅账户**和**API节点** — 它们互斥,因此一次只有一个身份处于活动状态。 | 功能 | 描述 | |------------|-------------| | **OpenAI兼容上游** | 通过任何兼容`responses`的端点路由Codex CLI | | **统一切换器** | 在订阅账户(`~/.codex/auth.json`)和API节点(`config.toml`)之间一键切换 | | **精确配置合并** | 将受管理的块注入`~/.codex/config.toml`,同时保留您自己的设置;全局片段 + 按节点TOML覆盖 | | **cc-switch同步** | 从本地cc-switch一键导入Codex提供商(上游/模型/密钥),保留`model_reasoning_effort`、`mcp_servers`和其他设置;确定性ID去重避免重复节点(与Claude对称) | **快速开始:** 打开AIUsage → Codex代理 → 新建节点(或选择一个订阅账户)→ 配置 → 激活。`~/.codex/config.toml`会自动合并。已经在使用cc-switch?在工具栏中点击“同步cc-switch”一键导入。 ### OpenCode代理 无需手动编辑`opencode.json`即可在任意数量的上游之间切换OpenCode。AIUsage注入一个受管理的提供商块(并将顶层的`model`指向它),然后在停用时恢复您原始的配置 — 备份是真实来源,因此接管是幂等的。 | 功能 | 描述 | |------------|-------------| | **多协议** | OpenAI兼容(`@ai-sdk/openai-compatible`)、Anthropic(`@ai-sdk/anthropic`)和OpenAI Responses(`@ai-sdk/openai`)— npm包遵循节点的协议 | | **直接或代理模式** | 直接模式重写`opencode.json`以与上游通信;代理模式将其指向本地直通进程以获取每个请求的日志(用量/成本仍来自`opencode.db`) | | **按节点用量** | 每个节点写入一个不同的受管理`providerID`,因此本地OpenCode会话账本将Token和模型.dev定价的成本归属于正确的节点 | | **模型库和定价** | 按节点模型列表,具有独立的按模型定价(美元/人民币);从库中选择默认模型,并从节点卡片切换 | | **cc-switch同步** | 从本地cc-switch一键导入OpenCode提供商(上游/模型/密钥/定价),确定性ID去重,可配置的cc-switch目录 | **快速开始:** 打开AIUsage → OpenCode代理 → 新建节点 → 配置模型和定价 → 激活。`~/.config/opencode/opencode.json`会自动接管(需要OpenCode ≥ 1.2以进行用量追踪)。 Claude Code和Codex的用量和计费详情记录在[docs/USAGE_AND_BILLING.md](docs/USAGE_AND_BILLING.md)中。OpenCode成本直接从其本地会话账本(`opencode.db`)读取,按[models.dev](https://models.dev)预定价。 --- ## 调用分析 查看您实际使用的**MCP服务器、技能和工具**。AIUsage解析Claude Code、Codex和OpenCode的本地会话日志 — 只读,零检测 — 并将工具调用转化为用量洞察:发现您依赖的MCP服务器,并清理已安装但从未调用的“僵尸”技能。 | 功能 | 描述 | |------------|-------------| | **Top-N排名** | MCP服务器(按服务器折叠)、技能和内置工具按调用次数排名,具有稳定的平局打破机制 | | **每日趋势** | 在选定的7/30/90天或全部时间窗口内的每日调用量 | | **零调用检测** | 标记已安装但从未调用的技能和已配置但未使用的MCP服务器 — 按应用范围,因此每个工具自己的清理候选是可操作的 | | **按源范围** | 按Claude Code / Codex / OpenCode过滤或查看全部;技能和MCP通过其自己的技能目录和配置文件归属于每个工具 | > Codex技能调用是启发式的 — Codex没有离散的技能调用事件,因此它们是从`SKILL.md`读取推断的。规则命中次数不被追踪:规则作为上下文注入,而不是离散调用。 --- ## 致谢 灵感来源于[`CodexBar`](https://github.com/steipete/CodexBar)和[`Quotio`](https://github.com/nguyenphutrong/quotio)。 ## 赞助商 <p align="center"> <a href="https://sucloud.vip"> <img src="docs/images/sucloud-logo.png" alt="Sucloud" width="180"> </a> </p> <p align="center"> <a href="https://sucloud.vip"><strong>Sucloud</strong></a> — AI API聚合平台,拥有500+模型。<br> 全模态覆盖(文本、图像、视频、音频),包括Claude、GPT、Gemini等。<br> 支持人民币支付,无需海外信用卡。 </p> <p align="center"> <img alt="Models" src="https://img.shields.io/badge/500%2B%20Models-full%20modality-6366f1?style=flat-square"> <img alt="Pricing" src="https://img.shields.io/badge/0.7%C2%A5%20%3D%20%241-pay--as--you--go-22c55e?style=flat-square"> <img alt="Bonus" src="https://img.shields.io/badge/%240.2-welcome%20bonus-f59e0b?style=flat-square"> </p> ## 支持作者 如果AIUsage对您有帮助,请考虑请作者喝杯咖啡。您的支持有助于保持项目的维护和改进。 <p align="center"> <img src="docs/images/donate-qrcode.jpg" alt="Donation QR code" width="220"> </p> ## 友情链接 - [Linux.do社区](https://linux.do) ## 许可证 [Apache License 2.0](LICENSE)