clui-cc-claude-overlay by aradotso/trending-skills
npx skills add https://github.com/aradotso/trending-skills --skill clui-cc-claude-overlay技能由 ara.so 提供 — Daily 2026 技能集合。
Clui CC 将 Claude Code CLI 包装在一个透明的、悬浮的 macOS 悬浮窗中,支持多标签会话、权限批准界面(通过 PreToolUse HTTP 钩子)、通过 Whisper 的语音输入、对话历史记录以及技能市场。它需要一个已认证的 claude CLI,并完全在本地运行 — 无需遥测或云端依赖。
| 要求 | 最低版本 | 备注 |
|---|---|---|
| macOS | 13+ | 悬浮窗仅限 macOS |
| Node.js | 18+ | 推荐 LTS 20 或 22 |
| Python | 3.10+ | 在 3.12+ 上需要 setuptools |
| Claude Code CLI | 任意 | 必须已认证 |
| Whisper CLI |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 任意 |
| 用于语音输入 |
# 1. Xcode CLI 工具(用于本地模块编译)
xcode-select --install
# 2. 通过 Homebrew 安装 Node.js
brew install node
node --version # 确认 ≥18
# 3. Python setuptools(Python 3.12+ 必需)
python3 -m pip install --upgrade pip setuptools
# 4. Claude Code CLI
npm install -g @anthropic-ai/claude-code
# 5. 认证 Claude Code
claude
# 6. 用于语音输入的 Whisper
brew install whisper-cli
git clone https://github.com/lcoutodemos/clui-cc.git
# 然后在 Finder 中打开 clui-cc 文件夹,并双击 install-app.command
首次启动时,macOS 可能会阻止未签名的应用 — 请前往 系统设置 → 隐私与安全性 → 仍要打开。
git clone https://github.com/lcoutodemos/clui-cc.git
cd clui-cc
npm install
npm run dev # 热重载渲染进程;重启以应用主进程更改
./commands/setup.command # 环境检查 + 安装依赖
./commands/start.command # 从源代码构建并启动
./commands/stop.command # 停止所有 Clui CC 进程
npm run build # 生产构建(不打包)
npm run dist # 打包为 macOS .app → release/
npm run doctor # 环境诊断
| 快捷键 | 操作 |
|---|---|
⌥ + 空格 | 显示 / 隐藏悬浮窗 |
Cmd + Shift + K | 备用切换键(如果 ⌥+空格 被占用) |
UI 提示 → 主进程生成 claude -p → NDJSON 流 → 实时渲染
→ 工具调用? → 权限界面 → 批准/拒绝
claude -p --output-format stream-json 作为子进程。RunManager 解析 NDJSON;EventNormalizer 规范化事件。ControlPlane 管理标签页生命周期:connecting → idle → running → completed/failed/dead。PermissionServer(仅限 localhost)。--resume <session-id> 恢复。src/
├── main/
│ ├── claude/ # ControlPlane, RunManager, EventNormalizer
│ ├── hooks/ # PermissionServer (PreToolUse HTTP 钩子)
│ ├── marketplace/ # 插件目录获取 + 安装
│ ├── skills/ # 技能自动安装器
│ └── index.ts # 窗口创建,IPC 处理器,托盘
├── renderer/
│ ├── components/ # TabStrip, ConversationView, InputBar, …
│ ├── stores/ # Zustand 会话存储
│ ├── hooks/ # 事件监听器,健康状态协调
│ └── theme.ts # 双色调色板 + CSS 自定义属性
├── preload/ # 安全的 IPC 桥接(window.clui API)
└── shared/ # 规范类型,IPC 通道定义
window.clui)预加载桥接在渲染进程中暴露 window.clui。关键方法:
// 向活动标签页的 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[]>
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 }
}
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)
}
工具调用在执行前通过 PreToolUse HTTP 钩子被 PermissionServer 拦截。渲染进程收到 permission_request 事件并必须解决它。
// 渲染进程:监听权限请求
window.clui.onTabEvent(tabId, async (event) => {
if (event.type !== 'permission_request') return
const { requestId, toolName, toolInput } = event
// 显示你的批准界面,然后:
const approved = await showApprovalDialog({ toolName, toolInput })
await window.clui.resolvePermission(requestId, approved)
})
// 主进程:PermissionServer 向 claude -p 注册钩子
// 钩子端点接收来自 Claude Code 的 POST 请求,例如:
// { "tool": "bash", "input": { "command": "rm -rf dist/" }, "session_id": "..." }
// 它会保持请求,直到渲染进程解决它。
语音输入在本地使用 Whisper。它由 install-app.command 自动安装,或通过 brew install whisper-cli 安装。无需 API 密钥 — 转录完全在设备上运行。
// 通过 IPC 从 InputBar 组件触发
window.clui.startVoiceInput(): Promise<void>
window.clui.stopVoiceInput(): Promise<{ transcript: string }>
无需离开界面即可从 Anthropic 的 GitHub 仓库安装技能(插件)。
// 获取可用技能(缓存 5 分钟,从 raw.githubusercontent.com 获取)
const skills = await window.clui.marketplace.list()
// [{ id, name, description, repoUrl, version }, ...]
// 安装技能(从 api.github.com 下载 tarball)
await window.clui.marketplace.install(skillId: string)
// 列出已安装的技能
const installed = await window.clui.marketplace.listInstalled()
市场进行的网络调用:
| 端点 | 目的 | 必需 |
|---|---|---|
raw.githubusercontent.com/anthropics/* | 技能目录(5 分钟缓存) | 否 — 优雅降级 |
api.github.com/repos/anthropics/*/tarball/* | 技能 tarball 下载 | 否 — 失败时跳过 |
// src/renderer/theme.ts — 带有 CSS 自定义属性的双色调色板
// 通过 UI 或编程方式切换:
window.clui.setTheme('dark' | 'light' | 'system')
自定义 CSS 属性应用于 :root,并可在渲染进程样式表中覆盖:
:root {
--clui-bg: rgba(20, 20, 20, 0.85);
--clui-text: #f0f0f0;
--clui-accent: #7c5cfc;
--clui-pill-radius: 24px;
}
技能从 ~/.clui/skills/ 自动加载。技能是一个包含 skill.js 入口的目录:
// ~/.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('my trigger')) return false // 传递下去
await clui.sendMessage(tabId, `由 my-skill 处理:${prompt}`)
return true // 已消费 — 不转发给 claude
},
}
npm run doctor
首次启动时应用被阻止 → 系统设置 → 隐私与安全性 → 仍要打开
node-pty 编译失败
xcode-select --install
python3 -m pip install --upgrade pip setuptools
npm install
找不到 claude
npm install -g @anthropic-ai/claude-code
claude # 认证
which claude # 确认它在 PATH 上
找不到 Whisper
brew install whisper-cli
which whisper-cli
PermissionServer 端口冲突 HTTP 钩子服务器仅在 localhost 上运行。如果另一个进程占用了它的端口,请重启:
./commands/stop.command
./commands/start.command
缺少 setuptools (Python 3.12+)
python3 -m pip install --upgrade pip setuptools
悬浮窗不显示
Cmd + Shift + K| 组件 | 版本 |
|---|---|
| macOS | 15.x Sequoia |
| Node.js | 20.x LTS, 22.x |
| Python | 3.12 (+ setuptools) |
| Electron | 33.x |
| Claude Code CLI | 2.1.71 |
每周安装次数
267
仓库
GitHub 星标数
10
首次出现
6 天前
安全审计
安装于
gemini-cli266
github-copilot266
codex266
amp266
cline266
kimi-cli266
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 claude CLI and runs entirely local — no telemetry or cloud dependency.
| Requirement | Minimum | Notes |
|---|---|---|
| macOS | 13+ | Overlay is macOS-only |
| Node.js | 18+ | LTS 20 or 22 recommended |
| Python | 3.10+ | Needs setuptools on 3.12+ |
| Claude Code CLI | any | Must be authenticated |
| Whisper CLI | any | For voice input |
# 1. Xcode CLI tools (native module compilation)
xcode-select --install
# 2. Node.js via Homebrew
brew install node
node --version # confirm ≥18
# 3. Python setuptools (required on Python 3.12+)
python3 -m pip install --upgrade pip setuptools
# 4. Claude Code CLI
npm install -g @anthropic-ai/claude-code
# 5. Authenticate Claude Code
claude
# 6. Whisper for voice input
brew install whisper-cli
git clone https://github.com/lcoutodemos/clui-cc.git
# Then open the clui-cc folder in Finder and double-click install-app.command
On first launch macOS may block the unsigned app — go to System Settings → Privacy & Security → Open Anyway.
git clone https://github.com/lcoutodemos/clui-cc.git
cd clui-cc
npm install
npm run dev # Hot-reloads renderer; restart for main-process changes
./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 diagnostic
| Shortcut | Action |
|---|---|
⌥ + Space | Show / hide the overlay |
Cmd + Shift + K | Fallback toggle (if ⌥+Space is claimed) |
UI prompt → Main process spawns claude -p → NDJSON stream → live render
→ tool call? → permission UI → approve/deny
claude -p --output-format stream-json as a subprocess.RunManager parses NDJSON; EventNormalizer normalizes events.ControlPlane manages tab lifecycle: connecting → idle → running → completed/failed/dead.PermissionServer (localhost only).--resume <session-id>.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 definitions
window.clui)The preload bridge exposes window.clui in the renderer. Key methods:
// 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[]>
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 }
}
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)
}
Tool calls are intercepted by PermissionServer via PreToolUse HTTP hooks before execution. The renderer receives a permission_request event and must resolve it.
// 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)
})
// 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.
Voice input uses Whisper locally. It is installed automatically by install-app.command or via brew install whisper-cli. No API key is needed — transcription runs entirely on-device.
// Triggered from InputBar component via IPC
window.clui.startVoiceInput(): Promise<void>
window.clui.stopVoiceInput(): Promise<{ transcript: string }>
Install skills (plugins) from Anthropic's GitHub repos without leaving the UI.
// 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 |
|---|---|---|
raw.githubusercontent.com/anthropics/* | Skill catalog (5 min cache) | No — graceful fallback |
api.github.com/repos/anthropics/*/tarball/* | Skill tarball download | No — skipped on failure |
// 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 :root and can be overridden in renderer stylesheets:
:root {
--clui-bg: rgba(20, 20, 20, 0.85);
--clui-text: #f0f0f0;
--clui-accent: #7c5cfc;
--clui-pill-radius: 24px;
}
Skills are auto-loaded from ~/.clui/skills/. A skill is a directory with a skill.js entry:
// ~/.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
},
}
npm run doctor
App blocked on first launch → System Settings → Privacy & Security → Open Anyway
node-pty fails to compile
xcode-select --install
python3 -m pip install --upgrade pip setuptools
npm install
claude not found
npm install -g @anthropic-ai/claude-code
claude # authenticate
which claude # confirm it's on PATH
Whisper not found
brew install whisper-cli
which whisper-cli
Port conflict on PermissionServer The HTTP hook server runs on localhost only. If another process occupies its port, restart with:
./commands/stop.command
./commands/start.command
setuptools missing (Python 3.12+)
python3 -m pip install --upgrade pip setuptools
Overlay not showing
Cmd + Shift + K| 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 |
Weekly Installs
267
Repository
GitHub Stars
10
First Seen
6 days ago
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
gemini-cli266
github-copilot266
codex266
amp266
cline266
kimi-cli266
超能力技能使用指南:AI助手技能调用优先级与工作流程详解
41,800 周安装