RE: https://neuromatch.social/@jonny/116324676116121930

Part 2 of exploring The Claude Code Source Leak Exclusion Zone continues here.

(the reply tree under the prior thread is getting expensive to render and the bottom no longer renders unless you're logged in lol)

end of prior thread: https://neuromatch.social/@jonny/116345400731237947

One thing that's odd about this package is the amount of internal, anthropic-specific tooling that's in it. Aside from the sort of comical gating behind the USER_TYPE='ant' env var, normally in a well designed package you would expect that it would provide proper hooks so that internal tooling could just be a set of plugins rather than in the source itself.

Claude code does have a number of extension points: agents, hooks, plugins, skills, and tools - even if their structure is somewhat, ah, gestural.

Some things could potentially become features (like the MagicDocs thing, even if that's a comically expensive idea, i'll write more about that later tho), but there are also some things that make no sense to be in here. Like in the startBackgroundHousekeeping task there is an 'ant'-gated task to clean their .npm-cache directory.

There are even notes in here like "this used to block the whole event loop" which you think might have indicated that they might have, say, "just written some separate cron task that runs totally outside claude code." So it seems like "writing claude code with claude code" leads to a collapse of separation of concerns, where anthropic can't really manage the distinction between their projects to the point of inlining the devtools - this can also be seen in comments re: code duplication with Cowork, which i'll also get to later. It also confirms what they say publicly, that they just have claude code sessions running 24/7 (where having a task run every 24 hours makes sense)

Something I'm trying to track down is how this remote claude session thing works. A general pattern in the claude code source is that more recent features are implemented in a way more chaotic way than more "core" features, which reflects the nature of vibe coding: because you don't have a solid foundation, and there is a progressive layer of crust and special cases, the only real way to add more features is to keep adding more crust and special cases. Like rather than having a set of blocks that are self contained and you add another block, you need to slice across all the prior blocks and add something to each of them.

There are a number of places, both in comments and code, that rely on "this session is running in claude code remote session" in some VM, and so therefore they use the filesystem for state (e.g. storing the api and oauth keys), but those parts of the code are in no way cleanly isolated from the rest of the code. So I suppose if i were a pentester or security auditor or whatever what i'd be looking for is places where the mashup of "in remote session / not in remote session" assumptions fails, and we do something naughty on the host system rather than a VM. Like I said still reading, just sort of musing about some of the problems with the package that are larger than individual functions and features.

(We are in the more thoughtful, large scale evaluation of this thing, so it may be more boringer than the more popcorn style snapshots of wow that's fucked up. But those small fucked up things are also the easiest to fix, where what I am trying to get across now is the larger intractable problems in how things work and how they are built)

So there is a feature in claude code: /statusline that is a reasonably good example of a feature that promises a natural language interface to do something that should be simple when done programmatically: here's some callback that shows some values or progress or whatever on a line in my TUI while i use the tool. How does that work?

Well when you call /statusline {progress bar on the withering decay of my life} , first you encounter the statusline "command." there's a lot to see even in just this declaration so we'll take it slow.

first is in allowedTools: You might think that ToolName(params) syntax is some standard thing, where tools have a short name, and then everything inside those parens gets passed as some standard argument to a permission checker. That is not the case: the codepath that parses those rules is only used for the filesystem (read, write, edit), shell, and agent tools, the rest just ignore it. There are in fact two implementations of a parser that splits out the tool name from its params: one in permissionSetup and another in permissionRuleParser that do slightly different things, twice.

What does this look like from the point of view of a tool? The permission given here is ~/** , or anything within my home directory, which is neat that that's so easy to declare and entirely escapes any other rules I have declared for directory scoping. The Read tool doesn't receive that, instead it receives a ToolUseContext object, where then one access the whole app state, and then additionally gets the toolPermissionContext which includes all the rules unparsed. So then the Read tool needs to parse every rule in entirely custom logic to even extract those params, let alone process them.

Parsing every single rule happens up to six times per tool call that I can see, but the Read tool doesn't just process the params in a Read(~/**) rule - since it has access to all the rules it might as well use them - it also checks for edit and write access, among a handful of other invisible exceptions: since every tool has access to the entire set of rules every time, not through dependency injection just like "the check permission callback passes the entire program state" kind of way, it sure as hell uses them.

So there's no consistency to how rules are set, there's special behavior to how they are parsed, passed, interpreted, and applied for every single tool, and since it is the tool itself that decides whether it is allowed to run - rather than some idk ORCHESTRATOR THAT SHOULD SERVE AS THE ENTIRE BACKBONE OF WHAT CLAUDE CODE IS, it can just return true and always run. So that's why there aren't any plugin tools for claude code (they say use MCP instead), because they are intrinsically unsafe and have no real structure.

ok having fun? we haven't even talked about statusline

So returning to statusline: what the fuck? A command has some callback getPromptForCommand - there are two basic kinds of commands, those that "do something" and are a function call, and those that are "prompt commands" which just return a prompt back to the main LLM loop.

To to set your statusline, the statusline command creates prompt text that TELLS THE MAIN LOOP to SPAWN AN AGENT with a given prompt. note that this does not directly spawn an agent, it is merely a suggestion. so right off the bat it is POSSIBLE TO FAIL EVEN INVOKING the command.

But before we get there, we have to pass through what happens after a slash command is issued, and one of the steps along the way is "if something looks like a slash command but we don't know about that command, then throw it back up to the main loop with some special Caveat Message that says "ok just ignore this please"

quick aside - is there anything more emblematic of the way this entire thing undermines human agency than the fact that there are some commands that the user cannot invoke and instead must ask the LLM to invoke for them

I am going to breeze past all the code duplication in the processSlashCommand for now - again, as I have said before, every line of this package is fucked up in a unique way so it's very hard to describe just how one thing is fucked up at a time.

There is a special mode for claude "coordinator mode" where the entire thing claude does is dispatch commands to other sub-agents. so in that case, we are three layers deep in self-prompting: the LLM is prompted to output some prompt text that informs a subagent that it should call some skill which then returns a prompt that instructs the LLM to spawn some additional subagent to create statusline for us. sound good?

but assuming we're not in coordinator mode, the prompt that instructs the main LLM to create an agent with the prompt text to create our statusline script is emitted, and if that works, then an agent will be run with the statusline system prompt, which is awesome.

So the prompt tells the LLM to modify the $PS1 variable in the shell configuration. for those non-computer touchers out there, the PS1 variable is the thing that customizes "what happens before my cursor on the shell line" - it's what makes it so sometimes it shows that folder you are in, and how people make their terminal look very fancy.

So the prompt text includes a whole fake JSON string that says "write a function that receives these kinds of parameters and then returns a whatever"

observe the prompt text in first image's description of fields and then the description on the claude code docs website. notice that they are ... different!!! like where is the cost field in the prompt description? the docs give a whole example of using this, but if you were to invoke it via the slash command, then it would just have no idea how to do that. the only way this succeeds is by virtue of the fact that the llm is just generating the most likely text anyway and so the odds of any of this succeeding are just "that some script that calls some variables with some maximally likely names represent some value that is maxmially likely, based on the training set prior."

We also reach the familiar pattern: begging the LLM to keep what already exists, which is a pretty challenging thing to do when you are being explicitly asked to change what already exists.

Also notice the closing IMPORTANT note - if the user is not happy with whatever was produced, that the LLM will hold in its context some instruction with the name of the agent to invoke to make further changes. So any appearance of some UI loop where you gradually refine the statusline is statistical coincidence

But wait! we can produce some bash script at ~/.claude/statusline.sh, but we were also given permission to read the user's ~/** and told to read the PS1 in their local configuration! how does this work again? what is going on? How is the statusline actually invoked by the program?

it turns out that all that stuff about PS1, and the entire need to access our local configuration is totally irrelevant! instead we have another incoherent call chain to actually invoke it - the TUI builds the input args, calls executeStatusLineCommand, which then routes into some execCommandHook function which is 600 lines long and handles ... uhhh.. wait no it just handles the status line command and one other thing... and uh... fuck the entire hooks system is ah... there isn't really a concept of a 'command-based hook' except for in this one context so... , well.... ok let's just say it goes into one of hundreds of "execute something" functions.

So what happens is that even though the whole TUI is an execution environment that behaves like a shell and controls all string rendering, it then invokes your system shell to run your statusline bash script and return a string. even that is too simple by half - there's actually a whole command wrapping system and the ability to execute further agents off the results of stdout

See what i'm saying about the yarnball of bullshit being impossible to stop unraveling once you start pulling at any single thing?

Pause and reflect. What were we doing here again? oh right, a custom status bar.

The way this might be done in any other normal program is by saying "you can declare a function that return a string, it gets these things." and then you might "call that function with those things" and "print the result in a specific location." That might take someone a few minutes.

In order to make it a natural language controlled magical feature, what we had to do was write some description, submit it to the main LLM loop, which tells a subagent to go read my whole shell configuration and integrate that into the context window, compose some bash script based in incorrect information that I never see and have no means of correcting, save that in a file, return some prompt string to the parent agent that instructs it to edit my local configuration to invoke this bash script, and then it throws that and the rest of the system state into a call chain that is shared with a random subset of other shell based commands, executes that, and passes that string back into the TUI environment for display. If i need to make edits to this script, I don't necessarily know where it is or how it's configured, but I can invoke another round of agent editing maybe if the parent agent correctly interprets the prompt command from the subagent to spawn the same kind of agent.

simple right?

So that's one command, next time we'll see how the /plan command works and how every command works differently top to bottom just like every tool works differently top to bottom because there is absolutely nothing in this package that makes a goddamn bit of sense.

just tested and yes it incorrectly concluded that cost information is not present in its arguments even though it is, created a hardcoded version of some cost estimator for the current model that outputs wildly varying amounts and hardcodes most of the values to zero. it used 0% of the information from my $PS1 so that entire part of the implementation is irrelevant noise, and the cpu usage of my terminal window while idle roughly doubled. great job.

to its credit, it actually did get the price values correct for the model. to not its credit, those values are in its system prompt.

to be clear - what does this one extremely simple feature reflect for the user?

In the "traditional way," the user can go to a website and see an example of how to do this themselves with information that's derived from the actual values used in computation. cool.

In the "LLM way," the user has no agency, can't see why the LLM might fail because they can't see the system prompt is directly feeding in the metadata about the available fields and thus has no idea that the model is capable of being wrong about its own fucking code and so they are shown wrong fucking values.

So the cost of transforming something to the "just prompt it" modality is "it being completely fucking wrong" even when that thing is literally just a feature that refers to the program state that is entirely owned by the fucking program" - to say nothing about how that pattern of development being recursively applied to the develpoment of the tool causes it to be fucking wrong as a matter of practice.

the perennial question of "well when i do it with a normal thing it mostly works" deserves a proper answer, but for now - the problem is that people don't always do normal things, and when if the surface of people not doing normal things is "any arbitrary code could be executed in any extravagant fuck you complexity including the LLM deciding to just yolo your browser history onto pastebin" (though see the "don't throw browser history onto pastebin prompt) vs. "the program throws an error and stops" then software stops being possible.

The entire notion of "a software supply chain" and being able to build more complex things off a tree of dependencies that mostly do the thing that they say is completely undermined as soon as you introduce the nonsense transformation gas cloud.

@jonny

I seldom do "normal" things. I'm almost always an outlier - you know, where learning and creativity happen.

If people are stung whenever they get confident enough to try new things, explore new ideas, their creativity is curtailed and the models themselves have yet another way to inhibit learning, crush creativity and prevent the generation of new content for them to gobble up and regurgitate.

Every time I see more, #LLMs problems grow.

@happyborg @jonny

“Sometimes the critical constraining resource is what you can and can’t imagine.”

Jonny, I appreciate you and the work you are doing in these threads. Thank you so much.

For me when I look at this code and how inchoate it is I end up not wanting to imagine anything with it.

For a non-coder maybe the capability sparks their imagination.

I find this very puzzling and disturbing.

Another path I took 15 years ago.

https://learnmaketeachshare.org/creating%20with%20software/2018/09/15/imagining-what-could-be.html

Imagining what could be.

Sometimes the critical constraining resource is what you can and can’t imagine. In 2011 Google Foundation gave us a large un-solicited grant to recreate an HTML5 version of our Java program Molecular Workbench. I desperately wanted to shift what people imagined was possible.

Learn Make Teach Share

@jonny

Nonsense Transformation Gas Cloud is a Squarepusher side-project you can't fool me

@jonny

post-apocalypse cartoon caption: "sure, we depleted the water supply for many cities, but sometimes we output a status line"

@jonny I would be impressed by their commitment to the bit but this is just fanaticism
@jonny good idea that you started new thread.
Thanks again for writing this up.
I guess now anthropic can take all your analysis and add it to their prompt/context, sure it will make the next version of claude code better, am i right
@prema my descriptions will probably cover about 1% of the code, so i suppose i am giving that prompt fodder for free - the problem is that the entire dynamic of the development empirically does not produce outcomes that we might expect from normal development like "receiving feedback, resolving problems, and adapting approach" but instead produces outcomes like "make a bunch of momentary code jitter in response to the immediate present without regard for the larger design implications for the rest of the package and so the 1% that is described just drifts further into special case territory against the 99% unmentioned"
@jonny @prema Do not forget to include invisible unicode encoded additional instructions 😆
@jonny @prema I really love how much money is spent on asking the computer to please not do mistakes. I mean, we all had seen the CLAUDE/AGENTS.md files of open source projects but the incompetence goes all the way up
@prema @jonny we are always just one good prompt away from hittin it big
@jonny this feels like a "how many agents does it take to change a lightbulb" joke, except the answer is: "It's for entertainment purposes only: don't let it change a lightbulb!'
@discontinuity @jonny Get used to darkness or get left behind!

@jonny I feel like there is an attack vector here in the sense that (according to an Anthropic study) it takes only 250 malicious samples in the training data to fuck with the thing.

So if they have it vibe code its internal commands on the fly, it might be possible to inject code here by posting shit on the internet.

@scheme i am trying to steer wide and clear of any security analysis because it is not my lane but
@jonny this is The Future, Jonny. Get On Board or Get Left Behind
@pikesley
Going to surprise everyone when the conclusion of this thread is "after a deep analysis of the Claude code source, I have concluded it whips ass and everyone should use it"
@jonny All of this code is a complete garbage fire.
@jonny computer says no
@SnoopJ @jonny we thought that was going to be the problem and certainly in some systems it still is, but I wasn't ready for the world where "computer says 'great job boss, you're brilliant and that is a fantastic idea'" is actually a way bigger problem
@glyph @SnoopJ @jonny IMHO it's the same problem, authority bias.
@Dany @SnoopJ @jonny the reason the second thing is worse is that it's two problems now; authority bias and … I don't know if we even have a term for this, but the driver of "elite panic" democratized for everyone, conditioning via sycophancy
@glyph @SnoopJ @jonny No, i mean "authority bias" describes both of them. Does not matter whether a person in servitude apes authority or if authority apes itself. Huh... we need to stictly define "authority". That could be problematic these days. He.
@jonny It's almost as if the whole point (alright: one of the main points) of the scam is to convince the user that "the AI knows best".
@jonny that's what I feared as soon as I heard "oh yes you are totally safe, just run this agent on your data and let the program itself decide which files it wants to edit and which files its allowed to edit" :(
@jonny thanks for digging into this for our entertainment, sounds painful

@jonny

I'm definitely not a professional programmer, but the more of this leak I see, both from you and from others, the more convinced I am that, at least once upon a time, there was an idea of a core of halfway decent code in there, somewhere. That they were actually trying to make SOMETHING that didn't totally suck to maintain, and could actually cleanly scale.

Then they all ran their brains through the ChatGPT grinder a couple thousand times, and what came out is this vibeslop mess of completely insane, totally unmaintainable spaghetti that somehow is the Messiah™ of all programming to come to thousands of reddit and twitter sysadmins.

And one of the few big questions I can even think of to ask is: How can anyone, with ANY professional experience, look at this shit and say "Yeah no this is perfectly acceptable, ship it."????

What are we DOING, man???

@dogiedog64 that's more or less what i'm trying to look at now, it's like you find an old haunted house full of hideous nightmares, but then after you think you've spelunked around in it for awhile, you find out there is an entire underground tunnel network like 20 times the size of the house that seems where the real demons lie.

@dogiedog64 @jonny

>with ANY professional experience

implying they have any professional experience, or RESPECT for professional experience to begin with.

if anything, the people behind AI actively RESENT needing to pay respects to professional experience, and are looking for shortcuts where there are none.

>What are we DOING, man???

trying to set the tune while stiffing the piper out of pocket.

@jonny You are doing "God's work" even though I'm a committed atheist.
(-: I gather the Claude Code leak can also only be used for entertainment purposes 🙂