source dump of claude code
at main 89 lines 3.7 kB view raw
1/** 2 * Undercover mode — safety utilities for contributing to public/open-source repos. 3 * 4 * When active, Claude Code adds safety instructions to commit/PR prompts and 5 * strips all attribution to avoid leaking internal model codenames, project 6 * names, or other Anthropic-internal information. The model is not told what 7 * model it is. 8 * 9 * Activation: 10 * - CLAUDE_CODE_UNDERCOVER=1 — force ON (even in internal repos) 11 * - Otherwise AUTO: active UNLESS the repo remote matches the internal 12 * allowlist (INTERNAL_MODEL_REPOS in commitAttribution.ts). Safe default 13 * is ON — Claude may push to public remotes from a CWD that isn't itself 14 * a git checkout (e.g. /tmp crash repro). 15 * - There is NO force-OFF. This guards against model codename leaks — if 16 * we're not confident we're in an internal repo, we stay undercover. 17 * 18 * All code paths are gated on process.env.USER_TYPE === 'ant'. Since USER_TYPE is 19 * a build-time --define, the bundler constant-folds these checks and dead-code- 20 * eliminates the ant-only branches from external builds. In external builds every 21 * function in this file reduces to a trivial return. 22 */ 23 24import { getRepoClassCached } from './commitAttribution.js' 25import { getGlobalConfig } from './config.js' 26import { isEnvTruthy } from './envUtils.js' 27 28export function isUndercover(): boolean { 29 if (process.env.USER_TYPE === 'ant') { 30 if (isEnvTruthy(process.env.CLAUDE_CODE_UNDERCOVER)) return true 31 // Auto: active unless we've positively confirmed we're in an allowlisted 32 // internal repo. 'external', 'none', and null (check not yet run) all 33 // resolve to ON. The check is primed in setup.ts; only 'internal' → OFF. 34 return getRepoClassCached() !== 'internal' 35 } 36 return false 37} 38 39export function getUndercoverInstructions(): string { 40 if (process.env.USER_TYPE === 'ant') { 41 return `## UNDERCOVER MODE — CRITICAL 42 43You are operating UNDERCOVER in a PUBLIC/OPEN-SOURCE repository. Your commit 44messages, PR titles, and PR bodies MUST NOT contain ANY Anthropic-internal 45information. Do not blow your cover. 46 47NEVER include in commit messages or PR descriptions: 48- Internal model codenames (animal names like Capybara, Tengu, etc.) 49- Unreleased model version numbers (e.g., opus-4-7, sonnet-4-8) 50- Internal repo or project names (e.g., claude-cli-internal, anthropics/…) 51- Internal tooling, Slack channels, or short links (e.g., go/cc, #claude-code-…) 52- The phrase "Claude Code" or any mention that you are an AI 53- Any hint of what model or version you are 54- Co-Authored-By lines or any other attribution 55 56Write commit messages as a human developer would — describe only what the code 57change does. 58 59GOOD: 60- "Fix race condition in file watcher initialization" 61- "Add support for custom key bindings" 62- "Refactor parser for better error messages" 63 64BAD (never write these): 65- "Fix bug found while testing with Claude Capybara" 66- "1-shotted by claude-opus-4-6" 67- "Generated with Claude Code" 68- "Co-Authored-By: Claude Opus 4.6 <…>" 69` 70 } 71 return '' 72} 73 74/** 75 * Check whether to show the one-time explainer dialog for auto-undercover. 76 * True when: undercover is active via auto-detection (not forced via env), 77 * and the user hasn't seen the notice before. Pure — the component marks the 78 * flag on mount. 79 */ 80export function shouldShowUndercoverAutoNotice(): boolean { 81 if (process.env.USER_TYPE === 'ant') { 82 // If forced via env, user already knows; don't nag. 83 if (isEnvTruthy(process.env.CLAUDE_CODE_UNDERCOVER)) return false 84 if (!isUndercover()) return false 85 if (getGlobalConfig().hasSeenUndercoverAutoNotice) return false 86 return true 87 } 88 return false 89}