302 lines
8.2 KiB
Markdown
302 lines
8.2 KiB
Markdown
# nanocode
|
|
|
|
Minimal Claude Code alternative using DSPy RLM! Single Python file, ~305 lines.
|
|
|
|
Shoutout to Rahul for inspiring the boilerplate. Here's his initial [nanocode implementation](https://x.com/rahulgs/status/2010179011033608227).
|
|
|
|

|
|
|
|
## Features
|
|
|
|
- Full agentic loop with tool use via [DSPy RLM](https://dspy.ai/)
|
|
- Tools: `read`, `write`, `edit`, `glob`, `grep`, `bash`
|
|
- Conversation history with context
|
|
- Colored terminal output
|
|
- **Modaic Integration**: Push, version, and share as a [Modaic](https://modaic.dev) autoprogram
|
|
|
|
---
|
|
|
|
## Prerequisites
|
|
|
|
Before using nanocode (or any DSPy RLM-based program), you need to install the Deno code interpreter:
|
|
|
|
```bash
|
|
brew install deno
|
|
```
|
|
|
|
This is required for the RLM's code execution capabilities.
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
### Option 1: Use as a Modaic AutoProgram
|
|
|
|
Load and run nanocode directly from the Modaic Hub without cloning:
|
|
|
|
```python
|
|
from modaic import AutoProgram
|
|
|
|
# Load the precompiled nanocode agent from Modaic Hub
|
|
agent = AutoProgram.from_precompiled(
|
|
"farouk1/nanocode",
|
|
config={
|
|
"lm": "openrouter/openai/gpt-5.2-codex",
|
|
"max_iters": 50
|
|
}
|
|
)
|
|
|
|
# Run a coding task
|
|
result = agent(task="What Python files are in this directory?")
|
|
print(result.answer)
|
|
```
|
|
|
|
### Option 2: Run Locally (Interactive CLI)
|
|
|
|
```bash
|
|
export OPENROUTER_API_KEY="your-key"
|
|
python nanocode.py
|
|
```
|
|
|
|
To use a specific model:
|
|
|
|
```bash
|
|
export OPENROUTER_API_KEY="your-key"
|
|
export MODEL="openai/gpt-4"
|
|
python nanocode.py
|
|
```
|
|
|
|
---
|
|
|
|
## Configuration
|
|
|
|
When using as a Modaic AutoProgram, you can configure these options:
|
|
|
|
| Parameter | Type | Default | Description |
|
|
|-----------|------|---------|-------------|
|
|
| `lm` | str | `openrouter/openai/gpt-5.2-codex` | Primary language model |
|
|
| `sub_lm` | str | `openrouter/openai/gpt-5-mini` | Sub-LM for reasoning steps |
|
|
| `max_iters` | int | `50` | Maximum agent iterations |
|
|
| `api_base` | str | `https://openrouter.ai/api/v1` | API base URL |
|
|
| `max_tokens` | int | `50000` | Maximum tokens per request |
|
|
| `max_output_chars` | int | `100000` | Maximum output character limit |
|
|
| `verbose` | bool | `False` | Enable verbose logging |
|
|
| `track_usage` | bool | `True` | Track token usage |
|
|
|
|
Example with custom configuration:
|
|
|
|
```python
|
|
from modaic import AutoProgram
|
|
|
|
agent = AutoProgram.from_precompiled(
|
|
"farouk1/nanocode",
|
|
config={
|
|
"lm": "openrouter/anthropic/claude-sonnet-4",
|
|
"sub_lm": "openrouter/openai/gpt-4.1-mini",
|
|
"max_iters": 30,
|
|
"max_tokens": 8000,
|
|
"verbose": True,
|
|
"track_usage": False
|
|
}
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## CLI Commands
|
|
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `/c` | Clear conversation history |
|
|
| `/q` or `exit` | Quit the application |
|
|
|
|
---
|
|
|
|
## Tools
|
|
|
|
The agent has access to the following tools:
|
|
|
|
| Tool | Description |
|
|
|------|-------------|
|
|
| `read_file(path, offset, limit)` | Read file contents with line numbers |
|
|
| `write_file(path, content)` | Write content to a file |
|
|
| `edit_file(path, old, new, replace_all)` | Replace text in a file (old must be unique unless `replace_all=True`) |
|
|
| `glob_files(pattern, path)` | Find files matching a glob pattern, sorted by modification time |
|
|
| `grep_files(pattern, path)` | Search files for a regex pattern |
|
|
| `run_bash(cmd)` | Run a shell command and return output |
|
|
|
|
---
|
|
|
|
## Example Usage
|
|
|
|
### Interactive CLI
|
|
|
|
```
|
|
ââââââââââââââââââââââââââââââââââââââââ
|
|
⯠what files are here?
|
|
ââââââââââââââââââââââââââââââââââââââââ
|
|
|
|
⺠Thinking...
|
|
⺠globfiles(pattern='**/*', path='.')
|
|
|
|
⺠I found the following files:
|
|
- nanocode.py
|
|
- README.md
|
|
- modaic/SKILL.md
|
|
```
|
|
|
|
### Programmatic Usage
|
|
|
|
```python
|
|
from modaic import AutoProgram
|
|
|
|
agent = AutoProgram.from_precompiled("farouk1/nanocode")
|
|
|
|
# Read a file
|
|
result = agent(task="Read the first 10 lines of nanocode.py")
|
|
print(result.answer)
|
|
|
|
# Search for patterns
|
|
result = agent(task="Find all functions that contain 'file' in their name")
|
|
print(result.answer)
|
|
|
|
# Make edits
|
|
result = agent(task="Add a comment at the top of README.md")
|
|
print(result.answer)
|
|
```
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
### Overview
|
|
|
|
```
|
|
nanocode.py
|
|
âââ File Operations
|
|
â âââ read_file() - Read with line numbers
|
|
â âââ write_file() - Write content
|
|
â âââ edit_file() - Find & replace
|
|
âââ Search Operations
|
|
â âââ glob_files() - Pattern matching
|
|
â âââ grep_files() - Regex search
|
|
âââ Shell Operations
|
|
â âââ run_bash() - Execute commands
|
|
âââ DSPy Components
|
|
â âââ CodingAssistant (Signature)
|
|
â âââ RLMCodingProgram (PrecompiledProgram)
|
|
â â âââ forward() - Run agent on task
|
|
â â âââ get_tools() - Get available tools
|
|
â â âââ set_tool() - Add/replace a tool
|
|
â â âââ remove_tool() - Remove a tool
|
|
â â âââ reload_lms() - Recreate LMs from config
|
|
â â âââ load_state() - Load state with LM fix
|
|
â âââ RLMReasoningCallback
|
|
âââ Modaic Integration
|
|
âââ RLMCodingConfig (PrecompiledConfig)
|
|
```
|
|
|
|
### Key Classes
|
|
|
|
#### `RLMCodingConfig`
|
|
Configuration class extending `PrecompiledConfig` for experiment-specific parameters.
|
|
|
|
```python
|
|
class RLMCodingConfig(PrecompiledConfig):
|
|
max_iters: int = 50
|
|
lm: str = "openrouter/openai/gpt-5.2-codex"
|
|
sub_lm: str = "openrouter/openai/gpt-5-mini"
|
|
api_base: str = "https://openrouter.ai/api/v1"
|
|
max_tokens: int = 50000
|
|
max_output_chars: int = 100000
|
|
verbose: bool = False
|
|
track_usage: bool = True
|
|
```
|
|
|
|
#### `RLMCodingProgram`
|
|
Main program class extending `PrecompiledProgram`. Wraps a DSPy RLM agent with coding tools.
|
|
|
|
```python
|
|
class RLMCodingProgram(PrecompiledProgram):
|
|
config: RLMCodingConfig
|
|
|
|
def forward(self, task: str) -> dspy.Prediction:
|
|
# Returns prediction with .answer
|
|
return self.agent(task=task)
|
|
|
|
def get_tools(self) -> dict:
|
|
# Returns dict of available tools
|
|
|
|
def set_tool(self, name: str, tool: callable):
|
|
# Add or replace a tool
|
|
|
|
def remove_tool(self, name: str):
|
|
# Remove a tool by name
|
|
|
|
def reload_lms(self):
|
|
# Recreate LM objects from current config
|
|
```
|
|
|
|
#### `CodingAssistant`
|
|
DSPy Signature defining the agent's input/output schema.
|
|
|
|
```python
|
|
class CodingAssistant(dspy.Signature):
|
|
"""You are a concise coding assistant with access to sub agents."""
|
|
|
|
task: str = dspy.InputField(desc="The user's coding task or question")
|
|
answer: str = dspy.OutputField(desc="Your response to the user after completing the task")
|
|
```
|
|
|
|
---
|
|
|
|
## Publishing Your Own Version
|
|
|
|
If you modify nanocode and want to publish your own version to Modaic Hub:
|
|
|
|
```python
|
|
from nanocode import RLMCodingProgram, RLMCodingConfig
|
|
|
|
# Create and optionally optimize your program
|
|
program = RLMCodingProgram(RLMCodingConfig())
|
|
|
|
# Push to your Modaic Hub repo
|
|
program.push_to_hub(
|
|
"your-username/my-nanocode",
|
|
commit_message="My customized nanocode",
|
|
with_code=True # Include source code for AutoProgram loading
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## Dependencies
|
|
|
|
- [DSPy](https://dspy.ai/) - Framework for programming language models
|
|
- [Modaic](https://modaic.dev/) - Hub for sharing and versioning DSPy programs
|
|
- OpenRouter API key (for accessing language models)
|
|
|
|
Install dependencies:
|
|
|
|
```bash
|
|
pip install dspy modaic
|
|
# or with uv
|
|
uv add dspy modaic
|
|
```
|
|
|
|
---
|
|
|
|
## Environment Variables
|
|
|
|
| Variable | Required | Description |
|
|
|----------|----------|-------------|
|
|
| `OPENROUTER_API_KEY` | Yes | Your OpenRouter API key |
|
|
| `MODEL` | No | Override the default model selection |
|
|
| `MODAIC_TOKEN` | For Hub | Required for pushing/loading from Modaic Hub |
|
|
|
|
---
|
|
|
|
## License
|
|
|
|
MIT
|