Tinycast 扩展安装完全指南:注册表搜索、Raycast 导入、本地目录与源码构建全流程
2026/9/20 10:44:28 网站建设 项目流程
  • 桌面应用

【免费下载链接】tinycast

Tinycast — a tiny, fully native macOS launcher, hotkeys, and clipboard history.

项目地址:https://gitcode.com/GitHub_Trending/ti/tinycast
点击查看免费下载

导读

Tinycast 是一款完全原生的 macOS 启动器(launcher),同时内置热键与剪贴板历史功能,并原生运行 Raycast 扩展。本文围绕Settings → Extensions → Install这一入口,系统讲解 Tinycast 安装扩展的三种途径(注册表搜索、从 Raycast 导入、从本地文件夹添加),深入剖析其背后的双注册表模型(预编译 Store 与 GitHub 源码仓库)、包管理器自动探测与 PATH 搜索机制,以及存储与卸载的完整生命周期,帮助你在不依赖 Node 工具链的情况下完成绝大多数扩展的安装,并理解源码安装时的构建细节。

三种安装途径概览

Settings → Extensions → Install面板中,Tinycast 提供了三种互补的安装方式,它们的核心差异在于"扩展以什么形态进入你的 Mac":

途径形态是否需要工具链
Search Registries(搜索注册表)从已启用的注册表在线获取,安装即用取决于所选注册表(Store 不需要,GitHub 源码需要)
Import from Raycast(从 Raycast 导入)直接复制本机 Raycast 已构建好的扩展完全不需要
Add from folder(从文件夹添加)从含 manifest 与构建产物的本地文件夹安装不需要(但要求文件夹内是已构建产物)

其中"从 Raycast 导入"是最省心的一条路径:不构建任何东西,不需要 Node、不需要包管理器、不需要网络,因为扩展早已构建完成,只需原样搬移。这一点在源码中有直接印证:导入逻辑(Tinycast/Features/Extensions/Service/ExtensionCatalog.swift中的importableFromRaycast())只扫描扩展目录中的package.jsonmanifest 与已存在的<command>.js构建产物,并对不满足条件的半安装或纯源码目录直接跳过。

搜索注册表(Search Registries)

搜索注册表会同时查询每一个已启用的注册表,并从任意命中者中安装。这是日常使用中最常见的安装方式。

搜索请求在客户端侧是并行发起的:ExtensionStoreClient.search(_:in:)(Tinycast/Features/Extensions/Service/ExtensionStoreClient.swift)使用withTaskGroup同时向所有启用的注册表发起查询,但结果按注册表配置顺序而非完成顺序返回,保证列表不会在多次搜索之间重新洗牌;单个注册表失败也不会拖垮其他注册表的结果。

值得注意的细节:GitHub 注册表本身没有"搜索"能力,因此 Tinycast 会在本地对仓库内的扩展文件夹名做模糊匹配(FuzzyMatch)排名,只读取排名最高的前 12 个候选(githubCandidateLimit)逐一拉取package.json摘要,避免浪费请求配额。Store 则走其官网搜索所使用的端点。

从 Raycast 导入(Import from Raycast)

该功能把你在这台 Mac上已经通过 Raycast 装好的扩展直接复制进来,无需任何构建与联网。

  • Tinycast 会同时检查~/.config/raycast~/.config/raycast-x两个目录(ExtensionCatalog.raycastExtensionRoots()明确枚举了这两个路径,其中raycast-x对应 Beta v2 通道);当一个扩展在两个目录中都存在时,只提供一次(导入列表按 manifest 的name去重,较早的根目录优先)。
  • 面板提供Import All(全部导入)按钮:批量导入时界面会实时显示(done, total)进度(见 Tinycast/Features/Extensions/Settings/ExtensionsSettingsView.swift 中的importProgress状态与importAll(_:)方法),避免一次导入几十个扩展时"静默无反馈"。
  • 每次打开该面板都会重新检查一遍,并提示你"Raycast 中有、但 Tinycast 还没有"的扩展(pending列表在task启动时通过raycastImportCandidates()刷新),例如显示"N not here yet — …"的摘要。
  • 导入只认已构建的扩展:Raycast 以 UUID 作为目录键,因此 Tinycast 只能靠 manifest 判断目录里装的是什么;只有当目录内存在对应<command>.js构建产物时才视为可导入。

从文件夹添加(Add from folder)

第三种方式面向你自己构建好的项目:指向任意一个包含 manifest(package.json)和已构建命令文件的文件夹即可安装。

复制动作非常克制(见 Tinycast/Features/Extensions/Service/ExtensionCatalog.swift 中install(from:)的实现):

  • 只复制package.json、所有已构建的<command>.js文件以及assets/目录;
  • 绝不复制node_modules,绝不复制.js.map源映射——它们既占空间又暴露源码;
  • 安装前会校验 manifest 是否存在(否则报notAnExtension)、扩展是否支持 macOS(否则报wrongPlatform)、是否存在至少一个已构建命令(否则报noBuiltCommands,提示"Tinycast 只安装预构建扩展,请在扩展目录先运行ray build,或从已安装的 Raycast 导入")。

一个值得留意的细节:GitHub 源码下载会丢失文件的可执行位(mode bits),因此安装与每次扫描时,Tinycast 会按文件内容识别可执行负载(shebang#!或 Mach-O/ELF 魔数)并恢复执行权限(restoreExecutablePermissions),保证扩展内的辅助可执行脚本可以正常运行。

注册表(Registries)

Tinycast 出厂自带两个注册表,你可以自由地添加自己的注册表。两者本质上是两种完全不同的"供货渠道":

Raycast StoreGitHub 仓库
提供给你一个已构建好的扩展源代码
你需要准备什么都不需要Node 与一个包管理器

Store 正是大多数人完全不需要工具链的原因——它直接把已经构建好的产物交给你。

从源码看(Tinycast/Features/Extensions/Model/ExtensionRegistry.swift),两个内置注册表的定位是:

  • Raycast Storekind == .raycastStore):默认开启,通过 Raycast 官网搜索所用的端点提供预编译扩展;它不是一个官方 API,因此 Store 端点若变化,GitHub 注册表就是兜底方案;
  • 官方 GitHub 注册表raycast/extensionskind == .github):默认关闭,因为它提供的是源码、安装时需要构建工具链。

GitHub 注册表的形态与添加方式

一个 GitHub 注册表就是任何"每个扩展一个文件夹"布局的仓库,例如raycast/extensions。添加时输入owner/repo,或直接粘贴仓库中某个扩展文件夹的链接。解析逻辑(ExtensionRegistry.parse(_:name:))会剥离https://github.com/等前缀与末尾的.git,并识别浏览器复制出来的/tree/<ref>/<path>形式的链接(ref默认main,路径默认extensionspath会被规范化去掉首尾斜杠)。

几个关键行为:

  • 只下载扩展自己的文件夹,绝不下载整个仓库:客户端用一次递归 Git tree API 拿到目标路径下的文件清单,再逐个拉取 raw 文件,并跳过node_modulesmetadata目录(后者体积大且与运行无关)。若目录过大导致 tree 被截断,会直接报错而不是下载一个不完整的扩展。
  • 注册表还支持指定ref(分支、标签或 commit);分支意味着"那里现在有什么就用什么"。
  • 内置注册表(Store 与官方 GitHub)不可编辑、不可删除,只有用户自己添加的注册表可以删除或改名。
  • 由于 Store 是预编译的,在合并搜索结果时Store 结果优先ExtensionStoreClient.search的注释明确写着 "the store wins, because it is prebuilt")。

从源码安装的构建流程

从 GitHub 源码安装时,Tinycast 会依次执行:

  1. <package manager> install --ignore-scripts——安装依赖;
  2. 运行扩展自身的构建脚本(对 Raycast 扩展而言通常是ray build)。

安装脚本被刻意跳过--ignore-scripts),因为那是"没人要求运行的代码"。如果扩展在缺少安装脚本的情况下无法构建,那么它会在构建步骤直接失败,而不是先装一个半残的扩展。对应的参数定义见 Tinycast/Features/Extensions/Model/ExtensionPackageManager.swift:pnpm/Yarn/Bun 使用install --ignore-scripts,npm 额外追加--no-audit --no-fund关掉审计与赞助提示。

构建细节同样值得了解(Tinycast/Features/Extensions/Service/ExtensionInstaller.swift):

  • node_modules/.bin/ray存在,会调用ray build -e <env> -o <output> --non-interactive,且输出目录永远不会指向源码目录(防止开发式安装清空源码);若不存在ray(非标准 Raycast 项目),则退化为运行 manifest 的build脚本并在原地校验产物。
  • 构建环境参数-e会自动探测:如果扩展目录里出现Cargo.toml(即包含 Rust 辅助组件),使用dev环境(其 Rust 插件会桩化掉仅为 Windows 服务的rust:类型命令),否则使用dist——因为dist会为 Windows 构建rust:助手,那是 macOS 上的死代码且需要本机没有的 Rust 工具链。
  • 子进程设置CI=1(阻止 npm 向输出里刷进度条)与NO_COLOR=1;失败时只截取输出的末尾 6 行展示(包管理器真正的错误信息都在尾部)。
  • 整个安装有5 分钟超时commandTimeout = 300),足以覆盖慢速网络下的冷安装,又不会让一个卡死的子进程无限挂起;临时工作目录使用tinycast-install-<UUID>命名并保证无论成功失败都会清理(defer删除),这也是下文"存储清理"能兜底崩溃残留的基础。

安装进度会以明确的阶段呈现:Downloading…Installing dependencies with pnpm…Building…Installing…,避免长时间静默被误认为卡死。

包管理器(Package managers)

配置入口:Settings → Extensions → Package manager

Automatic(自动,默认)会按pnpm → Bun → Yarn → npm的顺序使用你本机第一个可用的包管理器(源码中ExtensionPackageManager.preferenceOrder = [.pnpm, .bun, .yarn, .npm])。理由写在注释里:最快、最省磁盘的排最前,几乎必然存在的 npm 排最后

这里有一个关键的技术背景:从 Dock 启动的 GUI 应用不会继承你终端里的PATH。因此 Tinycast 不会依赖 shell 环境,而是自行在常规位置探测可执行文件(searchPaths数组,见ExtensionPackageManager.swift):

  • Homebrew:/opt/homebrew/bin/usr/local/bin,以及兜底的/usr/bin/bin
  • Volta:~/.volta/bin
  • Bun:~/.bun/bin
  • asdf:~/.asdf/shims
  • mise:~/.local/share/mise/shims
  • fnm:~/.local/share/fnm/aliases/default/bin
  • nvm:~/.nvm/versions/node/current/bin
  • Yarn:~/.yarn/bin
  • 以及~/.npm-global/bin

包管理器面板会如实显示探测结果,例如 "Found pnpm at /opt/homebrew/bin/pnpm",或者告诉你本机什么都没装(此时使用源码注册表会失败)。由于ray build运行在 Node 之上,构建前还会单独探测node可执行文件(nodeURL),并把 Node 所在目录插入子进程 PATH 的最前面——因为版本管理器常常把 Node 藏起来,而包管理器会从 PATH 上派生ray

自定义搜索路径(Custom search paths)

对于内置列表之外的场景(典型如Nix),Registries 面板提供Custom search paths(自定义搜索路径):一个用冒号分隔的文件夹列表,语义与PATH相同,并且排在常规位置之前检查——因此你自定义的目录可以覆盖内置路径。例如:

~/.local/share/mise/shims
/etc/profiles/per-user/you/home-path/bin

(后者即 Nix Home Manager 的用户环境路径;~/.local/share/mise/shims同时是面板输入框的默认提示文本。)设置一次,之后每一次从源码安装都会生效。解析规则(ExtensionRegistriesPanel.parseSearchPaths)按:切分并丢弃空段与纯空白段,所以连续冒号不会产生空目录项。

哪些内容不参与备份

以下三项会被刻意排除在备份之外(参见 Tinycast 备份文档),因为它们描述的是这台 Mac,而不是可迁移的用户数据:

  • 注册表列表(registry list)
  • 包管理器选择(package manager choice)
  • 自定义搜索路径(custom search paths)

换句话说,备份的是"内容"而不是"环境":换一台机器恢复备份时,扩展本身会回来,但"从哪里下载、用什么工具构建"这种环境偏好不会跟着走。

存储与卸载

所有扩展都存放在 Tinycast 的 Application Support 文件夹下(~/Library/Application Support/<bundle-id>/,其中extensions/存放扩展本体、extension-data/存放扩展数据、extension-support/存放每个扩展各自的 scratch 目录)。

卸载一个扩展会删除与之相关的全部内容,包括:

  • 扩展本体与其存储、缓存
  • 它的偏好设置与 support 文件夹
  • 它在 Keychain 中的登录凭据(sign-ins)
  • 图标选择(icon choice)
  • 命令快捷键、收藏(favorites)、别名(aliases)与学习到的排序(learned ranking)

卸载实现(ExtensionCatalog.uninstall)同时清理扩展目录与其专属 support 目录,两条路径都覆盖到。

Settings → Extensions → Storage则负责测量并清理"残留构建文件夹"——那种崩溃的安装可能遗留下来的东西(例如命名前缀tinycast-install-的临时工作目录,以及孤立在 support/data 根下、不再对应任何已安装扩展的条目)。清理逻辑见 Tinycast/Features/Extensions/Service/ExtensionCleanup.swift:

  • 只扫描三个明确根目录(临时目录、support、data),范围刻意收窄;
  • 即使扩展整体被关闭也依然可用(设置面板把 Storage 区块放在"启用扩展"开关组之外,注释明确说 "leftovers are on disk whether or not extensions are on");
  • 正常情况下它显示为空——因为正常安装的临时目录会被defer及时清掉;
  • 清理前会先计算可回收的报告(reclaimable),按钮按下前就能显示将释放多少项、多少字节,且计数使用与 Finder 一致的文件大小口径(ByteCountFormattercountStyle: .file),让面板数字与"Get Info"对得上。

最后一点边界保证:Tinycast 永远不会触碰你自己的~/Library/pnpm~/.npm——它只在自己的沙箱目录内作业,你的全局包管理器缓存始终保持干净。

小结

围绕Install入口,Tinycast 给出了清晰的取舍:日常安装走Store 注册表(预编译、零工具链);已有 Raycast 环境则一键Import from Raycast(纯复制、离线完成);想构建自己的扩展,用Add from folder指向构建产物;需要自定义来源时添加GitHub 注册表(此时才需要 Node 与包管理器,且--ignore-scripts保证只运行显式声明的构建脚本)。理解注册表两种形态、Automatic 的探测顺序与自定义搜索路径的优先级,就能在绝大多数场景下做到"安装即用、卸载干净"。

  • 桌面应用

【免费下载链接】tinycast

Tinycast — a tiny, fully native macOS launcher, hotkeys, and clipboard history.

项目地址:https://gitcode.com/GitHub_Trending/ti/tinycast
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询