firstp1ck/pi-coding-agent-forge/design-patterns

Claude Code and agent skill by firstp1ck/pi-coding-agent-forge

Trust tier 3
  • community
  • ext:[{"type":"hook","description":"Pre/post lifecycle hooks"}]
Source check pending

Checking that the SKILL.md file is still in the repository.

Agents should invoke this skill when choosing patterns, designing traits/interfaces/components, deciding abstraction boundaries, evaluating dependency injection/callbacks, or comparing implementation approaches in Rust, TypeScript/React, or Django/Python.

Install

npx vskill@latest install firstp1ck/pi-coding-agent-forge/design-patterns

Semi-extensibleMentions customization, but needs skill-specific knowledge. Read the extensible skills standard

SKILL.md

Design Patterns

Pattern recommendations tailored to the user's tech stacks. Every pattern recommendation includes when to use it, when to avoid it, and the trade-offs.

Quick Start

Choose a Pattern
  1. Identify the problem: What design challenge are you solving?
  2. Consider the context: What language? What scale? How often will this change?
  3. Evaluate options: 2-3 candidate patterns with trade-offs
  4. Recommend: The best fit for this specific context (not the "best pattern in general")

The golden rule: Patterns are tools, not goals. Use the simplest pattern that solves the problem. If no pattern fits, a plain function or struct is fine.


Rust Patterns

Newtype Pattern

Wrap a primitive to add type safety and domain meaning.

rust
struct UserId(u64);
struct OrderId(u64);
// Now the compiler prevents mixing up UserId and OrderId
fn get_order(user: UserId, order: OrderId) -> Order { ... }

When to use: When two values have the same underlying type but different meanings. When to skip: One-off uses where a type alias suffices.

Builder Pattern

Construct complex objects step by step.

rust
let config = ServerConfig::builder()
.host("localhost")
.port(8080)
.max_connections(100)
.build()?;

When to use: Structs with many optional fields, complex construction logic. When to skip: Structs with 1-3 required fields — just use new().

Typestate Pattern

Encode state transitions in the type system so invalid states are unrepresentable.

rust
struct Connection<S: State> { /* ... */ state: PhantomData<S> }
struct Disconnected;
struct Connected;
struct Authenticated;
impl Connection<Disconnected> {
fn connect(self) -> Result<Connection<Connected>> { ... }
}
impl Connection<Connected> {
fn authenticate(self, creds: &Credentials) -> Result<Connection<Authenticated>> { ... }
}
impl Connection<Authenticated> {
fn query(&self, sql: &str) -> Result<Rows> { ... }
}
// Can't call query() on a Disconnected connection — compile error

When to use: Protocols with clear state transitions (connections, workflows, parsing stages). When to skip: Simple on/off states — a boolean or enum is clearer.

Trait Objects vs Generics
ApproachDispatchBinary SizeFlexibility
impl Trait (generics)Static (monomorphized)Larger (one copy per type)Known at compile time
dyn Trait (trait objects)Dynamic (vtable)Smaller (one copy)Extensible at runtime

Use generics when: Performance matters, types are known at compile time, you want zero-cost abstraction. Use trait objects when: You need heterogeneous collections, plugin systems, or the set of types is open-ended.

Error Handling Patterns
PatternWhenCrate
thiserrorLibrary errors — structured, specific variantsthiserror
anyhowApplication errors — context-rich, propagate quicklyanyhow
Custom enumWhen you need exhaustive matching by callersstd only

Rule of thumb: Libraries use thiserror (callers need to match). Applications use anyhow (callers need context).


TypeScript / React Patterns

Compound Components

Components that work together implicitly via shared context.

tsx
<Select>
<Select.Trigger>Choose a fruit</Select.Trigger>
<Select.Options>
<Select.Option value="apple">Apple</Select.Option>
<Select.Option value="banana">Banana</Select.Option>
</Select.Options>
</Select>

When to use: Complex UI components with multiple related parts (menus, accordions, tabs). When to skip: Simple components with 1-2 elements.

Custom Hook Composition

Extract and compose behavior into reusable hooks.

tsx
function useDebounce<T>(value: T, delay: number): T { ... }
function usePagination(items: Item[], pageSize: number) { ... }
function useLocalStorage<T>(key: string, initial: T) { ... }

When to use: Shared stateful logic across components, complex state management within a component. When to skip: One-off logic that doesn't repeat.

Discriminated Unions

Type-safe state modeling using TypeScript's union types.

typescript
type AsyncState<T> =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: T }
| { status: "error"; error: Error };
// Exhaustive switch — TypeScript ensures all cases handled
function render(state: AsyncState<User>) {
switch (state.status) {
case "idle": return <Placeholder />;
case "loading": return <Spinner />;
case "success": return <UserCard user={state.data} />;
case "error": return <ErrorBanner error={state.error} />;
}
}

When to use: State machines, API response states, form states, anything with distinct modes. When to skip: Boolean flags are fine for simple on/off states.

State Management Decision Tree
  1. UI-local state? -> useState / useReducer
  2. Shared between siblings? -> Lift state to common parent
  3. Shared across distant components? -> React Context
  4. Complex state logic? -> useReducer + Context
  5. Server state (API data)? -> TanStack Query / SWR
  6. Global app state? -> Zustand / Jotai (prefer over Redux for new projects)

Django / Python Patterns

Service Layer

Separate business logic from views and models.

python
# services/order_service.py
class OrderService:
@staticmethod
def create_order(user: User, items: list[CartItem]) -> Order:
"""Business logic lives here, not in the view."""
order = Order.objects.create(user=user, total=calculate_total(items))
OrderItem.objects.bulk_create([...])
send_confirmation_email(user, order)
return order

When to use: Business logic that involves multiple models, external calls, or complex validation. When to skip: Simple CRUD with no business rules beyond Django's built-in validation.

Repository Pattern (QuerySet Abstraction)

Custom managers and querysets to encapsulate query logic.

python
class PublishedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(status="published")
class Article(models.Model):
objects = models.Manager() # Default
published = PublishedManager() # Article.published.all()

When to use: Complex or reusable query logic, domain-specific filtering. When to skip: One-off queries or simple filters.

Signals vs Explicit Calls
ApproachProsCons
Django signalsDecoupled, works across appsHidden control flow, hard to debug, ordering issues
Explicit callsVisible, debuggable, testableCoupling between modules

Rule of thumb: Use signals for truly cross-cutting concerns (audit logging, cache invalidation). Use explicit calls for business-critical logic where you need to understand and test the flow.


Anti-Patterns (All Stacks)

Anti-PatternProblemFix
Premature abstractionAbstracting before seeing the pattern repeatWait for 3 instances before extracting
Inheritance over compositionDeep inheritance hierarchies, fragile base classPrefer composition (traits, hooks, mixins)
God objectOne class/module that does everythingSplit by responsibility (SRP)
Shotgun surgeryOne change requires editing many filesGroup related code together
Feature envyA function uses another class's data more than its ownMove the function to the class it envies
Speculative generalityBuilding for use cases that may never comeYAGNI — build for now, refactor when needed
Golden hammerUsing the same pattern/tool for everythingChoose the right tool for the job

Pattern Selection Guide

When asked "which pattern should I use?":

  1. Describe the problem (not the pattern you think fits)
  2. Identify constraints (performance, extensibility, team size, timeline)
  3. Present 2-3 options with trade-offs
  4. Recommend one with clear justification
  5. Note when to revisit — "If X changes, reconsider Y"

Integration

  • Data: Pattern decisions logged to MEMORY.md (Patterns in Use section)
  • Cross-reference: architecture-review skill for structural assessment, refactoring-advisor for migration planning
  • Anti-patterns: When anti-patterns are detected, link to refactoring-advisor for remediation planning

_Arc skill — Design pattern selection and guidance_

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
5

Not refreshed yet.

Extension points

  • hookPre/post lifecycle hooks

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/firstp1ck/pi-coding-agent-forge/design-patterns/badge)](https://verified-skill.com/skills/firstp1ck/pi-coding-agent-forge/design-patterns)

Something wrong with this skill or its page? Tell us.