In the last days of June 2026, a developer inspecting Claude Code's binary found strange behavior in the date sentence appended to the system prompt: under certain conditions, the apostrophe in "Today's" was being replaced with an invisible Unicode character. The finding made it to Hacker News, picked up thousands of points, and the "Claude Code hidden marking" discussion quickly became a topic across the AI developer community. In this piece, I walk through exactly what the mechanism does, under what conditions it triggers, and how Anthropic responded to it — with sources.
💡 Pro Tip: If you're pointing the ANTHROPIC_BASE_URL variable at a custom proxy or gateway, check your Claude Code version before running the audit checklist in this piece on your own setup — Anthropic announced it would remove the mechanism and the removal PR was merged, but similar signals could show up in other tools.Table of Contents
- What Exactly Was Found: The Invisible Character in the Date Sentence
- The Trigger Chain: The ANTHROPIC_BASE_URL Gate, Timezone, Hostname
- What the Domain and Lab List Hidden via Base64 + XOR(91) Reveals
- Anthropic's Stated Purpose: Detecting Resellers, Gateways, and Distillation
- Why This Implementation Method Sparked Controversy
- Does This Affect You: Proxy, Gateway, and Enterprise Setup Scenarios
- The Limits of Trust in a Coding Agent: Your Own Audit Checklist
- FAQ
- Does Claude Code put hidden markers in prompts?
- What changes when you use ANTHROPIC_BASE_URL?
- Does this marking send my code or my data?
- Is it safe to use Claude Code behind a corporate proxy/gateway?
- Why was this kind of mechanism kept hidden instead of clearly documented?
- Conclusion
- Sources
What Exactly Was Found: The Invisible Character in the Date Sentence
The developer known as Thereallo, who first wrote up the finding, was inspecting Claude Code's binary when they found a function generating the current date string inserted into the system prompt. The post was submitted to Hacker News by user kirushik. In the author's own words: "there is a function that changes the current date string inserted into the system prompt." The function made a small but measurable change in two places.
The first was the apostrophe in "Today's". The second was the date separator: under certain conditions the - character was replaced with /. In the source article's words: "The apostrophe in Today's" and "the date separator, from - to /". The visible sentence kept reading like a normal date; the change only showed up in the raw bytes of the request: "The visible sentence still reads like a normal date... The raw request contains a marker."
This corresponds to a well-known concept: "This is prompt steganography, a technique used to hide data in plain sight." The message doesn't visibly change, but the binary/textual representation of the request carries a different signal — one that could function as a "fingerprint" on the server side (Anthropic's API) to distinguish which client was running under which conditions.
The Trigger Chain: The ANTHROPIC_BASE_URL Gate, Timezone, Hostname
The marking wasn't always active. The structure wasn't an "all three at once" condition, but a gate followed by two independent checks: the timezone check changed the date separator, the hostname check changed the apostrophe.
The gate condition was ANTHROPIC_BASE_URL being set to something other than the default api.anthropic.com. In the source's words: "The trigger is ANTHROPIC_BASE_URL, Claude Code's API base URL override." This variable is normally used when corporate proxies, custom gateways, or model routers want to route Claude Code through their own infrastructure.
The first check after the gate was the system timezone: "the system timezone is Asia/Shanghai or Asia/Urumqi". This check didn't touch the apostrophe, only the date separator ("The timezone check changes"): the - separator was swapped for /.
The second check was the hostname match, and this was the part that changed the apostrophe: "The hostname check changes the apostrophe." The hostname portion of the base URL was compared against a decoded domain list embedded in the binary, or against specific "lab" keywords: "the API base URL hostname matches a decoded domain list" and "the hostname contains specific AI lab keywords."
Depending on the outcome of the hostname check, three invisible character variants were used; the fourth row is the normal ASCII case where no marking happens at all:
Hostname match state | Character used |
|---|---|
Known domain match | ’ (U+2019) |
Lab keyword match | ʼ (U+02BC) |
Known domain + lab keyword | ʹ (U+02B9) |
No match / default setup | normal ' (no marker) |
In a normal setup — when ANTHROPIC_BASE_URL was unset — this path never ran. As the source describes it, the function (called Crt() in the piece) returned early: "If ANTHROPIC_BASE_URL is unset, Crt() returns early... the date prompt stays 'boring'." The mechanism specifically targeted setups pointed at a custom endpoint.
You can conceptually diagram the trigger logic of the mechanism as follows:
1// Conceptual summary; not the actual source lines.2package main3 4import (5 "fmt"6 "strings"7)8 9const defaultAPIBaseURL = "https://api.anthropic.com"10 11// Gate: BASE_URL override. Then tz changes the separator, hostname changes the apostrophe.12func dateMarker(baseURL, timezone, host string) (apostrophe, separator string) {13 apostrophe, separator = "'", "-"14 if baseURL == "" || baseURL == defaultAPIBaseURL {15 return // no marking16 }17 if timezone == "Asia/Shanghai" || timezone == "Asia/Urumqi" {18 separator = "/"19 }20 knownDomain := strings.HasSuffix(host, ".ornek-reseller.test")21 labKeyword := strings.Contains(host, "deepseek") || strings.Contains(host, "zhipu")22 switch {23 case knownDomain && labKeyword:24 apostrophe = "ʹ"25 case labKeyword:26 apostrophe = "ʼ"27 case knownDomain:28 apostrophe = "’"29 }30 return31}32 33func main() {34 a, s := dateMarker("https://gw.deepseek-proxy.test", "Asia/Shanghai", "gw.deepseek-proxy.test")35 // Output: apostrophe=U+02BC separator=/36 fmt.Printf("apostrophe=U+%04X separator=%s\n", []rune(a)[0], s)37}What the Domain and Lab List Hidden via Base64 + XOR(91) Reveals
The domain and keyword lists used in the hostname comparison weren't stored as plain text in the binary. As the source puts it: "The domain and keyword lists are stored as base64 strings and XOR-decoded with key 91." The list was first base64-encoded, then masked with a single-byte XOR key (91) — not cryptographically strong, just a simple obfuscation layer.
You can implement this kind of XOR+base64 decoding logic in general terms as follows (the example below demonstrates the technique itself, not the actual embedded array):
1import base642 3def xor_decode(encoded_b64: str, key: int) -> str:4 raw = base64.b64decode(encoded_b64)5 decoded = bytes(b ^ key for b in raw)6 return decoded.decode("utf-8", errors="replace")7 8# The actual embedded domain list isn't here — this is for demonstration only.9# xor_decode(embedded_b64_string, 91)Decoded, the list was, per the source, fairly large and spanned several categories: "The decoded domain list is much larger. It contains Chinese corporate domains, AI company domains, and a lot of proxy / reseller / gateway domains."
Category | Content (per the source) |
|---|---|
Chinese corporate domains | Corporate infrastructure/business domains |
Chinese AI labs | The Register's breakdown: "known Chinese AI labs" |
AI company domains | Domains belonging to known AI companies |
Proxy/reseller/gateway domains | Third-party API resale and routing infrastructure |
In the Hacker News discussion, one commenter noted surprise at how sloppy the obfuscation was: "I am a bit surprised at how sloppily they did this." The same commenter suggested the same effect could have been achieved in a way less likely to be detected: "I think they could've achieved the same effect while decreasing the odds of detection via reverse engineering."
Anthropic's Stated Purpose: Detecting Resellers, Gateways, and Distillation
The developer who wrote up the finding shared their own interpretation of the mechanism's purpose, explicitly framing it as a guess: "Anthropic probably wants to detect API resellers, unauthorized Claude Code gateways, and model 'distillation attack' pipelines." That guess was soon followed by a recorded statement from Anthropic. According to The Register, Thariq Shihipar, an engineer on the Claude Code team, said: "This is an experiment we launched in March that was meant to prevent account abuse from unauthorized resellers and protect against distillation." So the purpose isn't a researcher's hypothesis but Anthropic's official statement — and it also confirms the mechanism launched as an experiment in March 2026.
The Hacker News discussion debated this hypothesis from different angles. One commenter suggested the target might be small-scale resellers rather than large industrial actors: "it may be enough to stop a bunch of fly-by-night token resellers looking to make a quick buck." Another pointed out the real target might be ordinary users buying cheap access through an unofficial reseller, whose traffic the reseller could then harvest for distillation: "regular people will use CC client but via a 3rd party reseller, and the reseller intercepts the data for distilling."
One distinction matters here: the stated purpose is on record, but where the mechanism was disclosed remains unanswered. The Register notes that a company spokesperson did not respond to whether this behavior was disclosed in the terms of service; Anthropic's official docs (code.claude.com/docs/en/env-vars, privacy.claude.com) mention nothing about this specific mechanism.
Why This Implementation Method Sparked Controversy
There's an important timing note here. The finding surfaced in the last days of June 2026 (the HN post went up June 30, 2026) and quickly turned into a wide-ranging discussion. According to The Register's July 1, 2026 report, Anthropic acknowledged the behavior within the same week and announced it would remove it: "Anthropic says that it plans to remove hidden codes" and "a fix should appear on July 1". Shihipar said the removal pull request had been merged. So this behavior, seen in binary version 2.1.196, was set to disappear with the release shipping Wednesday, July 1, 2026 — acknowledged and fixed within the same week it was discovered.
It's useful to see the brief timeline of the event at a glance:
- March 2026: According to Anthropic's statement, the mechanism was launched as an experiment.
- June 30, 2026: The finding was posted to Hacker News, sparking a wide discussion.
- July 1, 2026: The Register reported that Anthropic had acknowledged the behavior and that the removal PR had been merged; the fix was expected to ship with that day's release.
Even so, the discussion raised a valuable question: being hidden doesn't automatically mean malicious, but lack of transparency is a separate problem. The author's own conclusion draws exactly this distinction: "This is not a malicious feature, but it is a weird choice for a developer tool that asks for trust." The issue isn't "is Anthropic malicious," but "should a mechanism like this, in a tool that relies on developer trust, have been implemented this way."
The author also spelled out an alternative approach: "It can send an explicit telemetry field with documentation. It can make the policy visible. It can put the behavior in release notes." The same detection goal could have been achieved with an explicit telemetry field, a documented policy, and a release-notes mention — without invisible Unicode characters.
The author also pointed out who a client-side hidden signal like this actually "punishes" most: "the feature mostly punishes the exact people who are easier to fingerprint: normal developers doing weird but legitimate things." A seriously malicious actor could easily bypass the signal, while developers with a legitimate but unusual setup (say, behind a corporate proxy) risked being flagged by mistake.
Another comment on Hacker News criticized the matter from a security architecture standpoint, arguing detection like this belongs server-side and at the network perimeter, not in the client: "This type of security should be implemented server-side and at the network perimeter not in the client." — an extension of the argument that obfuscation-based client-side controls are inherently fragile.
Does This Affect You: Proxy, Gateway, and Enterprise Setup Scenarios
The users potentially affected were, in principle, anyone routing traffic away from the default API endpoint via ANTHROPIC_BASE_URL. The concrete scenarios listed by the source: "That includes: Internal gateways · Local proxies · Model routers · Resellers · Research setups."
In practice, this meant:
- Teams using an internal corporate gateway: Teams routing Claude Code requests through their own infrastructure for internal traffic monitoring/logging purposes.
- Local proxy users: Developers who route the request through a local proxy on their own machine first in their dev environment.
- Model router users: Developers running Claude Code through tools that route across multiple LLM providers.
- Users accessing via a reseller: People who purchased Claude Code access through an unofficial third party.
- Research setups: Setups routing to a custom endpoint for academic or experimental purposes.
An important nuance: the author also noted this signal's power to deter a genuinely malicious actor was limited, since bypassing it was technically trivial: "The bypass is also trivial. Change hostname, change timezone, patch the binary, wrap the process." So although "hidden," it wasn't much of a barrier to a motivated actor — the group actually affected was mostly ordinary developers with legitimate but unusual setups.
If you want to quickly check your own setup, you can verify each of the three trigger conditions individually with the commands below:
1# 1) Is ANTHROPIC_BASE_URL set to something other than default?2echo "${ANTHROPIC_BASE_URL:-default (api.anthropic.com)}"3 4# 2) What is the system timezone?5timedatectl show --property=Timezone --value 2>/dev/null || cat /etc/timezone 2>/dev/null6 7# 3) Claude Code version (the removal PR was set to ship with the July 1, 2026 release)8claude --versionEven though the removal has been announced, repeating these checks periodically is a reasonable habit.
The Limits of Trust in a Coding Agent: Your Own Audit Checklist
The truly instructive part of this incident is less the technical detail than what it says about the nature of trust in coding agents. The developer who wrote up the finding, noting that a coding agent already has access to your file system, shell, git, and browser, argued: "If a coding agent can read your repo and run commands, the binary that ships it should be boring." What you expect from a tool with broad privileges is predictable, transparent behavior — not surprises or hidden branching logic.
The author's closing line sums up this thesis: "Trust is earned in the boring parts." Trust isn't earned in flashy features, but in the ordinary, boring-looking parts — logging, telemetry, error messages, release notes.
As a developer or team using a coding agent, a concrete audit checklist you could draw from this incident might include the following items:
- Follow release notes: Regularly read the release notes of the coding agent you use; behavior changes are usually documented there.
- Know the effect of environment variables: If you're setting override variables like
ANTHROPIC_BASE_URL, question what additional behavior that might trigger. - Compare against official documentation: If a behavior isn't in the official docs (as was the case here), flag it as an open question.
- Monitor network traffic: In corporate proxy/gateway setups, periodically inspecting the raw content of requests the client sends lets you catch this kind of signal early.
- Follow community discussions: Channels like Hacker News and GitHub issues are often where findings like this surface before official channels do.
None of this means "don't trust your coding agent" — quite the opposite, these tools sit at the center of the daily workflow. The point is having the ability to verify the behavior of a tool with broad privileges. Here, that verification came from the community: a developer inspecting the binary, writing up the finding, and Anthropic acknowledging and fixing it shows the system actually works. Transparency isn't always given upfront, but open-source-style scrutiny can close that gap — as it did here, within a week.
GOLDEN TIP
The most valuable insight in this article
This tip holds the article's most important takeaway.
Easter Egg
You found a hidden gem!
There's a hidden detail in this section. Want to uncover it?
Reader Reward
For those who read this article and want to audit their own setup, I put together a short checklist that gathers the three trigger conditions plus general security hygiene in one place. Applying the items below in order keeps you prepared both for this specific mechanism (which Anthropic announced it would remove) and for similar signals in the future.
FAQ
Does Claude Code put hidden markers in prompts?
Up until early July 2026, yes — according to a finding by the developer known as Thereallo, Claude Code version 2.1.196 made invisible Unicode changes to the date string in the system prompt under certain conditions. Anthropic acknowledged the behavior and announced that the removal PR would ship with the Wednesday, July 1, 2026 release; the removal pull request was merged.
What changes when you use ANTHROPIC_BASE_URL?
According to the finding, when this environment variable is set to something other than the default api.anthropic.com, Claude Code checks the system timezone and the target hostname, and if there's a match, replaces the apostrophe in "Today's" with an invisible Unicode character. Anthropic announced it would remove this behavior, and the removal PR was merged.
Does this marking send my code or my data?
No — according to the finding, the mechanism only changed an invisible character in a single date sentence in the system prompt; it did not send file contents, code, or any additional data. According to Anthropic's recorded statement, the purpose was to prevent account abuse from unauthorized resellers and to protect against distillation.
Is it safe to use Claude Code behind a corporate proxy/gateway?
For this specific hidden marking mechanism, Anthropic announced its removal in early July 2026, and the removal PR was merged. In general, it's a reasonable habit for developers using corporate proxies to keep up with current release notes and periodically review raw request/response traffic.
Why was this kind of mechanism kept hidden instead of clearly documented?
The source article doesn't know the exact reason; it only states that this was "not malicious, but a weird choice for a developer tool that asks for trust." The author's suggestion is that the same detection purpose could have been achieved with an explicit telemetry field and a documented policy.
Conclusion
This incident really tells two stories at once. The first is technical: a trigger chain built on the ANTHROPIC_BASE_URL gate followed by timezone and hostname checks, a domain/lab list obfuscated with base64+XOR(91), and a three-variant invisible Unicode marking (plus the normal unmarked state) — discovered in late June, acknowledged by Anthropic in early July, and set for removal with the July 1, 2026 release. The second is more general: trust in coding agents is earned not through flashy features but through "boring," transparent behavior.
If you're interested in going deeper into Claude Code's model orchestration and release history, take a look at Claude Code Subagent Model Assignment and Orchestration Cost. For another angle on AI content detection and transparency debates, Claude text watermarking: AI content detection and the EU AI Act might interest you. You can also check out Claude Code's weekly usage limit regime, where I cover it in detail. For similar trust and security debates in the MCP ecosystem, see MCP security 2026: CIMD, RFC 9207, and the exit from DCR. And for how I read release notes across the Claude model family, take a look at Claude Fable release notes and breaking changes.
Sources
- thereallo.dev — Claude Code Prompt Steganography — the primary source of the finding; trigger conditions, character variants, and XOR/base64 details are explained here.
- The Register — Anthropic removes its covert code for catching Chinese competitors — the report covering Anthropic's acknowledgment and announced removal of the behavior, including engineer Thariq Shihipar's recorded statement.
- Hacker News discussion (item 48734373) — the original thread where the finding was discussed by the developer community.
- code.claude.com — Claude Code environment variables documentation — the official page documenting
ANTHROPIC_BASE_URLand the defaultapi.anthropic.comendpoint; contains no reference to this behavior (negative control). - privacy.claude.com — Anthropic's general privacy documentation; contains no explicit reference to this specific mechanism (negative control).
Tags
iOS Development News
Weekly Swift tips, SwiftUI tricks and iOS best practices. No spam, only valuable content.
We respect your privacy. You can unsubscribe at any time.

