clui-cc-claude-overlay
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseClui CC — Claude Code Desktop Overlay
Clui CC — Claude Code 桌面悬浮覆盖层
Skill by ara.so — Daily 2026 Skills collection.
Clui CC wraps the Claude Code CLI in a transparent, floating macOS overlay with multi-tab sessions, a permission approval UI (PreToolUse HTTP hooks), voice input via Whisper, conversation history, and a skills marketplace. It requires an authenticated CLI and runs entirely local — no telemetry or cloud dependency.
claude由ara.so开发的技能工具——属于Daily 2026 Skills合集。
Clui CC 将Claude Code CLI封装为一款透明的macOS悬浮覆盖层,支持多标签会话、权限审批UI(PreToolUse HTTP钩子)、基于Whisper的语音输入、对话历史记录以及技能市场。它需要已认证的 CLI,且完全本地运行——无遥测数据或云端依赖。
claudePrerequisites
前置要求
| Requirement | Minimum | Notes |
|---|---|---|
| macOS | 13+ | Overlay is macOS-only |
| Node.js | 18+ | LTS 20 or 22 recommended |
| Python | 3.10+ | Needs |
| Claude Code CLI | any | Must be authenticated |
| Whisper CLI | any | For voice input |
bash
undefined| 要求 | 最低版本 | 说明 |
|---|---|---|
| macOS | 13+ | 悬浮覆盖层仅支持macOS系统 |
| Node.js | 18+ | 推荐使用LTS 20或22版本 |
| Python | 3.10+ | 3.12+版本需要安装 |
| Claude Code CLI | 任意版本 | 必须已完成认证 |
| Whisper CLI | 任意版本 | 用于语音输入功能 |
bash
undefined1. Xcode CLI tools (native module compilation)
1. Xcode CLI工具(用于原生模块编译)
xcode-select --install
xcode-select --install
2. Node.js via Homebrew
2. 通过Homebrew安装Node.js
brew install node
node --version # confirm ≥18
brew install node
node --version # 确认版本≥18
3. Python setuptools (required on Python 3.12+)
3. Python setuptools(Python 3.12+版本必需)
python3 -m pip install --upgrade pip setuptools
python3 -m pip install --upgrade pip setuptools
4. Claude Code CLI
4. 安装Claude Code CLI
npm install -g @anthropic-ai/claude-code
npm install -g @anthropic-ai/claude-code
5. Authenticate Claude Code
5. 完成Claude Code认证
claude
claude
6. Whisper for voice input
6. 安装Whisper用于语音输入
brew install whisper-cli
---brew install whisper-cli
---Installation
安装步骤
Recommended: App installer (non-developer)
推荐:应用安装包(非开发者用户)
bash
git clone https://github.com/lcoutodemos/clui-cc.gitbash
git clone https://github.com/lcoutodemos/clui-cc.gitThen open the clui-cc folder in Finder and double-click install-app.command
然后在访达中打开clui-cc文件夹,双击install-app.command运行
On first launch macOS may block the unsigned app — go to **System Settings → Privacy & Security → Open Anyway**.
首次启动时macOS可能会阻止未签名应用——前往**系统设置 → 隐私与安全性 → 仍要打开**。Developer workflow
开发者工作流
bash
git clone https://github.com/lcoutodemos/clui-cc.git
cd clui-cc
npm install
npm run dev # Hot-reloads renderer; restart for main-process changesbash
git clone https://github.com/lcoutodemos/clui-cc.git
cd clui-cc
npm install
npm run dev # 热重载渲染器;主进程变更需重启Command scripts
命令脚本
bash
./commands/setup.command # Environment check + install deps
./commands/start.command # Build and launch from source
./commands/stop.command # Stop all Clui CC processes
npm run build # Production build (no packaging)
npm run dist # Package as macOS .app → release/
npm run doctor # Environment diagnosticbash
./commands/setup.command # 环境检测 + 安装依赖
./commands/start.command # 构建并从源码启动
./commands/stop.command # 停止所有Clui CC进程
npm run build # 生产构建(不打包)
npm run dist # 打包为macOS .app文件 → release/目录
npm run doctor # 环境诊断Key Shortcuts
常用快捷键
| Shortcut | Action |
|---|---|
| Show / hide the overlay |
| Fallback toggle (if ⌥+Space is claimed) |
| 快捷键 | 操作 |
|---|---|
| 显示/隐藏悬浮覆盖层 |
| 备用切换快捷键(当⌥+Space被占用时) |
Architecture
架构
UI prompt → Main process spawns claude -p → NDJSON stream → live render
→ tool call? → permission UI → approve/denyUI输入 → 主进程启动claude -p → NDJSON流 → 实时渲染
→ 工具调用? → 权限UI → 批准/拒绝Process flow
流程说明
- Each tab spawns as a subprocess.
claude -p --output-format stream-json - parses NDJSON;
RunManagernormalizes events.EventNormalizer - manages tab lifecycle:
ControlPlane.connecting → idle → running → completed/failed/dead - Tool permission requests arrive via HTTP hooks to (localhost only).
PermissionServer - Renderer polls backend health every 1.5 s and reconciles tab state.
- Sessions resume with .
--resume <session-id>
- 每个标签页都会启动作为子进程。
claude -p --output-format stream-json - 解析NDJSON;
RunManager标准化事件格式。EventNormalizer - 管理标签页生命周期:
ControlPlane。连接中 → 空闲 → 运行中 → 完成/失败/终止 - 工具权限请求通过HTTP钩子发送至(仅本地主机)。
PermissionServer - 渲染器每1.5秒轮询后端健康状态并同步标签页状态。
- 通过恢复会话。
--resume <session-id>
Project structure
项目结构
src/
├── main/
│ ├── claude/ # ControlPlane, RunManager, EventNormalizer
│ ├── hooks/ # PermissionServer (PreToolUse HTTP hooks)
│ ├── marketplace/ # Plugin catalog fetch + install
│ ├── skills/ # Skill auto-installer
│ └── index.ts # Window creation, IPC handlers, tray
├── renderer/
│ ├── components/ # TabStrip, ConversationView, InputBar, …
│ ├── stores/ # Zustand session store
│ ├── hooks/ # Event listeners, health reconciliation
│ └── theme.ts # Dual palette + CSS custom properties
├── preload/ # Secure IPC bridge (window.clui API)
└── shared/ # Canonical types, IPC channel definitionssrc/
├── main/
│ ├── claude/ # ControlPlane、RunManager、EventNormalizer
│ ├── hooks/ # PermissionServer(PreToolUse HTTP钩子)
│ ├── marketplace/ # 插件目录获取与安装
│ ├── skills/ # 技能自动安装器
│ └── index.ts # 窗口创建、IPC处理器、托盘管理
├── renderer/
│ ├── components/ # 标签栏、对话视图、输入栏等
│ ├── stores/ # Zustand会话存储
│ ├── hooks/ # 事件监听器、健康状态同步
│ └── theme.ts # 双色调色板 + CSS自定义属性
├── preload/ # 安全IPC桥接(window.clui API)
└── shared/ # 标准类型定义、IPC通道定义IPC API (window.clui
)
window.cluiIPC API (window.clui
)
window.cluiThe preload bridge exposes in the renderer. Key methods:
window.cluitypescript
// Send a prompt to the active tab's claude process
window.clui.sendPrompt(tabId: string, text: string): Promise<void>
// Approve or deny a pending tool-use permission
window.clui.resolvePermission(requestId: string, approved: boolean): Promise<void>
// Create a new tab (spawns a new claude -p process)
window.clui.createTab(): Promise<{ tabId: string }>
// Resume a past session by id
window.clui.resumeSession(tabId: string, sessionId: string): Promise<void>
// Subscribe to normalized events from a tab
window.clui.onTabEvent(tabId: string, callback: (event: NormalizedEvent) => void): () => void
// Get conversation history list
window.clui.getHistory(): Promise<SessionMeta[]>预加载桥接层在渲染器中暴露对象。核心方法:
window.cluitypescript
// 向当前活跃标签页的claude进程发送输入
window.clui.sendPrompt(tabId: string, text: string): Promise<void>
// 批准或拒绝待处理的工具使用权限
window.clui.resolvePermission(requestId: string, approved: boolean): Promise<void>
// 创建新标签页(启动新的claude -p进程)
window.clui.createTab(): Promise<{ tabId: string }>
// 通过会话ID恢复历史会话
window.clui.resumeSession(tabId: string, sessionId: string): Promise<void>
// 订阅标签页的标准化事件
window.clui.onTabEvent(tabId: string, callback: (event: NormalizedEvent) => void): () => void
// 获取对话历史列表
window.clui.getHistory(): Promise<SessionMeta[]>Working with Tabs and Sessions
标签页与会话管理
Creating a tab and sending a prompt (renderer)
创建标签页并发送输入(渲染器端)
typescript
import { useEffect, useState } from 'react'
export function useClaudeTab() {
const [tabId, setTabId] = useState<string | null>(null)
const [messages, setMessages] = useState<NormalizedEvent[]>([])
useEffect(() => {
window.clui.createTab().then(({ tabId }) => {
setTabId(tabId)
const unsubscribe = window.clui.onTabEvent(tabId, (event) => {
setMessages((prev) => [...prev, event])
})
return unsubscribe
})
}, [])
const send = (text: string) => {
if (!tabId) return
window.clui.sendPrompt(tabId, text)
}
return { messages, send }
}typescript
import { useEffect, useState } from 'react'
export function useClaudeTab() {
const [tabId, setTabId] = useState<string | null>(null)
const [messages, setMessages] = useState<NormalizedEvent[]>([])
useEffect(() => {
window.clui.createTab().then(({ tabId }) => {
setTabId(tabId)
const unsubscribe = window.clui.onTabEvent(tabId, (event) => {
setMessages((prev) => [...prev, event])
})
return unsubscribe
})
}, [])
const send = (text: string) => {
if (!tabId) return
window.clui.sendPrompt(tabId, text)
}
return { messages, send }
}Resuming a past session
恢复历史会话
typescript
async function resumeLastSession() {
const history = await window.clui.getHistory()
if (history.length === 0) return
const { tabId } = await window.clui.createTab()
const lastSession = history[0] // most recent first
await window.clui.resumeSession(tabId, lastSession.sessionId)
}typescript
async function resumeLastSession() {
const history = await window.clui.getHistory()
if (history.length === 0) return
const { tabId } = await window.clui.createTab()
const lastSession = history[0] // 最新会话排在首位
await window.clui.resumeSession(tabId, lastSession.sessionId)
}Permission Approval UI
权限审批UI
Tool calls are intercepted by via PreToolUse HTTP hooks before execution. The renderer receives a event and must resolve it.
PermissionServerpermission_requesttypescript
// Renderer: listen for permission requests
window.clui.onTabEvent(tabId, async (event) => {
if (event.type !== 'permission_request') return
const { requestId, toolName, toolInput } = event
// Show your approval UI, then:
const approved = await showApprovalDialog({ toolName, toolInput })
await window.clui.resolvePermission(requestId, approved)
})typescript
// Main process: PermissionServer registers a hook with claude -p
// The hook endpoint receives POST requests from Claude Code like:
// { "tool": "bash", "input": { "command": "rm -rf dist/" }, "session_id": "..." }
// It holds the request until the renderer resolves it.工具调用会在执行前被通过PreToolUse HTTP钩子拦截。渲染器会收到事件并需要处理该请求。
PermissionServerpermission_requesttypescript
// 渲染器:监听权限请求
window.clui.onTabEvent(tabId, async (event) => {
if (event.type !== 'permission_request') return
const { requestId, toolName, toolInput } = event
// 显示自定义审批UI,然后执行:
const approved = await showApprovalDialog({ toolName, toolInput })
await window.clui.resolvePermission(requestId, approved)
})typescript
// 主进程:PermissionServer向claude -p注册钩子
// 钩子端点会接收来自Claude Code的POST请求,格式如下:
// { "tool": "bash", "input": { "command": "rm -rf dist/" }, "session_id": "..." }
// 它会暂停请求直到渲染器完成审批。Voice Input
语音输入
Voice input uses Whisper locally. It is installed automatically by or via . No API key is needed — transcription runs entirely on-device.
install-app.commandbrew install whisper-clitypescript
// Triggered from InputBar component via IPC
window.clui.startVoiceInput(): Promise<void>
window.clui.stopVoiceInput(): Promise<{ transcript: string }>语音输入使用本地的Whisper工具。它会被自动安装,也可通过手动安装。无需API密钥——转录完全在本地设备上运行。
install-app.commandbrew install whisper-clitypescript
// 通过IPC从输入栏组件触发
window.clui.startVoiceInput(): Promise<void>
window.clui.stopVoiceInput(): Promise<{ transcript: string }>Skills Marketplace
技能市场
Install skills (plugins) from Anthropic's GitHub repos without leaving the UI.
typescript
// Fetch available skills (cached 5 min, fetched from raw.githubusercontent.com)
const skills = await window.clui.marketplace.list()
// [{ id, name, description, repoUrl, version }, ...]
// Install a skill (downloads tarball from api.github.com)
await window.clui.marketplace.install(skillId: string)
// List installed skills
const installed = await window.clui.marketplace.listInstalled()Network calls made by the marketplace:
| Endpoint | Purpose | Required |
|---|---|---|
| Skill catalog (5 min cache) | No — graceful fallback |
| Skill tarball download | No — skipped on failure |
无需离开UI即可从Anthropic的GitHub仓库安装技能(插件)。
typescript
// 获取可用技能(缓存5分钟,从raw.githubusercontent.com获取)
const skills = await window.clui.marketplace.list()
// [{ id, name, description, repoUrl, version }, ...]
// 安装技能(从api.github.com下载压缩包)
await window.clui.marketplace.install(skillId: string)
// 列出已安装技能
const installed = await window.clui.marketplace.listInstalled()技能市场的网络请求:
| 端点 | 用途 | 是否必需 |
|---|---|---|
| 技能目录(5分钟缓存) | 否——无网络时会优雅降级 |
| 技能压缩包下载 | 否——失败时会跳过 |
Theme Configuration
主题配置
typescript
// src/renderer/theme.ts — dual palette with CSS custom properties
// Toggle via the UI or programmatically:
window.clui.setTheme('dark' | 'light' | 'system')Custom CSS properties are applied to and can be overridden in renderer stylesheets:
:rootcss
:root {
--clui-bg: rgba(20, 20, 20, 0.85);
--clui-text: #f0f0f0;
--clui-accent: #7c5cfc;
--clui-pill-radius: 24px;
}typescript
// src/renderer/theme.ts — 带CSS自定义属性的双色调色板
// 通过UI或编程方式切换:
window.clui.setTheme('dark' | 'light' | 'system')自定义CSS属性会应用到,可在渲染器样式表中覆盖:
:rootcss
:root {
--clui-bg: rgba(20, 20, 20, 0.85);
--clui-text: #f0f0f0;
--clui-accent: #7c5cfc;
--clui-pill-radius: 24px;
}Adding a Custom Skill
添加自定义技能
Skills are auto-loaded from . A skill is a directory with a entry:
~/.clui/skills/skill.jstypescript
// ~/.clui/skills/my-skill/skill.js
module.exports = {
name: 'my-skill',
version: '1.0.0',
description: 'Does something useful',
// Called when the skill is activated by a matching prompt
async onPrompt(context) {
const { prompt, tabId, clui } = context
if (!prompt.includes('my trigger')) return false // pass through
await clui.sendMessage(tabId, `Handled by my-skill: ${prompt}`)
return true // consumed — don't forward to claude
},
}技能会从目录自动加载。一个技能是包含入口文件的目录:
~/.clui/skills/skill.jstypescript
// ~/.clui/skills/my-skill/skill.js
module.exports = {
name: 'my-skill',
version: '1.0.0',
description: '实现某些实用功能',
// 当输入匹配触发条件时激活技能
async onPrompt(context) {
const { prompt, tabId, clui } = context
if (!prompt.includes('我的触发词')) return false // 不处理,转发给claude
await clui.sendMessage(tabId, `由my-skill处理:${prompt}`)
return true // 已处理,不转发给claude
},
}Troubleshooting
故障排除
Self-check
自检命令
bash
npm run doctorbash
npm run doctorCommon issues
常见问题
App blocked on first launch
→ System Settings → Privacy & Security → Open Anyway
node-ptybash
xcode-select --install
python3 -m pip install --upgrade pip setuptools
npm installclaudebash
npm install -g @anthropic-ai/claude-code
claude # authenticate
which claude # confirm it's on PATHWhisper not found
bash
brew install whisper-cli
which whisper-cliPort conflict on PermissionServer
The HTTP hook server runs on localhost only. If another process occupies its port, restart with:
bash
./commands/stop.command
./commands/start.commandsetuptoolsbash
python3 -m pip install --upgrade pip setuptoolsOverlay not showing
- Try the fallback shortcut:
Cmd + Shift + K - Check that Clui CC has Accessibility permission: System Settings → Privacy & Security → Accessibility
首次启动时应用被阻止
→ 系统设置 → 隐私与安全性 → 仍要打开
node-ptybash
xcode-select --install
python3 -m pip install --upgrade pip setuptools
npm install找不到命令
claudebash
npm install -g @anthropic-ai/claude-code
claude # 完成认证
which claude # 确认已添加到PATH找不到Whisper
bash
brew install whisper-cli
which whisper-cliPermissionServer端口冲突
HTTP钩子服务器仅在本地主机运行。如果端口被其他进程占用,通过以下命令重启:
bash
./commands/stop.command
./commands/start.command缺少(Python 3.12+)
setuptoolsbash
python3 -m pip install --upgrade pip setuptools悬浮覆盖层不显示
- 尝试备用快捷键:
Cmd + Shift + K - 检查Clui CC是否已获得辅助功能权限:系统设置 → 隐私与安全性 → 辅助功能
Tested Versions
已测试版本
| Component | Version |
|---|---|
| macOS | 15.x Sequoia |
| Node.js | 20.x LTS, 22.x |
| Python | 3.12 (+ setuptools) |
| Electron | 33.x |
| Claude Code CLI | 2.1.71 |
| 组件 | 版本 |
|---|---|
| macOS | 15.x Sequoia |
| Node.js | 20.x LTS、22.x |
| Python | 3.12(需安装setuptools) |
| Electron | 33.x |
| Claude Code CLI | 2.1.71 |
References
参考链接
- Claude Code docs
- Architecture deep-dive
- Troubleshooting guide
- MIT License
- Claude Code 文档
- 架构深度解析
- 故障排除指南
- MIT 许可证