Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 216 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
name: release

# 自动打包 pipeline(第一版:macOS .app + .dmg,arm64 + Intel)。
# macos-14 (Apple Silicon arm64 原生) + macos-15-intel (Intel x64 原生)
# 触发: push tag v* 或 workflow_dispatch(手动填 version)
# 产物: cargo tauri build 直出 .dmg, 每个附 .sha256, 收口到一个 draft GitHub
# release 让你手动确认转正式。
# (.pkg / Windows .exe 暂未启用, 后续需要时再加。)
#
# === 签名(重点,避免"打包出来不可用")===
# macOS: 默认 ad-hoc 签名(APPLE_SIGNING_IDENTITY="-")。完全未签的 .app 在 macOS
# Sequoia 15+ 会被 Gatekeeper 无条件拒绝(报"已损坏"、连"仍要打开"都没有);
# ad-hoc 签后用户可"右键 → 打开"绕过。这是免费的最低保障。
# 若日后配齐下面 6 个可选 secrets,则自动升级为真签名 + 公证(双击即用、无警告):
# APPLE_CERTIFICATE / APPLE_CERTIFICATE_PASSWORD Developer ID Application .p12 (base64) + 密码
# APPLE_SIGNING_IDENTITY 形如 "Developer ID Application: Name (TEAMID)"
# APPLE_API_KEY_BASE64 / APPLE_API_KEY / APPLE_API_ISSUER App Store Connect API key(.p8 base64)+ Key ID + Issuer ID(公证用)
#
# 注意: macOS 不能"先 build app + 手动 codesign + 再 build dmg"——第二次 build 会重新
# bundle .app 覆盖签名。必须让 Tauri 在同一次 build 内完成签名链(本 workflow 即如此)。

on:
push:
tags: ['v*']
workflow_dispatch:
inputs:
version:
description: '不带 v 前缀(如 0.1.0)'
required: true

permissions:
contents: write

env:
CARGO_TERM_COLOR: always

jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- os: macos-14
target: aarch64-apple-darwin
plat: macOS-arm64
# Intel Mac: macos-15-intel 是 GitHub 在 macos-13 退役后为 Intel x64 新设的
# runner 标签, 公开仓免费, 原生编译 x86_64-apple-darwin。
- os: macos-15-intel
target: x86_64-apple-darwin
plat: macOS-x64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 20

- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}

- uses: Swatinem/rust-cache@v2
with:
workspaces: 'src-tauri -> target'
key: ${{ matrix.target }}

- name: Cache cargo-tauri binary
id: cache-tauri-cli
uses: actions/cache@v4
with:
path: ~/.cargo/bin/cargo-tauri
key: ${{ runner.os }}-${{ matrix.target }}-cargo-tauri-cli-v1

- name: Install tauri-cli
if: steps.cache-tauri-cli.outputs.cache-hit != 'true'
timeout-minutes: 25
run: cargo install tauri-cli --version "^2" --locked

- name: Install frontend deps
run: npm install

- name: Resolve VERSION
id: ver
shell: bash
run: |
if [[ -n "${{ github.event.inputs.version }}" ]]; then
V="${{ github.event.inputs.version }}"
Comment thread
Cmochance marked this conversation as resolved.
else
V="${GITHUB_REF_NAME#v}"
fi
echo "version=$V" >> "$GITHUB_OUTPUT"
echo "Resolved VERSION=$V"

# 版本一致性: tag/输入的版本必须等于 tauri.conf.json 的 version, 否则产物名
# 和 binary 内部版本会对不上, 早 fail。
- name: Verify version matches tauri.conf.json
shell: bash
run: |
CONF_V=$(node -p "require('./src-tauri/tauri.conf.json').version")
if [[ "$CONF_V" != "${{ steps.ver.outputs.version }}" ]]; then
echo "::error::tag/输入版本 '${{ steps.ver.outputs.version }}' != tauri.conf.json version '$CONF_V'。请先把 src-tauri/tauri.conf.json 的 version 改成一致再发 tag。"
exit 1
fi
echo "version OK: $CONF_V"

# macOS: ad-hoc 默认, 有 Developer ID secret 则导入证书 + 公证。
- name: Import macOS signing cert (optional)
if: env.CERT != ''
uses: apple-actions/import-codesign-certs@v3
with:
p12-file-base64: ${{ secrets.APPLE_CERTIFICATE }}
p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
env:
CERT: ${{ secrets.APPLE_CERTIFICATE }}

- name: Write Apple notary API key (optional)
if: env.KEY_B64 != ''
shell: bash
env:
KEY_B64: ${{ secrets.APPLE_API_KEY_BASE64 }}
KEY_ID: ${{ secrets.APPLE_API_KEY }}
run: |
mkdir -p ~/.appstoreconnect/private_keys
echo "$KEY_B64" | base64 -d > ~/.appstoreconnect/private_keys/AuthKey_${KEY_ID}.p8
echo "APPLE_API_KEY_PATH=$HOME/.appstoreconnect/private_keys/AuthKey_${KEY_ID}.p8" >> "$GITHUB_ENV"

- name: cargo tauri build (app + dmg)
shell: bash
env:
APPLE_SIGNING_IDENTITY_RAW: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_API_ISSUER_RAW: ${{ secrets.APPLE_API_ISSUER }}
APPLE_API_KEY_RAW: ${{ secrets.APPLE_API_KEY }}
run: |
set -euo pipefail
# 未配置的 secret 在 env 里是空串, 显式判空再 export, 空时不暴露给 build。
[[ -n "${APPLE_SIGNING_IDENTITY_RAW:-}" ]] && export APPLE_SIGNING_IDENTITY="$APPLE_SIGNING_IDENTITY_RAW"
[[ -n "${APPLE_API_ISSUER_RAW:-}" ]] && export APPLE_API_ISSUER="$APPLE_API_ISSUER_RAW"
[[ -n "${APPLE_API_KEY_RAW:-}" ]] && export APPLE_API_KEY="$APPLE_API_KEY_RAW"
if [[ -z "${APPLE_SIGNING_IDENTITY:-}" ]]; then
# 无 Developer ID → ad-hoc, 让 Tauri 在 build 内 codesign --sign -。
export APPLE_SIGNING_IDENTITY="-"
echo "::notice::macOS 无 Developer ID secret, 使用 ad-hoc 签名(-)"
fi
cargo tauri build --target "${{ matrix.target }}" --bundles app,dmg

- name: Verify macOS bundles (codesign / hdiutil)
shell: bash
run: |
set -euo pipefail
BDIR="src-tauri/target/${{ matrix.target }}/release/bundle"
APP="$BDIR/macos/agent_theme_companion.app"
echo "::group::codesign --verify .app (深度严格)"
codesign --verify --deep --strict --verbose=2 "$APP"
echo "::endgroup::"
echo "::group::hdiutil verify dmg"
for d in "$BDIR"/dmg/*.dmg; do
[[ -f "$d" ]] || continue
hdiutil verify "$d"
sz=$(wc -c < "$d"); (( sz > 1048576 )) || { echo "::error::.dmg 太小($sz)疑似坏包: $d"; exit 1; }
done
echo "::endgroup::"

- name: Stage + rename + sha256
shell: bash
run: |
set -euo pipefail
V="${{ steps.ver.outputs.version }}"; PLAT="${{ matrix.plat }}"
BDIR="src-tauri/target/${{ matrix.target }}/release/bundle"
mkdir -p staging
shopt -s nullglob
for f in "$BDIR"/dmg/*.dmg; do cp "$f" "staging/Agent-Theme-v${V}-${PLAT}.dmg"; done
cd staging
for f in *; do shasum -a 256 "$f" > "$f.sha256"; done
echo "Staged for $PLAT:"; ls -la
files=(*)
if (( ${#files[@]} == 0 )); then
echo "::error::没有产物 staged($PLAT)"; find "../$BDIR" -maxdepth 3 -type f | sed -n '1,80p'; exit 1
fi

- uses: actions/upload-artifact@v4
with:
name: bundle-${{ matrix.plat }}
path: staging/*
if-no-files-found: error

release:
needs: build
runs-on: ubuntu-22.04
steps:
- uses: actions/download-artifact@v4
with:
path: dist
merge-multiple: true

- name: Resolve VERSION
id: ver
shell: bash
run: |
if [[ -n "${{ github.event.inputs.version }}" ]]; then
V="${{ github.event.inputs.version }}"
else
V="${GITHUB_REF_NAME#v}"
fi
echo "version=$V" >> "$GITHUB_OUTPUT"

- name: List artifacts
run: ls -la dist/

- uses: softprops/action-gh-release@v2
with:
files: 'dist/*'
tag_name: v${{ steps.ver.outputs.version }}
name: v${{ steps.ver.outputs.version }}
draft: true
generate_release_notes: true
29 changes: 23 additions & 6 deletions README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@

Agent Theme is a standalone desktop app (Tauri v2). The agent (Codex Desktop / Antigravity) is launched with `--remote-debugging-port` to expose a CDP port; this app connects over WebSocket and uses `Page.addScriptToEvaluateOnNewDocument` to inject a script before the page loads — adding a background layer, overriding the agent UI's design tokens, and applying `backdrop-filter` frosted glass to each panel. The whole theme lives only at runtime: turn off the toggle or restart the agent and it disappears, **without modifying the agent's binary or any config file**.

## Supported Apps

| Agent | Status | How it's reskinned |
|---|---|---|
| **Codex Desktop** | ✅ Supported | overrides Tailwind v4 `--color-token-*` design tokens + per-module frosted glass |
| **Antigravity** | ✅ Supported | overrides shadcn / `--vscode-*` semantic tokens + per-panel frosted glass + chat-prose / code-block recolouring |

> Both are injected at the CDP runtime and share `theme.json`'s colour knobs; support for more agents will be added over time.

## Theme Showcase

Every theme is **colour-matched individually** to its own background — glass tinted from the image's dark tones, accent taken from the character's signature colour, and the legibility scrim calibrated per-wallpaper by brightness — so chat text stays readable on any image instead of hiding behind a uniform dark overlay. Below is the actual look on Antigravity (sidebar & input text blurred for privacy):
Expand Down Expand Up @@ -53,14 +62,22 @@ Every theme is **colour-matched individually** to its own background — glass t
- 💾 **Persistent config** — settings saved to `~/.codex/agent-theme/config.json`
- 🔒 **Single-instance guard** — prevents conflicting companion windows

## Install
## Download & Install

Grab the `.dmg` for your chip from [Releases](https://github.com/Cmochance/agent-theme/releases) (each ships a `.sha256` checksum):

| Platform | Asset | Notes |
|---|---|---|
| macOS · Apple Silicon | `Agent-Theme-v<ver>-macOS-arm64.dmg` | M-series |
| macOS · Intel | `Agent-Theme-v<ver>-macOS-x64.dmg` | Intel x64 |

Open the `.dmg` and drag the app into Applications.

### macOS first launch (important)

1. Download the latest `.dmg` from [Releases](https://github.com/Cmochance/agent-theme/releases)
2. Drag `Agent Theme Companion.app` into Applications
3. If macOS Gatekeeper blocks it on first launch ("unidentified developer"): `right-click → Open` once, or go to `System Settings → Privacy & Security` and click "Open Anyway"
4. Launch — the UI shows the agent's run state
Not Apple-notarized yet, so the app uses **ad-hoc signing** (which avoids the "is damaged / can't be opened" error), but Gatekeeper will warn "unidentified developer" on first launch — **right-click the app → Open** once to allow it, or go to `System Settings → Privacy & Security` and click "Open Anyway". Verify the download with `shasum -a 256 -c <file>.sha256`.

> **macOS only** for now (`agent.rs` process detection & paths depend on `~/Library/Application Support/`). Windows / Linux support is planned.
> **Runtime platform**: **macOS only** for now (`agent.rs` process detection & paths depend on `~/Library/Application Support/`). Windows / Linux support is planned.

## Quick Start

Expand Down
29 changes: 23 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@

Agent Theme 是一个独立的桌面应用(Tauri v2)。代理(Codex Desktop / Antigravity)启动时附带 `--remote-debugging-port` 暴露 CDP 端口,本应用通过 WebSocket 连上去,用 `Page.addScriptToEvaluateOnNewDocument` 在页面加载前注入一段脚本:插入背景图层 + 覆盖代理 UI 的设计令牌(design tokens)+ 给各面板加 `backdrop-filter` 磨砂玻璃。整套主题只活在运行时,关掉开关或代理重启即自然消失,**不动代理的 binary、不改任何配置文件**。

## 已适配应用

| 代理 | 状态 | 换肤方式 |
|---|---|---|
| **Codex Desktop** | ✅ 已适配 | 覆盖 Tailwind v4 `--color-token-*` 设计令牌 + 各模块磨砂玻璃 |
| **Antigravity** | ✅ 已适配 | 覆盖 shadcn / `--vscode-*` 语义令牌 + 各面板磨砂玻璃 + 对话正文 / 代码块重配色 |

> 两者都通过 CDP 运行时注入、共用 `theme.json` 的配色旋钮;后续适配更多代理会陆续加入。

## 主题展示

每套主题都按自己的背景图**单独调色**——玻璃从画面暗部取色、强调色取角色的标志色、可读性 scrim 按壁纸亮度逐张校准,让聊天文字在任意壁纸上都清晰,而不是套一个统一的暗色蒙版。下面是 Antigravity 上的实际效果(侧栏与输入框文字已做模糊处理):
Expand Down Expand Up @@ -53,14 +62,22 @@ Agent Theme 是一个独立的桌面应用(Tauri v2)。代理(Codex Desktop / An
- 💾 **配置持久化** —— 设置保存到 `~/.codex/agent-theme/config.json`,重启不丢失
- 🔒 **单实例保护** —— 防止多个伴侣窗口同时运行导致冲突

## 安装
## 下载与安装

从 [Releases](https://github.com/Cmochance/agent-theme/releases) 下载对应芯片的 `.dmg`(每个附 `.sha256` 校验文件):

| 平台 | 资产 | 说明 |
|---|---|---|
| macOS · Apple Silicon | `Agent-Theme-v<版本>-macOS-arm64.dmg` | M 系列芯片 |
| macOS · Intel | `Agent-Theme-v<版本>-macOS-x64.dmg` | Intel x64 |

下载后把 `.dmg` 里的 App 拖入「应用程序」即可。

### macOS 首次打开(重要)

1. 从 [Releases](https://github.com/Cmochance/agent-theme/releases) 下载最新 `.dmg`
2. 将 `Agent Theme Companion.app` 拖入「应用程序」
3. 首次打开若被 macOS Gatekeeper 拦截(「来自身份不明的开发者」):`右键 App → 打开` 一次性放行,或到 `系统设置 → 隐私与安全性` 点「仍要打开」
4. 启动后界面即显示代理运行状态
当前未做 Apple 公证,App 用 **ad-hoc 签名**(已避免「已损坏、无法打开」),但首次打开会被 Gatekeeper 提示「来自身份不明的开发者」——**右键 App → 打开** 一次性放行即可,或到 `系统设置 → 隐私与安全性` 点「仍要打开」。下载完可用 `shasum -a 256 -c <文件>.sha256` 校验完整性。

> 当前**仅支持 macOS**(`agent.rs` 的进程检测与路径逻辑依赖 `~/Library/Application Support/`)。Windows / Linux 适配在计划中。
> **运行平台**:当前**仅支持 macOS**(`agent.rs` 的进程检测与路径依赖 `~/Library/Application Support/`)。Windows / Linux 适配在计划中。

## 快速开始

Expand Down
Loading