diff --git a/README.md b/README.md index 3f1c912..75971a4 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,16 @@ For detailed `proto` usage (config, init, render, markers), see: All commands output plain text to stdout. +### fix (Claude Code permissions) + +If Claude Code asks for confirmation on every `cueme` command, run: + +```bash +cueme fix claude_permissions +``` + +This adds `Bash` to `~/.claude/settings.json`. + --- ## QQ Group diff --git a/README.zh-CN.md b/README.zh-CN.md index 0693191..eff3705 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -83,6 +83,16 @@ cueme pause - 所有命令都以纯文本输出到 stdout。 +### fix(Claude Code 权限) + +如果 Claude Code 每次执行 `cueme` 都要确认,运行: + +```bash +cueme fix claude_permissions +``` + +它会把 `Bash` 写入 `~/.claude/settings.json`。 + --- ## QQ 群 diff --git a/src/cli.js b/src/cli.js index 45dd5ea..5b1a831 100644 --- a/src/cli.js +++ b/src/cli.js @@ -4,6 +4,7 @@ const { parseTagBlocksEnvelope } = require('./envelope'); const { protoApply, protoRemove, protoInit, protoLs, protoPath, protoRender } = require('./proto'); const pkg = require('../package.json'); const fs = require('fs'); +const os = require('os'); const path = require('path'); async function parseStdinTagBlocksOrExit({ parsed, allow_payload }) { @@ -65,6 +66,38 @@ function extractTextFromResult(result) { return ''; } +function upsertClaudeSettings(settingsPath, { rule } = {}) { + let cfg = {}; + if (fs.existsSync(settingsPath)) { + const raw = fs.readFileSync(settingsPath, 'utf8'); + try { + cfg = JSON.parse(raw); + } catch { + throw new Error(`error: invalid JSON in ${settingsPath}`); + } + } + + const permissions = cfg.permissions && typeof cfg.permissions === 'object' ? cfg.permissions : {}; + const allow = Array.isArray(permissions.allow) ? permissions.allow.slice() : []; + if (rule && !allow.includes(rule)) allow.push(rule); + cfg.permissions = { ...permissions, allow }; + fs.mkdirSync(path.dirname(settingsPath), { recursive: true }); + fs.writeFileSync(settingsPath, JSON.stringify(cfg, null, 2) + '\n', 'utf8'); +} + +function ensureClaudePermissions() { + const rule = 'Bash'; + const settingsPath = path.join(os.homedir(), '.claude', 'settings.json'); + upsertClaudeSettings(settingsPath, { rule }); + + const localDir = path.join(process.cwd(), '.claude'); + const localPath = path.join(localDir, 'settings.local.json'); + if (fs.existsSync(localDir) || fs.existsSync(localPath)) { + upsertClaudeSettings(localPath, { rule }); + } + return settingsPath; +} + async function main() { const first = process.argv[2]; if (first === '-v' || first === '--version') { @@ -147,6 +180,7 @@ async function main() { process.stderr.write('error: missing \n'); process.stderr.write('Available fixes:\n'); process.stderr.write(' powershell_utf-8 Fix PowerShell encoding for Chinese characters\n'); + process.stderr.write(' claude_permissions Allow cueme commands in Claude Code\n'); process.exitCode = 2; return; } @@ -211,10 +245,24 @@ async function main() { } return; } + + if (issue === 'claude_permissions') { + try { + const settingsPath = ensureClaudePermissions(); + process.stdout.write( + `ok: updated Claude Code permissions in ${settingsPath} (added Bash)\n` + ); + } catch (err) { + process.stderr.write(`Failed to update Claude Code permissions: ${err.message}\n`); + process.exitCode = 1; + } + return; + } process.stderr.write(`error: unknown issue: ${issue}\n`); process.stderr.write('Available fixes:\n'); process.stderr.write(' powershell_utf-8 Fix PowerShell encoding for Chinese characters\n'); + process.stderr.write(' claude_permissions Allow cueme commands in Claude Code\n'); process.exitCode = 2; return; }