macOS menu-bar controller (GPUI) for a bundled mihomo core.
Strategy JSON under ~/Library/Application Support/myproxy/ is the source of truth: subscriptions, node groups, rules, and Mixed port (HTTP + SOCKS5 on one loopback port). The UI is Chinese: 连接, 节点组, 规则, 设置.
Download myproxy-*.sparkle.zip from Releases, unzip, and move myproxy.app into Applications.
If the build is not Developer ID–notarized, macOS Gatekeeper may require a right-click → Open the first time.
Choose 正式版(Prod) or Nightly under 设置 → 更新 → 更新通道, then use 检查更新 or the menu-bar extra. The choice is saved in strategy.json; older configurations default to the installed build's channel. Switching back to Prod receives the next newer Prod build and does not downgrade the installed app.
| Channel | Sparkle feed | CI/CD |
|---|---|---|
| Prod | https://github.com/leaperone/myproxy/releases/latest/download/appcast.xml |
Push a vMAJOR.MINOR.PATCH tag, or run Release with channel prod and that existing tag. |
| Nightly | https://github.com/leaperone/myproxy/releases/download/nightly/appcast.xml |
Builds main daily at 18:00 UTC, or run Release with channel nightly. |
Nightly builds are GitHub prereleases with immutable build tags. The nightly prerelease points to the latest Nightly feed. Both channels generate Sparkle deltas from recent same-channel archives; Nightly never replaces GitHub's latest stable release. Existing published Prod tags cannot be overwritten by the workflow. While the core is connected, Check for Updates and archive/delta downloads use Mixed as an HTTP proxy.
Cargo.toml holds the next target release version. Since v0.0.3 is already released, main now targets 0.0.4: Prod uses v0.0.4, while Nightly uses v0.0.4-nightly.20260905.42.1 (UTC date, Release run number, attempt). The app displays the same version without the v prefix; the source commit is recorded in release notes. When a Prod release is ready, tag its matching commit, then advance main to the next target version. Nightly tags do not trigger the Prod workflow.
Both channels use the Release workflow's run number and attempt as CFBundleVersion, so Sparkle can compare builds across channels. The display version, build number, feed, and channel are validated against the packaged app before publication. A manually dispatched Prod release checks out the requested tag; its version must match Cargo.toml at that commit.
The title shows Dev for development builds and Nightly for Nightly builds; Prod has no badge. This identifies the installed build, independently of the selected update channel or developer logging. Local debug builds default to Dev and release builds to Prod; MYPROXY_BUILD_CHANNEL=dev|prod|nightly overrides this at build time.
The repository's release skill handles /release patch, /release minor, /release major, and /release nightly ($release in Codex). Stable increments start from the latest published Prod version, so an already-advanced development version is not incremented twice. Creating or reviewing the skill does not publish a release.
scripts/fetch-mihomo.sh
scripts/fetch-sparkle.sh # Sparkle.framework + generate_appcast
cargo run --bin myproxy # debug UI, no Sparkle
MYPROXY_PAGE=connections cargo run --bin myproxy
scripts/package-macos-app.sh # release .app with Sparkle
scripts/release-macos.sh # zip + appcast into dist/
cargo run --bin myproxyctl -- capabilitiesRust 1.98+ (rust-toolchain.toml). Subscription URLs are never written to myproxy.log.
myproxyctl is included in myproxy.app/Contents/MacOS/ and updated with the app. A first launch that does not yet have the PATH link opens a one-screen prompt to create ~/.cargo/bin/myproxyctl and copy the official Agent skill. Skipping or installing writes onboard.json next to strategy.json, so the prompt does not return. The MacBook Air install script creates the same link automatically.
The app's 设置 → 命令行工具 panel can create or update that link later, and copies the official Agent skill from .agents/skills/agent/SKILL.md. It refuses to replace an existing regular file. If a terminal cannot find myproxyctl, add ~/.cargo/bin to PATH. You can still invoke /Applications/myproxy.app/Contents/MacOS/myproxyctl directly.
All commands accept --json for one machine-readable success result on stdout. Runtime errors return a JSON error on stderr and a non-zero exit. The official Agent CLI skill explains how to inspect and configure myproxy.
myproxyctl --json capabilities
myproxyctl --json status
myproxyctl --json group listcargo run --bin myproxyctl -- subscription add 'https://…' --name Example
cargo run --bin myproxyctl -- filter --set '(?i)(流量|剩余|到期|官网)'
cargo run --bin myproxyctl -- group add PROXY --all
cargo run --bin myproxyctl -- rule add --name GitHub --keyword github --via PROXY
cargo run --bin myproxyctl -- apply
cargo run --bin myproxyctl -- connectDefault Mixed port is 7890.
Local packaging uses a Developer ID identity from the login keychain when one exists; otherwise it ad-hoc signs. Both CI release channels require Developer ID signing, notarization, and Sparkle signatures:
| Secret | Purpose |
|---|---|
SPARKLE_ED_PRIVATE_KEY |
EdDSA seed for generate_appcast / sign_update (required for in-app updates) |
APPLE_ID / APPLE_TEAM_ID / APPLE_APP_SPECIFIC_PASSWORD |
Required notarization |
CSC_LINK / CSC_KEY_PASSWORD |
Base64 Developer ID certificate and its password |
MYPROXY_HOST_DEVID_PROFILE / MYPROXY_NETWORK_EXTENSION_DEVID_PROFILE |
Provisioning profiles needed for System Extension activation |
Do not commit .env, .p12, or the Sparkle private key.