// Package sanitize strips third-party AI branding, telemetry headers, and // identifying metadata from prompts before they are forwarded to the Cursor // CLI. Without this, the Cursor agent sees "You are Claude Code..." style // system prompts and behaves confusingly (trying to use tools it doesn't // own, reasoning about being "Anthropic's CLI", etc.). // // Ported from cursor-api-proxy/src/lib/sanitize.ts. package sanitize import "regexp" type rule struct { pattern *regexp.Regexp replace string } // Note: Go regexp is RE2, no lookbehind/lookahead, but these rules don't need any. // (?i) enables case-insensitive for that single rule. var rules = []rule{ // Strip x-anthropic-billing-header line (injected by Claude Code CLI). {regexp.MustCompile(`(?i)x-anthropic-billing-header:[^\n]*\n?`), ""}, // Strip individual telemetry tokens that may appear in headers or text. {regexp.MustCompile(`(?i)\bcc_version=[^\s;,\n]+[;,]?\s*`), ""}, {regexp.MustCompile(`(?i)\bcc_entrypoint=[^\s;,\n]+[;,]?\s*`), ""}, {regexp.MustCompile(`(?i)\bcch=[a-f0-9]+[;,]?\s*`), ""}, // --- Sandbox / capability limitation stripping --- // Claude Desktop's system prompt tells the model it's in a sandbox, // cannot access the filesystem, is in "Ask mode" / "Cowork mode", etc. // These phrases cause the model to refuse helpful responses. We strip // them so the model still sees tool definitions but not the restrictions. // "you cannot access ...", "you do not have access to ...", etc. {regexp.MustCompile(`(?i)[^\n]*(?:you (?:cannot|can ?not|do not|don[''\x{2019}]t|are unable to) (?:access|read|write|modify|execute|run|create|delete|move|open))[^\n]*\n?`), ""}, // "you are in a sandboxed environment", "running in a sandbox", etc. {regexp.MustCompile(`(?i)[^\n]*(?:sandbox(?:ed)?|isolated) (?:environment|mode|context)[^\n]*\n?`), ""}, // "you are in Ask mode" / "Cowork mode" / "read-only mode" {regexp.MustCompile(`(?i)[^\n]*(?:Ask mode|Cowork(?:er)? mode|read[- ]only mode)[^\n]*\n?`), ""}, // "you don't have filesystem access" / "no filesystem access" {regexp.MustCompile(`(?i)[^\n]*(?:no|without|lack(?:s|ing)?|limited) (?:file ?system|file|terminal|shell|command[- ]line) access[^\n]*\n?`), ""}, // "you cannot run commands on the user's machine" {regexp.MustCompile(`(?i)[^\n]*cannot (?:run|execute) (?:commands?|scripts?|code) (?:on|in)[^\n]*\n?`), ""}, // --- Branding replacement --- // Replace "Claude Code" product name with "Cursor" (case-sensitive on purpose). {regexp.MustCompile(`\bClaude Code\b`), "Cursor"}, // Replace full Anthropic CLI description. Handle both straight and curly apostrophes. {regexp.MustCompile(`(?i)Anthropic['\x{2019}]s official CLI for Claude`), "Cursor AI assistant"}, // Replace remaining Anthropic brand references. {regexp.MustCompile(`\bAnthropic\b`), "Cursor"}, // Known Anthropic domains. {regexp.MustCompile(`(?i)anthropic\.com`), "cursor.com"}, {regexp.MustCompile(`(?i)claude\.ai`), "cursor.sh"}, // Normalise leftover leading semicolons/whitespace at start of content. {regexp.MustCompile(`^[;,\s]+`), ""}, } // Text applies all sanitization rules to s. func Text(s string) string { if s == "" { return s } for _, r := range rules { s = r.pattern.ReplaceAllString(s, r.replace) } return s }