MCP HubMCP Hub
スキル一覧に戻る

common-conventions

majiayu000
更新日 Today
21 閲覧
58
9
58
GitHubで表示
メタgeneral

について

このスキルは、プロジェクト間の一貫性を確保するために、ファイル構成、バレルエクスポート、命名パターン、モジュール構造に関するTMNLコードベースの規約を提供します。これはメタスキルとして機能し、開発者はコードスタイル、ファイル構造、命名規則についてのガイダンスが必要な際にこれを呼び出すべきです。主な必須ルールには、ドメイン型にはEffect Schemaを使用すること、12pxのタイポグラフィ下限を維持すること、ライブラリモジュールの特定のディレクトリレイアウトに従うことが含まれます。

クイックインストール

Claude Code

推奨
プラグインコマンド推奨
/plugin add https://github.com/majiayu000/claude-skill-registry
Git クローン代替
git clone https://github.com/majiayu000/claude-skill-registry.git ~/.claude/skills/common-conventions

このコマンドをClaude Codeにコピー&ペーストしてスキルをインストールします

ドキュメント

TMNL Common Conventions

Overview

TMNL maintains strict conventions for code organization, naming, and documentation. This skill codifies patterns observed across the codebase to ensure consistency.

Mandatory Conventions (Non-negotiable):

  1. Schema discipline — All domain types use Effect Schema
  2. Typography 12px floor — No text smaller than 12px
  3. Atom-as-State doctrine — No Effect.Ref for React consumers
  4. Dependency audit — Grep before cutting imports

Pattern 1: Library Module Structure

When: Creating a new library at src/lib/{feature}/

Standard Directory Layout

src/lib/{feature}/
├── index.ts              # Barrel export (required)
├── types.ts              # TypeScript types (UI props, configs)
├── schemas/              # Effect Schema definitions
│   └── index.ts
├── services/             # Effect.Service implementations
│   ├── index.ts
│   └── {Feature}Service.ts
├── atoms/                # effect-atom definitions
│   └── index.ts
├── hooks/                # React hooks
│   └── use{Feature}.ts
├── components/           # React components (if UI-heavy)
│   └── {Component}.tsx
├── machines/             # XState machines (if stateful)
│   └── {feature}-machine.ts
├── v1/, v2/              # Version directories (for evolution)
└── CLAUDE.{feature}.md   # Agent handoff documentation

When to Use Each Directory

DirectoryWhen to Create
services/Multiple Effect services, or single complex service
service.ts (root)Single simple service (e.g., src/lib/commands/service.ts)
atoms/effect-atom state management
hooks/Multiple React hooks
use{Feature}.tsx (root)Single hook
schemas/Domain types requiring validation
types.tsUI props, configs, non-validated types
machines/XState state machines
v1/, v2/Major version evolution (not breaking changes)

Pattern 2: Barrel File (index.ts) Structure

When: Every src/lib/{feature}/ directory requires a barrel export.

Standard Format

/**
 * {Feature} Library
 *
 * {Brief description}
 *
 * @example
 * ```tsx
 * import { Component, useFeature } from '@/lib/{feature}'
 * ```
 */

// ═══════════════════════════════════════════════════════════════════════════
// CORE EXPORTS
// ═══════════════════════════════════════════════════════════════════════════

export { MainComponent } from './components/Main'
export { FeatureService } from './services'

// ═══════════════════════════════════════════════════════════════════════════
// SCHEMAS
// ═══════════════════════════════════════════════════════════════════════════

export * from './schemas'

// ═══════════════════════════════════════════════════════════════════════════
// ATOMS (effect-atom)
// ═══════════════════════════════════════════════════════════════════════════

export {
  stateAtom,
  configAtom,
  operationsAtom,
} from './atoms'

// ═══════════════════════════════════════════════════════════════════════════
// REACT HOOKS
// ═══════════════════════════════════════════════════════════════════════════

export { useFeature, useFeatureState } from './hooks'

// ═══════════════════════════════════════════════════════════════════════════
// TYPES
// ═══════════════════════════════════════════════════════════════════════════

export type { FeatureConfig, FeatureState } from './types'

Section Separators

Use box-drawing characters for major sections:

// ═══════════════════════════════════════════════════════════════════════════
// SECTION NAME (all caps)
// ═══════════════════════════════════════════════════════════════════════════

Use simple dashes for subsections:

// ───────────────────────────────────────────────────────────────────────────
// Subsection name
// ───────────────────────────────────────────────────────────────────────────

Version Re-exports

For modules with v1/v2:

// Default exports from v1
export * from './v1'

// Explicit v2 namespace
export * as v2 from './v2'

Usage:

import { Slider } from '@/lib/slider'         // v1 (default)
import { Slider } from '@/lib/slider/v2'      // v2 (explicit)

Pattern 3: Naming Conventions

Atoms

PatternExampleUsage
{noun}AtomresultsAtomState atom
{noun}sAtomlayersAtomCollection atom
{verb}AtomcomputedAtomDerived/computed atom
{feature}OpsAtomlayerOpsAtomOperation atoms (mutations)
{verb}OpsearchOp, clearOpIndividual operation

Services

PatternExampleUsage
{Feature}ServiceDataManagerServiceEffect.Service class
{Feature}ServiceShapeChannelServiceShapeInterface type
{Behavior}BehaviorLinearBehavior, DecibelBehaviorStrategy pattern

Hooks

PatternExampleUsage
use{Feature}useSliderMain feature hook
use{Feature}ValueuseSliderValueRead-only value hook
use{Feature}StateuseMinibufferStateState + updater
use{Feature}OpsuseOverlayOpsOperations only
useAtom{Feature}useAtomValueAtom-specific

Components

PatternExampleUsage
{Name}.tsxSlider.tsxComponent file
{Name}PropsSliderPropsProps interface
{Name}ContextDataGridContextContext type
{Name}ProviderCommandProviderContext provider

Machines

PatternExampleUsage
{feature}MachineminibufferMachineXState machine
{Feature}MachineMinibufferMachineType alias
{Feature}ActorMinibufferActorActorRef type

Pattern 4: Comment Styles

File Header (JSDoc)

/**
 * {Module Name} — {Brief description}
 *
 * {Longer description if needed}
 *
 * @example
 * ```tsx
 * // Usage example
 * ```
 */

Architectural Notes

For non-obvious design decisions:

// ARCHITECTURAL NOTE:
// CommandProvider lives here (commands/), not in minibuffer/.
// Minibuffer is a generic prompt engine. Commands USES minibuffer, not the reverse.

TODO/FIXME

// TODO(prime): Migrate to v2 API after EPOCH-0003
// FIXME: This breaks when input is empty
// HACK: Workaround for WSLg rendering bug

Pattern 5: Types vs Schemas

When to Use types.ts

  • React component props
  • UI configuration
  • Local function parameters
  • Types that don't need runtime validation
// src/lib/slider/v1/types.ts
export interface SliderProps {
  value: number
  onChange: (value: number) => void
  min?: number
  max?: number
}

export interface SliderConfig {
  min: number
  max: number
  step: number
  defaultValue: number
}

When to Use schemas/

  • Domain types requiring validation
  • Event payloads
  • API responses
  • Discriminated unions with pattern matching
  • EventLog integration
// src/lib/overlays/schemas/core.ts
import { Schema } from 'effect'

export const OverlayId = Schema.String.pipe(
  Schema.brand('OverlayId')
)
export type OverlayId = typeof OverlayId.Type

export const OverlayOpened = Schema.TaggedStruct('OverlayOpened', {
  id: OverlayId,
  timestamp: Schema.DateFromSelf,
})

Pattern 6: Test File Organization

Location Patterns

PatternExampleWhen
__tests__/ directorysrc/lib/stx/__tests__/Multiple test files
.test.ts suffixservice.test.tsSingle test file
.bun.test.ts suffixeventlog-integration.bun.test.tsBun-specific

Test Naming

// src/lib/feature/__tests__/feature.test.ts
describe('FeatureService', () => {
  describe('operation', () => {
    it('does X when Y', () => { ... })
    it('fails with Z when W', () => { ... })
  })
})

Effect Service Tests

Use @effect/vitest with it.effect():

import { describe, it } from '@effect/vitest'

describe('MyService', () => {
  it.effect('returns data', () =>
    Effect.gen(function* () {
      const service = yield* MyService
      const result = yield* service.getData()
      expect(result).toBeDefined()
    }).pipe(Effect.provide(MyService.Default))
  )
})

Atom Tests

Use Registry.make():

it('atom updates', () => {
  const r = Registry.make()
  expect(r.get(counterAtom)).toBe(0)
  r.set(counterAtom, 1)
  expect(r.get(counterAtom)).toBe(1)
})

Pattern 7: Documentation Files

Per-Module Documentation

FilePurposeAudience
CLAUDE.{feature}.mdAgent handoffAI assistants
README.mdUser-facing docsDevelopers
ARCHITECTURE.mdDeep design analysisArchitects
AGENTS.{feature}.mdAgent-specific notesAI assistants

CLAUDE.{feature}.md Structure

# {Feature} — Claude Context

## Overview
{Brief description}

## Key Files
- `service.ts` — Main service implementation
- `atoms/index.ts` — Reactive state

## Patterns Used
- Effect.Service<>() for DI
- Atom.runtime() for state

## Gotchas
- Don't use X because Y
- Always Z before W

## Related Skills
- effect-patterns
- effect-atom-integration

Pattern 8: Service File Patterns

Single Service (Root Level)

// src/lib/commands/service.ts

/**
 * TMNL Commands — Effect Service
 */

// ───────────────────────────────────────────────────────────────────────────
// Atoms (Reactive State)
// ───────────────────────────────────────────────────────────────────────────

export const commandsAtom = Atom.make<ReadonlyMap<string, Command>>(new Map())

// ───────────────────────────────────────────────────────────────────────────
// Service Implementation
// ───────────────────────────────────────────────────────────────────────────

export class CommandService extends Effect.Service<CommandService>()('app/CommandService', {
  effect: Effect.gen(function* () {
    // ...
  }),
}) {}

Multiple Services (Directory)

src/lib/overlays/services/
├── index.ts              # Re-exports all services
├── OverlayRegistry.ts    # Registry service
├── PortHub.ts            # Port management
└── EventDispatcher.ts    # Event dispatch

Anti-Patterns

1. Barrel File Without Sections

// WRONG — Unorganized exports
export * from './components'
export * from './hooks'
export * from './types'
export * from './atoms'

// CORRECT — Sectioned exports
// ═══════════════════════════════════════════════════════════════════════════
// COMPONENTS
// ═══════════════════════════════════════════════════════════════════════════
export { Slider } from './components/Slider'

// ═══════════════════════════════════════════════════════════════════════════
// HOOKS
// ═══════════════════════════════════════════════════════════════════════════
export { useSlider } from './hooks/useSlider'

2. Types in Wrong Location

// WRONG — Domain type without Schema
// src/lib/feature/types.ts
export interface UserEvent {
  _tag: 'UserCreated'
  id: string
  name: string
}

// CORRECT — Domain type with Schema
// src/lib/feature/schemas/events.ts
export const UserCreated = Schema.TaggedStruct('UserCreated', {
  id: Schema.String,
  name: Schema.NonEmptyString,
})

3. Inconsistent Naming

// WRONG — Mixed naming styles
export const user_state_atom = Atom.make(...)  // snake_case
export const UseUserHook = () => { ... }       // PascalCase for hook
export const userservice = Effect.Service()    // no separator

// CORRECT — Consistent camelCase with type suffix
export const userStateAtom = Atom.make(...)
export const useUser = () => { ... }
export const UserService = Effect.Service()

4. Missing JSDoc on Exports

// WRONG — No documentation
export const searchOp = runtimeAtom.fn<string>()(...)

// CORRECT — JSDoc on public exports
/**
 * Search operation. Triggers search with given query.
 *
 * @param query - Search query string
 * @returns Effect that updates resultsAtom
 */
export const searchOp = runtimeAtom.fn<string>()(...)

Checklist: New Module Creation

When creating src/lib/{feature}/:

  • Create index.ts with JSDoc header and sectioned exports
  • Create types.ts for non-domain types (UI props, configs)
  • Create schemas/ for domain types using Effect Schema
  • Create services/ (or service.ts) with Effect.Service<>()
  • Create atoms/index.ts with Atom definitions
  • Create hooks/ with React hooks
  • Use section comments: // ═══════...
  • Add ARCHITECTURAL NOTE for non-obvious decisions
  • Create CLAUDE.{feature}.md for agent handoff
  • Prefer Atom.make<T>() over Effect.Ref<T> for React
  • Test with @effect/vitest for services, Registry.make() for atoms

Canonical Examples

ConventionBest ExampleFile
Barrel fileOverlayssrc/lib/overlays/index.ts
Service patternCommandssrc/lib/commands/service.ts
Atom organizationSlidersrc/lib/slider/v1/atoms/index.ts
Schema usageCommandssrc/lib/commands/types.ts
Hook namingCommandssrc/lib/commands/useCommandWire.tsx
Version strategySlidersrc/lib/slider/index.ts
Test organizationSTXsrc/lib/stx/__tests__/

Integration Points

  • tmnl-file-organization — Directory structure details
  • effect-patterns — Service definition patterns
  • effect-atom-integration — Atom patterns
  • tmnl-typography-discipline — Typography rules
  • effect-schema-mastery — Schema patterns

GitHub リポジトリ

majiayu000/claude-skill-registry
パス: skills/common-conventions

関連スキル

algorithmic-art

メタ

This Claude Skill creates original algorithmic art using p5.js with seeded randomness and interactive parameters. It generates .md files for algorithmic philosophies, plus .html and .js files for interactive generative art implementations. Use it when developers need to create flow fields, particle systems, or other computational art while avoiding copyright issues.

スキルを見る

subagent-driven-development

開発

This skill executes implementation plans by dispatching a fresh subagent for each independent task, with code review between tasks. It enables fast iteration while maintaining quality gates through this review process. Use it when working on mostly independent tasks within the same session to ensure continuous progress with built-in quality checks.

スキルを見る

executing-plans

デザイン

Use the executing-plans skill when you have a complete implementation plan to execute in controlled batches with review checkpoints. It loads and critically reviews the plan, then executes tasks in small batches (default 3 tasks) while reporting progress between each batch for architect review. This ensures systematic implementation with built-in quality control checkpoints.

スキルを見る

cost-optimization

その他

This Claude Skill helps developers optimize cloud costs through resource rightsizing, tagging strategies, and spending analysis. It provides a framework for reducing cloud expenses and implementing cost governance across AWS, Azure, and GCP. Use it when you need to analyze infrastructure costs, right-size resources, or meet budget constraints.

スキルを見る