Primary Purpose: This project serves as a testbed for exploring and validating Claude Code agent configurations, agent collaboration patterns, and Effect-TS best practices.
A real-time stock trading CLI application built with Effect-TS, designed to test how specialized AI agents collaborate on complex TypeScript projects with proper functional programming patterns.
This project was built to validate the following custom Claude Code agents:
| Agent | Purpose | Key Responsibilities |
|---|---|---|
| effect-expert | Effect services, layers, DI | Implements Effect services, dependency injection, scoped resources, and error handling following Effect best practices |
| test-writer | Comprehensive testing | Writes tests using @effect/vitest for Effect code and vitest for pure functions |
| domain-modeler | Type-safe domain models | Creates domain models using ADTs, unions, branded types, with comprehensive predicates and Schema derivation |
| spec-writer | Spec-driven development | Manages the workflow from instructions through requirements, design, and implementation planning |
| react-expert | Compositional React patterns | Implements React patterns with Effect Atom, component composition over boolean props |
- atom-state: Reactive state management with Effect Atom
- context-witness: Context Tag witness vs capability patterns for DI
- domain-predicates: Generating typeclasses and predicates for domain types
- layer-design: Effect layer composition and dependency management
- service-implementation: Fine-grained Effect service design
- typeclass-design: Curried signatures and dual APIs
Issue Discovered: Tests were failing with race conditions where items were published before subscriptions were established.
Solution: Following Effect's documented pattern:
const program = Effect.scoped(
Effect.gen(function* () {
const { pubsub } = yield* TradePubSub.TradePubSub
// FIRST: Subscribe (establishes subscription immediately)
const dequeue = yield* PubSub.subscribe(pubsub)
// THEN: Publish
yield* PubSub.publish(pubsub, trade)
// FINALLY: Consume
const trade = yield* Queue.take(dequeue)
})
)Key Insight: A subscriber only receives messages published while actively subscribed. This is a critical Effect pattern that was validated through agent collaboration.
Original Approach: Wrapped PubSub with custom publish/subscribe methods (~30+ lines)
Improved Approach: Expose Effect primitives directly (~5 lines)
export class TradePubSub extends Context.Tag("@services/TradePubSub")<
TradePubSub,
{ readonly pubsub: PubSub.PubSub<Trade.TradeData> }
>() {}Lesson: Don't over-abstract Effect primitives. Expose them directly and let consumers use Effect's APIs.
All subscriptions and resources properly managed using Effect.scoped and Layer.scoped patterns, ensuring no resource leaks.
- effect-expert successfully debugged and fixed PubSub implementation issues
- test-writer identified the race condition through detailed investigation
- Agents effectively communicated findings through structured reports
- Iterative refinement led to simpler, more correct implementation
Trade.TradeData- Real-time trade data with timestamp, symbol, price, volumeStatistics.Statistics- Aggregate statistics (volume, prices, trade count)Indicator.IndicatorValue- Technical indicator results
TradePubSub- PubSub for broadcasting trades to multiple subscribersMarketDataProvider- Abstract interface for market data (Finnhub, Polygon)StatsCollector- Real-time statistics aggregationTradeDisplay- Terminal UI renderingWebSocketPublisher- WebSocket server for web clients
- Moving Average (SMA)
- RSI (Relative Strength Index)
- Bollinger Bands
- VWAP (Volume-Weighted Average Price)
- Volatility
156 tests passing
0 tests failing
246 expect() calls
Test suites:
- Domain models: Trade, Statistics, Indicator
- Services: TradePubSub (8 tests including race condition fixes)
While the primary purpose is agent testing, this is a fully functional stock trading CLI.
- Bun installed
- Finnhub.io API token (free tier available)
bun install# Run tests
bun test
# Type check
bun run typecheck
# Run CLI (requires Finnhub API token)
bun run dev --token YOUR_API_TOKEN --symbol "AAPL,MSFT"# Single symbol
bun run dev --token YOUR_TOKEN --symbol "AAPL"
# Multiple symbols
bun run dev --token YOUR_TOKEN --symbol "AAPL,MSFT,TSLA"
# Crypto
bun run dev --token YOUR_TOKEN --symbol "BINANCE:BTCUSDT"
# Forex
bun run dev --token YOUR_TOKEN --symbol "OANDA:EUR_USD"- Runtime: Bun (TypeScript execution and testing)
- Framework: Effect-TS (Functional effect system)
- Testing: @effect/vitest (Effect-aware testing)
- Schema: Effect Schema (Type-safe data validation)
- CLI: Effect CLI (Command-line interface)
- WebSocket: Effect Platform (WebSocket support)
.claude/
agents/ # Custom agent configurations
skills/ # Reusable agent skills
instructions.md # Project-specific instructions
settings.json # Agent settings
src/
domain/ # Domain models with Schema
services/ # Effect services (PubSub, Stats, etc.)
indicators/ # Technical indicators
providers/ # Market data providers (Finnhub, Polygon)
layers/ # Effect layer compositions
ui/ # React UI components (with Effect Atom)
test-utils/ # Test fixtures and helpers
-
PubSub Patterns
- Subscribe-before-publish race conditions
- Multiple subscriber fan-out
- Proper scoped resource management
-
Effect Service Design
- Layer composition and DI
- No requirement leakage
- Clean service boundaries
-
Stream Processing
- Real-time data pipelines
- Backpressure handling
- Stream transformations (filtering, sorting, aggregation)
-
Type Safety
- Schema-based validation
- Branded types for domain primitives
- ADTs and pattern matching
This is primarily a testing project, but contributions that help validate additional agent patterns or Effect-TS best practices are welcome!
MIT
Built with Claude Code agents to explore AI-assisted development patterns
π€ Generated with Claude Code