sloppy~disq~

accent

your browser, your color. stays until you change it.

← back to notes seedling

What does thinking look like

Opening the detailed view on a Claude Code session and seeing the full cascade

February 2026

Pink thinking putty blob, dithered in zenburn palette

I was working on the Deep Bore dashboard — the satirical monitoring layer over real Factorio agents — and I opened the detailed view on the Claude Code session.

Claude was mid-plan. Multi-agent persistence for the bridge. I'd asked it to figure out how to keep session IDs across restarts so each agent could resume where it left off. Standard infrastructure problem.

The detailed view showed me what "figuring it out" actually looked like.

The first thing it did

Before touching any code, before reading any files, it called a tool I built with it eight months ago.

uroboro - uro_recap (MCP)(days: 7) Decisions (7) 1. claude CLI with --resume and -p for in-game relay over persistent stdin proxy 2. Post-tool Claude Code hook for auto-telemetry over manual relay_push.sh calls 3. Pipe to claude CLI over Claude Code SDK for bridge 4. Decompose bridge.py monolith into 7 focused modules over rewriting from scratch 5. Flat module structure (bridge/*.py) over nested package 6. Keep local SSE server as opt-in, not remove it 7. Split bridge.py into 6 focused modules over a single-file cleanup Recent Commits (11) feat: add thin-pipe bridge using claude CLI refactor: decompose bridge.py into thin-pipe architecture feat: shortcut bar icon, SDK fixes, improved start script docs: rewrite README for unified repo with quick-start ...

Uroboro. A decision-capture tool. I built the first version last June because context kept getting lost between sessions. The LLM would make a decision, the session would end, and the next session would re-derive the same decision from scratch. So I wrote a tool that records decisions in a structured format: what was chosen, what was rejected, why.

Eight months later, here it is in the system prompt, hooked into Claude Code as an MCP server, called automatically before any work begins. Seven decisions loaded. Eleven recent commits pulled. The system oriented itself using its own trail.

Then it entered plan mode.

Three agents, parallel

Plan mode launched three Explore subagents simultaneously. Each got a different research question. Each fanned out independently.

Agent 1 Explore multi-agent factorioctl What branch? How does FACTORIO_AGENT_ID work? Per-agent memory? Agent 2 Explore pipe.py session handling How are sessions tracked? What happens on restart? Could we persist to disk? Agent 3 Explore system prompt and personality How are system prompts configured? Per-agent or global? What personality infrastructure exists?

The detailed view scrolled. Fast.

What an agent does in 75 seconds

Agent 1 — the multi-agent researcher — completed 24 tool calls in 1 minute 15 seconds. Here's the raw sequence:

Bash git status Bash git branch -a Bash git log --oneline -20 Search **/factorioctl/**/*.rs Search list_agents|FACTORIO_AGENT_ID|agent_id in src/ Search agent in src/ Read src/bin/mcp.rs Search list_agents|agent_id|AGENT in mcp.rs Search list_agents|bind.*agent in lua.rs Search agent_id|struct FactorioClient in server.rs Read src/client/rcon.rs lines 1-100 Read src/client/server.rs lines 1-150 Read src/client/mod.rs lines 1-200 Read src/memory/mod.rs Bash grep -r "agent_memory" src/ --include="*.rs" Search AgentMemory|.load()|.save() in mcp.rs Search register_character_helpers|spawn_x in lua.rs Read README.md lines 1-300 Bash git log --oneline main..multi-agent Bash git rev-list --left-right main...multi-agent Bash git log --all --grep="agent" --oneline Bash grep -r "FACTORIO_AGENT_ID" . --include="*.md" --include="*.sh" Read src/client/lua.rs lines 413-442 Read src/bin/mcp.rs lines 1-50
24 tool calls 72.1k tokens 1m 15s

Five languages. Rust, Python, Lua, TypeScript, shell. Git operations to understand branch topology. Grep to locate patterns across files. Targeted reads of specific line ranges when a file was too large. Search, narrow, read, search again.

The other two agents ran the same kind of cascade simultaneously. Agent 2 did 18 tool calls in 56 seconds. Agent 3 did 16 in 32 seconds. All three finished before the parent agent continued planning.

58 total tool calls across 3 agents ~2 minutes wall clock

What it produced

From 58 tool calls across Rust source, Python modules, Lua game scripts, a Cloudflare Worker, and shell scripts, the agent assembled this:

┌───────────────────────────────────────────────────────┘ │ Single Factorio Server │ │ (headless, runs all agents' code) │ │ │ │ global.factorioctl_characters = { │ │ "agent-1" → character entity (x=0, y=0) │ │ "agent-2" → character entity (x=5, y=0) │ │ "agent-3" → character entity (x=10, y=0) │ │ } │ └───────────────────────────────────────────────────────┘ ▲ RCON (port 27015) │ ┌─────────────────┬─────────────────┐ │ │ │ ┌───────┬──────┐ ┌──────┬────────┐ ┌────┬──────────┐ │ MCP Server 1 │ │ MCP Server 2 │ │ MCP Server 3 │ │ agent-1 │ │ agent-2 │ │ agent-3 │ │ (stdio) │ │ (stdio) │ │ (stdio) │ └───────┬──────┘ └──────┬────────┘ └────┬──────────┘ │ │ │ └─────────────────┴─────────────────┘ │ ┌─────┬──────────┐ │ Claude Agent │ │ Instance │ └────────────────┘

Not drawn by a human. Assembled from evidence. The agent read the Rust struct definitions for ConnectionConfig, the Lua code that auto-creates characters at 5-tile offsets, the RCON connection layer, the MCP tool registration, and the environment variable routing. Then it synthesized a diagram that accurately represents how three independent MCP server processes share a single game server through RCON.

It also mapped the session lifecycle — the exact flow from player message to session lookup to Claude CLI invocation to session persistence. It identified the gap: sessions stored in RAM, lost on restart, orphaned on disk. Claude CLI keeps full conversation history in ~/.local/share/opencode/storage/session/, but the bridge loses the mapping. The data survives. The pointer doesn't.

Session lifecycle (as mapped by Agent 2) Bridge Start ↓ sessions = {} (empty dict in RAM) ↓ Player sends message via Factorio mod ↓ bridge looks up sessions[player_index] → None on first msg ↓ bridge runs: claude -p "prompt" (NO --resume flag) ↓ Claude creates NEW session, returns session_id ↓ sessions[player_index] = new_session_id (stored in RAM)[BRIDGE RESTART] ↓ sessions = {} (empty dict, session IDs LOST) ↓ Player sends message → None → starts NEW session ↓ Context is LOST

Clean problem statement. Derived from reading Python source, tracing the data flow through function calls, and identifying where state lives versus where it doesn't.

The planning layer

After the three agents returned, the parent synthesized their findings into design decisions. This part was visible too — the reasoning exposed in the detailed view:

● Thinking… Key findings: 1. Session persistence: Sessions are RAM-only, lost on restart. Claude CLI sessions persist on disk but the bridge loses the mapping. Fix: persist sessions dict to JSON file. 2. Multi-agent: factorioctl already supports FACTORIO_AGENT_ID env var, per-character binding, list_agents. Each agent needs its own MCP server instance + claude CLI process. 3. Personality: Currently a single generic SYSTEM_PROMPT. No per-agent personality. Need to support per-agent system prompts with lore/personality. For the config structure, I'm thinking a simple agents/ directory with individual agent files... Now I'm thinking more carefully about what agent continuity really means... The simplest solution is to just persist session IDs to disk keyed by agent name, so each agent can resume where it left off.

Then it launched a fourth agent — a Plan agent — to validate the design against the actual codebase. That agent read 14 more files, checked the existing .env configuration, verified the .gitignore patterns, and tested the claude --help output to confirm flag support. At the end it recorded two decisions through uroboro:

uro_decision: "Markdown files for agent profiles over JSON/TOML registry" uro_decision: "Single JSON file for session persistence over SQLite or per-agent files"

Breadcrumbs for the next session. The decisions this session made will appear in the next session's uro_recap. The trail extends.

40-year-old commands

Look at the tool calls again. grep. git log. ls. find. Commands from the late '70s and '80s, written for terminals that couldn't display color, running on an LLM subprocess spawned by another LLM.

grep doesn't know it's being called by a language model. It searches. It returns matches. The same way it did in 1973 when Ken Thompson wrote it. The same byte-by-byte scan, the same regex engine (more or less), the same stdout pipe. The orchestration layer is new. The tools are ancient.

There's something grounding about that. The system isn't magic. It's a coordinator that knows how to decompose "understand this codebase" into twenty grep calls, ten file reads, and five git operations — then synthesize the results into something a human can evaluate. The intelligence, to the extent the word applies, is in the decomposition and synthesis. The execution is grep -r "pattern" path/. It's always been grep -r "pattern" path/.

The recursive part

Here's what I was actually looking at:

An LLM using a tool I built with a previous instance of itself — uroboro — to recall context and intent from past sessions. Loading that context alongside its own built-in systems. Then using that context to plan a feature (session persistence) whose entire purpose is preventing context loss. Recording the decisions it made about context persistence using the context persistence tool. Leaving a trail for the next instance to pick up.

The tool that solves context loss was used to orient a session about solving context loss at a different layer. And the decisions made during that session were captured by the tool, extending the trail for the next session that will also use the tool to orient itself.

I've written about this pattern before. The outputs of the system are valid inputs to the system. But this time I wasn't thinking about it architecturally. I was watching it happen in real time through a scrolling log of Read and Search and Bash calls. The recursion wasn't a diagram. It was uro_recap at the top and uro_decision at the bottom with 58 tool calls between them.

The trajectory

The planning session I was watching happened at 2:35 AM. To understand why I was still awake, you need the full arc.

Feb 21 14:21 "Hey wanna try out this factorio mcp setup?" 88 tools 14:39 "let's continue playing" 244 tools 14:46 "does this scale horizontally? multiplanetary claude?" 198 tools 15:00 "can we build a mod to launch claude from factorio?" 566 tools, 10 hours Evening 21:27 microDoug upgrade on qryzone 41 tools 21:31 prompts page 49 tools Night 23:43 "Welcome?" first msg through the bridge 00:23 "The factory must grow." 00:32 "I know a Polish sound technician, and a Czech one, too." 00:33 "Oh come on Claude that one was gold! Nothing? Really?" 00:47 "Ah, you're here. Stretch your legs, have a look around." 00:50 "can you mine something?" first tool call through bridge 01:02 thin-pipe bridge rewrite 244 tools, 2.8 hours 02:05 parallel agent: "How are ya?" 41 tools 02:09 "songs of syx, dwarf fortress, quasimorph?" 02:12 "Bridge restarted, comm check. Come in ground team." 02:35 "i opened the detailed view..." ← this article 03:48 Multi-Agent GUI + Message Routing 67 tools 04:12 "Come in, this is a test from ground control" 04:23 Multisurface Support 206 tools, 108 edits 04:37 laptop dies 09:00 "centinue please" 09:05 done

19 hours. 33 sessions across 4 project directories. About 1,700 tool calls. From first contact with factorioctl to multiplanetary multi-agent Factorio with a satirical monitoring dashboard, an in-game chat bridge, and this article.

Look at 14:46. Barely an hour into trying factorioctl for the first time: "does this scale horizontally? can i have multiple claude players cooperating? multiplanetary claude?" The question that spawned the next 14 hours of work was there in the first hour. But the plan that answered it at 04:23 could not have been written at 14:46. Not even close.

A plan is a start

Sequential reasoning is not our strength. We don't think in straight lines. We think by association — bouncing between contexts, dragging connections from one problem space into another, refining a mental model through contact with adjacent problems we weren't deliberately trying to solve.

The multiplanetary plan at 04:23 was precise. File paths, line numbers, function names, exact code for the new preamble, a verification strategy that used the Rust compiler as the test suite. It worked as a oneshot — 108 edits, 19 minutes, clean compile. But that precision didn't come from studying the Rust code. It came from 14 hours of building adjacent layers.

Building the mod taught me how RCON commands map to Lua. Building the bridge taught me how sessions flow between the game and the CLI. Building Deep Bore taught me how telemetry propagates through the relay. Testing multi-agent at 1 AM — "Come in ground team" — taught me how FACTORIO_AGENT_ID routes to character entities. The Czech joke at midnight taught me nothing, but it kept me in the flow state where the adjacent learning was happening.

Each layer irrigated the same brainspace from a different angle. By 4 AM I understood the architecture well enough to write a plan that someone who can't write Rust could hand to something that can. Not because I planned to understand it that way. Because iterative work has self-reinforcing feedback loops — you build a thing, the thing teaches you about the system, the system understanding feeds the next thing you build. The mental model refines itself through contact with implementation, not through deliberate study.

A plan does not survive implementation unscathed. The multiplanetary plan mostly did — the compiler caught three CLI files the plan missed, fixed in 5 minutes. But the plan itself was already a product of implementation. It was refined by every layer that came before it. The testing sessions, the bridge debugging, the dashboard work, even the satirical framing — all of it was the same mental model being irrigated from different directions until the shape of the solution was obvious.

A plan is a start. The good ones are also an end — the crystallized output of enough associated work that the sequential steps finally become visible. You don't think your way to a plan. You build your way to one.

What does thinking look like

At 5:50 PM on February 21st, the first commit landed: "initial release: in-game Claude AI chat for Factorio 2.0." By 5:14 AM on the 22nd — less than 12 hours later — the last commit read "update to multiagent." In between: the mod, the MCP server, the SSE telemetry relay, the bridge, the thin-pipe rewrite, agent identity, session persistence, and this article. All of it. One day.

Uroboro is older. The first version was a shell script that appended decisions to a markdown file, and I've been iterating on it for months. But the rest of the connective tissue — the relay, the bridge, the in-game chat, the multi-agent routing — didn't exist 24 hours before I opened that detailed view.

Now the system loads its own decision trail, decomposes a research question into three parallel investigations, fans out 58 tool calls across five programming languages, synthesizes architecture diagrams from source code, reasons about design tradeoffs in visible chain-of-thought, and logs what it decided so the next instance can pick up where this one stopped. In under two minutes. On infrastructure that didn't exist that morning.

Doomer or booster, that's a different thing. Whether it's "thinking" is a question for philosophers. What it looks like is grep and git log and Read src/bin/mcp.rs lines 1-50, happening very fast, coordinated by something that knows what to look for and what to do with what it finds. And what it looks like from the human side is 33 sessions across 19 hours, bouncing between a game mod and a satirical dashboard and a bridge rewrite and a sound technician joke, irrigating the same mental model from every direction until the plan writes itself.

I opened the detailed view at 2:35 AM because I was curious. I kept watching because it was interesting. Not because it was sentient or magical. Because it was legible. Every step visible. Every tool call logged. Every decision recorded. A process you can inspect, evaluate, and disagree with.

That might be the most useful thing about all of it — the human thinking and the machine thinking both. Not that either one is better. That they're legible to each other.

first published on qry.zone, 2026-02-22 — moved here when the channel got its own roof.