Proxy 与 Native 模块
目录: src/proxy/、src/native/
这两个目录处理 网络代理 和 原生代码集成——企业/性能场景必备。
Proxy 模块
为什么需要代理?
企业网络常有HTTP 代理:
- 安全审计 — 所有出站流量通过代理
- 访问控制 — 白名单域名
- 缓存 — 省带宽
Claude Code 要能透过代理访问 Anthropic API。
代理配置
# 环境变量(标准)
export HTTPS_PROXY=http://proxy.company.com:8080
export NO_PROXY=localhost,127.0.0.1,*.internal
# 或 config
claude config set proxy.https http://proxy:8080
代理实现
// proxy/agent.ts
import { HttpsProxyAgent } from 'https-proxy-agent'
function getProxyAgent(url: string): Agent | undefined {
const proxy = process.env.HTTPS_PROXY ?? config.proxy?.https
if (!proxy) return undefined
// 检查 NO_PROXY
const hostname = new URL(url).hostname
const noProxy = (process.env.NO_PROXY ?? '').split(',')
if (noProxy.some(p => matchDomain(hostname, p))) return undefined
return new HttpsProxyAgent(proxy)
}
// 用法
const agent = getProxyAgent('https://api.anthropic.com')
fetch(url, { agent })
PAC(Proxy Auto-Config)
某些企业用 PAC 脚本动态决定代理:
// proxy.pac
function FindProxyForURL(url, host) {
if (host === 'api.anthropic.com') {
return 'PROXY proxy.company.com:8080'
}
return 'DIRECT'
}
import pacProxyAgent from 'pac-proxy-agent'
const agent = new PacProxyAgent('http://pac.company.com/proxy.pac')
代理认证
// 基础认证
const proxy = 'http://user:pass@proxy.company.com:8080'
// NTLM(Windows 企业)
import { HttpsProxyAgent } from 'https-proxy-agent'
import { NtlmClient } from 'ntlm-client'
SSL/TLS 考量
// 企业 CA 证书
https.globalAgent.options.ca = [
...tls.rootCertificates,
fs.readFileSync('/etc/ssl/company-ca.pem')
]
// 或配置
export NODE_EXTRA_CA_CERTS=/etc/ssl/company-ca.pem
代理诊断
claude proxy diagnose
输出:
Proxy Configuration:
HTTPS_PROXY: http://proxy.company.com:8080
HTTP_PROXY: (not set)
NO_PROXY: localhost,*.internal
Testing proxy:
→ Connect to proxy.company.com:8080 ... OK
→ Tunnel to api.anthropic.com:443 ... OK
→ Certificate valid ... OK
→ API reachable ... OK
Tests passed.
启动前诊断节省大量 debug 时间。
Native 模块
为什么需要原生代码?
某些功能纯 JS 太慢或无法实现:
- Tree-sitter — C 语言解析器,高性能
- 文件监控 — 平台原生 API(FSEvents/inotify)
- 键盘捕获 — 底层 TTY 操作
- 加密 — 硬件加速
原生依赖
// package.json
{
"dependencies": {
"tree-sitter": "^0.21.0",
"tree-sitter-bash": "^0.21.0",
"node-pty": "^1.0.0",
"chokidar": "^3.6.0",
"@napi-rs/keyring": "^1.1.0"
}
}
Tree-sitter
// native/treeSitter.ts
import Parser from 'tree-sitter'
import Bash from 'tree-sitter-bash'
import JavaScript from 'tree-sitter-javascript'
import TypeScript from 'tree-sitter-typescript'
const parsers = new Map<string, Parser>()
export function getParser(lang: string): Parser {
if (!parsers.has(lang)) {
const parser = new Parser()
parser.setLanguage(loadLanguage(lang))
parsers.set(lang, parser)
}
return parsers.get(lang)!
}
详见 utils/bash-security 的 AST 解析章节。
node-pty
真正的 PTY(pseudo-terminal)——比 spawn 更像真终端:
import * as pty from 'node-pty'
const shell = pty.spawn('bash', [], {
name: 'xterm-color',
cols: 80,
rows: 30,
cwd: process.cwd(),
env: process.env
})
shell.onData(data => process.stdout.write(data))
shell.write('ls\r')
对交互式程序(vim、top)必需 — 普通 spawn 不行。
keyring
OS 原生密钥存储:
import { Entry } from '@napi-rs/keyring'
const entry = new Entry('claude-code', 'anthropic-token')
// 保存
entry.setPassword('sk-ant-...')
// 读取
const token = entry.getPassword()
// 删除
entry.deletePassword()
不同 OS 用不同存储:
- macOS: Keychain
- Windows: Credential Manager
- Linux: libsecret
文件监控
import chokidar from 'chokidar'
chokidar.watch('src/**/*.ts', {
ignored: /node_modules/,
persistent: true
}).on('change', (path) => {
console.log(`Changed: ${path}`)
})
chokidar 内部用 FSEvents (macOS) / inotify (Linux) / ReadDirectoryChangesW (Windows)。
原生模块的打包问题
Bun bundle 时原生模块不能打包进单文件:
my-app.js (4MB)
+ node_modules/tree-sitter/build/Release/*.node
+ node_modules/node-pty/build/Release/*.node
+ ...
解决方案:
// 发布时包含原生模块
import path from 'path'
import { createRequire } from 'module'
const require = createRequire(import.meta.url)
const treeSitter = require(path.join(
process.env.CLAUDE_RUNTIME_DIR,
'tree-sitter.node'
))
跨平台构建
// package.json scripts
{
"build:darwin-arm64": "pkg . --target darwin-arm64 ...",
"build:darwin-x64": "pkg . --target darwin-x64 ...",
"build:linux-x64": "pkg . --target linux-x64 ...",
"build:win32-x64": "pkg . --target win32-x64 ..."
}
每个平台独立打包——原生模块不通用。
值得学习的点
Proxy:
- 尊重 HTTPS_PROXY/NO_PROXY — 标准环境变量
- PAC 支持 — 企业必备
- CA 证书注入 — 企业自签证书
- 启动前诊断 — 省 debug 时间
Native:
- Tree-sitter — AST 性能关键
- node-pty — 真 PTY 支持
- OS keyring — 原生密钥存储
- 平台适配打包 — 原生模块不通用
- chokidar — 跨平台文件监控