news 2026/8/30 15:10:14

Gitea Actions实战:在Apple硬件上跑通iOS自动化构建

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Gitea Actions实战:在Apple硬件上跑通iOS自动化构建

在移动端和客户端开发这个圈子里,一直存在一个非常现实的矛盾:只有 Apple 硬件才能编译和签名 iOS 应用,但 Apple 硬件并不便宜,更不好远程管理。

很多团队的做法是,买一台 Mac mini 放在机柜里,有人需要打包的时候远程登录上去手动点 Xcode。遇到版本更新、证书过期、需要批量出包的时候,整个流程就变得非常痛苦。于是大家自然会想到引入 CI,但一搜方案,又撞上另一堵墙:GitHub Actions 的 macOS runner 是按分钟计费的,而且代码要推到 GitHub 上;Jenkins 倒是能自托管,但配置越来越重,插件版本、权限体系和 Pipeline 脚本维护成本都不低。

如果你正在用 Gitea,或者正打算在内网搭建一套轻量代码托管和 CI 服务,那么 Gitea Actions 值得认真看一下。这套方案可以让你把自己手里的 Mac 变成 CI 执行节点,直接在 Apple 硬件上跑 iOS 构建、macOS 打包、Xcode 测试这类任务;语法风格接近 GitHub Actions,团队迁移成本低,而且代码仓库、CI 状态、Runner 管理都在 Gitea 一个平台里完成。

这篇文章会从运行原理讲起,然后完整演示如何把一台 Mac 接入 Gitea Actions,最终跑通一个 iOS 构建工作流。读完你可以照着落地,也能避开常见的那几个坑。

1. 为什么要在 Apple 硬件上跑 Gitea Actions

先回答一个更根本的问题:为什么偏偏要把 CI 跑在 Apple 硬件上?

原因是移动端构建有硬性依赖。iOS 应用必须使用 Xcode 编译,而 Xcode 只能运行在 macOS 上;提交到 App Store 的分发包还需要签名,签名过程涉及证书和私钥,这些敏感信息放在可控的内网环境里更安全。也就是说,无论你选什么 CI 系统,最终编译那一步大概率还是得落到一台 Mac 上。

对比一下几种常见方案的处境:

  • GitHub Actions 托管 macOS runner:方便,但按分钟计费,且默认策略需要你把代码放到 GitHub。对于企业内部项目、未公开代码或合规要求高的环境,这条路通常走不通。
  • 自建 Jenkins + macOS 节点:老牌方案,功能强大,但 Jenkins 的安装、插件管理、权限配置、节点标签、Pipeline 脚本都有一定使用门槛。团队如果只想“快速跑一个打包脚本”,Jenkins 显得偏重。
  • GitLab CI + macOS runner:也是一个成熟方案,注册 Runner 后用 tag 控制任务分发,很多团队在用。不过如果仓库本身已经迁到 Gitea,再单独维护一套 GitLab 就不太合理了。

Gitea Actions 的价值在于它把“代码托管、CI 触发、Runner 管理、日志查看”整合在了同一个轻量系统里。Gitea 本身非常轻量,一台 2 核 4G 的小机器就能长期稳定运行,Actions 功能开启后,开发者只需要在仓库里放一个.gitea/workflows/*.yml文件,推送代码就能自动触发构建。这套交互方式对用过 GitHub Actions 的开发者来说几乎是零成本。

这篇文章的核心判断是:如果你的团队已经有 Mac 设备、又在用 Gitea,那么 Gitea Actions 是当前把 Apple 硬件变成 CI 节点最平滑的方案之一。它的成本主要是前期一次性的 Runner 接入,收益是后续每次提交都能自动完成构建和检查。

2. Gitea Actions 的运行模型与核心概念

在动手操作之前,有必要把 Gitea Actions 的几个核心概念讲清楚,否则后面排查问题时容易一头雾水。

2.1 四个关键组件

Gitea Actions 的架构可以拆成四个部分:

  • Gitea 服务端:负责存储仓库、提供 Web 界面、接收 Git 事件,并把事件转换成 CI 任务放进队列。
  • act_runner:一个独立进程,部署在某台机器上,负责不断向 Gitea 服务端询问“有没有任务需要执行”。
  • 工作流文件:存放在仓库.gitea/workflows/目录下的 YAML 文件,描述“在什么事件触发下,执行哪些步骤”。
  • 执行环境:act_runner 拿到任务后,在指定环境中执行工作流步骤。这个环境可以是容器,也可以是 Runner 所在的宿主机。

用通俗的比喻来说:Gitea 是“调度中心”,act_runner 是“快递员”,工作流文件是“配送单”,执行环境就是快递员脚下的“交通工具”。

2.2 label 是什么,为什么它决定任务能否跑起来

act_runner 启动时会向 Gitea 服务端报告自己支持哪些 label。工作流里的runs-on字段会指定这次任务需要哪个 label,Gitea 会找到匹配的 Runner 并分配任务。

举个例子:

  • 某台 Linux 机器上的 Runner 声明支持ubuntu-latestlinux/amd64
  • 某台 Mac mini 上的 Runner 声明支持macos-arm64macos-latest
  • 工作流里写runs-on: macos-arm64,任务只会被分配给 Mac mini 上的 Runner。

很多初次使用 Gitea Actions 的用户遇到“任务一直排队,但 Runner 明明在线”的问题,十有八九就是 label 不匹配。这一点在 Apple 硬件场景尤其重要,因为 macOS Runner 默认的 label 往往需要手动指定成平台相关的名称。

2.3 与 GitHub Actions 的兼容性边界

Gitea Actions 的底层执行引擎是 act(nektos/act 的一个 fork/兼容实现),它的设计目标是尽量兼容 GitHub Actions 的语法。也就是说:

  • nameonjobssteps这些核心结构可以直接沿用;
  • actions/checkoutactions/upload-artifact这类常见 action 大部分可用;
  • 但部分 GitHub 云服务专属能力,比如一些深度依赖 GitHub API 的 action、需要访问 GitHub Cache Service 的缓存逻辑,在 Gitea 上行为可能不同。

所以更稳妥的工作流写法是:把重心放在run脚本上,减少对第三方 action 的依赖,尤其是那些和 GitHub 账号体系绑定的 action。这对在 macOS 上跑 Xcode 构建来说问题不大,因为核心步骤通常就是几条xcodebuild命令。

下表总结了常见平台和 Gitea Actions 的定位差异:

对比维度GitHub ActionsGitLab CIJenkinsGitea Actions
仓库托管GitHubGitLab无,独立 CIGitea
托管 macOS Runner有,按分钟计费有,配套收费无,需自建 Runner
内网部署不支持支持支持支持
工作流语法YAMLYAMLPipeline/脚本GitHub Actions 风格 YAML
资源占用无需自维护相对较重较重很轻

3. 在 Apple 硬件上运行 act_runner:模式与前置条件

这一节先解决两个问题:act_runner 在 macOS 上到底怎么执行任务,以及开始之前需要准备哪些东西。

3.1 Docker 模式还是宿主机模式

act_runner 默认支持容器化执行任务,也就是把每个 Job 放到一个临时容器里运行。这种方式隔离性好,适合 Linux 环境,比如你用一台服务器跑后端测试任务。

但到了 Apple 硬件场景,情况不同:iOS 构建必须用到 Xcode、模拟器、钥匙串、签名证书,这些在 macOS 的 Docker 容器里很难完整映射。更常见的做法是让 act_runner 直接以宿主机模式执行任务——也就是 Job 里的run命令直接在 macOS 系统上执行。这样xcodebuild能正常访问 Xcode 工具链,签名时也能访问钥匙串。

宿主机模式的代价是隔离性变差:只要被授予了运行权限的仓库,其工作流代码就能直接读写这台 Mac 的文件系统和部分系统配置。所以一个基本原则是:不要把不信任的仓库指向这台 Runner,更不能把公网可提交的仓库挂在宿主机模式的 Runner 上。

3.2 前置条件清单

部署之前,建议先确认以下条件:

  • 一台可用的 Mac,芯片类型确认清楚:Apple Silicon 还是 Intel,这直接影响后面的 label 命名;
  • macOS 版本尽量满足 Xcode 的要求;
  • 已安装 Xcode,并且在终端里执行xcode-select -p能正常输出路径;
  • 已安装 Git,macOS 自带的git一般够用;
  • 一个可访问的 Gitea 服务端实例,版本需要支持 Actions 功能;
  • 能创建一个 Gitea 访问令牌或通过后台注册 Runner。

补充一点:如果只想在 Linux 环境下体验 Gitea Actions,并不需要 Apple 硬件;但如果你要跑 iOS 构建,前面这些条件缺一不可。也有人在 Windows 上跑 Gitea,配合 Windows Runner 做 .NET 构建,那属于另一套配置,不在本文展开。

3.3 在 Gitea 服务端开启 Actions

在较新版本的 Gitea 中,Actions 功能通常需要在配置文件app.ini中显式开启。具体配置项会随版本变化,建议以你部署的 Gitea 版本官方文档为准。基本思路是:

[actions] ENABLED = true

修改配置后需要重启 Gitea 服务。如果你是从旧版本升级,还需要检查实例是否已经初始化相关数据表。这一部分如果配置不对,Web 界面里不会出现 Actions 相关入口。

3.4 用户 SSH 密钥管理

由于私有仓库的克隆通常走 SSH,Runner 在宿主机上 checkout 代码时需要用 SSH 密钥。建议在 Gitea 后台为专门的 CI 账号(例如ci-bot)配置 SSH 公钥,并把私钥放到 Mac Runner 的~/.ssh/目录下,或者在 checkout 阶段使用 HTTP 方式并在 URL 中嵌入令牌。

Gitea 的用户 SSH 密钥管理很简单:登录账号后进入“设置 -> SSH 密钥”,把公钥粘进去保存即可。不要用个人账号的高权限密钥直接放在 CI 机器上,更不要把私钥提交到仓库。

4. 部署 act_runner 到 Mac 的完整步骤

前置条件确认无误后,开始把 act_runner 装到 Mac 上。

4.1 下载或安装 act_runner

act_runner 是 Gitea 官方提供的 Runner 程序。可以到 Gitea 官方 Releases 页面下载对应 macOS 架构的二进制包,也可以使用 Homebrew 等包管理工具安装。考虑到网络环境差异,这里直接使用二进制方式演示:

# 假设已下载 act_runner 并放到 /usr/local/bin 下 chmod +x act_runner sudo mv act_runner /usr/local/bin/act_runner # 验证版本 act_runner --version

如果你的 Gitea 服务端是通过 Docker 部署的,act_runner 也可以作为容器启动。但如前面所说,在 macOS 上跑 iOS 构建建议用宿主机模式,因此这里直接以二进制方式运行。

4.2 在 Gitea 后台创建 Runner 注册令牌

登录 Gitea 实例,进入“管理后台 -> Runner”或“站点管理 -> Actions”,找到创建 Runner 的入口,生成一个新的注册令牌。这一步生成的 token 只用于初始注册,并不会长期保存在 Runner 配置里。

如果找不到管理入口,可以确认一下当前账号是否有管理员权限,以及 Gitea 版本是否已开启 Actions。

4.3 注册 Runner 并指定 label

在 Mac 终端执行注册命令:

act_runner register \ --instance http://gitea.example.com \ --token 这里填你的注册令牌 \ --name mac-mini-1 \ --labels macos-arm64 \ --no-interactive

注意几点:

  • --instance是 Gitea 服务端地址,内网环境请使用内网地址,避免流量绕行;
  • --labels这里非常关键,务必根据 Mac 芯片类型填写。Apple Silicon 写macos-arm64,Intel 写macos-amd64
  • --no-interactive表示非交互式注册,适合脚本化执行。

注册成功后,当前目录会生成一个config.yaml文件,这个文件保存了 Runner 的详细配置。

4.4 检查并调整 config.yaml

打开config.yaml,重点看 Runner 的 label 和执行模式。由于不同版本配置项有差异,这里只说明通用思路。需要确认 labels 和注册时一致,同时如果希望任务直接在宿主机执行,需要确保执行模式不是强制容器模式。

一个常见问题是:注册时把 label 写成了linux/amd64,导致工作流里写macos-arm64时找不到 Runner。如果发现 label 写错,可以直接修改config.yaml后重启 Runner,或者用--reset参数重新注册。

4.5 启动 Runner 并保持后台运行

前台启动方便调试:

act_runner daemon --config config.yaml

看到类似“runner started successfully”的日志后,说明 Runner 已连接到 Gitea。

要长期运行,可以把它注册为 launchd 服务,或者用nohup放到后台。考虑到 Mac 重启后 CI 服务最好能自动恢复,简单起见可以写一个全局 launchd plist,也可以先用 nohup:

nohup act_runner daemon --config config.yaml >> runner.log 2>&1 &

更推荐的做法是配置 launchd,让 Runner 在开机后自动拉起。如果你习惯用 Linux,也可以把 Runner 放到一台 Linux 机器上用 systemd 管理,但执行任务的 Mac 和运行 act_runner 的机器需要在同一个可访问网络内。

4.6 验证 Runner 在线状态

回到 Gitea 管理后台的 Runner 列表页面,应该能看到名为mac-mini-1的 Runner,状态为在线。如果显示离线,优先检查:

  • act_runner 进程是否还活着;
  • config.yaml里的 Gitea 地址是否可达;
  • 注册 token 是否过期。

到这里,Apple 硬件接入 Gitea Actions 的基础工作已经完成。下一步开始写工作流。

5. 编写第一个跑在 macOS 上的 Actions 工作流

在仓库根目录创建.gitea/workflows/ios-build.yml,写入一个最小但完整的 iOS 构建工作流。

5.1 最小可运行示例

name: iOS Build on: push: branches: - main jobs: build: runs-on: macos-arm64 steps: - name: Checkout uses: actions/checkout@v4 - name: Show Xcode version run: | xcodebuild -version xcode-select -p - name: Build without signing run: | xcodebuild build \ -project MyApp.xcodeproj \ -scheme MyApp \ -configuration Release \ -destination 'generic/platform=iOS' \ CODE_SIGNING_ALLOWED=NO

这段工作流的关键点:

  • runs-on: macos-arm64必须与 Runner 注册时的 label 完全一致;
  • actions/checkout@v4用于拉取代码,如果你的内网环境访问 GitHub 不稳定,建议使用 Gitea 兼容的 checkout 方式,或者手动执行git clone
  • CODE_SIGNING_ALLOWED=NO适用于先验证编译是否通过,不代表最终打包可以省略签名。

5.2 增加归档和导出 IPA 的完整流程

实际发布场景下,通常需要导出可分发的 IPA 文件。下面示例增加了 archive 和 exportArchive 两步:

name: iOS Archive and Export on: push: tags: - 'v*' workflow_dispatch: jobs: archive: runs-on: macos-arm64 steps: - name: Checkout uses: actions/checkout@v4 - name: Archive run: | mkdir -p build xcodebuild archive \ -project MyApp.xcodeproj \ -scheme MyApp \ -configuration Release \ -archivePath build/MyApp.xcarchive \ CODE_SIGNING_ALLOWED=NO - name: Export IPA run: | xcodebuild -exportArchive \ -archivePath build/MyApp.xcarchive \ -exportOptionsPlist ExportOptions.plist \ -exportPath build/ipa - name: Upload IPA uses: actions/upload-artifact@v4 with: name: MyApp-ipa path: build/ipa/*.ipa

如果项目还没有导出选项文件,需要先在 Xcode 中生成一份ExportOptions.plist,或者手动创建并指明导出方式(App Store / Ad Hoc / Development)。

5.3 处理签名证书

签名是 iOS 自动构建里绕不开的一步。常见做法是:

  1. .p12证书文件和描述文件放到 Runner 机器的一个安全目录,或者作为 Base64 环境变量传入;
  2. 在构建前把证书导入钥匙串,并设置钥匙串为默认搜索路径;
  3. xcodebuild命令中指定DEVELOPMENT_TEAMPROVISIONING_PROFILE_SPECIFIER

示例片段:

- name: Import signing certificate env: CERT_BASE64: ${{ secrets.CERT_BASE64 }} CERT_PASSWORD: ${{ secrets.CERT_PASSWORD }} run: | echo "$CERT_BASE64" | base64 --decode > /tmp/signing.p12 security create-keychain -p ci temp.keychain security import /tmp/signing.p12 -k temp.keychain -P "$CERT_PASSWORD" -A security set-key-partition-list -S apple-tool:,apple: -k ci temp.keychain security list-keychains -d user -s temp.keychain

这里涉及很多团队特定的证书管理方式,需要根据实际情况调整。注意secrets需在 Gitea 仓库或组织设置中提前配置,并且不要把证书密码写死在 YAML 里。

5.4 把工作流放到 Gitea 后如何触发

将 YAML 文件提交并推送后,on.push会立即触发一次任务。也可以先不写触发事件,使用 Gitea Web 界面上的 “Run workflow” 按钮手动触发(前提是配置了workflow_dispatch)。

6. 运行结果与效果验证

工作流提交后,在 Gitea 仓库页面的 “Actions” 标签页里,应该能看到新出现的运行记录。点击进入可以看到 job 列表和每个 step 的实时日志。

正常情况下,你会看到:

  • Checkout 步骤成功结束;
  • xcodebuild 输出 Xcode 版本信息;
  • Build without signing 步骤返回BUILD SUCCEEDED
  • 如果配置了 artifact 上传,运行结束后可以下载到 IPA 或 xcarchive。

如果 Runner 一直处于等待状态,优先检查runs-on标签是否与 Runner 注册的 label 一致。在线 Runner 但任务无人接收,大多是这种情况下发生的。

在 Mac 终端也可以观察 act_runner 的实时日志。使用tail -f runner.log能看到 Runner 是否收到任务、是否开始执行工作流、每个 step 的开始和结束时间。这一步对排查问题非常有帮助,比反复刷新 Web 页面更直接。

7. 常见问题与排查思路

以下是在 Apple 硬件上跑 Gitea Actions 时最容易遇到的问题,按经验整理成表格。

问题现象可能原因排查方式解决方案
Runner 在线,但任务一直 pending工作流runs-on与 Runner label 不一致查看 Runner 详情页的 label;检查 YAML 中的runs-on修改 YAML 或重新注册 Runner,保证两者完全匹配
Runner 显示离线进程退出、网络不通、token 失效查看 act_runner 日志;ping Gitea 地址重新启动 daemon;必要时重新注册
Checkout 失败,提示无权限SSH 密钥未配置或密钥权限过高在 Runner 机器执行 git 克隆测试为 CI 账号配置 SSH 公钥;或使用内置令牌 HTTP 克隆
提示 xcodebuild 找不到Command Line Tools 指向错误执行xcode-select -p执行sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
Build 报签名相关错误未配置签名参数、证书未导入查看签名 Error 中的具体描述先用CODE_SIGNING_ALLOWED=NO验证编译;再补签名配置
Job 在容器中执行,找不到 Xcode使用了容器模式跑 macOS 任务检查 act_runner 执行模式配置改为宿主机模式,并确保工作流使用宿主机 Runner
Action 内部的脚本使用 GitHub API 失败第三方 action 依赖 GitHub 云服务查看具体 action 的日志换成 Gitea 兼容的 action,或直接用run写命令
导出的 IPA 缺少描述文件ExportOptions.plist 配置不正确对比 Xcode 本地导出配置从 Xcode 重新生成 ExportOptions.plist

排查时有一条通用路径:先看 Gitea Web 日志,再看 act_runner 日志,最后到 Mac 本机手动执行 Xcode 命令。把手工能跑通的命令一步一步还原到工作流里,问题通常出在环境变量、PATH 或密钥访问权限上。

8. 最佳实践与工程建议

8.1 label 命名规范

建议从一开始就建立一套清晰的 label 规则,避免 Runner 一多就混乱。例如:

  • macos-arm64:Apple Silicon 通用任务;
  • macos-amd64:Intel Mac 通用任务;
  • macos-arm64-ios:专门承担 iOS 构建的 Apple Silicon 节点。

工作流中使用更具体的 label,可以有效避免任务被调度到不合适的机器上。

8.2 权限与安全边界

宿主机模式的 Runner 拥有较高系统权限,必须严格控制能触发任务的仓库范围。建议:

  • 将 Runner 注册在组织级或仓库级,而不是所有仓库共享;
  • 不使用个人高权限账号的 token 存放 Runner;
  • 定期轮换 Runner 注册令牌和 CI 机器人账号的访问令牌;
  • 存放证书和私钥的目录只允许 CI 机器人账号读取。

8.3 不要在一台 Mac 上跑过多并发

Apple 芯片性能虽强,但 iOS 构建是 CPU、磁盘高度密集的任务。如果一台 Mac 同时被多个 job 占满,会出现构建时间飙升、模拟器资源冲突等问题。建议在 Gitea Runner 配置中设置并发数限制,给每台机器留出余量。

8.4 与现有 CI/CD 链路的衔接

很多团队已经有 Jenkins 或 Drone,也有的在用 Gitea 配合 Harbor、Docker 和 Nginx 搭建完整发布链路。Gitea Actions 适合作为这整条链路里的“触发与构建”环节:

  • Gitea 负责代码托管和事件触发;
  • Actions 负责在 Mac 上完成 iOS/macOS 构建,或者在后端仓库里完成 Java 包构建、Docker 镜像构建;
  • 产物可以推送到 Harbor 镜像仓库或内部文件服务;
  • 部署环节可以继续由 Drone、Jenkins 或专门的发布系统负责。

如果你的团队目前是 “Jenkins + Gitea 实现 Spring Boot 打包部署”,不要急于推翻 Jenkins,可以先从 iOS 构建这种 Jenkins 配置成本高的任务切入,逐步把 Gitea Actions 引入流程。

8.5 日常维护清单

  • 定期检查 macOS 系统更新和 Xcode 版本兼容性;
  • 为 Runner 机器保留健康监控,磁盘不足时构建会莫名失败;
  • 备份config.yaml和 CI 机器人账号的配置;
  • Gitea 服务端升级前,先确认新版本对 Actions 的兼容性。

9. 总结与后续实践方向

这篇文章从“为什么 CI 需要 Apple 硬件”这个痛点出发,讲清楚了 Gitea Actions 的架构、act_runner 的执行模式、label 匹配机制,以及如何把一台 Mac 完整接入 Gitea 并跑通 iOS 构建工作流。核心结论是:Gitea Actions 真正降低的是自托管 CI 的接入门槛,尤其是对已有 Mac 设备和 Gitea 仓库的团队,可以用很少的成本获得一套接近 GitHub Actions 使用体验的构建系统。

下一步建议你从最小示例开始,先提交一个只打印 Xcode 版本的工作流,确认 Runner 调度正常,再逐步加入签名、归档、导出和产物上传。跑通之后,可以继续研究这套体系下的缓存策略、私有 action 管理、多 Runner 调度和与 Harbor/Drone 的联动。自托管 CI 的安全边界始终不能放松,Runner 一旦暴露给不可信任务,风险是真实存在的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/30 15:09:47

Replit与Slack合作背后:手把手搭建聊天窗口中的代码智能体

当代码智能体开始进入团队协作工具,开发方式就会发生一个很微妙的变化:开发动作不再只发生在 IDE、终端或者浏览器里,而是出现在团队成员每天都要打开的聊天窗口中。近来 Replit 与 Slack 在代码智能体方向上的合作,让很多做 AI 应…

作者头像 李华
网站建设 2026/8/30 15:03:09

推理引擎的运行保护设计

推理引擎的运行保护设计推理引擎处在模型、硬件和业务请求之间。它既要把输入交给合适的执行后端,也要在模型加载失败、设备不可用、请求超时或资源紧张时维持可理解的行为。运行保护并不是在每个错误后加一个兜底分支,而是先定义哪些状态可恢复、哪些必…

作者头像 李华
网站建设 2026/8/30 15:01:57

iOS/macOS 私密通信工具从零搭建:端到端加密与多端同步实践

如果你所在团队正在评估“能否在 Apple 生态内自建一套私密通信与协作工具”,这篇文章就是为你准备的。它不会只贴代码,也不会只讲概念,而是从 iOS/macOS 双端工程化的视角,把端到端加密、多端消息同步、App Group 数据共享、APNs…

作者头像 李华
网站建设 2026/8/30 14:56:43

Starship 启动慢?让 Shell 提示符加速到 50ms 以内的完整指南

Starship 启动慢?让 Shell 提示符加速到 50ms 以内的完整指南 【免费下载链接】starship ☄🌌️ The minimal, blazing-fast, and infinitely customizable prompt for any shell! 项目地址: https://gitcode.com/GitHub_Trending/st/starship St…

作者头像 李华