# AI Code Agent — Node.js Edition


> 基于 OpenAI 兼容协议的轻量级 AI 编程助手  
> 零外部依赖 · 纯 JavaScript · DeepSeek 默认 · 安全加固

[![npm version](https://img.shields.io/npm/v/@raolin2025/claude-code-node.svg)](https://www.npmjs.com/package/@raolin2025/claude-code-node) [![GitHub](https://img.shields.io/badge/GitHub-bg1avd%2Fclaude--code--node-blue)](https://github.com/bg1avd/claude-code-node) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
---

## 📦 安装

```bash
# npm 全局安装
npm install -g @raolin2025/claude-code-node

# 或 npx 直接运行（无需安装）
npx @raolin2025/claude-code-node

# 安装后使用 cc-node 命令
cc-node
```

## 🚀 快速开始

### 前置要求
- Node.js ≥ 18.0.0
- 至少一个 API Key：`DEEPSEEK_API_KEY`（默认）或 `LLM_API_KEY`（通用）

### 启动

```bash
# 进入项目目录

# 设置 API Key（DeepSeek 为默认）
export DEEPSEEK_API_KEY=your_key_here
# 或通用方式
export LLM_API_KEY=your_key_here

# 启动 REPL（默认使用 DeepSeek）
cc-node

# 一次性执行
cc-node "列出当前目录的文件"

# 指定模型
cc-node --model deepseek-reasoner

# 切换其他提供商
cc-node --model qwen-plus --api-base https://dashscope.aliyuncs.com/compatible-mode/v1

# 恢复上一次会话
cc-node --resume session-1747000000000-abc123
```

[![npm version](https://img.shields.io/npm/v/@raolin2025/claude-code-node.svg)](https://www.npmjs.com/package/@raolin2025/claude-code-node) [![GitHub](https://img.shields.io/badge/GitHub-bg1avd%2Fclaude--code--node-blue)](https://github.com/bg1avd/claude-code-node) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
---

## 📖 命令行参数

| 参数 | 短写 | 说明 | 默认值 |
|------|------|------|--------|
| `--model` | `-m` | LLM 模型名 | `deepseek-flash` |
| `--system-prompt` | `-s` | 系统提示词 | `""` |
| `--permission-mode` | `-p` | 权限模式 | `ask` |
| `--max-turns` | `-t` | 最大工具循环轮数 | `100` |
| `--api-base` | | API 基础 URL | `https://api.deepseek.com/v1` |
| `--resume` | `-r` | 恢复会话 ID | |
| `--verbose` | `-v` | 详细输出 | `false` |
| `--no-stream` | | 禁用流式响应 | `false` |
| `--max-messages` | | 消息条数上限，超过则折叠早期历史为摘要（解决本地小模型"条数过多变傻"） | `0`（关闭） |
| `--small-model` | | 小模型适配模式（强制工具调用 + 敷衍重试 + 意图引导 + 工具精简） | `false` |
| `--max-output-tokens` | | 覆盖单次响应输出上限（默认根据上下文窗口动态计算） | 窗口×1/16 |
| `--stdio` | | **JSON-RPC 服务器模式**（供桥接层/外部客户端接入，见下） | |
| `--help` | `-h` | 显示帮助 | |

### 🖥️ stdio 服务器模式（--stdio）

以独立子进程形态提供 **JSON-RPC 2.0 over NDJSON** 服务，供外部客户端（VS Code 扩展 / Web / Telegram 等）接入。
协议完整定义见 cc-node-bridge 项目 `docs/stdio-protocol.md`。

```bash
# 启动（stdin/stdout 为协议通道，stderr 为日志）
cc-node --stdio --api-base http://127.0.0.1:11434/v1 --model qwen2.5:0.5b

# 最小请求：initialize
printf '{"jsonrpc":"2.0","id":1,"method":"initialize"}\n' | cc-node --stdio
```

能力：流式输出（event/delta）、多模态（images）、remote 工具执行（toolCall 回传）、
会话管理、abort 中断、config 运行时配置。每个接入客户端建议独立子进程（由桥接层管理）。

### 权限模式

| 模式 | 说明 |
|------|------|
| `ask` | 每次工具调用需确认（安全，推荐） |
| `always-allow` | 自动允许所有工具调用（仍受安全策略约束） |
| `deny` | 拒绝所有工具调用 |

[![npm version](https://img.shields.io/npm/v/@raolin2025/claude-code-node.svg)](https://www.npmjs.com/package/@raolin2025/claude-code-node) [![GitHub](https://img.shields.io/badge/GitHub-bg1avd%2Fclaude--code--node-blue)](https://github.com/bg1avd/claude-code-node) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
---

## 💬 REPL 内置命令

进入 REPL 后，输入 `/` 开头的命令：

| 命令 | 说明 |
|------|------|
| `/help` | 显示帮助 |
| `/model NAME` | 切换模型 |
| `/tools` | 列出可用工具 |
| `/session` | 查看当前会话信息 |
| `/sessions` | 列出所有会话 |
| `/clear` | 清空当前对话 |
| `/config KEY` | 查看配置（支持点号路径如 `tools.bash.timeout`） |
| `/budget` | 查看 Token 预算使用情况 |
| `/window [N]` | 查看/设置上下文窗口（如 `/window 128k`、`/window auto`） |
| `/exit` `/quit` | 退出（Ctrl+C 也可以） |

[![npm version](https://img.shields.io/npm/v/@raolin2025/claude-code-node.svg)](https://www.npmjs.com/package/@raolin2025/claude-code-node) [![GitHub](https://img.shields.io/badge/GitHub-bg1avd%2Fclaude--code--node-blue)](https://github.com/bg1avd/claude-code-node) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
---

## 🧠 上下文窗口感知（自动压缩）

cc-node 会自动感知当前所用模型的**上下文窗口长度**，并在接近上限时**自动压缩**对话历史，
确保上下文**永不超出**模型窗口。

### 窗口来源优先级

| 优先级 | 来源 | 说明 |
|--------|------|------|
| 1 | **手动指定**（`/window N`） | 持久化到 config，每次启动优先采用 |
| 2 | **API 探测** | 从 `GET /models` 响应提取（vLLM `context_length`、Ollama `model_info` 等） |
| 3 | **内置模型表** | 内置 40+ 常见模型上下文表（DeepSeek/OpenAI/Qwen/GLM/Kimi 等） |
| 4 | **安全兜底** | 64K（探测不到且表里没有时） |

> 探测结果**不落盘**，每次启动重新探测；只有 `/window N` 手动指定才会持久化（方案 A）。
> 探测不精确时，用 `/window N` 手动纠正即可。

### 自动压缩机制（滑动窗口）

上下文**永不超出窗口**，采用"条数折叠 + 摘要优先 + 滑动窗口裁剪兜底"的多层策略：

**0. 发送前常驻工具结果截断**（v2.8.12）：每次发送前（不依赖是否超窗）对**超长工具结果**
（默认 >6000 字符）做截断，从源头压住"工具结果过程噪音"堆积，避免它们淹没模型对最新
指令的注意力。

**1. 消息条数折叠**（v2.8.12，`--max-messages N` 开启，默认关闭）：当上下文**消息条数**
超过 `N`（如 80）时，把早期历史折叠成一条摘要（保留 `Main goal` / 工具使用 / 关键结果），
仅保留最近 4 轮完整对话。这解决**本地小模型（如 27B）"token 未超窗但 200+ 条消息却变傻、
不干活"**的问题——这类模型对"消息条数"比"token 数"更敏感。

**2. 摘要式压缩**（信息量更高）：每次新消息加入 / 工具结果返回 / 发送前，用**实时 token
   估算**判断是否超窗；超窗时把早期对话压缩为摘要（保留最近 4 轮 + 摘要），目标压到窗口
   的 60%。摘要会**显式标注最早的 `Main goal`（核心任务主线）**，并保留最早的关键发现与
   最新结果，避免例行内容淹没核心任务（防止 AI 压缩后失忆）。
   > **保守触发（v2.8.11）**：由于启发式估算可能比模型真实 token 偏少，压缩**提前到
   > 可用窗口的 85%** 即触发（`compressSafetyFactor`，默认 0.85），给 tokenization 差异
   > 留余量，避免实际请求超过模型窗口（如 `exceed_context_size_error` 400 错误）。
**3. 滑动窗口精确裁剪**（兜底，保证永不超窗）：摘要压缩后仍超窗时，从**最早的消息**逐条
   挤出，**最新信息始终保留在末尾**，直到总 token ≤ 窗口上限。system 提示永不裁剪；
   **被裁剪的早期历史会压缩成一条摘要 system 保留**（避免 AI 丢失上下文主线）；极端情况
   （单条消息超窗）仍保留 system + 最近一条，保证至少能发出请求。

> 正是这个滑动窗口机制解决了"上下文满了之后新信息无法输入"的问题——窗口满时自动
> 挤出最早的对话（并保留摘要），让最新消息总能拼接进去、AI 也不会失忆。

### `/window` 命令用法

```
/window              → 查看当前窗口 + 来源 + 用量
/window 128k         → 手动指定 128K（持久化到 config）
/window 64k          → 手动指定 64K
/window 1m           → 手动指定 100 万
/window auto         → 清除手动指定，回到自动探测
/window reset        → 清除手动指定并立即重探测
```

> 切换模型（`/model`）后会自动重新探测窗口。`/budget` 也会显示当前窗口与 80% 触发阈值。

### 📤 单次输出上限（max_tokens）动态计算

cc-node 的**单次响应输出上限**（`max_tokens`）不再写死 4096，而是**根据上下文窗口大小动态计算**：

```
max_tokens = max(4096, 窗口大小 × 1/16)，且不超过窗口的一半
```

| 窗口 | 动态输出上限 |
|------|-------------|
| 65536 (64K) | 4096 |
| 131072 (128K) | **8192** |
| 200000 | 12500 |

这样窗口越大，单次输出空间越大，避免小模型 Write 大文件时被截断；同时输出**绝不超过窗口一半**，保证输入有足够空间、永不超窗。

> 可用 `--max-output-tokens N` 或 `config.maxOutputTokens` 覆盖（作为输出下限）。

### 🤖 小模型适配模式（--small-model）

> 专为 **本地小模型**（如 27B Q3 量化）设计，让编程工具在弱模型下也能可靠工作。
> 默认关闭，通过 `--small-model` 或 `config.smallModel=true` 开启。

小模型的核心弱点是"规划 + 工具调用 + 自我纠错"不稳定——常只回 `Solved by sharing best practices.`
这类空话、不调工具，或多轮往返后"丢"了目标。该模式把智能从"模型端"转移到"框架端"：

| 层 | 机制 | 作用 |
|----|------|------|
| **A · 兜底** | 强化 system prompt | 明确告诉模型"必须调用工具完成任务，不能只回文字" |
| **A · 兜底** | 敷衍输出检测 + 重试 | 检测到空话/太短/无工具调用时，追加强引导重试一次 |
| **A · 兜底** | 工具数量精简 | 按用户指令意图只暴露核心工具子集，降低选择负担 |
| **B · 替代** | 意图识别 + 引导 | 用规则把"写文档/找文件/跑命令/改代码"映射到明确工具，注入任务引导 |

```bash
cc-node --api-base http://127.0.0.1:18080/v1 --model ./local-model.gguf \
  --with-notify --small-model --max-messages 80
```

> **配合 `--max-messages N`**：两者互补——`--max-messages` 解决"条数过多"，
> `--small-model` 解决"模型不会自主调工具"。小模型场景建议一起开启。

> **自动清空 LLM 缓存（针对本地服务 500）**：工作几轮后报 `500`（llama.cpp
> `System message must be at the beginning`）的真正根因，是 **LLM 端 KV/prompt 缓存
> 无限叠加被塞满**——即便 cc-node 端 compact 后 context 变小，LLM 端旧的大 context
> 仍占着缓存导致新请求被拒。开启 `--small-model` 后：
> 1. 每个用户任务开始时自动向本地服务发一次轻量"清缓存"请求；
> 2. 每个 LLM 请求体带 `cache_prompt:false`，让本地服务（llama.cpp/Ollama/vLLM）
>    本轮不复用、不累积上一次的 prompt 缓存，每次都全新计算——等价于"每轮清空缓存"。
> 同时把所有 system 消息**合并为单条**放在开头，彻底消除 `system=2` 触发 Jinja 报错。

---

## 🛠️ 内置工具（10 个）

| 工具 | 说明 | 权限级别 | 安全检查 |
|------|------|---------|---------|
| **Bash** | 执行 shell 命令 | `ask` | ✅ 命令安全扫描 |
| **Read** | 读取文件 | `always-allow` | ✅ 路径安全检查 |
| **Edit** | 精确文本替换编辑 | `ask` | ✅ 写入路径安全 |
| **Write** | 创建/覆盖文件 | `ask` | ✅ 写入路径安全 |
| **Glob** | 文件模式搜索 | `always-allow` | — |
| **Grep** | 内容搜索（rg/grep） | `always-allow` | — |
| **WebFetch** | 抓取网页内容（安全管道 + Jina 兜底） | `ask` | ✅ SSRF + 重定向 + 脱敏 |
| **WebSearch** | 网页搜索 | `ask` | 需 API Key；可改接配套的免 Key 搜索 MCP「[mcp-search-server](https://github.com/bg1avd/mcp-search-server)」 |
| **GitTool** | GitHub PR 自动化（审查/合并/评论） | `high` | ✅ 预检查 |
| **NpmPublish** | npm 发布一键工具（版本/打包/发布） | `ask` | ✅ token 校验 |
| **AskUserQuestion** | 向用户提问 | `always-allow` | — |

[![npm version](https://img.shields.io/npm/v/@raolin2025/claude-code-node.svg)](https://www.npmjs.com/package/@raolin2025/claude-code-node) [![GitHub](https://img.shields.io/badge/GitHub-bg1avd%2Fclaude--code--node-blue)](https://github.com/bg1avd/claude-code-node) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
---

## 🔒 安全架构

本项目包含 **4 层安全防护**，总计 **964 行安全代码**：

### 1️⃣ SSRF 防护（178 行）
阻止 LLM 通过 WebFetch 访问内网和云元数据：

```
🚫 10.0.0.0/8          — 私有网络
🚫 172.16.0.0/12       — 私有网络
🚫 192.168.0.0/16      — 私有网络
🚫 169.254.0.0/16      — AWS/GCP 元数据
🚫 100.64.0.0/10       — 阿里云元数据 (100.100.100.200)
🚫 fc00::/7            — IPv6 唯一本地
🚫 fe80::/10           — IPv6 链路本地
✅ 127.0.0.0/8         — 回环（允许，本地开发）
✅ ::1                 — IPv6 回环
```

### 🕸️ WebFetch 安全抓取（安全管道 + Jina 兜底）

`WebFetch` 内置完整安全管道（移植自 safe-jina-fetch 设计，`src/security/fetch-guard.js`）：

- **协议白名单**：仅 `http/https`，拒绝 `file://`、`ftp://`、`data:` 等
- **连接级 SSRF**：TCP 连接建立时对全部解析地址逐一校验（防 DNS rebinding），
  并对 IP 字面量前置校验（Node 对 IP 不走 DNS lookup，必须显式拦截）
- **重定向逐跳校验**：默认最多 5 跳，每跳重新校验协议 + SSRF（防 302 → 内网绕过）
- **响应大小上限**：10MB；**超时**：30s；**强制 SSL**（证书错误直接拒绝）
- **敏感数据自动脱敏**：API Key / Bearer / AWS Key / 私钥 / OpenAI `sk-` / Slack token 等
  命中即替换为 `[REDACTED:类型]` 并告警（`src/security/redact.js`）

**Jina Reader 兜底**（`src/tools/web-fetch-providers.js`）：

- 直连失败（403 / 反爬 / 网络错误 / 超时）时，自动经 `r.jina.ai` 清洗后返回 Markdown
- 直连返回 200 但正文 < 200 字符（疑似 JS 挑战页，如豆瓣）也触发兜底
- `extractMode` 参数：`auto`（默认，直连优先 + 兜底）/ `direct`（强制直连）/ `jina`（强制 Jina）
- Jina 凭据三选一（可选，匿名约 20 RPM）：环境变量 `JINA_API_KEY` > 配置 `web.fetch.jinaApiKey` > 匿名

### 2️⃣ Bash 命令安全（279 行）
阻止 LLM 执行危险 shell 命令：
| 类别 | 示例 | 严重性 |
|------|------|--------|
| 破坏性操作 | `rm -rf /`, `dd of=/dev/sda`, `mkfs` | 🚫 CRITICAL |
| 敏感文件访问 | `cat /etc/shadow`, `~/.ssh/id_rsa` | 🚫 CRITICAL/HIGH |
| 远程执行 | `curl \| bash`, `wget \| sh` | 🚫 CRITICAL |
| 提权 | `sudo su`, `pkexec` | ⚠️ HIGH |
| 容器逃逸 | `nsenter --target 1`, 特权 docker | 🚫 CRITICAL |
| 内网数据外泄 | `curl http://192.168.x.x` | 🚫 CRITICAL |
| 系统重定向 | `> /etc/hosts` | 🚫 CRITICAL |

### 3️⃣ 路径安全防护（190 行）
防止 LLM 访问/修改敏感文件：

- **路径遍历检测** — `../../../etc/passwd` → 阻止
- **SSH 密钥保护** — 禁止读取 `~/.ssh/id_*` 私钥
- **系统目录写入保护** — 禁止写 `/etc/`, `/boot/`, `/usr/bin/`
- **敏感路径列表** — `/etc/shadow`, `/etc/sudoers` 等

### 4️⃣ 增强权限系统（310 行）

```mermaid
graph TD
    A[工具调用请求] --> B{安全检查}
    B -->|🚫 不安全| C[直接拒绝]
    B -->|✅ 安全| D{规则匹配}
    D -->|DENY 规则| C
    D -->|ALLOW 规则| E[执行工具]
    D -->|无匹配| F{权限模式}
    F -->|ask| G[请求用户确认]
    F -->|always-allow| E
    F -->|deny| C
    C --> H[审计日志]
    E --> H
    G --> H
```

特性：
- **规则持久化** — 保存到 `.claude-code/permissions.json`
- **审计日志** — 记录到 `.claude-code/audit.log`
- **安全一票否决** — 即使规则允许，安全检查不通过仍拒绝

[![npm version](https://img.shields.io/npm/v/@raolin2025/claude-code-node.svg)](https://www.npmjs.com/package/@raolin2025/claude-code-node) [![GitHub](https://img.shields.io/badge/GitHub-bg1avd%2Fclaude--code--node-blue)](https://github.com/bg1avd/claude-code-node) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
---

## 🌐 API — OpenAI 兼容协议（全行业通用）

### DeepSeek（默认）
```bash
export DEEPSEEK_API_KEY=your_key_here
cc-node
```

### 其他 OpenAI 兼容提供商
```bash
# 通义千问
export LLM_API_KEY=your_key_here
cc-node --model qwen-plus --api-base https://dashscope.aliyuncs.com/compatible-mode/v1

# 智谱 GLM
cc-node --model glm-4-flash --api-base https://open.bigmodel.cn/api/paas/v4

# Moonshot Kimi
cc-node --model kimi-k2-0711 --api-base https://api.moonshot.cn/v1

# OpenAI
cc-node --model gpt-4o --api-base https://api.openai.com/v1

# Ollama / 自建本地服务（Ollama / llama.cpp / vLLM 等）
# 指向 localhost 或内网地址时【无需 apiKey】，直接可用
cc-node --api-base http://localhost:11434/v1 --model qwen2.5

# 内网自建服务（局域网 IP，同样无需 apiKey）
# 将 <内网IP> 替换为你的服务器地址，如 192.168.x.x
cc-node --api-base http://<内网IP>:11434/v1 --model qwen3.6:27b

# 未指定模型 → 自动拉取服务端 /models 列表供交互选择
cc-node --api-base http://localhost:11434/v1
```

> 💡 **自建本地服务支持**：cc-node 会自动识别 apiBase 指向本地/内网
> （`localhost`、回环、`192.168.x` / `10.x` / `172.16-31.x` 私有段、`.local` 域名）
> 的自建 LLM 服务（Ollama、llama.cpp、vLLM 等 OpenAI 兼容端点），
> 此类服务**无需 apiKey 也能正常调用**，且不会强制附加 `Bearer undefined` 头。
> 云端厂商（DeepSeek/OpenAI/Kimi 等）仍需 apiKey。

[![npm version](https://img.shields.io/npm/v/@raolin2025/claude-code-node.svg)](https://www.npmjs.com/package/@raolin2025/claude-code-node) [![GitHub](https://img.shields.io/badge/GitHub-bg1avd%2Fclaude--code--node-blue)](https://github.com/bg1avd/claude-code-node) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
---

## 📂 配置文件

### 项目级
`.claude-code/config.json` — 存放在项目根目录

### 用户级
`~/.claude-code/config.json` — 全局默认配置

### 配置项

```json
{
  "model": "deepseek-flash",
  "maxTurns": 100,
  "maxBudgetTokens": 128000,
  "maxMessages": 80,
  "smallModel": true,
  "permissionMode": "ask",
  "tools": {
    "bash": { "timeout": 120 },
    "fileRead": { "maxLines": 2000 },
    "webFetch": { "timeout": 30 }
  },
  "mcp": {
    "servers": {}
  }
}
```

> **`maxBudgetTokens`**：手动指定的上下文窗口上限（token 数）。
> 为 `0` 或未设置时，自动探测模型真实窗口；手动指定后优先于自动探测，
> 等价于 `/window N` 的效果，并持久化保存。
>
> **`maxMessages`**：消息条数上限（可选，默认关闭/`0`）。当上下文消息条数超过该值时，
> 自动折叠早期历史为摘要（保留 Main goal + 最近 4 轮完整对话），解决本地小模型
> "条数过多、token 不高却变傻"的问题。等价于 `--max-messages N`。
>
> **`smallModel`**：小模型适配模式（可选，默认关闭/`false`）。开启后启用强制工具调用
> 引导、敷衍输出检测重试、意图识别 + 工具精简，让弱模型（如 27B Q3 量化）也能可靠
> 完成编程任务；并针对自建本地服务（llama.cpp/Ollama/vLLM）**每轮自动清空 LLM 缓存**
> （`cache_prompt:false` + 合并 system 为单条），根治"工作几轮后 500"。
> 等价于 `--small-model`。

[![npm version](https://img.shields.io/npm/v/@raolin2025/claude-code-node.svg)](https://www.npmjs.com/package/@raolin2025/claude-code-node) [![GitHub](https://img.shields.io/badge/GitHub-bg1avd%2Fclaude--code--node-blue)](https://github.com/bg1avd/claude-code-node) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
---

## 🔌 MCP 客户端 / 接入 MCP 服务器

cc-node 可作为 **MCP 客户端**，通过 Model Context Protocol 连接外部 MCP 服务器，把它们暴露的**工具接入运行时工具表**，让模型可直接调用。支持 **stdio** 与 **远程 HTTP(streamable)** 两种传输。

### 快速上手：在配置里声明即可用

在 `.claude-code/config.json` 加一段 `mcp.servers`，**无需改任何代码**，cc-node 启动时自动连接并把工具注入工具表；不配置就完全不生效：

```jsonc
{
  "mcp": {
    "servers": {
      "search": {                 // 任意名字，会变成工具前缀 "search:search"
        "type": "http",           // 远程 HTTP(streamable) 传输
        "url": "https://search.example.com/mcp",
        "token": "你的 API key"    // 作为 Authorization: Bearer 原样透传
      }
      // 例如要接 stdio 本地 MCP：
      // "fs": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem"], "env": {} }
    }
  }
}
```

启动后运行 `/tools` 即可看到来自 MCP 的工具（命名 `<服务器名>:<工具名>`，如 `search:search`）。
工具仍走常规 `ask` 权限确认流，不会绕过安全模型。某个 MCP 连不上时会告警跳过，**绝不阻塞启动或崩溃**。

### 到哪里去找 MCP 服务器软件

先确认你想要的"工具"，再到官方/社区仓库搜对应 MCP：

- **MCP 官方汇总**：<https://modelcontextprotocol.io> — 协议规范 + 官方参考实现
- **官方/精选 MCP 服务器列表**
  `Awesome MCP Servers`（GitHub）：<https://github.com/punkpeye/awesome-mcp-servers> —
  收录了大量现成 server：filesystem、github、postgres、fetch、slack、memory 等
- **npm 搜包**：多数用 `npx <pkg>` 即可启动 → `npm search mcp`，或查官方 registry。
  常见的现成 MCP（`npx`/stdio 直接可用）：
  - 文件系统 `@modelcontextprotocol/server-filesystem`
  - Git `@modelcontextprotocol/server-github`（需 token）
  - 搜索类也有多个社区实现，但多数要自己的 API key
- 若要**免 API key 的网页搜索**：见下方"配套搜索服务器"，两行命令即可自建。

### 配套的搜索服务器 mcp-search-server（免搜索引擎 API key，独立仓库）

搜索类 MCP 服务器**常用但多数要 API key**。你要是也想要"零搜索成本、能放外网搜索节点上"的，
本生态配套一个独立仓库：

> **[mcp-search-server](https://github.com/bg1avd/mcp-search-server)** —— 零依赖、独立部署、
> 带 **API key 鉴权**、**streamable HTTP**。搜索后端默认接**自建 SearXNG**（聚合并回退 Bing），规避
> 数据中心 IP 被单引擎验证码封禁的问题（见该仓库 README 的实测与路由说明）。

建议架构：**SearXNG(独自/容器) ← mcp-search-server(负责鉴权+对 cc-node) ← cc-node(客户端)**。

```bash
# 0) (可选) 先起一个 SearXNG 当搜索后端 —— 或让 mcp-search-server 自动回退到 Bing
#推荐 docker 跑 SearXNG，再让 mcp-search-server 指过去。
docker run -d --name searxng -p 127.0.0.1:8809:8080 searxng/searxng:latest

# 1) 生成 API key（明文只打印一次，落盘只存 sha256 摘要）
cd mcp-search-server && node src/cli.js keygen --file ./apikeys.json

# 2) 启动服务器（指向 SearXNG + 用刚生成的 key）
node src/cli.js serve --port 7397 --host 0.0.0.0 \
     --searxng-url http://127.0.0.1:8809 \
     --api-keys-file ./apikeys.json
```

然后 cc-node 的 `mcp.servers` 指向 `http://<服务器>:7397/mcp`，token 填第 1 步打印的 key 即可。
完整架设步骤、Cloudflare/Nginx 反代、搜到的实际效果见该仓库 README。

### 程序化接入（进阶）

若不通过 config、希望代码里动态装工具，可用：

```javascript
import { loadMcpToolsFromConfig } from './src/mcp/loadTools.js'
const { tools, registry } = await loadMcpToolsFromConfig(config)  // tools: ToolDef[]
for (const t of tools) registryOfAgent.register(t)                 // 并入你的 ToolRegistry
```



[![npm version](https://img.shields.io/npm/v/@raolin2025/claude-code-node.svg)](https://www.npmjs.com/package/@raolin2025/claude-code-node) [![GitHub](https://img.shields.io/badge/GitHub-bg1avd%2Fclaude--code--node-blue)](https://github.com/bg1avd/claude-code-node) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
---

## 📊 项目结构

```
claude-code-node/              33 文件 · 4307 行
├── src/
│   ├── core/                  1279 行 — 引擎、CLI、会话、配置
│   ├── tools/                  944 行 — 10 个内置工具
│   ├── security/               964 行 — 4 层安全防护
│   ├── utils/                  544 行 — 差异、文件、进程、格式
│   ├── mcp/                    385 行 — MCP 客户端+注册表
│   ├── types/                  125 行 — 类型定义
│   ├── permission/              37 行 — 基础权限（兼容）
│   └── index.js                  8 行 — 入口
└── package.json
```

[![npm version](https://img.shields.io/npm/v/@raolin2025/claude-code-node.svg)](https://www.npmjs.com/package/@raolin2025/claude-code-node) [![GitHub](https://img.shields.io/badge/GitHub-bg1avd%2Fclaude--code--node-blue)](https://github.com/bg1avd/claude-code-node) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
---

## ⚠️ 安全注意事项

1. **始终使用 `ask` 权限模式** — 除非你完全信任 LLM 输出
2. **不要暴露 API Key** — 使用环境变量，不要硬编码
3. **WebSearch 需要单独配置** — 设置 `BRAVE_SEARCH_API_KEY` 或 `GOOGLE_SEARCH_API_KEY`
4. **审计日志定期审查** — 检查 `.claude-code/audit.log` 中的 DENY 记录
5. **安全规则可持久化** — 使用 `/allow` 命令添加会话级规则

[![npm version](https://img.shields.io/npm/v/@raolin2025/claude-code-node.svg)](https://www.npmjs.com/package/@raolin2025/claude-code-node) [![GitHub](https://img.shields.io/badge/GitHub-bg1avd%2Fclaude--code--node-blue)](https://github.com/bg1avd/claude-code-node) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
---

## 🔧 与原 Claude Code 的对比

| 特性 | 原版 (TypeScript/Bun) | 本版 (Node.js) |
|------|----------------------|----------------|
| 运行时 | Bun | Node.js ≥ 18 |
| 语言 | TypeScript | JavaScript (ESM) |
| 依赖 | ~200 npm 包 | **0 外部依赖** |
| 代码量 | 512,000+ 行 | 4,307 行 |
| 工具数 | ~40 | 10（核心） |
| API 协议 | Anthropic | **OpenAI 兼容（全行业通用）** |
| SSRF 防护 | ✅ | ✅ |
| 命令安全 | ✅ (2592行) | ✅ (279行) |
| 路径安全 | ✅ | ✅ |
| 审计日志 | ✅ | ✅ |
| MCP 支持 | ✅ 完整 | ✅ 简化版 |
| 流式响应 | ✅ | ✅ |
| 会话管理 | ✅ | ✅ |
| UI | Ink (React CLI) | 纯 readline |

[![npm version](https://img.shields.io/npm/v/@raolin2025/claude-code-node.svg)](https://www.npmjs.com/package/@raolin2025/claude-code-node) [![GitHub](https://img.shields.io/badge/GitHub-bg1avd%2Fclaude--code--node-blue)](https://github.com/bg1avd/claude-code-node) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
---

*基于 Claude Code 架构的 OpenAI 兼容重构*  
*零外部依赖 · DeepSeek 默认 · 安全加固 · MIT License*

## 📡 通讯通道 (Notification Channels)

cc-node 通过 **Telegram** 消息推送，任务完成或出错时自动通知到手机，并支持远程编程。

### 支持的通道

| 通道 | 配置方式 | 说明 |
|------|----------|------|
| **Telegram** | Bot Token + Chat ID | 唯一支持通道，支持富媒体、Markdown、远程编程 |

### 快速配置 (Telegram)

```bash
# 1. 在 Telegram 找 @BotFather 创建 Bot，拿到 Token
# 2. 获取你的 Chat ID（给 Bot 发消息后访问 https://api.telegram.org/bot<TOKEN>/getUpdates）
# 3. 设置环境变量
export CC_NODE_CHANNEL_TELEGRAM_TOKEN=123456:ABC-DEF
export CC_NODE_CHANNEL_TELEGRAM_CHAT_ID=78901234
export CC_NODE_CHANNEL_DEFAULT=telegram

# 4. 启动 cc-node，会自动加载
cc-node
```

### 配置文件方式

在 `.claude-code/config.json` 中：

```json
{
  "channels": {
    "telegram": {
      "type": "telegram",
      "token": "123456:ABC-DEF",
      "chatId": "78901234"
    }
  },
  "defaultChannel": "telegram"
}
```

### REPL 命令

```
/channel list           — 列出已配置通道
/channel test           — 测试通道连通性
/channel send hello     — 手动发送消息
```

### 通知时机

- ✅ **任务完成**（one-shot 模式自动通知）
- ❌ **执行出错**（自动通知错误内容）
- 🔄 **手动发送**（`/channel send` 命令）

## 📱 Telegram 远端编程（v2.0 新增）

通过 Telegram Bot API 实现远程编程控制。独立、零依赖、无需 OpenClaw。

### 前置配置

1. 在 Telegram 中与 [@BotFather](https://t.me/BotFather) 对话，创建机器人并获取 **Bot Token**
2. 与机器人发起对话，获取你的 **Chat ID**（数字，可用 `/getUpdates` 查看）
3. 配置环境变量：

```bash
export CC_NODE_CHANNEL_TELEGRAM_TOKEN=你的BotToken
export CC_NODE_CHANNEL_TELEGRAM_CHAT_ID=你的ChatID
# 可选：走代理（如网络受限）
# export CC_NODE_CHANNEL_TELEGRAM_PROXY=127.0.0.1:1080
```

### 使用方式

启动 cc-notify 后，直接在 Telegram 里给机器人发消息：

```
帮我写一个快速排序
/ping
/status
/run ls -la
/notify 任务完成！
```

### 技术架构

```
Telegram消息 → Bot API 长轮询(getUpdates) → cc-notify → cc-node
cc-node → cc-notify → Telegram Bot API (api.telegram.org/bot<token>) → Telegram消息
```

- **认证**: `Bot Token` 认证（`Bearer <token>`）
- **发送**: `sendMessage` / `sendPhoto` / `sendVideo` / `sendAudio` / `sendDocument`
- **接收**: 长轮询 `getUpdates`（offset 持久化，重启不重放）
- **富媒体**: 支持图片、视频、音频、文件上传
- **定时提醒**: 集成调度系统，支持相对时间 / cron 表达式
- **参考**: `src/channel/tg-listener.js`、`src/tools/telegram-tools.js`

---

## 🔔 后台运行 (cc-notify v2.0)

cc-notify 是独立的通知守护进程，**不需要 cc-node 在前台运行**，开机自启后随时可用。
支持 **Telegram** 远程编程。

### v2.0 新特性

- ✅ **Telegram 监听** — 速率限制、Markdown 安全编码、多轮对话
- ✅ **统一消息处理器** — Telegram 通道共享同一路由逻辑
- ✅ **长消息分段** — 自动切分超过 4000 字符的回复
- ✅ **API Key 持久化** — 自动生成并保存，重启不丢失

### 三种运行方式

| 方式 | 命令 | 说明 |
|------|------|------|
| **前台** | `cc-notify` | 调试用，Ctrl+C 退出 |
| **后台守护** | `cc-notify --daemon` | 脱离终端后台运行 |
| **系统服务** | `systemctl start cc-notify` | 开机自启，最推荐 |

### 手机交互

在 Telegram 上给 Bot 发消息：

```
你好                     → 当作一次性任务发给 cc-node 执行
/ping                    → 检查服务是否在线
/run ls -la              → 执行 shell 命令
/notify 任务完成！       → 通过 Telegram 广播通知
/status                  → 查看服务状态
/cancel                  → 取消当前操作
/help                    → 查看完整帮助（含 AI 编程命令）
/model gpt-4o            → 切换模型
/window 128k             → 设置上下文窗口
/budget                  → 查看 token 预算
/compact                 → 压缩上下文
/clear                   → 清空对话
```

> 除上述系统命令外，所有 `/help` 列出的 AI 编程命令（`/model`、`/window`、`/budget`、
> `/compact`、`/clear`、`/sessions`、`/config`、`/cost`、`/cd`、`/tools`、`/stop`、`/allow`
> 等）都会自动转发给 cc-node 处理，结果回发到 Telegram。`/help <命令>` 可查看详细用法。

### HTTP API（守护模式可用）

```bash
# 发送通知
curl -X POST http://localhost:3456/send \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: <你的API_Key>' \
  -d '{"text":"构建完成 ✅"}'

# 远程编程
curl -X POST http://localhost:3456/chat \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: <你的API_Key>' \
  -d '{"text":"帮我查下当前目录"}'

# 查看状态（无需 API Key）
curl http://localhost:3456/status
```

### systemd 开机自启

```bash
# 安装服务
sudo cp cc-notify.service /etc/systemd/system/
# 编辑 Token
sudo vim /etc/systemd/system/cc-notify.service
# 启用
sudo systemctl daemon-reload
sudo systemctl enable cc-notify
sudo systemctl start cc-notify

# 查看日志
journalctl -u cc-notify -f
```

## 🔧 GitTool - PR 自动化管理

GitTool 是 GitHub PR 自动化管理工具，支持查看、审查、合并 PR，以及批量操作和智能分析。

### 前置配置

```bash
# 1. 创建 GitHub Personal Access Token (classic, 有 repo 权限)
export GITHUB_TOKEN=ghp_xxx

# 2. 设置仓库信息
export GITHUB_OWNER=your_org
export GITHUB_REPO=your_repo

# 可选：启用 LLM 智能分析
export DEEPSEEK_API_KEY=sk-xxx
export DEEPSEEK_API_BASE=https://api.deepseek.com/v1
```

或在 `~/.claude-code/config.json` 中配置：

```json
{
  "github": {
    "owner": "your_org",
    "repo": "your_repo"
  },
  "llm": {
    "apiKey": "sk-xxx",
    "apiBase": "https://api.deepseek.com/v1",
    "model": "deepseek-flash"
  },
  "reviewRules": {
    "checks": {
      "codeQuality": true,
      "security": true,
      "tests": true,
      "docs": true
    }
  }
}
```

### 使用示例

在 REPL 中调用 GitTool：

```
/GitTool list-prs
/GitTool review-pr 123 --auto-comment false
/GitTool check-mergeable 123
/GitTool approve 123 "Looks good"
/GitTool merge-pr 123 --method squash
```

命令行脚本（`test-git-tool.mjs`）:

```bash
# 列出 PR
node test-git-tool.mjs list

# 审查 PR（规则检查，无 LLM）
node test-git-tool.mjs review 123

# 使用 LLM 智能分析
DEEPSEEK_API_KEY=sk-xxx node test-git-tool.mjs review-llm 123

# 检查可合并性
node test-git-tool.mjs check-mergeable 123

# Approve PR
node test-git-tool.mjs approve 123 "Approved"

# 提交审查意见
node test-git-tool.mjs comment 123 "Please add tests"

# 行级评论（自动计算 diff position）
node test-git-tool.mjs comment 123 "Fix needed" --path src/index.js --line 42
```

### 自动化工作流

- **每日自动审查**: 设置 cron 运行 `auto-review-all`
- **自动合并**: 为满足条件的 PR 添加 `auto-merge` 标签，运行 `auto-merge-eligible`
- **集成 OpenClaw Heartbeat**: 通过 `cron` 工具定期执行

```bash
# 每天 10:00 自动审查所有 PR
cron add "0 10 * * *" "session:git-automation" \
  --payload '{"kind":"agentTurn","message":"/GitTool auto-review-all"}'
```

### 合并策略

PRMergePolicy 支持以下检查（可配置）：

- ✅ 最少 Approvals 数量
- ✅ CI 状态全部通过
- ✅ 无 `changes_requested`
- ✅ 分支保护规则
- ✅ 自动合并标签（如 `auto-merge`）
- ✅ 合并冲突检测

### 安全与权限

- GitTool 工具注册为 `high` 权限级别（合并操作需要确认）
- 操作会被记录在审计日志中
- 禁止合并到受保护分支（main/master）

### 与 OpenClaw 集成

- GitTool 已内置到 cc-node 工具集中
- 可通过 `/tools` 查看
- 审查结果可与 Telegram 通道集成，发送通知



