A mini Claude Code built with ~140 lines of TypeScript. It demonstrates how to turn a general-purpose LLM into a reliable coding assistant through Harness Engineering.
- Interactive REPL: Chat with an LLM directly in your terminal.
- Tool Use: The assistant can invoke tools to help you:
read_file— Read file contents.write_file— Write (overwrite) a file.str_replace_file— Replace a substring in a file.execute_command— Run a system command.
- Multi-turn tool chains: The model can call multiple tools in a row until it produces a final answer.
In LLM application development, Harness Engineering is the practice of guiding and constraining a powerful but unpredictable model through systematic scaffolding—rather than relying on raw prompt magic alone.
Think of a large language model as a strong horse. Without a harness, it might gallop off in any direction, hallucinate file contents, or attempt actions outside its capabilities. Harness Engineering builds the structure that keeps the model on track.
nanocc demonstrates this in three layers:
-
Identity Harness (System Prompt)
The model is given a strict identity: "You are a command-line coding assistant." This sets the behavioral boundary before any user input arrives. -
Capability Harness (Tool Schema)
Instead of letting the model generate free-text commands, nanocc registers a tight set of function schemas (read_file,write_file,str_replace_file,execute_command). The model can only act by invoking these named tools with validated JSON arguments. It cannot invent tools or bypass the schema. -
Execution Harness (Control Loop)
The main loop insrc/index.tsenforces the workflow:
User Request -> LLM -> Tool Call -> Run Tool -> Return Result -> LLM Again -> Final Answer
This loop prevents the model from executing commands on its own. Every tool call is intercepted, logged, and its result is fed back into the conversation history before the model is allowed to continue.
By combining these three harnesses, nanocc turns a general-purpose LLM into a reliable, file-aware coding assistant.
- Node.js 18+ (for native
fetch) - An OpenAI-compatible API key
npm installnanocc requires three environment variables to connect to your LLM provider:
| Variable | Required | Default | Description |
|---|---|---|---|
API_KEY |
Yes | — | Your API key (e.g., sk-xxxxxx) |
MODEL |
No | deepseek-chat |
The model name to use |
BASE_URL |
No | https://api.deepseek.com |
The base URL of the API endpoint |
Set temporarily for the current session:
export API_KEY="sk-xxxxxx"
export MODEL="deepseek-chat"
export BASE_URL="https://api.deepseek.com"
npm startTo persist, add the export lines to your shell profile (~/.bashrc, ~/.zshrc, etc.), then reload:
source ~/.zshrcnpm startThen type your requests. Type exit to quit.
nanocc started (type "exit" to quit)
> read package.json for me
[Tool] [read_file] {"path":"package.json"}
[Result]:
{ "name": "nanocc", ... }
[Assistant] Here is the content of package.json ...
.
├── src/
│ └── index.ts # Main entry point
├── package.json
├── tsconfig.json
└── README.md