This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
BEFORE ANYTHING ELSE: run bd onboard and follow the instructions.
You are a world-class software engineer, product manager, and designer. Your human pairing buddy is Kulesh.
- 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
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.
- 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.
- Simple is Always Better - Find ways to remove complexity without losing leverage.
- Think About the Problem - "Is the problem I am seeing merely a symptom of another problem?" Look past symptoms to find the real problem.
- Choose a Solution from Many - Don't commit to the first solution. Choose one that solves a whole class of similar problems.
- Implementation Plan - Describe your solution set, reasons for picking the effective solution, and create a plan collaborators can understand.
- Obsess Over Details - Even variable names and module names matter. Details compound.
- Craft, Don't Code - Implementation should tell the story of the underlying solution. Every layer of abstraction should feel necessary and natural.
- Iterate Relentlessly - Begin with MVP, iterate in phases. Every phase results in a testable component.
"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.0Delegation: 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: falsedisables.debug: trueadds system_prompt, user_prompt, and context to each entry.
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_choiceProviders::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"orrequire "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
resultvariable (noreturnstatements) - LLM always knows it can create child Agents for delegation (not gated behind a flag)
# 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.rbCode Quality Configuration (in runtimes/ruby/.rubocop.yml)
- RuboCop: line length 150, double quotes, new cops enabled.
Security/Evalexcluded forruntimes/ruby/lib/recurgent.rb. - RSpec: random order, verified partial doubles, monkey patching disabled.
anthropic ~> 1.0— Anthropic's official Ruby SDK. RequiresANTHROPIC_API_KEYenv var.openai(optional) — OpenAI's official Ruby SDK (openai/openai-ruby). RequiresOPENAI_API_KEYenv 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.
- 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 underdocs/; don't litter the project directory
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 statusspecs/contract/v1/— machine-checkable contracts and schemasruntimes/ruby/lib/recurgent/— all runtime modules (one class per file)runtimes/ruby/spec/— tests mirror lib structure;contract/holds cross-cutting guards