Mini Harness
Overview
mini-harness is a cleanroom implementation of an autonomous terminal coding agent, built from scratch in ~180 lines of TypeScript using Bun and the official @anthropic-ai/sdk. By stripping away all framework bloat (no LangChain, no heavy orchestrators), it exposes the exact mechanics powering modern coding agents like Claude Code: a naked while loop, an in-memory message history, streaming SSE deltas, and self-correcting tools.
Technical Architecture & Flow
The harness separates concerns into three focused modules:
user turn ──▶ history[] ──▶ ask() ──▶ [ Claude Model ]
▲ │ stream (SSE)
│ ▼
tool_result[] ◀── runTool() ◀── tool_use
│ (Promise.all)
└──────── loop until stop_reason !== "tool_use"
src/llm.ts(The Translator): Houses the SDK client and the system prompt SOP. Exposes a singleask()streaming entry point configured withmax_tokens: 8192(critical to prevent generation truncation during large multi-file write payloads).src/tools.ts(The Hands): Defines the tool catalog using strict JSON Schemas (read_file,write_file,list_files,web_fetch). The executor validates inputs prior to disk operations (preventing corrupted files likeundefinednames) and includes token-budget guards (max_charstruncation withstart_charpagination). Crucially, failures return stringifiedERROR: ...messages rather than throwing exceptions, allowing the model to inspect the error and self-correct in the subsequent turn.src/index.ts(The Brain): Manages a dual-loop lifecycle:
- Outer Loop (REPL): Built on Node
readline/promises. Holds the singleMessageParam[]history array that represents session memory. Commands like/resetwipe the array in-place, giving the agent instant amnesia without process restart. - Inner Loop (Agent Turn): Iterates up to
MAX_ITERATION = 10. Pipes streaming tokens toprocess.stdout.writeas deltas arrive. When the model stops withtool_use, it gathers all requested tool calls, executes them concurrently viaPromise.all(), matches outputs totool_use_id, appends a unified user result message, and loops.
Tech stack
Architecture
mini-harness/
├── src/
│ ├── index.ts # REPL shell + agent while-loop (Promise.all parallel tools)
│ ├── llm.ts # Anthropic SDK client & streaming ask() entry point
│ └── tools.ts # Tool definitions (JSON Schema) & stringified executor
├── bun.lock # Lockfile (zero runtime deps beyond @anthropic-ai/sdk)
├── package.json # Manifest
├── tsconfig.json # Strict TS config for Bun
└── README.md