npm package: @geoffai/coder
Description: A terminal-based AI coding agent.
Latest version: 1.0.0

# 🚀 Geoff Coder

A terminal-based AI coding agent built with **Bun.js** featuring an agentic loop with tool call support. This agent can read files, write code, execute commands, and iterate on tasks autonomously.

## Features

- **Agentic Loop**: Autonomous task execution with tool calling
- **System Reminders**: Context-aware reminders injected at key points (inspired by Claude Code)
- **OpenAI-Compatible API**: Works with any OpenAI-compatible inference API
- **Containerized**: Docker support for isolated execution
- **Tool Suite**: File operations, shell commands, code search, diff application
- **Streaming Support**: Real-time response streaming for verbose mode

## Architecture

The system is built around patterns observed in production coding agents like Claude Code, Cline, and OpenCode:

```
┌─────────────────────────────────────────────────────────────┐
│                        CLI Interface                         │
├─────────────────────────────────────────────────────────────┤
│                         Agent Loop                           │
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐     │
│  │   Message   │───▶│  LLM Call   │───▶│   Tool      │     │
│  │   History   │    │  (Stream)   │    │  Execution  │     │
│  └─────────────┘    └─────────────┘    └─────────────┘     │
│         ▲                                     │              │
│         │         ┌─────────────┐             │              │
│         └─────────│   System    │◀────────────┘              │
│                   │  Reminders  │                            │
│                   └─────────────┘                            │
├─────────────────────────────────────────────────────────────┤
│                      Tool Registry                           │
│  read_file │ write_file │ execute_command │ search_files    │
│  apply_diff │ list_files │ task_complete                    │
└─────────────────────────────────────────────────────────────┘
```

### Key Components

1. **Agent Loop** (`src/agent/loop.ts`): The core execution engine that:
   - Manages conversation history
   - Calls the LLM with tool definitions
   - Handles tool call responses
   - Injects system reminders at appropriate times
   - Iterates until task completion

2. **System Reminders** (`src/prompts/system.ts`): Context-aware prompts injected at:
   - Pre-user message (task focus)
   - Post-tool result (verification reminders)
   - Context refresh (iteration warnings)
   - Task boundaries (completion prompts)

3. **Tool Registry** (`src/tools/registry.ts`): Extensible tool system with:
   - File read/write operations
   - Shell command execution
   - Code search (grep)
   - Diff application for surgical edits
   - Task completion signaling

4. **API Client** (`src/agent/api-client.ts`): OpenAI-compatible client with:
   - Streaming support
   - Tool call accumulation
   - Error handling and retries

## Installation

### Prerequisites

- [Bun](https://bun.sh) v1.0+
- An OpenAI-compatible API key

### Local Installation

```bash
# Clone or download the project
cd geoff-coder

# Install dependencies
bun install

# Set your API key
export OPENAI_API_KEY="your-api-key"

# Run the agent
bun run src/index.ts "Create a hello world Express server"
```

### Docker Installation

```bash
# Build the image
docker build -t geoff-coder .

# Run interactively
docker run -it --rm \
  -e OPENAI_API_KEY="your-api-key" \
  -v $(pwd)/workspace:/workspace \
  geoff-coder

# Or use docker-compose
export OPENAI_API_KEY="your-api-key"
docker compose up
```

## Usage

### Single Task Mode

```bash
# Execute a single task
bun run src/index.ts "Create a REST API with Express"

# With verbose output
bun run src/index.ts -v "Fix the bug in auth.ts"

# With custom model
bun run src/index.ts -m "gpt-4-turbo" "Write tests for utils"
```

### Interactive Mode

```bash
# Start interactive REPL
bun run src/index.ts -i

# In the REPL
>>> Create a new React component for user profiles
>>> Add validation to the form
>>> exit
```

### With Local LLM (Ollama)

```bash
# Using Ollama
bun run src/index.ts \
  -u "http://localhost:11434/v1" \
  -m "llama3" \
  -k "not-needed" \
  "Explain this codebase"

# Or with docker-compose
docker compose --profile local up
```

### CLI Options

```
Usage: bun run src/index.ts [options] [prompt]

Options:
  -h, --help              Show help message
  -v, --verbose           Enable verbose output
  -i, --interactive       Run in interactive mode (REPL)
  -m, --model <model>     Model to use (default: gpt-4o)
  -u, --base-url <url>    API base URL
  -k, --api-key <key>     API key
  -d, --dir <path>        Working directory
  --max-iterations <n>    Maximum loop iterations (default: 20)
  --max-tokens <n>        Maximum tokens per response (default: 4096)
  -t, --temperature <n>   Temperature (default: 0.7)
```

### Environment Variables

```bash
OPENAI_API_KEY      # Required: Your API key
OPENAI_BASE_URL     # Optional: API endpoint (default: https://api.openai.com/v1)
OPENAI_MODEL        # Optional: Model name (default: gpt-4o)
```

## Customization

### Adding Custom Tools

Extend the tool registry in `src/tools/registry.ts`:

```typescript
// Add to toolDefinitions array
{
  type: "function",
  function: {
    name: "my_custom_tool",
    description: "Description of what this tool does",
    parameters: {
      type: "object",
      properties: {
        param1: { type: "string", description: "Parameter description" }
      },
      required: ["param1"]
    }
  }
}

// Add handler in createToolRegistry function
handlers.set("my_custom_tool", async (args): Promise<ToolResult> => {
  // Implementation
  return { success: true, output: "Result" }
})
```

### Adding System Reminders

Extend the reminders in `src/prompts/system.ts`:

```typescript
systemReminders.push({
  id: "my_reminder",
  content: "<system-reminder>Your reminder text</system-reminder>",
  injectionPoint: "post_tool_result",
  priority: 5,
  condition: (state) => state.iteration > 3
})
```

### Project-Specific Instructions

Create an `AGENTS.md` file in your project root with custom instructions that will be loaded by the agent.

## How It Works

### The Agentic Loop

1. **User Input**: User provides a task description
2. **System Prompt**: Base instructions + system reminders are assembled
3. **LLM Call**: Request sent to the model with tool definitions
4. **Response Processing**:
   - If tool calls: Execute tools, add results to history, continue loop
   - If text only: Check for completion indicators
5. **Iteration**: Loop continues until:
   - `task_complete` tool is called
   - Max iterations reached
   - No more tool calls and response looks complete

### System Reminders (Key Innovation)

Inspired by Claude Code's `<system-reminder>` pattern, reminders are injected:

- **Pre-user message**: Focus on task, avoid unnecessary changes
- **Post-tool result**: Verify changes after file operations
- **Context refresh**: Warning after many iterations
- **Task boundary**: Prompt to use `task_complete`

This helps maintain agent focus and prevents drift in long-running tasks.

## Comparison with Similar Tools

| Feature | This Agent | Claude Code | Cline | OpenCode |
|---------|-----------|-------------|-------|----------|
| Open Source | ✅ | ❌ | ✅ | ✅ |
| Provider Agnostic | ✅ | ❌ | ✅ | ✅ |
| System Reminders | ✅ | ✅ | ❌ | ❌ |
| Containerized | ✅ | ❌ | ❌ | ❌ |
| Runtime | Bun | Node | Node | Go/Bun |
| IDE Integration | ❌ | ✅ | ✅ | ❌ |

## Development

```bash
# Run in development mode (with auto-reload)
bun --watch run src/index.ts -i

# Type check
bun run tsc --noEmit

# Build for distribution
bun build src/index.ts --outdir dist --target bun
```

## License

MIT

## Acknowledgments

Architecture patterns inspired by:
- [Claude Code](https://claude.ai) - System reminder injection pattern
- [Cline](https://github.com/cline/cline) - Tool definitions and agentic loop
- [OpenCode](https://github.com/sst/opencode) - CLI design and provider abstraction
- [OpenAI Codex CLI](https://github.com/openai/codex) - Agent loop implementation