cchistory:追踪 Claude Code 系统提示词与工具变更
cchistory: Tracking Claude Code System Prompt and Tool Changes
Mario Zechner 推出 cchistory.mariozechner.at,可选择两个 Claude Code 版本对比系统提示词、工具定义及首条用户消息附加内容的差异。该工具基于其此前开发的 claude-trace,后者通过 monkeypatch fetch 记录 Claude Code 与 Anthropic 服务器的请求-响应对,并可从 npm 下载旧版本 Claude Code 运行采集。
正文
当前显示原文,中文全文译文尚未就绪。
2025-08-03
Today I got nerd sniped by Thomas. He suggested someone (wink wink) should collect the system prompts of various Claude Code versions and maybe show diffs. Naturally, I couldn't stop thinking about that for a while and decided to just implement it.
I've been using Claude Code for a couple of months now and have become part of the 5% (sorry, not sorry). As a heavy user, I've become very sensitive to changes in the system prompts and tool definitions, which generally express themselves through Claude using tools differently, sometimes less efficiently, sometimes more efficiently, depending on the changes. So this isn't just me falling for a nerd snipe. It's also me creating a tool that helps me understand why Claude does things the way it does.
You can now visit cchistory.mariozechner.at to select two Claude Code versions and see the changes to system prompts, tool definitions, and any additional information Claude adds to your first user message. (I LOVE iframes.)
Here's how that works.
Hacking Claude: claude-trace
Thankfully, I already had most of the infrastructure ready to get this going. A few weeks ago, I wanted to better understand how Claude Code works so I could improve my usage of it. I wrote a tool called claude-trace, which allows you to record all request-response pairs Claude Code makes to Anthropic's servers. This gives us full introspection into what's going on behind the scenes, and that includes system prompts and tool definitions. From these request-response pairs, claude-trace builds not only a log you can use, but also a self-contained HTML file that renders your conversation like below (click and scroll around):
Want to get to the request-response pairs? First you gotta debug the Claude binary. The beautiful thing about the Node.js ecosystem is that you don't need IDA, Ghidra, or Frida. Just open the big-ass file, format it with Biome, search for "inspect-brk" or "debug", locate the anti-debug function, and rip it out. Here's Claude's anti-debug:
Once you can attach a debugger, things become even more interesting. You can search for strings being output during program flow and set breakpoints. You can observe all kinds of things. And eventually you find out that Claude Code is just using Anthropic's SDK, which makes sense. And that SDK is just using fetch.
Informed people would have used a man-in-the-middle proxy. I like doing things the stupid idiot way. So to capture request-response pairs, I inject a little bit of JavaScript into Claude Code that monkeypatches fetch, intercepts all communication between client and server, and writes that out to a JSON file on disk. This JSON file contains the full HTTP request and response pairs from which I can fully reconstruct the conversation.
Now even more informed people would say: "Wait Mario, Claude Code actually stores the entire conversation on disk in JSONL files in the .claude directory in your home directory." You'd be right, this could also be parsed. However, this doesn't contain things like the system prompt, the tools, and all the other stuff I'm interested in.
They also don't include requests to the Haiku model, which are very entertaining.
Haiku this, Haiku that
Here's what Claude Code uses Haiku for:
To generate those little whimsical messages you see while you wait for a response for every. token. you. input:
To generate a summary of the conversation for the resume feature (I think):
Or to generate a title for your terminal based on what topic you're currently talking about:
Or to check if a bash command that Claude tries to execute on your disk has some form of injection with which it tries to escape the sandbox:
Which is an interesting party trick: letting one LLM judge whether a bash command by another LLM is dangerous. YMMV.
With the request-response pairs in hand, I do a little data munching and write out the HTML file. And that's how claude-trace works.
claude-trace eventually got a sibling called claude-bridge, which allows you to swap in other models and providers instead of Anthropic's Claude. Here's a thread on the site that shouldn't be named where I show how well this works with different providers. Spoiler: it doesn't work very well. Not because of claude-bridge, but because Claude Code is obviously tuned for Claude, and because other models are simply not as good at tool calling. They usually just shit the bed in various forms and colors. Beautiful, really.
Hacking Claude Again: cchistory
With claude-trace in hand, cchistory was really just a two-hour vibe coding job. The basic principle is that I run claude-trace passing -p "hello" to Claude Code, which will generate a single request-response pair that claude-trace stores on disk in a JSONL file. This includes the system prompt, the tools, and the first user message with any augmentations that Claude Code makes.
But there's a catch. This obviously only gives me the system prompt, tools, and augmentations for the current Claude Code version I'm running.
Luckily for us, the system prompt and tool definitions are part of the Claude Code binary. This means we can just download old versions of Claude Code from npm and run them through claude-trace as described. But there's of course another catch.
As part of Claude Code startup, it checks what the current version is and compares that to its own version. If it's outdated, it just exits.
Now expert software engineers would say: "Oh, we can just parse out the system prompt and tool definitions from the Claude Code binary."
That's a cool idea, except that prompts are full of string interpolation or whatever your kids call it. You actually need to run Claude Code to get the full system prompt and tool definitions.
So how can we make Claude Code continue even if it's outdated? Well, as the world's leading JavaScript hacker man, I'm simply applying the same method I used to patch Claude Code for debugging. cchistory looks for the string "It looks like your version of Claude Code", then locates the first "function" string before that, and then matches curly braces. This finds the full "check if version is older and exit" function, which may have a different name between different Claude Code versions due to obfuscation and minification. Once I have located that function, I strip it out.
And tada! I can now run any old Claude Code version.
The only thing left then is to enumerate all the Claude Code versions that have been released. I start at 1.0.0, download them all, run them all through claude-trace, and write the system prompt, tools definitions, and augmentations of the first user message to a markdown file. These markdown files can then be compared with each other via diffing, which tells us what Anthropic changed in the system prompts, tools definitions, and augmentations between versions.
Add a simple website with the Monaco editor at 3 megabytes in size to show diffs between markdown files. And bam, you got cchistory.
So what can we observe?
Findings from the Diff Mines
Now there's a lot to learn from these diffs and I don't wanna spoil all your fun. So here are just a handful of observations about what has changed in the system prompts, tool definitions, and user message augmentations between versions 1.0.0 and the latest at the time of writing, 1.0.67.
User Message Changes
I suppose this one was removed because Claude was happy to remove a lot of things it shouldn't have removed.
We all strive to minimize the pollution in our contexts and then Claude Code comes along and just spits something in there and then tells Claude, "eh, this may or may not be relevant." At least they shortened that IMPORTANT instruction.
System Prompt Changes
This triggers quite a bit when I work on C, C++ code bases with assembly mixed in. At least they made it shorter. And while it has stopped refusing modifying non-malicious code for me, it still doesn't like changing a license file from MIT to GPL, because that's a big no-no. Seems to be enforced server-side.
They like their new security instructions so much they duplicated it.
I fucking hate emojis and LLMs injecting emojis into every little nook and cranny they can find. So this is a welcome system prompt change. Doesn't always work, but it's getting better.
Damn right, who needs to know what bash commands are doing? YOLO all the way. Though this might actually have to do more with decreasing the amount of requests to the overloaded servers.
Something I turn off in every new Claude Code installation is to-dos. And now, Anthropic has actually stopped telling the model to read the to-dos (because I think the current to-dos are returned by the TodoWrite tool).
And from the department of context pollution, they stopped adding the entire project file structure to the system prompt. Good stuff.
Tools Changes
The Bash tool has a metric ton of instructions in it. Previously, the PR analysis was wrapped in XML tags. Not quite sure why. They removed that, but they kept the very important three exclamation marks.
Still in the description of the Bash tool, appears that the Claude Code team has discovered multiple branches can exist in a repo. (Excuse this little quip. Love you, team.)
The Edit tool received additional emoji defenses. Everybody hates emojis now.
I love this change to the Grep tool. Previously I had a fucked up alias for grep, Claude would keep using grep via Bash, passing parameters my aliased grep would choke on. Since this change, the situation has improved vastly. (And I also fixed my alias.)
Oh wow! Claude Code can now natively read PDFs. Probably converting them to Markdown and then poisoning the context completely. It's amazing! Seriously though, this seems like a useful feature for the Read tool.
And finally, the Write tool also got emoji restrictions. Consistent with other editing tools. Fuck emojis.
Wrapping Up
Well, this was a fun ride. The cchistory website updates every 30 minutes, so if there's a new Claude Code release, you'll see it there with all the juicy diffs ready to explore.
You can also run cchistory yourself locally, provided you have Claude Code installed and are logged in:
This will fetch all the prompts for versions between (and including) 1.0.0 and the latest version into your current working directory. You can then analyze or slice and dice things however you want. Yes, I'm a master at creating CLIs.