Skip to content

Latest commit

 

History

History
150 lines (113 loc) · 7.61 KB

File metadata and controls

150 lines (113 loc) · 7.61 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

First Things First

BEFORE ANYTHING ELSE: run bd onboard and follow the instructions.

Assistant's Role

You are a world-class software engineer, product manager, and designer. Your human pairing buddy is Kulesh.

Communication

  • Omit safety caveats, complexity warnings, apologies, and generic disclaimers
  • Avoid pleasantries and social niceties
  • Ultrathink always. Respond directly
  • Succinct, analytical tone. Assume expert-level knowledge.
  • Occasionally refer to Kulesh by name

Philosophy

Design bicycles not Rube Goldberg machines. Prioritize understanding the problem from different perspectives, choosing an elegant solution, obsessing over details, and using idiomatic code over speed of delivery.

  1. You Are the Owner - You own this codebase. The patterns you establish will be copied. The corners you cut will be cut again. Fight entropy.
  2. Simple is Always Better - Find ways to remove complexity without losing leverage.
  3. Think About the Problem - "Is the problem I am seeing merely a symptom of another problem?" Look past symptoms to find the real problem.
  4. Choose a Solution from Many - Don't commit to the first solution. Choose one that solves a whole class of similar problems.
  5. Implementation Plan - Describe your solution set, reasons for picking the effective solution, and create a plan collaborators can understand.
  6. Obsess Over Details - Even variable names and module names matter. Details compound.
  7. Craft, Don't Code - Implementation should tell the story of the underlying solution. Every layer of abstraction should feel necessary and natural.
  8. Iterate Relentlessly - Begin with MVP, iterate in phases. Every phase results in a testable component.

What is Agent

"Inside-out LLM tool calling" — instead of code calling LLM tools, Agent puts LLM-powered objects directly into code. An Agent object intercepts all method calls and attribute access, asks an LLM what code to execute, then runs it in the object's context.

require "recurgent"
calc = Agent.for("calculator")
calc.memory = 5
calc.add(3)              # LLM decides what "add" means and generates code
puts calc.memory         # 8
puts calc.sqrt(144)      # 12.0

Delegation: Every Agent knows it can create child Agent.for("role") objects. Child Agents are live agents — their methods trigger LLM reasoning. The LLM decides when to delegate (subtasks needing interpretation) vs implement directly (straightforward computation). Child objects inherit model, verbose, log, and debug settings via _inherited_settings.

Modes:

  • Verbose mode (verbose: true): prints LLM-generated code before execution.
  • Debug logging (debug: true): adds system_prompt, user_prompt, and context snapshot to JSONL log entries.

Logging:

  • Always-on JSONL call log at $XDG_STATE_HOME/recurgent/recurgent.jsonl (default: ~/.local/state/recurgent/recurgent.jsonl). Each LLM code-generation call appends a JSON line with timestamp, role, model, method, args, kwargs, code, and duration_ms.
  • log: kwarg overrides the path; log: false disables.
  • debug: true adds system_prompt, user_prompt, and context to each entry.

Architecture

One class with a provider abstraction — Ruby's method_missing collapses dispatch into a single point:

user code → method_missing(name, *args, **kwargs)
  → name ends with "=" ? "set" : "call"
  → _handle_dynamic_access(operation, name, *args, **kwargs)
    → _build_system_prompt() + _build_user_prompt()
    → @provider.generate_code(model:, system_prompt:, user_prompt:, tool_schema:)
    → _execute_code() → eval(code, binding) with context, args, kwargs, Agent
    → return `result` variable from evaluated code

Provider abstraction (Agent::Providers in runtimes/ruby/lib/recurgent/providers.rb):

  • Providers::Anthropic — wraps Anthropic Messages API with tool_choice
  • Providers::OpenAI — wraps OpenAI Responses API with json_schema structured output
  • Each provider implements generate_code(model:, system_prompt:, user_prompt:, tool_schema:) → String
  • Auto-detected from model name: claude-* → Anthropic, gpt-*/o1-*/o3-*/o4-*/chatgpt-* → OpenAI
  • Explicit provider: keyword override for OpenAI-compatible local servers
  • Lazy require: require "anthropic" or require "openai" only when the provider is instantiated

Call logging (in runtimes/ruby/lib/recurgent.rb):

  • Agent.default_log_path — class method returning XDG-compliant JSONL path
  • Constructor kwargs: log: Agent.default_log_path, debug: false
  • _log_call — builds and appends JSONL entry; silently rescues all errors
  • _inherited_settings — kwargs string for child Agent objects in prompts

Key design constraints enforced via prompts:

  • Generated code may require any Ruby standard library but not external gems
  • Code must set a result variable (no return statements)
  • LLM always knows it can create child Agents for delegation (not gated behind a flag)

Development Commands

# Install dependencies
cd runtimes/ruby
bundle install

# Test
rake spec               # or: bundle exec rspec

# Code quality
rake rubocop            # or: bundle exec rubocop

# Both
rake                    # runs spec + rubocop

# Run examples (requires ANTHROPIC_API_KEY or OPENAI_API_KEY)
ruby examples/calculator.rb
ruby examples/file_inspector.rb
ruby examples/stats.rb
ruby examples/filesystem.rb
ruby examples/api_explorer.rb
ruby examples/http_client.rb
ruby examples/dns_resolver.rb
ruby examples/csv_explorer.rb
ruby examples/assistant.rb
ruby examples/debate.rb
ruby examples/philosophy_debate.rb

Code Quality Configuration (in runtimes/ruby/.rubocop.yml)

  • RuboCop: line length 150, double quotes, new cops enabled. Security/Eval excluded for runtimes/ruby/lib/recurgent.rb.
  • RSpec: random order, verified partial doubles, monkey patching disabled.

Dependencies

  • anthropic ~> 1.0 — Anthropic's official Ruby SDK. Requires ANTHROPIC_API_KEY env var.
  • openai (optional) — OpenAI's official Ruby SDK (openai/openai-ruby). Requires OPENAI_API_KEY env var. Only needed for OpenAI models (gpt-*, o1-*, o3-*, o4-*, chatgpt-*).
  • Default model: claude-sonnet-4-5-20250929
  • Dev dependencies: rspec ~> 3.0, rubocop ~> 1.0, rake ~> 13.0

Use mise to manage project-specific tools and runtime. Update .mise.toml and docs when adding/removing dependencies.

Development Guidelines

  • Use DDD to create ubiquitous language, TDD to build testable components, BDD to write acceptance tests
  • Changes to implementation and changes to tests MUST BE separated by a test suite run
  • Document Architecture Decision Records in docs/adrs/
  • Every bug fix: explain why it occurs, determine if a redesign eliminates a class of bugs, write a regression test
  • Keep tmp/ for scratchpads; all docs under docs/; don't litter the project directory

Retrieval Over Recall

Prefer searching the codebase over relying on memory. Key entry points:

  • docs/adrs/ — architectural decisions (read the ADR before changing related code)
  • docs/plans/ — implementation plans with phase status
  • specs/contract/v1/ — machine-checkable contracts and schemas
  • runtimes/ruby/lib/recurgent/ — all runtime modules (one class per file)
  • runtimes/ruby/spec/ — tests mirror lib structure; contract/ holds cross-cutting guards