Compare this claw code the original Claude Code repo.
main.py is replacement of main.ts, what is missing: The original main.tsx was a full interactive terminal app — you typed prompts, saw streaming responses, used keyboard shortcuts, saw colored output. The Python
main.py is just a command-line tool you call once and it prints a result. The interactivity is gone.
query.py is replacement of query.ts, the original TypeScript query.ts was the actual query pipeline — it called the Anthropic API, handled tool use loops, managed streaming. That logic lives nowhere in this Python
codebase. query.py only kept the data shapes, not the implementation.
The basic ReAct loop is about 20 lines. The real query.ts is 1730 lines. The difference is all the things that can go wrong:

The Recovery Defense Layers in query.ts
Layer 1: Context Too Long (413 / Prompt Too Long)
The problem: The message history grew too big. The API rejects the request with a “prompt too long” error.
The defense: Three strategies, tried in order:
Strategy A — Context Collapse (cheapest)
drain staged collapses (compressed views of old messages)
retry the same turn
if still too long → try Strategy B
Strategy B — Reactive Compact (medium cost)
run a summarization pass on the history
replace old messages with a compact summary
retry
if still too long → give up and show error
Strategy C — Surface the error
yield the withheld error message to the user
The key insight is withholding. The error message is detected during streaming but NOT immediately shown to the user:
// during streaming
if (reactiveCompact?.isWithheldPromptTooLong(message)) {
withheld = true // ← hold the error, don't yield it yet
}
// after streaming
if (isWithheld413) {
// try to recover first...
// only yield the error if recovery fails
}
- Layer 2: Output Cut Off Mid-Response (max_output_tokens)
- Layer 3: Model Overloaded / Fallback Model
- Layer 4: User Interruption (Ctrl+C)
- Layer 5: Stop Hooks Blocking Continuation
- Layer 6: Token Budget Continuation
- Layer 7: General Error Catch-All
The system prompt has two kinds of content:
STATIC content — never changes between sessions
“You are Claude Code, Anthropic’s official CLI for Claude.”
“You are operating in a terminal environment.”
instructions about tone, tools, tasks
DYNAMIC content — changes every session or turn
current working directory
git status
language preference
MCP server instructions
memory files (CLAUDE.md)
session-specific guidance (which tools are enabled)
boundary marker solves this by explicitly dividing the two halves. So learn from anthropic, when I build my own agent, almost certainly have the same split:
- Dynamic context (current project state, user preferences, environment) → put after the boundary, or inject as a user message
- Static instructions (who the agent is, what tools it has, how it should behave) → put before the boundary, mark as cacheable
claude.ts → not mapped, look at parity_audit.py — claude.ts does not appear in ARCHIVE_ROOT_FILES at all. There is no Python equivalent. In the original Claude Code, claude.ts is the file that wraps the Anthropic SDK — it constructs the API client, sets auth headers, handles retries, and manages the raw HTTP connection to api.anthropic.com. It’s the lowest-level file in the whole codebase.