前言

最近一段时间,我在使用 Claude Code 辅助写代码时,经常遇到一个问题:

AI Agent 在终端里执行任务,我切到浏览器或其他窗口后,很难判断它现在到底是:

  • 还在思考
  • 正在执行工具
  • 已经完成
  • 还是在等待我确认

每次都要切回终端看一眼,比较打断心流。

刚好 iPhone 的 Apple Intelligence 工作时,屏幕边缘会出现很漂亮的虹光效果。我觉得这种「余光可感知」的设计很适合 AI 编程场景,于是做了一个 macOS 小工具:EdgeGlow

它把类似 iPhone AI 边缘虹光的效果带到了 Mac 上。


EdgeGlow 是什么?

EdgeGlow 是一个 macOS 菜单栏应用。

当 Claude Code 或其他 AI Coding Agent 工作时,它会在屏幕边缘显示流光效果;任务完成后,流光自动淡出。

效果类似:

AI 开始工作  → 屏幕边缘出现虹彩流光
AI 完成任务  → 流光淡出消失

项目地址:

https://github.com/vector4wang/EdgeGlow

效果图:
在这里插入图片描述


核心特性

EdgeGlow 目前支持:

  • iPhone Apple Intelligence 风格的边缘虹光效果
  • 5 种颜色主题:虹彩、炫酷、柔和、烈焰、冰雪
  • 两种光效模式:流动模式、呼吸模式
  • 多显示器支持
  • 多终端支持
  • 中英双语界面
  • 参数可调:速度、宽度、亮度、方向
  • 本地 HTTP hooks 联动
  • 无遥测、无数据收集
  • MIT 开源协议

性能方面:

指标 数值
安装包大小 约 892KB
CPU 占用 约 0%
内存占用 约 50MB
系统要求 macOS 13.0+

快速安装

方式一:下载 Release

进入 GitHub Releases 页面下载:

https://github.com/vector4wang/EdgeGlow/releases

下载 EdgeGlow-v1.3.0.zip 后解压运行。

如果首次打开遇到 macOS 安全提示,可以右键应用,选择「打开」。

方式二:源码编译
git clone https://github.com/vector4wang/EdgeGlow.git
cd EdgeGlow
./build.sh
open Build/EdgeGlow.app

Claude Code 配置方式

EdgeGlow 的联动方式很简单:

它在本地启动一个 HTTP 服务,只监听:

127.0.0.1:9876

Claude Code hooks 在不同事件触发时调用对应接口:

/start  → 显示流光
/pulse  → 保持状态
/stop   → 流光淡出

可以在 ~/.claude/settings.json 中添加类似配置:

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "curl -s http://127.0.0.1:9876/start"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "curl -s http://127.0.0.1:9876/start"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "curl -s http://127.0.0.1:9876/pulse"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "curl -s http://127.0.0.1:9876/stop"
          }
        ]
      }
    ]
  }
}

实际使用时,EdgeGlow 设置界面也提供了「复制引导词」的方式,可以让 Claude Code 自动帮你生成配置。


工作原理

整体流程如下:

Claude Code 开始任务
        ↓
触发 UserPromptSubmit / PreToolUse hook
        ↓
curl http://127.0.0.1:9876/start
        ↓
EdgeGlow 显示屏幕边缘流光
        ↓
任务完成后触发 Stop hook
        ↓
curl http://127.0.0.1:9876/stop
        ↓
流光淡出

这样做的好处是:

  • 不需要修改 Claude Code
  • 不需要插件系统
  • 不需要联网
  • 任意支持 HTTP 请求的 Agent 理论上都能接入

为什么做成边缘流光?

传统的状态提醒方式一般有几种:

  1. 终端输出日志
  2. 系统通知
  3. 声音提醒
  4. 任务完成后弹窗

但 AI Agent 的工作过程比较特殊:它可能会频繁读文件、执行命令、等待确认,也可能持续工作几十秒到几分钟。

如果用通知,会比较打扰;如果只看终端,又需要不断切换窗口。

边缘流光的优势是:

  • 不打断当前工作
  • 余光就能看到状态
  • 比日志和通知更轻量
  • 很适合多任务场景

这也是 EdgeGlow 的核心设计目标:让 AI Agent 的状态变成环境反馈,而不是打断式提醒。


技术实现概览

EdgeGlow 使用原生 macOS 技术实现,主要包括:

Swift
SwiftUI
AppKit
Core Animation
Network.framework
UserDefaults
Combine

整体结构大致如下:

Sources/
├── main.swift              # 应用入口、菜单栏
├── GlowWindow.swift        # 流光窗口、光效绘制、动画
├── ControlServer.swift     # 本地 HTTP 控制服务
├── HooksInstaller.swift    # Agent 配置引导
├── L10n.swift              # 中英文国际化
├── Settings/
│   ├── AppSettings.swift   # 设置持久化
│   └── SettingsView.swift  # SwiftUI 设置界面
└── Themes/
    └── ColorTheme.swift    # 颜色主题

技术细节:透明覆盖窗口

屏幕边缘流光需要显示在整个屏幕边缘,因此 EdgeGlow 使用一个透明的覆盖窗口。

核心思路是:

  • 创建无边框透明窗口
  • 覆盖所有屏幕的联合区域
  • 不抢焦点
  • 不影响用户点击和正常操作

多显示器环境下,需要计算所有屏幕的 union frame:

func totalScreenFrame() -> NSRect {
    var frame = NSRect.zero
    for screen in NSScreen.screens {
        frame = NSUnionRect(frame, screen.frame)
    }
    return frame
}

当屏幕参数变化时,例如外接显示器插拔,重新计算路径并重建图层。


技术细节:复刻 iPhone AI 边缘虹光

默认的虹彩主题参考了 iPhone Apple Intelligence 的视觉效果。

颜色变化大致是:

紫 → 蓝 → 青 → 粉 → 橙 → 金

为了让边缘流光更接近真实霓虹效果,EdgeGlow 使用多层 CAShapeLayer 叠加:

Layer 1: 高模糊 + 低透明度,作为外层光晕
Layer 2: 中模糊 + 中透明度,作为中层扩散
Layer 3: 低模糊 + 高透明度,作为主色线
Layer 4: 无模糊 + 高亮度,作为中心亮芯

这种做法比单层描边更自然,能够模拟发光边缘的层次感。


技术细节:动画实现

一开始我尝试使用 CABasicAnimation 去驱动 lineDashPhase,类似这样:

let animation = CABasicAnimation(keyPath: "lineDashPhase")
animation.fromValue = 0
animation.toValue = perimeter
animation.repeatCount = .infinity
shapeLayer.add(animation, forKey: "flow")

但实际测试时发现,窗口隐藏后再显示,Core Animation 的状态可能会丢失,导致动画卡住、跳变或者方向异常。

后来改成直接用定时器驱动状态更新:

flowTimer = Timer.scheduledTimer(withTimeInterval: 1.0 / 60.0, repeats: true) { [weak self] _ in
    self?.tickFlow()
}

每一帧只更新 lineDashPhase,实际 CPU 占用很低。


技术细节:本地 HTTP 服务

EdgeGlow 使用 NWListener 启动本地 HTTP 服务。

安全设计上做了几件事:

  • 只监听 127.0.0.1
  • 使用 acceptLocalOnly
  • 只接受 GET 请求
  • 不返回 CORS 头
  • 不收集任何数据

这意味着外部网络无法访问这个服务,网页 JavaScript 也无法直接跨域调用。


技术细节:多终端状态管理

如果同时打开多个 Claude Code 终端,就会出现一个问题:

一个终端完成了,不代表其他终端也完成了。

因此 EdgeGlow 需要维护一个活动状态计数或活动标识集合,只有所有任务都完成后,才让流光消失。

简化逻辑类似:

case "/start":
    activeCount += 1
    showGlow()

case "/stop":
    activeCount = max(0, activeCount - 1)
    if activeCount == 0 {
        hideGlow()
    }

同时还需要安全超时机制,避免 Agent 异常退出导致流光一直不消失。


适用人群

我觉得 EdgeGlow 比较适合这些场景:

  • 经常使用 Claude Code 的开发者
  • 同时开多个 AI Coding Agent 的用户
  • 需要在多个窗口之间频繁切换的人
  • 喜欢轻量原生 macOS 工具的人
  • 对 AI 编程状态反馈有需求的人

总结

EdgeGlow 本质上不是一个复杂工具,它解决的是一个很小但高频的问题:

AI Agent 到底还在不在工作?

通过屏幕边缘流光,EdgeGlow 把这个状态变成了一个环境信号。你不需要切回终端,不需要看通知,余光一扫就能知道当前状态。

项目完全开源,代码也比较简单,如果你对 macOS 原生应用、SwiftUI、Core Animation 或 AI Agent 工具联动感兴趣,可以参考或一起完善。

项目地址:

https://github.com/vector4wang/EdgeGlow

欢迎 Star、Issue、PR。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐