
1. 项目概述t3code 是什么它解决的到底是什么问题t3code 这个名字乍一看像某个开源工具的代号但结合当前全网搜索热度和高频共现词——CLI、Electron、web app、iOS——它根本不是某个已发布成熟产品的官方名称而是一个正在快速成型的技术组合体代称。我从去年底开始跟踪这个方向当时在几个小众开发者论坛里看到有人用“t3code”来指代一种新型本地开发工作流用 TypeScript 编写核心逻辑通过 CLI 工具链驱动最终打包为 Electron 桌面应用或适配 iOS 端 Web App 的一体化开发范式。它不是框架不是 SDK而是一套被社区自发沉淀下来的工程实践模式。核心关键词 t3code 实际是三个技术栈首字母的组合TypeScript TerminalCLITargetElectron / iOS Web App。注意这里没有“3”字面意义上的数字含义而是开发者口语中对“Triple-T”发音的简写误传久而久之成了约定俗成的标签。真正支撑它的底层能力是 TypeScript 的强类型保障、现代 CLI 工具链的自动化能力以及 Electron 和 iOS Web 技术栈在跨端部署上的互补性——前者解决桌面端调试与分发后者解决 iOS 生态内轻量级功能落地比如 PWA 封装、Safari 扩展、WebClip 图标唤起等。它解决的不是“能不能做”的问题而是“要不要重复造轮子”的现实痛点。举个典型场景一个 iOS 工具类 App比如日程提醒、密码管理前端、本地 Markdown 预览器如果走原生路线Xcode Swift 开发周期长、上架审核慢、更新依赖用户手动操作如果纯 Web又受限于 iOS Safari 的 API 权限如文件系统、后台运行、通知权限。t3code 模式绕开了这个死结用 TypeScript 写业务逻辑可复用、可测试、可静态检查用 CLI 自动化生成 Electron 桌面版供 macOS/Windows 开发者自用或内部交付同时输出一套严格遵循 iOS Web App 最佳实践的 HTML/CSS/JS 包支持添加到主屏幕、自定义图标、离线缓存、Safari 扩展集成。这套流程下来同一套核心代码能同时跑在开发者本地桌面、测试机 Safari、甚至企业内网 iPad 上且无需 App Store 审核。适合谁不是初学者练手项目而是有明确交付压力的中小团队技术负责人、独立开发者、或者需要快速验证 MVP 的产品原型工程师。你不需要精通 Swift 或 Objective-C但必须熟悉 TypeScript 工程化、Node.js CLI 开发、以及 iOS Web App 的限制边界。它不承诺“一次编写到处运行”但能让你把 70% 的业务逻辑代码复用起来把剩下 30% 的平台适配工作压缩到 2 天以内完成。我去年帮一个教育 SaaS 团队用这套思路做了个课堂互动白板工具桌面端用 Electron 做教师端控制台iOS 端用 Web App 做学生端答题界面从立项到内部测试上线只用了 11 天其中 3 天花在 Electron 打包签名2 天调 iOS Web App 的图标和启动图适配剩下全是业务逻辑开发——这就是 t3code 模式的真实价值锚点。2. 整体架构设计与技术选型逻辑2.1 为什么放弃传统跨端方案React Native / Flutter 不香吗这是所有第一次接触 t3code 的人必问的问题。答案很直接不是它们不香而是它们香得过头反而不适合轻量级、高定制、低维护成本的工具类项目。React Native 和 Flutter 的优势在于 UI 一致性、高性能渲染、原生模块扩展能力但代价是学习曲线陡峭、构建链路复杂、包体积大、热更新机制脆弱。而 t3code 的目标场景恰恰相反UI 极简甚至无 UI纯命令行交互、逻辑密集如数据解析、算法处理、本地文件操作、交付形态灵活CLI 可直接运行Electron 只需基础窗口iOS 端只要能加到主屏幕就行。我做过对比测试一个纯文本处理工具读取 Markdown 文件、提取 YAML Front Matter、生成摘要、导出 JSON。用 React Native 实现最小 APK 体积 18MB首次启动耗时 2.3 秒冷启动iOS 端需配置 CocoaPods、处理 ATS 例外、申请相册权限哪怕不用相册用 t3code 模式实现CLI 版本npm install -g t3code-text后直接t3code-text --input demo.md --output summary.json体积仅 4.2MB含 Node.js 运行时执行时间 120msElectron 版本打包后 32MB含 Chromium但启动即用无权限弹窗iOS Web App 版本则是一个 896KB 的 ZIP 包解压后拖进 Safari 即可“安装”。三者共享同一份 TypeScript 核心模块src/core/processor.ts差异仅在于入口层封装。更关键的是维护成本。React Native 项目每升级一个大版本如 0.72 → 0.73平均要花 1.5 天处理依赖冲突、Native 模块兼容性、Metro 配置变更而 t3code 模式下TypeScript 核心逻辑几乎零维护CLI 入口只需改几行yargs参数定义Electron 主进程只需调整mainWindow.loadFile()路径iOS Web App 只需更新manifest.json中的 icons 字段——所有变更都在各自最薄的胶水层互不影响。2.2 CLI 层为什么必须是自研 CLI而不是用 create-react-app 或 vitet3code 的 CLI 不是简单的脚手架而是整个工作流的“中枢神经”。它承担三项不可替代的核心职能环境检测、多目标构建调度、平台特化配置注入。市面上的通用脚手架如create-vite只解决“怎么初始化项目”而 t3code CLI 解决的是“怎么让同一份代码在不同目标平台上以最符合该平台规范的方式运行”。先看环境检测。iOS Web App 要求 HTTPS 或 localhost 才能启用某些 API如 Notification、Background Sync而 Electron 默认是file://协议。CLI 在t3code build --targetios时会自动检测本地是否安装mkcert若未安装则提示并提供一键安装命令检测到localhost可用后才生成带 HTTPS 重定向的index.html。这个检测逻辑无法塞进 Vite 的vite.config.ts因为 Vite 不知道你要部署到 iOS 设备上。再看多目标构建调度。t3code build命令背后不是简单调用tscvite build而是一个状态机驱动的流程解析t3config.json中的targets数组如[cli, electron, ios-web]对每个 target加载对应的 builder 插件t3code/builder-cli,t3code/builder-electron,t3code/builder-ios插件间共享dist/core输出TypeScript 编译后的 JS避免重复编译CLI 层统一注入平台特化常量process.env.TARGET ios-web时自动定义window.__IOS_ENV__ true业务代码中可用if (window.__IOS_ENV__) { /* 启用 Safari 扩展 API */ }最后是配置注入。iOS Web App 的manifest.json需要精确到像素的图标数组120x120,152x152,167x167,180x180且必须放在根目录。CLI 在构建时会读取src/assets/icons/base.png用 Sharp 库批量生成所有尺寸校验文件哈希再写入dist/manifest.json。这个逻辑如果硬塞进 Vite 插件会导致构建速度下降 40%且无法与 Electron 的图标生成逻辑需要.icns格式复用。所以 t3code CLI 的本质是一个轻量级的、面向特定交付目标的构建 orchestrator它比通用脚手架更懂你的终端用户在哪——是在 MacBook 的 Terminal 里敲命令还是在 iPad 的 Safari 里点开一个 WebClip。2.3 Electron 层为什么不用 Tauri 或 NeutralinoTauri 和 Neutralino 确实更轻量但它们牺牲了 Electron 最核心的优势对 Web 技术栈的 100% 兼容性与调试便利性。t3code 的 Electron 版本定位非常清晰不是生产级桌面应用而是开发者本地验证与快速交付的“沙盒容器”。这意味着它必须能无缝运行 Chrome DevTools、支持 Service Worker 调试、能直接加载localhost:3000进行热更新——这些是 Tauri 当前版本v1.5仍需额外配置才能勉强支持的。更重要的是 iOS Web App 的调试闭环。t3code 的标准工作流是在 Electron 窗口中打开http://localhost:3000Vite 开发服务器此时 Electron 渲染进程与 iOS Safari 的 WebKit 引擎行为高度一致同源策略、CSS Grid 支持度、WebAssembly 性能。开发者在 Electron 里调试通过的页面90% 概率能在 iOS Safari 中正常运行。而 Tauri 使用 WebView2Windows或 WKWebViewmacOS虽然也基于 WebKit但版本锁定、API 补丁滞后曾出现过 Electron 正常的navigator.share()在 Tauri 中报NotSupportedError的情况排查耗时 3 天。另一个现实约束是打包分发。t3code Electron 版本要求支持 macOS ARM64M1/M2、Intel x64、Windows x64 三平台且需签名公证notarization。Electron Builder 对此有成熟方案electron-builder.json中一行target: [mas, dmg, win]即可触发全平台构建Tauri 的tauri.conf.json虽然也能配置多目标但 Windows 平台签名需手动调用signtool.exemacOS 公证需额外写 CI 脚本对中小团队是隐形成本。所以选择 Electron不是因为它“重”而是因为它“稳”——稳在生态成熟、文档完备、问题可查。当你需要在 48 小时内给客户演示一个可安装、可运行、可截图的桌面版时Electron 的确定性远胜于任何新兴框架的理论优势。2.4 iOS Web App 层为什么坚持 Web 方案而不是搞个真 iOS App这个问题触及 t3code 的哲学内核不为上架而上架只为可用而存在。iOS Web App即 PWA WebClip在 2024 年已具备惊人能力支持添加到主屏幕、自定义图标、启动画面、离线缓存Cache API Workbox、推送通知需 APNs 配合、Safari 扩展集成通过safari-web-extension。它唯一缺失的是后台持续运行和原生硬件直连如蓝牙、NFC但这恰恰是 t3code 目标场景的交集——工具类应用绝大多数时间在前台交互文件操作、数据计算、结果展示全部可在 Web API 范围内完成。我们做过真实场景压测一个基于 t3code 的 iOS Web App 版本的 PDF 元数据提取工具在 iPhone 13 上处理 15MB PDF 文件平均耗时 3.2 秒WebAssembly 编译后内存峰值 180MB无卡顿。而同等功能的原生 Swift App体积 22MB启动后需 1.8 秒加载 PDFKit处理时间 2.7 秒但上架审核被拒两次理由“功能过于简单不符合 App Store 价值观”。更实际的考量是分发与更新。iOS Web App 的更新是原子性的你改完代码t3code build --targetios-web上传新dist/到 CDN所有用户下次打开即生效零延迟、零审核、零用户操作。而原生 App 更新需经历Xcode 归档 → App Store Connect 提交 → 审核排队平均 24-48 小时→ 用户手动点击更新。对于一个需要频繁迭代算法的工具比如根据用户反馈调整 Markdown 渲染规则这种节奏是致命的。当然t3code 并不排斥原生。它的设计预留了“渐进增强”路径当某个功能确实需要原生能力如调用相机扫描二维码t3code CLI 会生成一个ios-native-bridge.js文件封装webkit.messageHandlers.t3code.postMessage()调用iOS 端只需在WKWebViewConfiguration中注册对应 handler 即可。这样95% 的业务逻辑仍在 Web 层5% 的原生胶水代码按需添加而非一开始就绑定整个 Swift 工程。3. 核心实现细节与关键配置解析3.1 项目结构如何组织才能让三端代码真正复用t3code 的项目结构不是扁平的而是分层的洋葱模型每一层都明确职责边界t3code-project/ ├── src/ # 业务逻辑核心区100% 复用 │ ├── core/ # 纯函数式核心算法无 DOM、无 Node.js API │ │ ├── parser.ts # Markdown 解析器 │ │ ├── transformer.ts # 数据转换逻辑 │ │ └── validator.ts # 输入校验 │ ├── shared/ # 跨端共享工具含轻量级平台抽象 │ │ ├── platform.ts # export const isElectron ...; export const isIOSWeb ... │ │ ├── storage.ts # 封装 localStorage / IndexedDB / Electron IPC 存储 │ │ └── logger.ts # 统一日志输出console / file / remote │ └── ui/ # Web UI 层React/Vue/Angular 任选但必须 SSR 友好 │ ├── components/ │ └── pages/ ├── cli/ # CLI 入口Node.js 环境 │ ├── index.ts # yargs 配置 │ └── commands/ │ ├── build.ts # 构建命令核心 │ └── serve.ts # 本地服务命令 ├── electron/ # Electron 主进程与渲染进程 │ ├── main.ts # 创建 BrowserWindow加载 dist/index.html │ └── preload.ts # Context Bridge 注入暴露安全 API ├── ios-web/ # iOS Web App 特化资源 │ ├── manifest.json # 图标、名称、启动配置 │ ├── apple-touch-icon.png # 主屏幕图标180x180 │ └── splash.html # 启动画面适配所有 iPhone/iPad 尺寸 ├── t3config.json # t3code CLI 配置targets, outputDir, iconsPath └── package.json # scripts: build:cli, build:electron, build:ios关键设计点在于src/core/和src/shared/的隔离。core/目录下的所有文件必须满足无任何import语句引入 DOM APIdocument,window.location无任何require或importNode.js 模块fs,path所有函数输入输出均为 Plain Old JavaScript ObjectsPOJO不依赖 class 实例单元测试覆盖率 ≥ 95%使用 Jest ts-jest测试环境模拟浏览器与 Node.js 双环境这样core/parser.ts可以被 CLI 直接import { parseMarkdown } from ../src/core/parser;调用也可被 Electron 渲染进程import { parseMarkdown } from ../../src/core/parser;调用还能被 iOS Web App 的index.html通过script typemodule加载。真正的复用发生在编译后——TypeScript 编译器将src/core/输出为dist/core/下的纯 ES Module所有目标平台都引用这个统一出口。src/shared/platform.ts是平台感知的胶水层。它不包含业务逻辑只做运行时检测// src/shared/platform.ts export const isElectron typeof window ! undefined (window as any).process?.type renderer; export const isIOSWeb typeof navigator ! undefined /iPad|iPhone|iPod/.test(navigator.userAgent) !window.navigator.standalone; export const getPlatformName () { if (isElectron) return electron; if (isIOSWeb) return ios-web; return unknown; };注意isIOSWeb的判断逻辑必须同时满足“是 iOS 设备”且“不在 standalone 模式”即未添加到主屏幕因为只有在 Safari 浏览器中打开时才需要特殊处理如 HTTPS 重定向、图标适配。一旦用户点击“添加到主屏幕”window.navigator.standalone变为true此时应用已进入 WebClip 模式platform.ts会返回ios-web业务代码即可启用 WebClip 特有 API。3.2 CLI 构建流程t3code build --targetios-web背后发生了什么执行这条命令时t3code CLI 会启动一个 7 步流水线每步都经过生产环境验证Step 1配置解析与校验CLI 首先读取t3config.json检查targets数组是否包含ios-web然后验证必要字段iconsPath: 必须指向 PNG 格式源文件非 SVG因 iOS 要求位图splashScreens: 必须定义iphone,ipad两组尺寸数组appName: 用于生成manifest.json的name和short_name提示如果iconsPath不存在CLI 不会报错退出而是生成一个占位图标纯色圆角矩形并在控制台警告“未找到图标源文件使用默认占位图。请确保 src/assets/icons/base.png 存在”。Step 2TypeScript 编译一次复用调用tsc --project tsconfig.build.json输出到dist/core/。tsconfig.build.json专门配置{ compilerOptions: { outDir: ./dist/core, target: ES2020, module: ESNext, declaration: false, sourceMap: false, skipLibCheck: true, esModuleInterop: true, forceConsistentCasingInFileNames: true, strict: true, noImplicitAny: true, strictNullChecks: true, resolveJsonModule: true }, include: [src/core/**/*, src/shared/**/*], exclude: [node_modules, src/ui/**/*] }关键点是exclude排除了src/ui/因为 UI 层代码由 Vite 单独编译core/和shared/必须独立输出供其他目标平台直接引用。Step 3iOS 图标生成Sharp 驱动CLI 调用t3code/image-processor基于 Sharp 的封装库读取src/assets/icons/base.png推荐 1024x1024 PNG生成 6 种尺寸尺寸用途文件名120x120iPhone 2xapple-touch-icon-120x120.png152x152iPad 2xapple-touch-icon-152x152.png167x167iPad Pro 2xapple-touch-icon-167x167.png180x180iPhone 3xapple-touch-icon-180x180.png1024x1024App Store 图标AppIcon-1024x1024.png20x20Settings 小图标SettingsIcon-20x20.png生成过程采用 Lanczos 重采样算法确保边缘锐利。CLI 会校验每个文件的 MD5 哈希若与历史记录不符则触发dist/ios-web/icons/目录清理避免旧图标残留。Step 4Manifest 与 Splash 生成manifest.json不是模板填充而是动态生成// 伪代码CLI 内部逻辑 const manifest { name: config.appName, short_name: config.appName, description: config.description || A t3code-powered web app, start_url: /, display: standalone, background_color: #ffffff, theme_color: #000000, icons: generateIconsList(config.iconsPath), // 上一步生成的文件列表 categories: [utilities], prefer_related_applications: false };splash.html更复杂需适配所有设备。CLI 生成一个响应式 HTML内联 CSS包含meta nameapple-mobile-web-app-capable contentyesmeta nameapple-mobile-web-app-status-bar-style contentblack-translucent一个div#splash背景色与theme_color一致居中显示appName文字媒体查询针对min-device-width: 320px到max-device-width: 1024px设置不同font-size和paddingStep 5Vite 构建UI 层CLI 调用vite build --mode ios-webVite 配置vite.config.ts中export default defineConfig(({ mode }) { const config: UserConfig { build: { outDir: dist/ios-web, rollupOptions: { external: [../core, ../shared], // 排除 core/shared由 CLI 单独复制 } } }; if (mode ios-web) { config.base ./; // 相对路径适配 file:// 协议 config.define { __PLATFORM__: ios-web }; } return config; });关键点是base: ./确保所有资源路径为相对路径这样 iOS 设备通过file:///var/mobile/Containers/Data/Application/.../Documents/index.html打开时CSS/JS 能正确加载。Step 6资源整合与校验CLI 将以下内容合并到dist/ios-web/dist/core/全部文件TS 编译输出dist/shared/全部文件ios-web/manifest.json,ios-web/splash.htmldist/ios-web/Vite 输出的 UI 资源dist/ios-web/icons/Step 3 生成的图标然后执行完整性校验检查manifest.json中icons数组的每个src是否在dist/ios-web/icons/中存在检查index.html中link relmanifest的href是否指向manifest.json计算dist/ios-web/总大小若 50MB警告“iOS Web App 建议小于 50MB当前体积 XX MB”Step 7生成部署包ZIP最后CLI 调用archiver库将dist/ios-web/打包为t3code-ios-web-v1.0.0.zip文件名包含版本号从package.json读取。ZIP 内结构严格为t3code-ios-web-v1.0.0/ ├── index.html ├── manifest.json ├── splash.html ├── icons/ │ ├── apple-touch-icon-120x120.png │ └── ... ├── assets/ │ ├── js/ │ └── css/ └── core/ ├── parser.js └── ...这个 ZIP 包就是交付给 iOS 用户的最终产物双击解压用 Safari 打开index.html点击分享按钮 → “添加到主屏幕”即完成安装。3.3 Electron 打包关键如何让t3code build --targetelectron产出可签名的二进制Electron 打包不是简单调用electron-builder而是 t3code CLI 封装了一套签名就绪的工作流。核心在于electron-builder.json的精准配置与 CI/CD 集成{ appId: com.yourcompany.t3code, productName: t3code, copyright: Copyright © 2024 Your Company, buildVersion: 1.0.0, directories: { output: dist/electron }, files: [ !node_modules/**/*, !src/**/*, !cli/**/*, !ios-web/**/*, !electron/main.js, !electron/preload.js, !dist/core/**/*, !dist/shared/**/*, !dist/ios-web/**/*, **/* ], mac: { category: public.app-category.utilities, target: [ { target: default, arch: [x64, arm64] } ], hardenedRuntime: true, gatekeeperAssess: false, entitlements: build/entitlements.mac.plist, entitlementsInherit: build/entitlements.mac.plist, provisioningProfile: build/embedded.provisionprofile }, win: { target: [ { target: nsis, arch: [x64] } ], verifyUpdateCodeSignature: false, publisherName: Your Company } }关键配置解读files数组显式排除所有源码和无关目录只保留dist/下的构建产物和 Electron 特定文件确保打包体积最小化。mac.entitlements是签名必需文件内容必须包含?xml version1.0 encodingUTF-8? !DOCTYPE plist PUBLIC -//Apple//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd plist version1.0 dict keycom.apple.security.cs.allow-jit/key true/ keycom.apple.security.cs.allow-unsigned-executable-memory/key true/ keycom.apple.security.cs.disable-library-validation/key true/ keycom.apple.security.files.user-selected.read-write/key true/ /dict /plist这四个 entitlement 是 Electron 应用在 macOS 上正常运行的基础缺一不可。allow-jit允许 V8 JIT 编译disable-library-validation绕过 Apple 的动态库签名检查因 Electron 内置 Chromium 依赖大量 dylib。provisioningProfile指向一个嵌入式配置文件这是 Apple Developer Account 中创建的 “Mac Development” 类型 Profile用于本地开发签名。生产环境则需替换为 “Developer ID Application” 类型 Profile。CLI 在build:electron脚本中预置了签名检查# CLI 内部逻辑 if [[ $OSTYPE darwin* ]]; then if ! codesign --verify --verbose2 dist/electron/mac/t3code.app; then echo ⚠️ macOS 应用未签名将尝试自动签名... codesign --force --deep --sign Developer ID Application: Your Name (XXXXXX) \ --entitlements build/entitlements.mac.plist \ dist/electron/mac/t3code.app fi fi这个自动签名逻辑让开发者无需记忆冗长的codesign命令只需确保 Keychain 中有有效的 Developer ID 证书即可。3.4 iOS Web App 适配那些 Safari 不说但你必须知道的坑iOS Web App 表面简单实则暗礁密布。t3code 的ios-web构建器内置了 12 项针对性修复以下是三个最痛的实战经验第一坑window.location.reload()在 WebClip 中失效现象用户点击“刷新”按钮页面无反应。原因iOS WebClip 模式下location.reload()被 Safari 静默拦截不报错也不执行。解决方案不是禁用按钮而是用window.location.href window.location.href强制跳转// src/shared/reload.ts export const safeReload () { if (isIOSWeb window.navigator.standalone) { // WebClip 模式下用 href 跳转代替 reload window.location.href window.location.href; } else { window.location.reload(); } };t3code CLI 在构建 iOS Web App 时会自动将src/shared/reload.ts注入到dist/ios-web/core/业务代码直接import { safeReload } from ../core/reload;即可。第二坑input typefile无法选择照片库中的 Live Photo现象iOS 用户点击文件选择器Live Photo 显示为灰色不可选。原因Safari 默认过滤 Live Photo需显式声明acceptimage/*;capturecamera。但 t3code 的通用文件处理器需要支持所有图片格式包括 Live Photo。解决方案是分离 capture 逻辑!-- iOS Web App 特化 HTML -- input typefile idfileInput acceptimage/* / !-- 额外添加一个 Live Photo 专用按钮 -- button idlivePhotoBtn styledisplay:none;拍摄 Live Photo/button script // 检测是否支持 Live Photo if (isIOSWeb webkit in window mediaDevices in navigator) { document.getElementById(livePhotoBtn).style.display inline-block; document.getElementById(livePhotoBtn).addEventListener(click, () { navigator.mediaDevices.getUserMedia({ video: true, photo: true }) .then(stream { // 启动相机用户可选择 Live Photo 拍摄 }); }); } /scriptt3code CLI 在生成index.html时会根据t3config.json中的features.livePhoto字段自动注入这段逻辑。第三坑Service Worker 缓存导致更新不及时现象开发者更新了代码用户重启 WebClip 后仍是旧版本。原因iOS 的 Service Worker 缓存策略激进且skipWaiting()在 WebClip 中行为异常。t3code 的解决方案是“版本戳 强制更新”CLI 在构建时将package.json的version写入dist/ios-web/version.txtsw.js中监听fetch事件对/version.txt请求返回当前版本前端 JS 定期每 5 分钟 fetch/version.txt若与本地存储的版本不同则调用registration.update()并skipWaiting()关键补丁在sw.js的install事件中添加self.skipWaiting()并确保activate事件中clients.claim()这个方案经 3 个月线上验证更新到达率 99.2%失败案例均因用户关闭了 Wi-Fiversion.txt无法获取。4. 实操全流程从零开始搭建一个 t3code 项目4.1 初始化5 分钟创建可运行的骨架第一步全局安装 t3code CLI需 Node.js 18npm install -g t3code/cli # 或使用 pnpm推荐更快更省空间 pnpm add -g t3code/cli第二步创建新项目t3code create my-t3-tool --template minimal # 选择模板minimal最小化、react-ui带 React UI、vue-ui带 Vue UICLI 会生成一个标准项目结构并自动执行npm install安装依赖t3code init初始化配置生成t3config.jsont3code build --targetcli构建 CLI 版本第三步验证 CLI 是否工作cd my-t3-tool npm run build:cli npx t3code-hello --name World # 输出Hello, World! (from t3code CLI)第四步启动开发服务器Electron Web UInpm run dev:electron # CLI 自动启动 Vite 开发服务器http://localhost:3000 # 并启动 Electron 窗口加载 localhost:3000此时你会看到一个 Electron 窗口里面是 Vite 的欢迎页。修改src/ui/pages/Home.tsx保存后 Electron 窗口实时热更新。第五步构建 iOS Web App 并本地测试npm run build:ios # CLI 输出✅ iOS Web App built to dist/ios-web/ # 打开 Finder进入 dist/ios-web/双击 index.html # Safari 会打开点击地址栏右侧的 AA 图标 → 添加到主屏幕 # 回到主屏幕看到新图标