
发布仅 2 天狂揽 900 星冲上 GitHub 趋势日榜tendedero 把截图“晾”到了屏幕顶上【免费下载链接】tendederoScreenshots, hung out to dry. A tiny native macOS app that hangs every screenshot on a line at the top of your screen.项目地址: https://gitcode.com/gh_mirrors/te/tendedero2026 年 10 月 8 日的 GitHub 趋势日榜上头部被数学语料、Rust 重写的 Adobe 级软件这类大项目占据而榜单第 18 位塞进了一只“小不点”一个个人开发者前一天刚发布的纯 Swift 原生 macOS 应用。榜单快照时它已累计 497 星两天后总数停在约 913 星。这就是 tendedero——总共不到 2000 行 App 代码的菜单栏工具功能只有一件把你截的每一张图像衣服一样“晾”在屏幕顶部的隐形衣绳上。这篇文章从源码层面拆三件事它如何在不截一帧屏的情况下“拦截”系统截图、它如何改掉 macOS 的截图设置又保证退出时归还、以及一个无网络、无账号、1.7 MB 的小工具凭什么两天冲上趋势榜。一、先说清楚概念它是截图的“收件箱”不是贴图工具中文社区最熟悉的同类工具是“截图贴图”路线Snipaste 是典型代表后来的 PixPin 又叠了 OCR 与长截图。这类工具的交互是“主动”的——按键把当前画面“钉”在桌面上再随意拖动。tendedero 走了相反的路。它从不截图你照常按 ⌃⇧5或任何第三方工具区别在于文件一落盘就变成一张用木夹子挂在绳上的“卡片”带着随机的小倾角/// Every photo hangs a little crooked, like on a real line. let tilt Double.random(in: -2.5...2.5)绳子本身是一根抛物线LineView.swift 里的下垂量与屏幕宽度成正比、封顶 30ptstatic func sag(width: CGFloat) - CGFloat { min(30, width * 0.018) }未展示时整个面板整体上移自身高度加 12pt藏在屏幕顶缘之上鼠标靠近菜单栏它才滑下来像自动隐藏的 Dock。绳上容量按屏幕宽度动态计算AppDelegate.swift 中为max(3, min(12, (panelWidth-200)/174))挂满后最旧的卡片会悄悄掉下去不会无限堆积。首次启动时还会把空绳展示 5 秒提示“Take a screenshot and it will hang here”。二、两天 913 星一条可以核对的增长曲线把已知事实排一下时间轴仓库唯一初始提交时间为 2026-10-07 10:59UTC-7一次性提交 30 个文件、2,976 行含 README 与构建脚本作者为 Alejandro Buján应用默认提供英/西双语2026-10-08 的 GitHub 日榜快照距发布约 30 小时显示累计 497 星位列按 24 小时增速筛选的前 20 名第 18 位发布两天后累计约 913 星。分段计算前 30 小时约 497 星均值约 16 星/小时第二天约 416 星 / 18 小时均值接近 23 星/小时——增速在第二天明显抬升。这个量级对一个个人小工具而言已经很猛而它的“含金量”在于背景同一份榜单前列是 8,000 星单日增量的 AI 数学语料和重做 Photoshop 工作流的 Rust 项目一只 1.7 MB 的纯本地小应用能挤进 Top 20本身就是一次罕见的注意力事件。另外两个容易被忽略的细节代码 MIT 许可但 README.md 明确声明“名称和图标不在许可范围内fork 需要自己改名换标”应用经 Developer ID 签名并通过 Apple 公证还提供 Homebrew cask 安装brew install --cask alejandrobujan/tap/tendedero这种“产品化”的收尾方式在个人开源项目里不多见。三、核心设计一不截屏所以不需要截屏权限macOS 的“屏幕录制”权限是一道敏感门槛任何调用屏幕捕获接口的应用都会触发系统授权弹窗用户的第一反应往往是警惕。tendedero 用一个架构决策绕开了它ScreenshotWatcher.swift 头部的注释写得很直白/// Tendedero never takes screenshots itself: you keep your usual shortcut /// (or CleanShot, or anything else) and the line just picks them up.做法是“监听 macOS 保存截图的文件夹”确定目录从com.apple.screencapture偏好域读保存位置。值得注意的是面向 macOS 27 的正式版把这个 key 改名为location-screenshot且忽略旧 key代码因此新旧两个 key 都读、都写——这是全项目最“贴身跟踪系统”的部分监听文件事件对目录挂DispatchSourceFileSystemObject监听 write/rename/delete0.2 秒防抖因为 macOS 实际是“先写隐藏临时文件再改名”文件出现瞬间内容可能未写完// macOS writes a hidden temp file and renames it; give it a moment. DispatchQueue.main.asyncAfter(deadline: .now() 0.2, execute: work)甄别真截图监听桌面时只认带系统扩展属性com.apple.metadata:kMDItemIsScreenCapture的图片防止把随手存的图挂上绳。收益直接⌃⇧4、⌃⇧5、任意第三方工具的产物都能被接住且全程不申请屏幕录制权限。四、核心设计二Inbox 模式借走系统设置、退出时归还macOS 截图的默认路径是存桌面 右下角浮动缩略图停留 5 秒。缩略图是仪式感也是等待点——文件要 5 秒后才落定桌面则越攒越乱。Inbox.swift 的“Inbox 模式”干两件事关掉浮动缩略图文件即刻写盘、把保存位置改到~/Library/Application Support/Tendedero/Screenshots即直接写系统偏好域set(locationKey, folder.path) set(screenshotLocationKey, folder.path) set(thumbnailKey, false)而“改系统偏好”这件事的工程边界感体现在周围一圈处理上只问一次首次启动用 NSAlert 征求“Let Tendedero handle your screenshots?”wasOffered标志防止反复打扰先备份再改三个 key 的原值存入自己的 UserDefaults保证归还退出时恢复由于kill式终止不会触发applicationWillTerminateAppDelegate.swift 额外为SIGTERM/SIGINT/SIGHUP注册了信号处理器兜底执行恢复安全网Inbox 模式下另开一个桌面安全 watcher——注释写道如果某个 macOS 版本无视了新设置macOS 27 恰好改了 key 名截图落在桌面上也照样会被挂上绳可一键撤销菜单栏可随时关闭该模式关掉即还原。对应的注释值得抄进团队规范“Changing system settings is the users call, never ours.”改系统设置是用户的决定永远不是我们的。这是“高效”与“越界”之间的那条线。五、核心设计三像 Dock 一样隐藏全屏时自我克制面板是一个borderless nonactivatingPanel的 NSPanelfloating 层级、canJoinAllSpaces stationary ignoresCycle、永不抢焦点。真正的难点是鼠标事件面板横跨整屏宽度若吞掉所有点击会挡住下方一切。解法是 LineView.swift 用 SwiftUIPreferenceKey把每张卡片的真实 frame 回传给Line.hitRects主循环30fps 定时器据此动态切换ignoresMouseEvents——只有指针在照片上时面板才接收点击其余区域一律穿透。显隐时序则是一组精心调过的阈值条件行为鼠标在菜单栏“停留” 0.25s该屏幕的绳滑下“短到感觉即时长到路过菜单栏不会触发”鼠标离开绳区域 0.5s收回点击菜单栏任意位置立即收起防止“你刚开的菜单上又冒出一条绳”⌃⌥T手动显隐快捷键走 Carbon 的RegisterEventHotKeyHotKey.swift 的注释特意强调这条路径与全局键监听不同不需要辅助功能权限。全屏是边界情况。FullScreen.swift 通过两个私有 CGS 接口查询当前 Space 是否为全屏 Spacetype 4// These calls are private but stable for a decade, need no permission, // and are what window managers like yabai rely on.注释很诚实这两个调用私有但十年稳定、无需权限正是 yabai 这类窗口管理器所依赖的手段。一旦有全屏应用视频、演示绳永远隐藏。全屏时不刷存在感是这个小工具“高级感”的来源之一。六、动效是人格飞行、落绳、随风让人愿意为演示 GIF 点赞的是 CaptureFlight.swift 里的“飞行”动画截图文件自带系统扩展属性kMDItemScreenCaptureGlobalRect主显示器坐标系下的捕获区域代码读出这个 rect 后开一个无边框、不激活的整屏窗口以 120fps 跑 0.65 秒的动画——static let duration: CFTimeInterval 0.65轨迹是拱高 30pt 的 ease-in-out cubic截图在飞行中缩小、按卡片的固定倾角扭转、玻璃相框与木夹的透明度从行程 35% 开始渐显——落地时“飞行的副本”与绳上真卡以 0.16 秒交叉淡入肉眼看不出接缝。被丢弃的卡片则从绳上“坠落”下坠 520pt、倾角持续加大、0.55 秒淡出回收站丢弃还会播放系统自带的“drag to trash”音效代码直接引用 CoreAudio 组件里的 aif。环境细节同样到位每 7~16 秒来一阵“风”各卡片随机错开、摆动 1.6~3.4°挂绳时播放 “Tink”、掉落时 “Pop”。Line.swift 的注释把意图说破了/// Every so often a little wind moves the line. It is the detail that /// makes it feel like an object and not a widget.隔一阵小风吹动绳子这个细节让它像个物件而不是个控件。七、一套手势契约点、按、拖三个动词各管一件事手势集极其克制且每个拖拽落点语义唯一GrabArea.swift手势效果单击PNG 与文件 URL 写入系统剪贴板随处可粘贴长按 0.45s打开系统 Markup 标注双击用预览Preview打开拖到应用应用得到副本卡片留在绳上拖到文件夹文件移入该处卡片离开绳拖到废纸篓 / 点角落的叉丢弃Inbox 截图进回收站桌面上的只摘绳不动文件鼠标停在菜单栏绳滑下⌃⌥T显隐两个实现细节值得品拖拽的 operation mask 是[.copy, .move, .delete]——由接收方决定语义应用取副本、Finder 取原件、废纸篓执行删除松手在无接收方处时animatesToStartingPositionsOnCancelOrFail true让卡片“飞回”绳上而不是生硬回弹标注不内置编辑器而是调用系统com.apple.MarkupUI.Markup共享扩展Markup.swift用户点“完成”后由宿主进程把编辑结果原子写回原文件并刷新绳上缩略图。整个工具把标注、预览、Finder 全部“借”自系统自己只保留“挂”这一个动作。八、为什么偏偏是它隐私、极简与“纯原生”的三重叙事回到“为什么上榜”答案大多写在 README.md 的 Tech Specs 表里无账号、无网络、无分析、1.7 MB、免费、Developer ID 签名加公证。在“本地优先”这两年成为主基调的语境下这些字段逐项得分。但真正的差异化是零权限焦虑与零学习成本零权限焦虑不截屏无需屏幕录制、全局快捷键走 Carbon无需辅助功能、读 Space 状态用私有 CGS 接口无需权限首次运行唯一会触发的授权是桌面文件夹访问给桌面兜底 watcher 用且可整体关闭零学习成本没有设置页菜单栏菜单只有显隐、全部摘下、Inbox 开关、打开截图文件夹、声音、开机启动几项。工程侧它同样是一份少见的“可读源码”样本Sources/Tendedero下 14 个文件 1,953 行加上 scripts/ 里用代码画图标与宣传图的make-icon.swift、make-readme-art.swift总量约 2,600 行——仓库里甚至没有设计文件README 还提供了一张“Inside the app”表逐文件说明职责。本地化是 Localization.swift 里 8 行的L()函数按首选语言判断英/西。放到日榜语境里看逻辑就顺了榜单前列用“Rust 重写 Adobe”“722 篇数学论文”拼存在感这只 1.7 MB 的小工具拼的是一句“Your Desktop. Finally clear.”——痛点不大但人人可共情每次截图后等待 5 秒的浮动缩略图、越来越乱的桌面。tendedero 没有创造新工作流只是把截图的“位置”从堆在桌面移到悬在屏幕上方再用系统 API 让这段动效像个真实物件。两天 913 星的完整公式因此可以写出来每个 macOS 用户都有的小痛点 无需解释的“本地、无权限”卖点 10 秒就能看懂的演示外加一份愿意读源码的人可以逐行读完的实现。工具会迭代但“把一件小事做到边界感清晰”这件事它已经示范完了。【免费下载链接】tendederoScreenshots, hung out to dry. A tiny native macOS app that hangs every screenshot on a line at the top of your screen.项目地址: https://gitcode.com/gh_mirrors/te/tendedero创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考