2025-09-25
My AI Organization Ships Like We’re Funded, But It’s Just Me (Part 1)
Part 1: The Knowledge Infrastructure
I ship at the velocity of a funded startup, but it’s just me. The difference is giving AI assistants the same domain knowledge a human team member would have.
I’m not working harder or using productivity hacks. I’m helping AI move from a coding intern into something that can reason about product engineering and business knowledge.
The Evolution So Far
- How One Person Becomes a Dev Team with Claude Code - 5 specialists working in parallel
- From Dev Team to Engineering VP with Claude Code - Learned to orchestrate, not code
- This article - The knowledge infrastructure that makes AI accurate
The Difference That Domain Knowledge Makes
Without your specific context, AI will:
- Apply common practices that might not fit your needs
- Add abstraction layers you don’t want
- Miss requirements unique to your system
- Suggest solutions that violate your constraints
But when you document your domain knowledge:
- Your product helps [specific customer type] do [specific thing] better
- Customers stay because of [key differentiator], not features
- Variable names match what the business calls things (not generic “item” or “data”)
- “Good code” here means readable over clever, explicit over abstract
- That database choice was about compliance, not performance
- Multi-tenant isolation is non-negotiable due to [specific requirement]
- Past mistakes that shouldn’t be repeated
- The architecture patterns you actually strive for
Now AI makes the right architectural decisions without you explaining everything every time.
The Knowledge Infrastructure
Start with a Root CLAUDE.md
Here’s a reduced example from a production Rails app:
# CLAUDE.md - Domain Knowledge for Boswell
## What Boswell Does
- Client management system for food banks and community organizations
- Tracks households, people, distributions, and assistance programs
- Manages eligibility and benefits for food assistance recipients
## Core Architecture
- **Multi-tenant SaaS** with SQLite-per-tenant isolation
- **Tech Stack**: Rails 8, Turbo/Stimulus, Solid Queue, Passwordless auth
- **Real-time**: Turbo Streams and Action Cable for live updates
## Domain Knowledge Distribution
CLAUDE.md files exist throughout the codebase with area-specific guidance. Here are just a few:
- `app/models/CLAUDE.md` Model patterns and database architecture
- `app/controllers/CLAUDE.md` RESTful patterns and Turbo integration
- `app/business_logic/CLAUDE.md` Command pattern implementation
## Code Navigation
Look for AIDEV-NOTE comments in complex areas - they explain non-obvious decisions and gotchas.
# ... longer example at end of article
Document it once, and it’s available in every coding session.
Add Deep Documentation for Complex Systems
Reference docs by path and Claude Code reads them if needed, or use @path/to/doc.md
to always import the full content immediately. Here’s how I documented our payout system:
# Payout System
## Flow
ORDER → RevenueSplit → OrderItem (owner/referrer/platform shares)
↓
PayoutSchedulerJob (weekly)
↓
ProcessPayoutJob → Stripe Transfer
## Key Design Decisions
**Why weekly batching?**
Reduces Stripe fees and operational overhead vs daily payouts.
**Why PayoutItem junction table?**
Prevents double-payment via unique constraint on [order_item_id, payout_type].
## Troubleshooting
**No payout created?**
- User.find(id).stripe_connect_account_id must exist
- Check for existing PayoutItem blocking re-payment
# ... longer example at end of article
You can import these from any CLAUDE.md, prompt, command, or agent:
## Domain Knowledge
@docs/payout-system.md # Weekly payment processing logic
@docs/multi-tenant-isolation.md # Critical security boundaries
@docs/compliance-hipaa.md # Healthcare data requirements
@docs/api-rate-limiting.md # Customer throttling rules
Import these anywhere: in CLAUDE.md files, prompts, commands, or agent instructions.
Distribute Knowledge Throughout Your Codebase
Each major area gets its own CLAUDE.md file:
# app/models/CLAUDE.md
## Model Inheritance (STI)
class Album < Product # type = 'Album'
class Track < Product # type = 'Track'
## Money Handling
monetize :price_cents
# Usage: album.price = Money.new(1000, "USD") # $10.00
## Common Scopes
scope :published, -> { where(listing_state: "published") }
scope :salable, -> { published.where("release_date <= ?", Time.current) }
## Testing Models
- Test your behavior, not Rails
- Focus on custom methods, complex validations, business rules
# ... longer example at end of article
Leave Breadcrumbs with AIDEV-NOTE Comments
# AIDEV-NOTE: Critical section - must acquire lock
# This prevents the race condition we discovered in issue #234
# See: docs/payment-processing.md section 2.2
# Test coverage: spec/models/payment_spec.rb
def process_refund(amount)
with_advisory_lock("refund_#{id}") do
# implementation
end
end
Explain the non-obvious decisions directly in the code.
Less Prompting, More Accurate Results
Without domain knowledge:
You: "Add partial refund support"
AI: [Creates new PartialRefundsController]
[Adds refund_amount column to orders table]
[Direct Stripe API call in controller action]
[No idempotency handling]
[Doesn't update revenue reporting]
You: "No, we need to... let me explain our architecture..."
With domain knowledge:
You: "Add partial refund support"
AI: [Updates existing Commands::ProcessRefund to handle amounts]
[Records in ledger_entries with proper double-entry]
[Queues background job with idempotency key]
[Follows the same async pattern as other payment operations]
You: "Good, ship it"
The Compound Effect
Every piece of domain knowledge you add compounds over time. Clean commits and good documentation build on each other, while garbage commits become negative context that confuses future work.
Even with good domain knowledge, AI will make mistakes (you would too). The difference is catching them early:
- Create review agents with quality standards
- Review before committing
- When AI struggles, add the missing context
- Write clear specs when starting tasks
I’ve found two main failure points:
- Missing domain context - AI doesn’t know your business rules
- Ambiguous requirements - “Make it better” means nothing even with perfect context
Simple prompts like “add partial refund support” work when your domain docs define the concepts. For complex changes, write a spec that defines success.
The compound effect is real: each piece of context you add makes the next task easier. Clean as you go, and watch your velocity increase.
How to Get Started
Ask your AI to help create the documentation:
- “Generate CLAUDE.md files for each major area of this codebase”
- “What areas of this codebase would benefit from domain documentation?”
- “Create AIDEV-NOTE comments for the complex sections you found”
When AI struggles with something, that’s a signal. Ask it:
- “What context would help you understand this better?”
- “Where should we document this concept?”
- “Add what you just learned to [file].md, optimized for AI agents, concise but informative”
Use AI to help write the documentation once you’ve identified what’s needed.
Distribute CLAUDE.md files throughout your codebase - one per module, service, or complex area. Many small context files beat one giant file. AI can help identify where to place them.
Coming in Part 2
This is just domain knowledge. Next, I’ll show you how I:
- How I manage tickets and issues with AI
- The CI/CD setup and PR review process
- How code review works when your team is AI
For massive enterprise codebases, you’d need more complex memory management. But this simple approach works great for most projects and requires nothing beyond Claude Code itself.
Document your domain knowledge first. Everything else builds on that foundation.
Reduced Examples From Production
These are the actual knowledge files that turn AI assistants from interns into professionals.
Example: Reduced out of CLAUDE.md from Boswell (CBO Management System)
# CLAUDE.md - Domain Knowledge for Boswell
[NOTE: Production file contains more comprehensive documentation]
This file provides guidance to Claude Code when working with the Boswell repository.
## Project Overview
**Boswell** is a Rails 8 food assistance management system designed for Community Based Organizations (CBOs).
### What It Does
- Client management system for food banks and community organizations
- Tracks households, people, distributions, and assistance programs
- Manages eligibility and benefits for food assistance recipients
- Provides real-time updates for distribution events
### Who It's For
- Food banks
- Community organizations
- Social service agencies providing assistance to households in need
### Core Architecture
- **Multi-tenant SaaS** with SQLite-per-tenant isolation (each org gets its own database)
- **Tech Stack**: Rails 8, Turbo/Stimulus, Solid Queue, Passwordless auth, Pundit
- **Real-time**: Turbo Streams and Action Cable for live updates
- **UI**: Server-side rendering with BeerCSS components
## Development Workflows with Specialized Agents
### Orchestrator Commands
/orchestrators:tdd #<issue_number> # Full TDD for new features
/orchestrators:implement #<issue_number> # Direct implementation (faster)
/orchestrators:fix-bug #<issue_number> # Bug fixes with regression test
/orchestrators:refactor "description" # Safe refactoring with tests
### Specialized Agents
Use specialized subagents when appropriate for tasks like database migrations, bug diagnosis, code quality checks, and more. These will be auto-invoked based on the task context.
## Domain Knowledge Distribution
Always check for relevant CLAUDE.md for our coding standards, patterns and domain knowledge. The codebase contains many CLAUDE.md files with specialized guidance, here are a few:
- app/models/CLAUDE.md Model patterns and database architecture
- app/controllers/CLAUDE.md RESTful patterns and Turbo integration
- app/business_logic/CLAUDE.md Command pattern implementation
- app/policies/CLAUDE.md Authorization patterns with Pundit
- test/CLAUDE.md Testing philosophy and anti-patterns
## Essential Commands
# Development
bin/dev # Start Rails server
bin/rails console # Interactive console
# Database
bin/rails db:prepare # Setup from scratch
bin/rails db:migrate # Run migrations
# Testing & Quality
bin/rails test # Run full test suite
bin/rubocop -A # Auto-fix style issues
[... production file continues with more sections ...]
Example: Payout System Domain Documentation (Reduced out of Harmonic.fm)
# Payout System
[NOTE: Production file contains additional implementation details]
## Flow
ORDER → RevenueSplit → OrderItem (owner/referrer/platform shares)
↓
PayoutSchedulerJob (weekly via config/recurring.yml)
Finds users with:
- Unpaid owner shares (artists)
- Unpaid referrer shares (curators)
↓
CreatePayoutJob (per user)
↓
ProcessPayoutJob → Stripe Transfer
## Key Design Decisions
**Why weekly batching?**
Reduces Stripe fees and operational overhead vs daily payouts.
**Why combine owner + referrer earnings?**
Single transfer per user is simpler and cheaper than separate transfers.
**Why PayoutItem junction table?**
Prevents double-payment via unique constraint on `[order_item_id, payout_type]`.
## Troubleshooting
**No payout created?**
- `User.find(id).stripe_connect_account_id` must exist
- `OrderItem.unpaid_items_for_user(user)` must return records
- Check for existing `PayoutItem` blocking re-payment
**Stripe transfer failed?**
- Check Stripe Connect account status in Stripe Dashboard
- Verify platform has sufficient balance
- Review `Payout.last.error_message`
## Entry Points
- Schedule: `config/recurring.yml` → `payout_scheduler`
- Manual: `PayoutSchedulerJob.perform_now`
- Per-user: `Commands::CreatePayout.new(user: user).run`
[... production file continues with more details ...]
Example: Reduced Model-Specific CLAUDE.md
# /app/models/CLAUDE.md
[NOTE: Production file includes complete pattern library]
# Model & Database Patterns
## Best Practices
1. **Use scopes**: Named queries for readability
2. **Callbacks**: OK for same-model operations, avoid cross-model callbacks
3. **Commands for business logic**: Multi-step operations across models belong in Commands
4. **Index foreign keys**: Essential for performance
5. **Use concerns**: Extract shared behavior
6. **Validate data**: At database and model level
7. **Test your behavior, not Rails**: Focus on custom methods, complex validations, and business rules
## Common Models
- `User` - Authentication via Passwordless
- `Tenant` - Multi-tenant organization (food bank/CBO)
- `Household` - Family unit receiving assistance
- `Person` - Individual member of household
- `Distribution` - Distribution of assistance event
- `AssistanceProgram` - Programs offered (SNAP, WIC, etc.)
- `Allocation` - Resource assignments
- `Role` - User permissions within tenant
- `TagVocabulary` & `AllowedTag` - Flexible tagging system
## Model Inheritance (STI)
class Product < ApplicationRecord
# Base class for all products
end
class Album < Product
# type = 'Album'
has_many :tracks, foreign_key: :parent_id
has_one :album_variant
end
class Track < Product
# type = 'Track'
belongs_to :album, foreign_key: :parent_id, optional: true
has_one :track_variant
end
## Common Patterns
### Scopes
class Album < Product
scope :published, -> { where(listing_state: "published") }
scope :salable, -> { published.where("release_date <= ?", Time.current) }
scope :newest, -> { order(created_at: :desc) }
scope :by_genre, ->(genre) { tagged_with(genre) }
end
### JSONB Metadata
class Product < ApplicationRecord
# Access JSONB fields
store_accessor :metadata,
:artist_name, :release_date, :duration,
:track_number, :genre_list
# Usage
album.metadata_artist_name = "Artist Name"
album.metadata_release_date = Date.today
end
### Soft Delete
class Product < ApplicationRecord
include Discard::Model
# Usage
album.discard # Soft delete
album.undiscard # Restore
Album.kept # Non-deleted records
Album.discarded # Deleted records
end
## Associations
### Has Many Through
class User < ApplicationRecord
has_many :organization_memberships
has_many :organizations, through: :organization_memberships
has_many :orders
has_many :purchased_products, through: :orders, source: :product
end
### Polymorphic
class Recommendation < ApplicationRecord
belongs_to :user
belongs_to :recommendable, polymorphic: true
# Can recommend albums, tracks, etc.
end
## Validations
class Album < Product
validates :title, presence: true, length: { maximum: 255 }
validates :slug, uniqueness: { scope: :organization_id }
validates :price_cents, numericality: { greater_than_or_equal_to: 0 }
validate :has_items, on: :create
private
def has_items
errors.add(:base, "Must have items") if items.empty?
end
end
## Money Handling
class Product < ApplicationRecord
monetize :price_cents
# Usage
album.price = Money.new(1000, "USD") # $10.00
album.price_cents # => 1000
album.price.format # => "$10.00"
end
## Testing Models
class AlbumTest < ActiveSupport::TestCase
describe "validations" do
it "requires title" do
album = Album.new
refute album.valid?
assert_includes album.errors[:title], "can't be blank"
end
end
describe "scopes" do
it "returns published albums" do
published = Album.published
assert published.all? { |a| a.listing_state == "published" }
end
end
end
[... production file continues with more patterns and examples ...]