Skip to content

pookieclaw/camel-code

Repository files navigation

Camel Code

Two humps, zero runtime.

An unofficial, independent terminal AI coding assistant written in OCaml. Inspired by the UX patterns of modern AI CLI tools. Uses the Anthropic Messages API with your own API key.

This project is not affiliated with, endorsed by, or associated with Anthropic in any way. "Claude" is a trademark of Anthropic. This is a personal hobby project.

Demo

https://github.com/pookieclaw/camel-code/raw/main/docs/demo.mov

Version check, diagnostics, single-shot query, file write/read with tools, bash execution, file editing, and interactive REPL with slash commands.

Features

  • 14 built-in tools + dynamic MCP tools
  • Prompt cache optimization — deterministic payload ordering for 90% input token savings
  • Tooled subagents — Agent tool gets Read/Grep/Glob for actual codebase research
  • Provider failover — automatic retry with fallback model/key on rate limits
  • Lazy MCP — server connections deferred until first tool invocation
  • Pre/post query hooks — run shell commands before/after each API call
  • Session enrichment — sessions tagged with git repo, branch, and labels
  • Daemon mode — Unix socket server for editor/web integration
  • Doctor --fix — auto-repair common environment issues
  • Vim mode, permissions, skills, hooks, MCP, sessions

Quick Start

# Open in VS Code → Reopen in Container
# Then in the devcontainer terminal:

# Set your API key
echo '{"api_key": "sk-ant-..."}' > ~/.camel/config.json

# Install the binary
dune install

# Run it
camel

Usage

# Interactive REPL (like claude)
camel

# Single-shot prompt (like claude -p)
camel -p "What is OCaml?"

# Auto-approve tool execution (like claude --yes)
camel --yes

# Pick a model
camel --model claude-opus-4-20250514

# Resume last conversation
camel --continue

# Resume a specific session
camel --resume <session-id>

# Run diagnostics
camel doctor

# Auto-fix common issues (missing dirs, bad permissions, corrupt sessions)
camel doctor --fix

# Start as a background server (Unix socket for editor plugins)
camel daemon

# Show version
camel --version

Slash Commands

Inside the REPL:

Command Description
/help Show available commands
/clear Clear conversation history
/cost Show token usage and cost
/model Show or change model
/config Show current settings
/compact Compact conversation history
/resume List and resume past sessions
/doctor Run diagnostic checks
/vim Toggle vim mode
/exit Exit camel

Tools

Camel Code has 14 built-in tools, matching Claude Code's core set:

Tool Description
Bash Execute shell commands
Read Read file contents with line numbers
Write Write/create files
Edit Search and replace in files
Glob Find files by pattern (fff-accelerated)
Grep Search file contents with regex (fff-accelerated)
MultiGrep Multi-pattern OR search (fff-accelerated)
Agent Spawn subagents with Read/Grep/Glob tools
WebFetch Fetch URL content
AskUserQuestion Prompt user for input
Sleep Pause execution
TaskCreate Create a task to track work
TaskList List all tasks
TaskUpdate Update task status

Plus dynamic tools from MCP servers configured in ~/.camel/settings.json.

fff Search Engine

Glob, Grep, and MultiGrep can be accelerated by fff (Freakin Fast File Finder), a Rust-based fuzzy search engine with frecency ranking, typo-tolerant matching, and definition-aware grep. Enable with:

export CAMEL_FFF=1

The devcontainer builds libfff_c.so automatically. When the library isn't found, tools fall back to shell (find/grep). Path and glob constraints (e.g. Grep pattern path:lib/ or Grep pattern glob:*.ml) are forwarded to fff as inline query constraints, so scoped searches stay fast. Only paths outside the project root fall back to shell. Benchmarks show ~100-200x speedup on indexed repos.

Configuration

~/.camel/
  config.json          API key
  settings.json        Preferences (model, theme, vim mode, MCP servers, hooks)
  keybindings.json     Custom key bindings
  sessions/            Saved conversation sessions
  skills/              Custom skills (.md with YAML frontmatter)

MCP Servers

Add to ~/.camel/settings.json:

{
  "mcpServers": {
    "my-server": {
      "command": "node",
      "args": ["path/to/server.js"]
    }
  }
}

Provider Failback

Set a fallback model or API key in ~/.camel/config.json:

{
  "api_key": "sk-ant-primary...",
  "fallback_model": "claude-haiku-4-5-20251001",
  "fallback_api_key": "sk-ant-backup..."
}

Or via environment: CAMEL_FALLBACK_MODEL, CAMEL_FALLBACK_API_KEY.

On rate limits or overload, camel automatically retries with the fallback.

Hooks

{
  "hooks": {
    "PreToolUse": [
      { "command": "./my-hook.sh", "matcher": "Bash" }
    ],
    "PreQuery": [
      { "command": "./log-query.sh" }
    ],
    "PostQuery": [
      { "command": "./track-usage.sh" }
    ]
  }
}

Hook events: PreToolUse, PostToolUse, PreQuery, PostQuery, SessionStart, UserPromptSubmit, Notification.

Permission Rules

{
  "permissions": {
    "allow": [{ "tool": "Read" }, { "tool": "Glob" }],
    "deny": [{ "tool": "Bash", "path": "/etc/*" }]
  }
}

Daemon Mode

Run camel as a background server that accepts JSON commands over a Unix socket:

camel daemon
# Listening on ~/.camel/daemon.sock

# From another terminal:
echo '{"method": "query", "params": {"prompt": "What is OCaml?"}}' | socat - UNIX-CONNECT:~/.camel/daemon.sock
echo '{"method": "status"}' | socat - UNIX-CONNECT:~/.camel/daemon.sock
echo '{"method": "shutdown"}' | socat - UNIX-CONNECT:~/.camel/daemon.sock

Methods: query (send a prompt), status (check server), shutdown (stop daemon).

This is the foundation for editor plugins (Neovim, VS Code), web UIs, and multi-terminal shared sessions.

Prompt Cache Optimization

API request payloads are structured for maximum Anthropic prompt cache hits:

  1. System prompt (stable across turns) — cached prefix
  2. Model config (stable per session)
  3. Tools (sorted alphabetically, stable per session)
  4. Messages (changes every turn) — always last, never cached

This means the first ~90% of each request is identical turn-to-turn, so Anthropic can serve it from cache at 1/10th the input token cost.

Architecture

Layer Approach
TUI ANSI direct rendering
State Mutable refs
Concurrency Unix processes
Types Algebraic data types
Tools First-class modules
Build dune
Binary Native (zero runtime)

Scripts

# Unit + integration tests (75 tests)
dune test

# Live demo of all phase-8 features (runs tests, shows payload structure)
./scripts/demo.sh

# End-to-end with real API calls (query, tool use, daemon, sessions)
./scripts/e2e.sh

# Full developer workflow (explore → implement → debug → review → refactor)
./scripts/workflow.sh

The e2e and workflow scripts require an API key in ~/.camel/config.json.

Why?

A hobby project to explore building an AI coding assistant in OCaml — leveraging algebraic data types, first-class modules, and native compilation for fast startup.

Disclaimer

This project is not affiliated with, endorsed by, or associated with Anthropic, PBC. It is an independent, open-source project that uses the publicly documented Anthropic Messages API. "Claude" is a trademark of Anthropic. All trademarks belong to their respective owners.

License

MIT

About

Terminal AI coding assistant written in OCaml. Two humps, zero runtime.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors