参考站内的解析,vibe了个Claude Code 补丁包:订阅状态强制真 + 模型验证绕过 + Auto模式等
- 内容介绍
- 文章标签
- 相关推荐
image614×740 131 KB
仅支持 2.1.89
代码:
#!/usr/bin/env node
import fs from 'fs/promises';
import path from 'path';
import readline from 'readline';
const isWindows = process.platform === 'win32';
const isMac = process.platform === 'darwin';
const useColor = process.stdout.isTTY && !process.env.NO_COLOR;
const colors = {
reset: useColor ? '\x1b[0m' : '',
bold: useColor ? '\x1b[1m' : '',
dim: useColor ? '\x1b[2m' : '',
red: useColor ? '\x1b[31m' : '',
green: useColor ? '\x1b[32m' : '',
yellow: useColor ? '\x1b[33m' : '',
cyan: useColor ? '\x1b[36m' : '',
};
class PatchDef {
constructor(name, description, searchStr, findAndReplace, defaultEnabled = true) {
this.name = name;
this.description = description;
this.searchStr = searchStr;
this.findAndReplace = findAndReplace;
this.defaultEnabled = defaultEnabled;
}
}
function padTo(prefix, suffix, length) {
const padding = length - prefix.length - suffix.length;
if (padding < 0) return null;
return prefix + ' '.repeat(padding) + suffix;
}
// ========== 补丁 1:ToolSearch 域名限制解除 ==========
const patchToolsearch = new PatchDef(
'toolsearch',
'ToolSearch 域名限制解除',
'["api.anthropic.com"].includes',
(content) => {
let count = 0;
const pattern = /return\s*\[\s*["']api\.anthropic\.com["']\s*\]\s*\.includes\s*\([^)]*\)\s*\}\s*catch\s*\{\s*return!1\s*\}/g;
const result = content.replace(pattern, (match) => {
const replacement = padTo('return!0/*', '*/}catch{return!0}', match.length);
if (replacement === null) return match;
count++;
return replacement;
});
return { content: result, count };
},
false
);
// ========== 补丁 2:Chrome 订阅检查绕过(更新为匹配箭头函数属性) ==========
const patchChrome = new PatchDef(
'chrome',
'Chrome 订阅检查绕过 (/chrome)',
'fetchAndStoreUserRoles:',
(content) => {
let count = 0;
// 匹配 fetchAndStoreUserRoles:()=>{...} 或 fetchAndStoreUserRoles:()=>某个函数
const pattern = /fetchAndStoreUserRoles\s*:\s*\(\)\s*=>\s*[^,\n}]+/g;
const result = content.replace(pattern, () => {
count++;
return 'fetchAndStoreUserRoles:()=>!0';
});
return { content: result, count };
},
true
);
// ========== 补丁 3:Context Warning 禁用(更新为正则,匹配当前结构) ==========
const patchContextWarning = new PatchDef(
'context_warning',
'Context Warning 禁用',
'isAboveWarningThreshold',
(content) => {
let count = 0;
// 匹配 isAboveWarningThreshold: 后跟任意变量名(如 A、H 等)
const pattern = /isAboveWarningThreshold\s*:\s*[A-Za-z_$][A-Za-z0-9_$]*/g;
const result = content.replace(pattern, match => {
count++;
if (!match.includes('H')) {
return match;
}
return 'isAboveWarningThreshold: !!0';
});
return { content: result, count };
},
true
);
// ========== 补丁 4:Auth conflict 警告抑制 ==========
const patchAuthWarning = new PatchDef(
'auth_warning',
'Auth conflict 警告抑制',
'ANTHROPIC_AUTH_TOKEN',
(content) => {
let count = 0;
const pattern = /isActive:\s*\(\s*\)\s*=>\s*\{\s*let\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*=\s*[A-Za-z_$][A-Za-z0-9_$]*\s*\(\s*\)\s*;\s*return\s*[A-Za-z_$][A-Za-z0-9_$]*\s*\(\s*\)\s*&&\s*\(\s*\1\s*\.\s*source\s*===\s*["']ANTHROPIC_AUTH_TOKEN["']\s*\|\|\s*\1\s*\.\s*source\s*===\s*["']apiKeyHelper["']\s*\)\s*\}/g;
const result = content.replace(pattern, (match) => {
const replacement = padTo('isActive:(()=>!0)/*', '*/',match.length);
if (replacement === null) return match;
count++;
return replacement;
});
return { content: result, count };
},
true
);
// ========== 补丁 5:Read/Search 折叠禁用 ==========
const patchCollapseRS = new PatchDef(
'collapse_read_search',
'Read/Search 折叠禁用',
'isCollapsible',
(content) => {
let count = 0;
const pattern1 = /isCollapsible\s*:\s*!0\s*,\s*isSearch\s*:\s*!1\s*,\s*isRead\s*:\s*!1/g;
let result = content.replace(pattern1, (match) => {
const replacement = padTo('isCollapsible:!1/*', '*/isSearch:!1,isRead:!1', match.length);
if (replacement === null) return match;
count++;
return replacement;
});
const pattern2 = /isCollapsible\s*:\s*[A-Za-z_$][A-Za-z0-9_$]*\s*\|\|\s*\(\s*[A-Za-z_$][A-Za-z0-9_$]*\s*\(\s*\)\s*\?\s*[A-Za-z_$][A-Za-z0-9_$]*\s*===\s*[A-Za-z_$][A-Za-z0-9_$]*\s*:\s*!1\s*\)/g;
result = result.replace(pattern2, (match) => {
const replacement = padTo('isCollapsible:!1/*', '*/', match.length);
if (replacement === null) return match;
count++;
return replacement;
});
return { content: result, count };
},
true
);
// ========== 核心鉴权层劫持 ==========
const patchSubscriptionTier = new PatchDef(
'subscription_tier',
'订阅类型强制返回 max',
'function NK',
(content) => {
let count = 0;
const pattern = /function\s+NK\s*\(\s*\)\s*\{[\s\S]*?\}/g;
const result = content.replace(pattern, () => {
count++;
return 'function NK(){return "max"}';
});
return { content: result, count };
},
true
);
const patchSubscriptionStatus = new PatchDef(
'subscription_status',
'订阅状态强制返回 true',
'function l7',
(content) => {
let count = 0;
const pattern = /function\s+l7\s*\(\s*\)\s*\{[\s\S]*?\}/g;
const result = content.replace(pattern, () => {
count++;
return 'function l7(){return true}';
});
return { content: result, count };
},
true
);
const patchRateLimit = new PatchDef(
'rate_limit',
'速率限制虚拟提升',
'function VF',
(content) => {
let count = 0;
const pattern = /function\s+VF\s*\(\s*\)\s*\{[\s\S]*?\}/g;
const result = content.replace(pattern, () => {
count++;
return 'function VF(){return "default_claude_max_5x"}';
});
return { content: result, count };
},
true
);
// ========== Auto Mode 深度解锁 ==========
const patchModelValidation = new PatchDef(
'model_validation',
'模型验证绕过',
'function fG6',
(content) => {
let count = 0;
const pattern = 'function fG6(q){';
const result = content.replace(pattern, (match) => {
const paramMatch = match.match(/function\s+fG6\s*\(([^)]*)\)/);
const params = paramMatch ? paramMatch[1] : '';
count++;
return `function fG6(q){return true;`;
});
return { content: result, count };
},
true
);
const patchCloudConfigSYz = new PatchDef(
'cloud_config_syz',
'云端配置熔断 (SYz)',
'function SYz',
(content) => {
let count = 0;
const pattern = 'function SYz(){';
const result = content.replace(pattern, () => {
count++;
return 'function SYz(){return "enabled";';
});
return { content: result, count };
},
true
);
const patchCloudConfig_q7 = new PatchDef(
'cloud_config_q7',
'云端配置熔断 (_q7)',
'function _q7',
(content) => {
let count = 0;
const pattern = 'function _q7(q){';
const result = content.replace(pattern, (match) => {
const paramMatch = match.match(/function\s+_q7\s*\(([^)]*)\)/);
const params = paramMatch ? paramMatch[1] : '';
count++;
return `function _q7(q){return "enabled";`;
});
return { content: result, count };
},
true
);
const patchLocalPolicy = new PatchDef(
'local_policy',
'本地策略屏蔽',
'function Kq7',
(content) => {
let count = 0;
const pattern = 'function Kq7(){let';
const result = content.replace(pattern, () => {
count++;
return 'function Kq7(){return false; let';
});
return { content: result, count };
},
true
);
// ========== 全局工具箱解锁 ==========
const patchToolAvailability = new PatchDef(
'tool_availability',
'全局工具箱解锁',
'availability:["claude-ai"]',
(content) => {
let count = 0;
const pattern = 'availability:["claude-ai"]';
const result = content.replace(pattern, () => {
count++;
return 'availability:[]';
});
return { content: result, count };
},
true
);
// ========== Channels 协议击穿 ==========
const patchChannelRegister = new PatchDef(
'channel_register',
'Channels 后端注册强制',
'function r78',
(content) => {
let count = 0;
const pattern = 'function r78(q,K,_){';
const result = content.replace(pattern, (match) => {
const paramMatch = match.match(/function\s+r78\s*\(([^)]*)\)/);
const params = paramMatch ? paramMatch[1] : '';
count++;
return `function r78(q,K,_){return {action:"register"};`;
});
return { content: result, count };
},
true
);
const patchUIWarmup = new PatchDef(
'ui_warmup',
'Channels UI 预热',
'function vGY',
(content) => {
let count = 0;
const pattern = 'function vGY(){let q=sH();';
const result = content.replace(pattern, () => {
count++;
return `function vGY(){let q=sH();return{channels:q,disabled:false,noAuth:false,policyBlocked:false,list:q.map(Vq8).join(", "),unmatched:[]};`;
});
return { content: result, count };
},
true
);
const patchToolNameFixJ51 = new PatchDef(
'tool_name_fix_j51',
'Telegram 协议修复 (J51)',
'function J51',
(content) => {
let count = 0;
const pattern = 'function J51(q){';
const result = content.replace(pattern, (match) => {
count++;
return `function J51(q){let name=q.mcpInfo?m_6(q.mcpInfo.serverName,q.mcpInfo.toolName):q.name;return name||"default_tool";`;
});
return { content: result, count };
},
true
);
const patchToolNameFixUx4 = new PatchDef(
'tool_name_fix_ux4',
'Telegram 协议修复 (ux4)',
'function ux4',
(content) => {
let count = 0;
const pattern = 'function ux4(q,K){';
const result = content.replace(pattern, (match) => {
count++;
return `function ux4(q,K){let name=q||"default_tool";return{role:"assistant",content:[{type:"tool_use",name:name,input:K}]};`;
});
return { content: result, count };
},
true
);
// ========== 补丁列表 ==========
const ALL_PATCHES = [
patchToolsearch,
patchChrome,
patchContextWarning,
patchAuthWarning,
patchCollapseRS,
patchSubscriptionTier,
patchSubscriptionStatus,
patchRateLimit,
patchModelValidation,
patchCloudConfigSYz,
patchCloudConfig_q7,
patchLocalPolicy,
patchToolAvailability,
patchChannelRegister,
patchUIWarmup,
patchToolNameFixJ51,
patchToolNameFixUx4,
];
const BACKUP_SUFFIX = '.claude-patch-bak';
// ── 补丁引擎 ──────────────────────────────────────────────────────────
function applyAllPatches(content, patches = ALL_PATCHES) {
const counts = {};
let result = content;
for (const p of patches) {
const { content: newContent, count } = p.findAndReplace(result);
result = newContent;
counts[p.name] = count;
}
return { content: result, counts };
}
// ── 交互式选择补丁 ──────────────────────────────────────────────────────────
async function askConfirmation(question, defaultYes) {
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const defaultStr = defaultYes ? 'Y/n' : 'y/N';
return new Promise(resolve => {
rl.question(`${question} (${defaultStr}) `, answer => {
rl.close();
const normalized = answer.trim().toLowerCase();
if (normalized === '') resolve(defaultYes);
else if (normalized === 'y' || normalized === 'yes') resolve(true);
else if (normalized === 'n' || normalized === 'no') resolve(false);
else resolve(defaultYes);
});
});
}
async function interactiveSelectPatches(patches) {
console.log(`\n${colors.bold}请选择要应用的补丁(默认:除“安全分类器绕过”外全部启用)${colors.reset}\n`);
const selected = [];
for (const p of patches) {
// 默认:安全分类器绕过不选中,其他选中
const defaultEnable = p.name !== 'classifier';
const answer = await askConfirmation(` 应用补丁 “${colors.cyan}${p.name}${colors.reset}” - ${p.description}`, defaultEnable);
if (answer) {
selected.push(p);
console.log(` ${colors.green}✓ 将应用${colors.reset}`);
} else {
console.log(` ${colors.dim}✗ 跳过${colors.reset}`);
}
}
console.log(`\n${colors.bold}已选择 ${selected.length} 个补丁${colors.reset}`);
if (selected.length === 0) {
console.log(`${colors.red}未选择任何补丁,操作取消。${colors.reset}`);
process.exit(0);
}
return selected;
}
// ── 文件操作 ──────────────────────────────────────────────────────────
async function writeViaRename(targetPath, data) {
const tmpPath = targetPath + '.tmp';
const oldPath = targetPath + '.old';
await fs.unlink(tmpPath).catch(() => {});
await fs.unlink(oldPath).catch(() => {});
await fs.writeFile(tmpPath, data);
try {
await fs.rename(targetPath, oldPath);
} catch (err) {
await fs.unlink(tmpPath);
console.error(` 无法重命名 ${path.basename(targetPath)},请关闭 claude 后重试。`);
return false;
}
await fs.rename(tmpPath, targetPath);
await fs.unlink(oldPath).catch(() => {});
return true;
}
async function resignIfNeeded(targetPath) {
if (!isMac) return { ok: true, message: '' };
const { exec } = await import('child_process');
const { promisify } = await import('util');
const execPromise = promisify(exec);
try {
await execPromise(`codesign --force --sign - "${targetPath}"`);
return { ok: true, message: '已完成 macOS ad-hoc 重签名。' };
} catch (err) {
return { ok: false, message: err.stderr || err.stdout || 'codesign 执行失败' };
}
}
// ── 补丁应用 ──────────────────────────────────────────────────────────
async function applyPatchToInstallation(inst, patches = ALL_PATCHES) {
const data = await fs.readFile(inst.target);
const content = data.toString('utf8');
console.log('\n 检测关键字:');
for (const p of patches) {
const exists = content.includes(p.searchStr);
console.log(` ${exists ? colors.green + '✓' + colors.reset : colors.red + '✗' + colors.reset} ${p.name}: ${p.searchStr.slice(0, 30)}...`);
}
const { content: patchedContent, counts } = applyAllPatches(content, patches);
const total = Object.values(counts).reduce((a, b) => a + b, 0);
if (total === 0) {
console.log(`\n ${colors.red}✗${colors.reset} 未找到任何可补丁的目标。`);
console.log(` ${colors.dim}提示:关键字存在但正则不匹配,可能是代码结构变化。${colors.reset}`);
return false;
}
const backupPath = inst.target + BACKUP_SUFFIX;
try {
await fs.access(backupPath);
console.log(` ${colors.dim}备份已存在${colors.reset}`);
} catch {
await fs.copyFile(inst.target, backupPath);
console.log(` 已备份到 ${backupPath}`);
}
try {
await fs.writeFile(inst.target, patchedContent);
} catch (err) {
console.log(' 文件被占用,使用重命名方式替换...');
if (!await writeViaRename(inst.target, patchedContent)) return false;
}
const { ok, message } = await resignIfNeeded(inst.target);
if (!ok) {
console.log(` ${colors.red}✗${colors.reset} 补丁已写入,但重签名失败:${message}`);
return false;
}
if (message) console.log(` ${message}`);
for (const p of patches) {
const c = counts[p.name];
if (c > 0) console.log(` ${colors.green}✓${colors.reset} ${p.description}: 替换 ${c} 处`);
else console.log(` ${colors.dim}-${colors.reset} ${p.description}: 无匹配`);
}
return true;
}
async function restoreBackup(inst) {
const backupPath = inst.target + BACKUP_SUFFIX;
try {
await fs.access(backupPath);
} catch {
console.log(` ${colors.red}✗${colors.reset} 未找到备份文件 ${backupPath}`);
return false;
}
const backupData = await fs.readFile(backupPath);
try {
await fs.writeFile(inst.target, backupData);
} catch (err) {
console.log(' 文件被占用,使用重命名方式替换...');
if (!await writeViaRename(inst.target, backupData)) return false;
}
console.log(` ${colors.green}✓${colors.reset} 已从备份恢复。`);
return true;
}
// ── 安装检测 ──────────────────────────────────────────────────────────
async function findPnpmInstallations() {
const { exec } = await import('child_process');
const { promisify } = await import('util');
const execPromise = promisify(exec);
const results = [];
const pnpmRoot = await execPromise('pnpm root -g').then(r => r.stdout.trim()).catch(() => null);
if (pnpmRoot) {
const pkgDir = path.join(pnpmRoot, '@anthropic-ai', 'claude-code');
const cliJs = path.join(pkgDir, 'cli.js');
try {
await fs.access(cliJs);
results.push({ kind: 'pnpm', target: cliJs, description: `pnpm 全局安装 (${cliJs})` });
} catch {}
}
return results;
}
async function findAllInstallations() {
const all = [];
all.push(...await findPnpmInstallations());
const seen = new Set();
const deduped = [];
for (const inst of all) {
const key = path.resolve(inst.target);
if (!seen.has(key)) {
seen.add(key);
deduped.push(inst);
}
}
return deduped;
}
// ── 入口 ──────────────────────────────────────────────────────────
async function main() {
const args = process.argv.slice(2);
let mode = 'patch';
let autoAll = false;
for (const arg of args) {
if (arg === '--restore') mode = 'restore';
if (arg === '--auto') autoAll = true;
if (arg === '--help' || arg === '-h') {
console.log(`
用法: node patch.js [选项]
选项:
--restore 从备份恢复原始文件
--auto 自动应用所有补丁(包括安全分类器绕过),跳过交互选择
--help, -h 显示帮助信息
默认情况下(无 --restore 且无 --auto),进入交互模式,让用户选择要应用的补丁,
其中“安全分类器绕过”默认不选中,其他补丁默认选中。
`);
process.exit(0);
}
}
if (mode === 'restore') {
console.log('恢复模式:将还原所有备份文件');
const installations = await findAllInstallations();
if (installations.length === 0) {
console.log(`${colors.red}未检测到任何 Claude Code 安装。${colors.reset}`);
process.exit(1);
}
for (const inst of installations) {
console.log(`\n→ 处理:${inst.description}`);
await restoreBackup(inst);
}
console.log(`\n${colors.green}完成。${colors.reset}`);
process.exit(0);
}
console.log('正在扫描 Claude Code 安装...');
const installations = await findAllInstallations();
if (installations.length === 0) {
console.log(`${colors.red}未检测到任何 Claude Code 安装。${colors.reset}`);
process.exit(1);
}
let patchesToApply = ALL_PATCHES;
// 非自动模式下,且为标准输入输出终端时,进入交互选择
if (!autoAll && process.stdin.isTTY && process.stdout.isTTY) {
patchesToApply = await interactiveSelectPatches(ALL_PATCHES);
} else if (!autoAll && !process.stdin.isTTY) {
console.log(`${colors.yellow}检测到非交互环境,自动应用全部补丁(含安全分类器绕过)。${colors.reset}`);
patchesToApply = ALL_PATCHES;
} else if (autoAll) {
console.log(`${colors.dim}自动模式:应用全部补丁(含安全分类器绕过)。${colors.reset}`);
patchesToApply = ALL_PATCHES;
}
for (const inst of installations) {
console.log(`\n→ 处理:${inst.description}`);
await applyPatchToInstallation(inst, patchesToApply);
}
console.log(`\n${colors.green}完成。重启 claude 生效。${colors.reset}`);
}
main().catch(console.error);
食用方法:
node .\patch.js
参考文献:
网友解答:
- https://linux.do/t/topic/1872946
- Claude Code强制开启 Tool Search工具分享
--【壹】--:
patch完好像–enable-auto-mode是没问题的
--【贰】--:
太强了!大佬
--【叁】--:
太强了佬,可以支持auto mode嘛
--【肆】--:
确实,试出来了,感谢大佬(之前不可用原来是A畜自动给我升到90了
--【伍】--:
感谢大佬分享
image614×740 131 KB
仅支持 2.1.89
代码:
#!/usr/bin/env node
import fs from 'fs/promises';
import path from 'path';
import readline from 'readline';
const isWindows = process.platform === 'win32';
const isMac = process.platform === 'darwin';
const useColor = process.stdout.isTTY && !process.env.NO_COLOR;
const colors = {
reset: useColor ? '\x1b[0m' : '',
bold: useColor ? '\x1b[1m' : '',
dim: useColor ? '\x1b[2m' : '',
red: useColor ? '\x1b[31m' : '',
green: useColor ? '\x1b[32m' : '',
yellow: useColor ? '\x1b[33m' : '',
cyan: useColor ? '\x1b[36m' : '',
};
class PatchDef {
constructor(name, description, searchStr, findAndReplace, defaultEnabled = true) {
this.name = name;
this.description = description;
this.searchStr = searchStr;
this.findAndReplace = findAndReplace;
this.defaultEnabled = defaultEnabled;
}
}
function padTo(prefix, suffix, length) {
const padding = length - prefix.length - suffix.length;
if (padding < 0) return null;
return prefix + ' '.repeat(padding) + suffix;
}
// ========== 补丁 1:ToolSearch 域名限制解除 ==========
const patchToolsearch = new PatchDef(
'toolsearch',
'ToolSearch 域名限制解除',
'["api.anthropic.com"].includes',
(content) => {
let count = 0;
const pattern = /return\s*\[\s*["']api\.anthropic\.com["']\s*\]\s*\.includes\s*\([^)]*\)\s*\}\s*catch\s*\{\s*return!1\s*\}/g;
const result = content.replace(pattern, (match) => {
const replacement = padTo('return!0/*', '*/}catch{return!0}', match.length);
if (replacement === null) return match;
count++;
return replacement;
});
return { content: result, count };
},
false
);
// ========== 补丁 2:Chrome 订阅检查绕过(更新为匹配箭头函数属性) ==========
const patchChrome = new PatchDef(
'chrome',
'Chrome 订阅检查绕过 (/chrome)',
'fetchAndStoreUserRoles:',
(content) => {
let count = 0;
// 匹配 fetchAndStoreUserRoles:()=>{...} 或 fetchAndStoreUserRoles:()=>某个函数
const pattern = /fetchAndStoreUserRoles\s*:\s*\(\)\s*=>\s*[^,\n}]+/g;
const result = content.replace(pattern, () => {
count++;
return 'fetchAndStoreUserRoles:()=>!0';
});
return { content: result, count };
},
true
);
// ========== 补丁 3:Context Warning 禁用(更新为正则,匹配当前结构) ==========
const patchContextWarning = new PatchDef(
'context_warning',
'Context Warning 禁用',
'isAboveWarningThreshold',
(content) => {
let count = 0;
// 匹配 isAboveWarningThreshold: 后跟任意变量名(如 A、H 等)
const pattern = /isAboveWarningThreshold\s*:\s*[A-Za-z_$][A-Za-z0-9_$]*/g;
const result = content.replace(pattern, match => {
count++;
if (!match.includes('H')) {
return match;
}
return 'isAboveWarningThreshold: !!0';
});
return { content: result, count };
},
true
);
// ========== 补丁 4:Auth conflict 警告抑制 ==========
const patchAuthWarning = new PatchDef(
'auth_warning',
'Auth conflict 警告抑制',
'ANTHROPIC_AUTH_TOKEN',
(content) => {
let count = 0;
const pattern = /isActive:\s*\(\s*\)\s*=>\s*\{\s*let\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*=\s*[A-Za-z_$][A-Za-z0-9_$]*\s*\(\s*\)\s*;\s*return\s*[A-Za-z_$][A-Za-z0-9_$]*\s*\(\s*\)\s*&&\s*\(\s*\1\s*\.\s*source\s*===\s*["']ANTHROPIC_AUTH_TOKEN["']\s*\|\|\s*\1\s*\.\s*source\s*===\s*["']apiKeyHelper["']\s*\)\s*\}/g;
const result = content.replace(pattern, (match) => {
const replacement = padTo('isActive:(()=>!0)/*', '*/',match.length);
if (replacement === null) return match;
count++;
return replacement;
});
return { content: result, count };
},
true
);
// ========== 补丁 5:Read/Search 折叠禁用 ==========
const patchCollapseRS = new PatchDef(
'collapse_read_search',
'Read/Search 折叠禁用',
'isCollapsible',
(content) => {
let count = 0;
const pattern1 = /isCollapsible\s*:\s*!0\s*,\s*isSearch\s*:\s*!1\s*,\s*isRead\s*:\s*!1/g;
let result = content.replace(pattern1, (match) => {
const replacement = padTo('isCollapsible:!1/*', '*/isSearch:!1,isRead:!1', match.length);
if (replacement === null) return match;
count++;
return replacement;
});
const pattern2 = /isCollapsible\s*:\s*[A-Za-z_$][A-Za-z0-9_$]*\s*\|\|\s*\(\s*[A-Za-z_$][A-Za-z0-9_$]*\s*\(\s*\)\s*\?\s*[A-Za-z_$][A-Za-z0-9_$]*\s*===\s*[A-Za-z_$][A-Za-z0-9_$]*\s*:\s*!1\s*\)/g;
result = result.replace(pattern2, (match) => {
const replacement = padTo('isCollapsible:!1/*', '*/', match.length);
if (replacement === null) return match;
count++;
return replacement;
});
return { content: result, count };
},
true
);
// ========== 核心鉴权层劫持 ==========
const patchSubscriptionTier = new PatchDef(
'subscription_tier',
'订阅类型强制返回 max',
'function NK',
(content) => {
let count = 0;
const pattern = /function\s+NK\s*\(\s*\)\s*\{[\s\S]*?\}/g;
const result = content.replace(pattern, () => {
count++;
return 'function NK(){return "max"}';
});
return { content: result, count };
},
true
);
const patchSubscriptionStatus = new PatchDef(
'subscription_status',
'订阅状态强制返回 true',
'function l7',
(content) => {
let count = 0;
const pattern = /function\s+l7\s*\(\s*\)\s*\{[\s\S]*?\}/g;
const result = content.replace(pattern, () => {
count++;
return 'function l7(){return true}';
});
return { content: result, count };
},
true
);
const patchRateLimit = new PatchDef(
'rate_limit',
'速率限制虚拟提升',
'function VF',
(content) => {
let count = 0;
const pattern = /function\s+VF\s*\(\s*\)\s*\{[\s\S]*?\}/g;
const result = content.replace(pattern, () => {
count++;
return 'function VF(){return "default_claude_max_5x"}';
});
return { content: result, count };
},
true
);
// ========== Auto Mode 深度解锁 ==========
const patchModelValidation = new PatchDef(
'model_validation',
'模型验证绕过',
'function fG6',
(content) => {
let count = 0;
const pattern = 'function fG6(q){';
const result = content.replace(pattern, (match) => {
const paramMatch = match.match(/function\s+fG6\s*\(([^)]*)\)/);
const params = paramMatch ? paramMatch[1] : '';
count++;
return `function fG6(q){return true;`;
});
return { content: result, count };
},
true
);
const patchCloudConfigSYz = new PatchDef(
'cloud_config_syz',
'云端配置熔断 (SYz)',
'function SYz',
(content) => {
let count = 0;
const pattern = 'function SYz(){';
const result = content.replace(pattern, () => {
count++;
return 'function SYz(){return "enabled";';
});
return { content: result, count };
},
true
);
const patchCloudConfig_q7 = new PatchDef(
'cloud_config_q7',
'云端配置熔断 (_q7)',
'function _q7',
(content) => {
let count = 0;
const pattern = 'function _q7(q){';
const result = content.replace(pattern, (match) => {
const paramMatch = match.match(/function\s+_q7\s*\(([^)]*)\)/);
const params = paramMatch ? paramMatch[1] : '';
count++;
return `function _q7(q){return "enabled";`;
});
return { content: result, count };
},
true
);
const patchLocalPolicy = new PatchDef(
'local_policy',
'本地策略屏蔽',
'function Kq7',
(content) => {
let count = 0;
const pattern = 'function Kq7(){let';
const result = content.replace(pattern, () => {
count++;
return 'function Kq7(){return false; let';
});
return { content: result, count };
},
true
);
// ========== 全局工具箱解锁 ==========
const patchToolAvailability = new PatchDef(
'tool_availability',
'全局工具箱解锁',
'availability:["claude-ai"]',
(content) => {
let count = 0;
const pattern = 'availability:["claude-ai"]';
const result = content.replace(pattern, () => {
count++;
return 'availability:[]';
});
return { content: result, count };
},
true
);
// ========== Channels 协议击穿 ==========
const patchChannelRegister = new PatchDef(
'channel_register',
'Channels 后端注册强制',
'function r78',
(content) => {
let count = 0;
const pattern = 'function r78(q,K,_){';
const result = content.replace(pattern, (match) => {
const paramMatch = match.match(/function\s+r78\s*\(([^)]*)\)/);
const params = paramMatch ? paramMatch[1] : '';
count++;
return `function r78(q,K,_){return {action:"register"};`;
});
return { content: result, count };
},
true
);
const patchUIWarmup = new PatchDef(
'ui_warmup',
'Channels UI 预热',
'function vGY',
(content) => {
let count = 0;
const pattern = 'function vGY(){let q=sH();';
const result = content.replace(pattern, () => {
count++;
return `function vGY(){let q=sH();return{channels:q,disabled:false,noAuth:false,policyBlocked:false,list:q.map(Vq8).join(", "),unmatched:[]};`;
});
return { content: result, count };
},
true
);
const patchToolNameFixJ51 = new PatchDef(
'tool_name_fix_j51',
'Telegram 协议修复 (J51)',
'function J51',
(content) => {
let count = 0;
const pattern = 'function J51(q){';
const result = content.replace(pattern, (match) => {
count++;
return `function J51(q){let name=q.mcpInfo?m_6(q.mcpInfo.serverName,q.mcpInfo.toolName):q.name;return name||"default_tool";`;
});
return { content: result, count };
},
true
);
const patchToolNameFixUx4 = new PatchDef(
'tool_name_fix_ux4',
'Telegram 协议修复 (ux4)',
'function ux4',
(content) => {
let count = 0;
const pattern = 'function ux4(q,K){';
const result = content.replace(pattern, (match) => {
count++;
return `function ux4(q,K){let name=q||"default_tool";return{role:"assistant",content:[{type:"tool_use",name:name,input:K}]};`;
});
return { content: result, count };
},
true
);
// ========== 补丁列表 ==========
const ALL_PATCHES = [
patchToolsearch,
patchChrome,
patchContextWarning,
patchAuthWarning,
patchCollapseRS,
patchSubscriptionTier,
patchSubscriptionStatus,
patchRateLimit,
patchModelValidation,
patchCloudConfigSYz,
patchCloudConfig_q7,
patchLocalPolicy,
patchToolAvailability,
patchChannelRegister,
patchUIWarmup,
patchToolNameFixJ51,
patchToolNameFixUx4,
];
const BACKUP_SUFFIX = '.claude-patch-bak';
// ── 补丁引擎 ──────────────────────────────────────────────────────────
function applyAllPatches(content, patches = ALL_PATCHES) {
const counts = {};
let result = content;
for (const p of patches) {
const { content: newContent, count } = p.findAndReplace(result);
result = newContent;
counts[p.name] = count;
}
return { content: result, counts };
}
// ── 交互式选择补丁 ──────────────────────────────────────────────────────────
async function askConfirmation(question, defaultYes) {
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const defaultStr = defaultYes ? 'Y/n' : 'y/N';
return new Promise(resolve => {
rl.question(`${question} (${defaultStr}) `, answer => {
rl.close();
const normalized = answer.trim().toLowerCase();
if (normalized === '') resolve(defaultYes);
else if (normalized === 'y' || normalized === 'yes') resolve(true);
else if (normalized === 'n' || normalized === 'no') resolve(false);
else resolve(defaultYes);
});
});
}
async function interactiveSelectPatches(patches) {
console.log(`\n${colors.bold}请选择要应用的补丁(默认:除“安全分类器绕过”外全部启用)${colors.reset}\n`);
const selected = [];
for (const p of patches) {
// 默认:安全分类器绕过不选中,其他选中
const defaultEnable = p.name !== 'classifier';
const answer = await askConfirmation(` 应用补丁 “${colors.cyan}${p.name}${colors.reset}” - ${p.description}`, defaultEnable);
if (answer) {
selected.push(p);
console.log(` ${colors.green}✓ 将应用${colors.reset}`);
} else {
console.log(` ${colors.dim}✗ 跳过${colors.reset}`);
}
}
console.log(`\n${colors.bold}已选择 ${selected.length} 个补丁${colors.reset}`);
if (selected.length === 0) {
console.log(`${colors.red}未选择任何补丁,操作取消。${colors.reset}`);
process.exit(0);
}
return selected;
}
// ── 文件操作 ──────────────────────────────────────────────────────────
async function writeViaRename(targetPath, data) {
const tmpPath = targetPath + '.tmp';
const oldPath = targetPath + '.old';
await fs.unlink(tmpPath).catch(() => {});
await fs.unlink(oldPath).catch(() => {});
await fs.writeFile(tmpPath, data);
try {
await fs.rename(targetPath, oldPath);
} catch (err) {
await fs.unlink(tmpPath);
console.error(` 无法重命名 ${path.basename(targetPath)},请关闭 claude 后重试。`);
return false;
}
await fs.rename(tmpPath, targetPath);
await fs.unlink(oldPath).catch(() => {});
return true;
}
async function resignIfNeeded(targetPath) {
if (!isMac) return { ok: true, message: '' };
const { exec } = await import('child_process');
const { promisify } = await import('util');
const execPromise = promisify(exec);
try {
await execPromise(`codesign --force --sign - "${targetPath}"`);
return { ok: true, message: '已完成 macOS ad-hoc 重签名。' };
} catch (err) {
return { ok: false, message: err.stderr || err.stdout || 'codesign 执行失败' };
}
}
// ── 补丁应用 ──────────────────────────────────────────────────────────
async function applyPatchToInstallation(inst, patches = ALL_PATCHES) {
const data = await fs.readFile(inst.target);
const content = data.toString('utf8');
console.log('\n 检测关键字:');
for (const p of patches) {
const exists = content.includes(p.searchStr);
console.log(` ${exists ? colors.green + '✓' + colors.reset : colors.red + '✗' + colors.reset} ${p.name}: ${p.searchStr.slice(0, 30)}...`);
}
const { content: patchedContent, counts } = applyAllPatches(content, patches);
const total = Object.values(counts).reduce((a, b) => a + b, 0);
if (total === 0) {
console.log(`\n ${colors.red}✗${colors.reset} 未找到任何可补丁的目标。`);
console.log(` ${colors.dim}提示:关键字存在但正则不匹配,可能是代码结构变化。${colors.reset}`);
return false;
}
const backupPath = inst.target + BACKUP_SUFFIX;
try {
await fs.access(backupPath);
console.log(` ${colors.dim}备份已存在${colors.reset}`);
} catch {
await fs.copyFile(inst.target, backupPath);
console.log(` 已备份到 ${backupPath}`);
}
try {
await fs.writeFile(inst.target, patchedContent);
} catch (err) {
console.log(' 文件被占用,使用重命名方式替换...');
if (!await writeViaRename(inst.target, patchedContent)) return false;
}
const { ok, message } = await resignIfNeeded(inst.target);
if (!ok) {
console.log(` ${colors.red}✗${colors.reset} 补丁已写入,但重签名失败:${message}`);
return false;
}
if (message) console.log(` ${message}`);
for (const p of patches) {
const c = counts[p.name];
if (c > 0) console.log(` ${colors.green}✓${colors.reset} ${p.description}: 替换 ${c} 处`);
else console.log(` ${colors.dim}-${colors.reset} ${p.description}: 无匹配`);
}
return true;
}
async function restoreBackup(inst) {
const backupPath = inst.target + BACKUP_SUFFIX;
try {
await fs.access(backupPath);
} catch {
console.log(` ${colors.red}✗${colors.reset} 未找到备份文件 ${backupPath}`);
return false;
}
const backupData = await fs.readFile(backupPath);
try {
await fs.writeFile(inst.target, backupData);
} catch (err) {
console.log(' 文件被占用,使用重命名方式替换...');
if (!await writeViaRename(inst.target, backupData)) return false;
}
console.log(` ${colors.green}✓${colors.reset} 已从备份恢复。`);
return true;
}
// ── 安装检测 ──────────────────────────────────────────────────────────
async function findPnpmInstallations() {
const { exec } = await import('child_process');
const { promisify } = await import('util');
const execPromise = promisify(exec);
const results = [];
const pnpmRoot = await execPromise('pnpm root -g').then(r => r.stdout.trim()).catch(() => null);
if (pnpmRoot) {
const pkgDir = path.join(pnpmRoot, '@anthropic-ai', 'claude-code');
const cliJs = path.join(pkgDir, 'cli.js');
try {
await fs.access(cliJs);
results.push({ kind: 'pnpm', target: cliJs, description: `pnpm 全局安装 (${cliJs})` });
} catch {}
}
return results;
}
async function findAllInstallations() {
const all = [];
all.push(...await findPnpmInstallations());
const seen = new Set();
const deduped = [];
for (const inst of all) {
const key = path.resolve(inst.target);
if (!seen.has(key)) {
seen.add(key);
deduped.push(inst);
}
}
return deduped;
}
// ── 入口 ──────────────────────────────────────────────────────────
async function main() {
const args = process.argv.slice(2);
let mode = 'patch';
let autoAll = false;
for (const arg of args) {
if (arg === '--restore') mode = 'restore';
if (arg === '--auto') autoAll = true;
if (arg === '--help' || arg === '-h') {
console.log(`
用法: node patch.js [选项]
选项:
--restore 从备份恢复原始文件
--auto 自动应用所有补丁(包括安全分类器绕过),跳过交互选择
--help, -h 显示帮助信息
默认情况下(无 --restore 且无 --auto),进入交互模式,让用户选择要应用的补丁,
其中“安全分类器绕过”默认不选中,其他补丁默认选中。
`);
process.exit(0);
}
}
if (mode === 'restore') {
console.log('恢复模式:将还原所有备份文件');
const installations = await findAllInstallations();
if (installations.length === 0) {
console.log(`${colors.red}未检测到任何 Claude Code 安装。${colors.reset}`);
process.exit(1);
}
for (const inst of installations) {
console.log(`\n→ 处理:${inst.description}`);
await restoreBackup(inst);
}
console.log(`\n${colors.green}完成。${colors.reset}`);
process.exit(0);
}
console.log('正在扫描 Claude Code 安装...');
const installations = await findAllInstallations();
if (installations.length === 0) {
console.log(`${colors.red}未检测到任何 Claude Code 安装。${colors.reset}`);
process.exit(1);
}
let patchesToApply = ALL_PATCHES;
// 非自动模式下,且为标准输入输出终端时,进入交互选择
if (!autoAll && process.stdin.isTTY && process.stdout.isTTY) {
patchesToApply = await interactiveSelectPatches(ALL_PATCHES);
} else if (!autoAll && !process.stdin.isTTY) {
console.log(`${colors.yellow}检测到非交互环境,自动应用全部补丁(含安全分类器绕过)。${colors.reset}`);
patchesToApply = ALL_PATCHES;
} else if (autoAll) {
console.log(`${colors.dim}自动模式:应用全部补丁(含安全分类器绕过)。${colors.reset}`);
patchesToApply = ALL_PATCHES;
}
for (const inst of installations) {
console.log(`\n→ 处理:${inst.description}`);
await applyPatchToInstallation(inst, patchesToApply);
}
console.log(`\n${colors.green}完成。重启 claude 生效。${colors.reset}`);
}
main().catch(console.error);
食用方法:
node .\patch.js
参考文献:
网友解答:
- https://linux.do/t/topic/1872946
- Claude Code强制开启 Tool Search工具分享
--【壹】--:
patch完好像–enable-auto-mode是没问题的
--【贰】--:
太强了!大佬
--【叁】--:
太强了佬,可以支持auto mode嘛
--【肆】--:
确实,试出来了,感谢大佬(之前不可用原来是A畜自动给我升到90了
--【伍】--:
感谢大佬分享

