# ipswitch **Repository Path**: yeti1/ipswitch ## Basic Information - **Project Name**: ipswitch - **Description**: 原生 macOS 网络配置切换应用 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-05 - **Last Updated**: 2026-07-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README

IP Switch app icon

IP Switch · 网络配置切换

原生 macOS 应用,用于管理网络预设并一键切换系统 IP / DNS 配置。
SwiftUI 构建,通过 networksetup 与特权 XPC helper 真正修改系统网络设置,提供 GUI 与命令行(CLI)两种交付形态。

--- > 🖼️ 仓库根目录的 `index.html` 是项目的高保真前端原型 / 设计落地页,SwiftUI 实现以其为视觉与交互基准。 ## ✨ 功能特性 - 🗂️ **预设管理**:保存多套网络配置(网卡、服务名、手动/DHCP、IP、掩码、网关、DNS),增删改查。 - ⚡ **一键切换**:点击卡片或菜单栏项即可切换;可选切换前确认。 - 🍎 **菜单栏常驻**:`NSStatusItem` 动态预设菜单,配合主窗口使用。 - 🔄 **启动状态校正**:以记忆的激活预设为锚,校验当前网卡配置;被外部更改则提示,恰好匹配则自动采纳。同一时刻最多一个激活态。 - ⌨️ **CLI 工具**:`status` / `active` 子命令,支持 `--json`,可嵌入 shell 工作流。 - 🔐 **特权 helper**:XPC LaunchDaemon 执行需要 root 的写操作;**免签名脚本安装**,仅需免费 Apple ID 即可真机部署。 - 🔌 **系统集成**:登录时启动(`SMAppService`)、切换后通知(`UNUserNotificationCenter`)。 - 🛡️ **命令注入防护**:仅调用绝对路径 `/usr/sbin/networksetup`;IP/掩码/网关/DNS 严格 IPv4 校验;服务名仅来自系统枚举并统一加引号。 ## 📋 系统要求 - 🍎 macOS 26.5+,Apple Silicon(arm64) - 🛠️ Xcode 16+,Swift 5.0 - ✅ 构建/运行无需 Developer ID(helper 采用免签名安装) ## 🚀 快速构建 ```bash # Debug 构建(App + CLI + helper,helper 与 CLI 嵌入 App bundle) xcodebuild -project src/ipswitch/ipswitch.xcodeproj \ -scheme ipswitch -configuration Debug \ -derivedDataPath src/ipswitch/build build # Release 构建(分发用) xcodebuild -project src/ipswitch/ipswitch.xcodeproj \ -scheme ipswitch -configuration Release \ -derivedDataPath src/ipswitch/build build # 只构建 CLI(产物:src/ipswitch/build/Build/Products/Debug/ipswitch-cli) xcodebuild -project src/ipswitch/ipswitch.xcodeproj \ -target ipswitch-cli -configuration Debug \ -derivedDataPath src/ipswitch/build build # 跑单元测试 xcodebuild -project src/ipswitch/ipswitch.xcodeproj \ -scheme ipswitch -configuration Debug \ -derivedDataPath src/ipswitch/build test ``` 📦 构建产物: | 产物 | 位置 | |------|------| | `ipswitch.app` | `src/ipswitch/build/Build/Products/{Debug,Release}/ipswitch.app` | | App 主二进制 | `ipswitch.app/Contents/MacOS/ipswitch` | | CLI 二进制(嵌入 App) | `ipswitch.app/Contents/MacOS/ipswitch-cli` | | 特权 helper(嵌入 App) | `ipswitch.app/Contents/Library/LaunchServices/ipswitch-helper` | ## 🎮 使用方式 ### 🖥️ GUI 启动 `ipswitch.app`:主窗口管理预设,菜单栏图标快速切换。首次切换前,App 通过内置安装器部署特权 helper(`launchctl bootstrap`,弹管理员授权)。 状态持久化于 `~/Library/Application Support/IP Switch/state.json`(`{schemaVersion, presets[], activeId, settings}`,原子写)。 ### ⌨️ CLI CLI 嵌入 App bundle,也可单独构建: ```bash # 列出所有预设与激活态 ipswitch-cli status ipswitch-cli status --json # 查看当前激活预设(支持模糊匹配) ipswitch-cli active ipswitch-cli --help ipswitch-cli --version ``` 退出码:`0` ✅ 成功,`1` ⚠️ 一般失败(参数错误 / 未匹配 / 命令失败 / 授权取消),`2` 🔥 内部错误(state 解析失败等)。 ### 🔧 特权 helper 部署位置 - 二进制:`/Library/PrivilegedHelperTools/com.yeti.ipswitch.helper` - LaunchDaemon plist:`/Library/LaunchDaemons/com.yeti.ipswitch.helper.plist` 卸载由 App 内置安装器执行(`launchctl bootout` + 清理文件)。 ## 🧩 架构概览 工程含 4 个 target: | Target | Bundle ID | 说明 | |--------|-----------|------| | `ipswitch` | `com.yeti.ipswitch` | GUI App(SwiftUI) | | `ipswitch-cli` | `com.yeti.ipswitch.cli` | 命令行工具,共享 6 个核心源文件 | | `ipswitch-helper` | `com.yeti.ipswitch.helper` | 特权 XPC LaunchDaemon | | `ipswitchTests` | `com.yeti.ipswitchTests` | 单元测试 | 模块依赖: ``` ipswitchApp (@main, SwiftUI) └─ AppDelegate ── MenuBarController (NSStatusItem) └─ ContentView ── PresetCard / PresetEditorSheet / SettingsSheet / ToastView └─ AppViewModel (@MainActor ObservableObject,唯一协调者) ├─ PresetStore JSON 持久化 ├─ NetworkService 网卡枚举/读取/应用 + 启动状态校正 │ └─ CommandRunner (protocol) │ ├─ RealCommandRunner (NSAppleScript 提权 / Process 只读) │ └─ FakeCommandRunner (测试桩) ├─ PresetApplyExecutor 切换执行(helper 优先,回退直接 networksetup) │ └─ HelperClient ──XPC── ipswitch-helper └─ SystemIntegration SMAppService 登录项 / UNUserNotificationCenter ``` 🔀 **切换流程**:UI/菜单 → `AppViewModel.performSwitch` → `PresetApplyExecutor` → `HelperClient`(XPC)→ `ipswitch-helper` 拼装并执行 `networksetup` 命令组 → 成功则更新激活态、持久化、Toast、(可选)通知。 🔒 **helper 安装策略**:`HelperInstaller` 通过 `HelperInstallerStrategy` 协议隔离,默认 `ScriptInstallerStrategy`(免签名脚本安装,`launchctl bootstrap`/`bootout`);`SMJobBlessStrategy` 作为备选(需 Developer ID)。 ## 📂 项目结构 ``` ipswitch/ ├── index.html # 高保真前端原型 / 设计落地页 ├── 生成脚本.md # 常用构建命令速查 ├── src/ipswitch/ │ ├── ipswitch.xcodeproj/ # Xcode 工程 │ ├── ipswitch/ # App 源码 │ │ ├── ipswitchApp.swift # @main 入口 │ │ ├── AppDelegate.swift # NSApplicationDelegate │ │ ├── MenuBarController.swift # 菜单栏 NSStatusItem │ │ ├── ContentView.swift # 主窗口 │ │ ├── PresetCard.swift # 预设卡片 │ │ ├── AddPresetCard.swift # 新增预设入口 │ │ ├── PresetEditorSheet.swift # 预设编辑表单 │ │ ├── SettingsSheet.swift # 设置面板 │ │ ├── ToastView.swift # Toast 提示 │ │ ├── AppViewModel.swift # 状态协调者 │ │ ├── Models.swift # 数据模型(Preset/Settings/...) │ │ ├── PresetStore.swift # JSON 持久化 │ │ ├── NetworkService.swift # 网卡枚举/读取/应用 │ │ ├── CommandRunner.swift # 命令执行(提权/只读) │ │ ├── PresetApplyExecutor.swift # 切换执行器 │ │ ├── HelperClient.swift # XPC 客户端 │ │ ├── HelperProtocol.swift # XPC 协议 │ │ ├── HelperPayloads.swift # 请求/响应载荷 │ │ ├── HelperInstaller.swift # helper 安装器 │ │ ├── SystemIntegration.swift # 登录项/通知 │ │ ├── IPv4.swift / PresetValidation.swift # 校验 │ │ ├── DesignTokens.swift # 设计令牌 │ │ ├── HoverCursor.swift # 光标扩展 │ │ └── cli/ # CLI 专属源(仅 CLI target 编译) │ │ ├── main.swift │ │ ├── CLIDispatcher.swift │ │ ├── StatusCommand.swift │ │ ├── ActiveCommand.swift │ │ ├── FuzzyMatch.swift │ │ └── CLIInstaller.swift │ ├── ipswitch-helper/ # 特权 XPC helper │ │ ├── main.swift │ │ ├── HelperApplyPresetCommandBuilder.swift │ │ ├── launchd.plist │ │ └── Info.plist │ └── ipswitchTests/ # 单元测试 ├── tools/ # 验证脚本(Python) │ ├── verify_privileged_helper_task1.py … task10.py │ └── verify_unsigned_helper_install.py └── docs/superpowers/ # 设计文档 / 实现计划 / 验证报告 ├── specs/ ├── plans/ └── reports/ ``` ## 🧪 测试与验证 ### 单元测试 `src/ipswitch/ipswitchTests/` 注入 `FakeCommandRunner`,不触网、不提权,覆盖:IPv4 校验、表单校验、`PresetStore` JSON round-trip + 原子写、命令拼装(手动/DHCP/DNS 有值/DNS 清空)、helper client/installer、helper payloads、`PresetApplyExecutor`、CLI dispatch、active/active 模糊匹配、状态命令、网络服务、设置行。 测试中**不得**真实调用 `SMJobBless` / `SMJobRemove` / `AuthorizationCreate`。 ### 验证脚本 `tools/` 下 Python 脚本对每个变更任务做静态接线检查 + 实际 `xcodebuild` 构建/测试验证: - `verify_privileged_helper_task1.py` … `task10.py` — helper target 接线、XPC 协议、payload 校验、GUI 集成、构建矩阵、测试覆盖矩阵。 - `verify_unsigned_helper_install.py` — 免签名安装路径、launchctl 引导、健康检查。 运行示例: ```bash python3 tools/verify_privileged_helper_task10.py ``` ## 📚 文档与变更管理 - 📐 `docs/superpowers/specs/` — 各变更的技术设计文档(应用、CLI、特权 helper、免签名安装等)。 - 📝 `docs/superpowers/plans/` — 实现计划。 - 📊 `docs/superpowers/reports/` — 验证报告。 - 🌌 `openspec/` — OpenSpec delta spec 与变更目录(Comet 流程管理)。 ## 📌 状态 版本 1.0。开发中,本地构建与签名(ad-hoc / Personal Team),未公证。