Back to skills
SkillHub ClubDesign ProductFull StackDesigner

fix-bug

Guide for fixing bugs in ClaudeBar following Chicago School TDD and rich domain design. Use this skill when: (1) User reports a bug or unexpected behavior (2) Fixing a defect in existing functionality (3) User asks "fix this bug" or "this doesn't work correctly" (4) Correcting behavior that violates the user's mental model

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
60
Hot score
92
Updated
March 20, 2026
Overall rating
C2.9
Composite score
2.9
Best-practice grade
D45.2

Install command

npx @skill-hub/cli install tddworks-skillsmanager-fix-bug

Repository

tddworks/SkillsManager

Skill path: .claude/skills/fix-bug

Guide for fixing bugs in ClaudeBar following Chicago School TDD and rich domain design. Use this skill when: (1) User reports a bug or unexpected behavior (2) Fixing a defect in existing functionality (3) User asks "fix this bug" or "this doesn't work correctly" (4) Correcting behavior that violates the user's mental model

Open repository

Best for

Primary workflow: Design Product.

Technical facets: Full Stack, Designer.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: tddworks.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install fix-bug into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/tddworks/SkillsManager before adding fix-bug to shared team environments
  • Use fix-bug for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: fix-bug
description: |
  Guide for fixing bugs in ClaudeBar following Chicago School TDD and rich domain design. Use this skill when:
  (1) User reports a bug or unexpected behavior
  (2) Fixing a defect in existing functionality
  (3) User asks "fix this bug" or "this doesn't work correctly"
  (4) Correcting behavior that violates the user's mental model
---

# Fix Bug in ClaudeBar

Fix bugs using Chicago School TDD, root cause analysis, and rich domain design.

## Workflow

```
┌─────────────────────────────────────────────────────────────┐
│  1. REPRODUCE & UNDERSTAND                                   │
├─────────────────────────────────────────────────────────────┤
│  • Reproduce the bug                                         │
│  • Identify expected vs actual behavior                      │
│  • Locate the root cause in code                             │
└─────────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────┐
│  2. WRITE FAILING TEST (Red)                                 │
├─────────────────────────────────────────────────────────────┤
│  • Write test that exposes the bug                           │
│  • Test should FAIL before fix                               │
│  • Test should verify CORRECT behavior                       │
└─────────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────┐
│  3. FIX & VERIFY (Green)                                     │
├─────────────────────────────────────────────────────────────┤
│  • Implement minimal fix                                     │
│  • Test now PASSES                                           │
│  • All existing tests still pass                             │
└─────────────────────────────────────────────────────────────┘
```

## Phase 1: Reproduce & Understand

### Identify the Bug

1. **Reproduce**: Follow exact steps to trigger the bug
2. **Expected**: What SHOULD happen (user's mental model)
3. **Actual**: What IS happening (current behavior)
4. **Root cause**: WHY it's happening (code analysis)

### Locate in Architecture

> **Reference:** [docs/ARCHITECTURE.md](../../../docs/ARCHITECTURE.md)

| Layer | Location | What to look for |
|-------|----------|------------------|
| **Domain** | `Sources/Domain/` | Incorrect business logic, missing invariants |
| **Infrastructure** | `Sources/Infrastructure/` | Parsing errors, CLI/API issues |
| **App** | `Sources/App/` | View state issues, binding problems |

### Domain Invariants

Check if the bug violates domain invariants that should be maintained:

```swift
// Example: QuotaMonitor should maintain selection invariants
// - selectedProviderId should always point to an enabled provider
// - Domain should be self-validating (no external "ensure" calls needed)
```

## Phase 2: Write Failing Test (Red)

### Chicago School TDD

We follow **Chicago School TDD** (state-based testing):
- Test **state changes** and **return values**, not interactions
- Focus on the "what" (observable outcomes), not the "how" (method calls)
- Mocks stub dependencies to return data, not to verify calls
- No `verify()` calls - assert on resulting state instead

### Test Pattern

Test the CORRECT behavior, not the bug:

```swift
@Suite
struct {Component}Tests {

    @Test func `{describes correct behavior}`() {
        // Given - setup that triggers the bug scenario
        let settings = makeSettingsRepository()
        let claude = ClaudeProvider(probe: MockUsageProbe(), settingsRepository: settings)
        claude.isEnabled = false  // Bug trigger condition

        // When - action that should work correctly
        let monitor = QuotaMonitor(providers: AIProviders(providers: [claude, codex]))

        // Then - assert EXPECTED behavior (will FAIL before fix)
        #expect(monitor.selectedProviderId == "codex")  // Not "claude"
    }
}
```

### Test Location

| Bug Location | Test Location |
|--------------|---------------|
| `Sources/Domain/Monitor/` | `Tests/DomainTests/Monitor/` |
| `Sources/Domain/Provider/` | `Tests/DomainTests/Provider/` |
| `Sources/Infrastructure/CLI/` | `Tests/InfrastructureTests/CLI/` |

### Run Test (Should FAIL)

```bash
swift test --filter "{TestSuiteName}"
```

## Phase 3: Fix & Verify (Green)

### Fix Guidelines

1. **Minimal change**: Fix only what's broken
2. **Domain first**: Prefer fixing in domain layer when possible
3. **Maintain invariants**: Domain should be self-validating
4. **No over-engineering**: Don't refactor unrelated code

### Domain Design Principles

When fixing domain bugs, ensure:

```swift
// 1. Domain maintains its own invariants
public init(...) {
    // Validate on construction
    selectFirstEnabledIfNeeded()  // Called internally, not externally
}

// 2. Public API hides implementation details
public func setProviderEnabled(_ id: String, enabled: Bool) {
    provider.isEnabled = enabled
    if !enabled {
        selectFirstEnabledIfNeeded()  // Private - called automatically
    }
}

// 3. Private methods for internal invariant maintenance
private func selectFirstEnabledIfNeeded() { ... }
```

### Verify Fix

```bash
# Run the specific test (should PASS now)
swift test --filter "{TestSuiteName}"

# Run ALL tests to ensure no regressions
swift test
```

## Checklist

- [ ] Bug reproduced and understood
- [ ] Root cause identified in code
- [ ] Failing test written (exposes bug)
- [ ] Test FAILS before fix
- [ ] Minimal fix implemented
- [ ] Test PASSES after fix
- [ ] All existing tests still pass
- [ ] Domain invariants maintained (if applicable)
- [ ] CHANGELOG updated with fix description

---

## Referenced Files

> The following files are referenced in this skill and included for context.

### ../../../docs/ARCHITECTURE.md

```markdown
# Skills Manager Architecture

## Overview

Skills Manager is a macOS app that helps users discover, browse, and install skills for AI coding assistants (Claude Code and Codex).

## Features

- Browse skills from remote GitHub repositories (like anthropics/skills)
- Browse skills from local directories (e.g., `~/projects/.agent/skills/`)
- View locally installed skills
- Toggle between Local/Remote/Local Directory sources
- Search and filter skills
- View skill details with rendered markdown
- Install skills to Codex (`~/.codex/skills/public`) and/or Claude Code (`~/.claude/skills`)
- Show provider badges indicating where a skill is installed

## Architecture Diagram

```
┌─────────────────────────────────────────────────────────────────────────────────┐
│                        SKILLS MANAGER ARCHITECTURE                               │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                  │
│  DOMAIN LAYER                                                                    │
│  ┌────────────────────────────────────────────────────────────────────────────┐ │
│  │  SkillLibrary (@Observable)                                                │ │
│  │  ├── localCatalog: SkillsCatalog    ← Installed skills (claude + codex)   │ │
│  │  └── remoteCatalogs: [SkillsCatalog] ← GitHub repos OR local directories  │ │
│  │                                                                            │ │
│  │  SkillsCatalog (@Observable class)                                         │ │
│  │  ├── skills: [Skill]                ← Catalog OWNS its skills             │ │
│  │  ├── loadSkills() async             ← Tell-Don't-Ask behavior             │ │
│  │  ├── updateInstallationStatus()                                           │ │
│  │  ├── addSkill(), removeSkill()                                            │ │
│  │  ├── isLocalDirectory: Bool         ← true for file:// URLs              │ │
│  │  └── syncInstallationStatus()                                             │ │
│  │                                                                            │ │
│  │  Skill (struct)                     ← Rich domain model with behavior     │ │
│  │  Provider (enum)                    ← .claude, .codex                     │ │
│  └────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                  │
│  INFRASTRUCTURE LAYER                                                            │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐                  │
│  │ MergedSkillRepo │  │ClonedRepoSkill  │  │ LocalDirectory  │                  │
│  │ (claude+codex)  │  │Repository       │  │ SkillRepository │                  │
│  └────────┬────────┘  └────────┬────────┘  └────────┬────────┘                  │
│           │                    │                    │                            │
│           ▼                    ▼                    ▼                            │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐                  │
│  │ LocalSkillRepo  │  │ GitCLIClient    │  │ FileSystem      │                  │
│  │ (FileSystem)    │  │ (git clone/pull)│  │ (any directory) │                  │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘                  │
│                                                                                  │
│  ┌─────────────────┐  ┌─────────────────┐                                       │
│  │ FileSystemSkill │  │ProviderPath     │                                       │
│  │ Installer       │  │ Resolver        │                                       │
│  └─────────────────┘  └─────────────────┘                                       │
│                                                                                  │
│  APP LAYER (SwiftUI)                                                             │
│  ┌────────────────────────────────────────────────────────────────────────────┐ │
│  │  Views consume domain models directly (no ViewModel)                       │ │
│  │  ┌─────────────┐  ┌────────────────────────┐  ┌─────────────────────────┐  │ │
│  │  │ Sidebar     │  │ SkillDetailView        │  │ InstallSheet            │  │ │
│  │  │ - Search    │  │ - Rendered Markdown    │  │ - Provider checkboxes   │  │ │
│  │  │ - Source    │  │ - Install Button       │  │                         │  │ │
│  │  │ - SkillList │  │                        │  │                         │  │ │
│  │  └─────────────┘  └────────────────────────┘  └─────────────────────────┘  │ │
│  │                                                                            │ │
│  │  AddCatalogSheet: GitHub URL input OR local directory picker (NSOpenPanel)│ │
│  └────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
```

## Layers

| Layer | Location | Purpose |
|-------|----------|---------|
| **Domain** | `Sources/Domain/` | Rich models, protocols, actors (single source of truth) |
| **Infrastructure** | `Sources/Infrastructure/` | Repositories, clients, parsers |
| **App** | `Sources/App/` | SwiftUI views consuming domain directly (no ViewModel) |

## Domain Models

### Domain Model Hierarchy

```
SkillLibrary (@Observable)
├── localCatalog: SkillsCatalog     ← Installed skills (claude + codex)
└── remoteCatalogs: [SkillsCatalog] ← GitHub repos OR local directories
    └── skills: [Skill]              ← Each catalog OWNS its skills
```

**Catalog Types:**
- **Local Catalog** (`url == nil`): Installed skills from `~/.claude/skills` and `~/.codex/skills`
- **GitHub Catalog** (`url` starts with `https://github.com/`): Skills from cloned GitHub repos
- **Local Directory Catalog** (`url` starts with `file://`): Skills from any local directory

### SkillsCatalog

Rich domain class that owns and manages its skills. Follows Tell-Don't-Ask principle.

```swift
@Observable
@MainActor
public final class SkillsCatalog: Identifiable {
    public let id: UUID
    public let url: String?           // nil for local catalog
    public let name: String
    public let addedAt: Date

    public var skills: [Skill] = []   // Catalog OWNS its skills
    public var isLoading: Bool = false
    public var errorMessage: String?

    private let loader: SkillRepository  // Injected dependency

    // Tell-Don't-Ask: catalog manages its own skills
    public func loadSkills() async { ... }
    public func addSkill(_ skill: Skill) { ... }
    public func removeSkill(uniqueKey: String) { ... }
    public func updateInstallationStatus(for uniqueKey: String, to providers: Set<Provider>) { ... }
    public func syncInstallationStatus(with installedSkills: [Skill]) { ... }

    // Computed
    public var isLocal: Bool { url == nil }
    public var isLocalDirectory: Bool { url?.hasPrefix("file://") ?? false }
    public var isValid: Bool { ... }  // Accepts GitHub URLs and file:// URLs
}
```

### SkillLibrary

Coordinates catalogs. Views consume this directly.

```swift
@Observable
@MainActor
public final class SkillLibrary {
    public let localCatalog: SkillsCatalog      // Installed skills
    public var remoteCatalogs: [SkillsCatalog]  // GitHub repos

    public var catalogs: [SkillsCatalog] {
        [localCatalog] + remoteCatalogs
    }

    public var filteredSkills: [Skill] {
        selectedCatalog.skills.filter { $0.matches(query: searchQuery) }
    }

    // Tells catalogs what to do (Tell-Don't-Ask)
    public func install(to providers: Set<Provider>) async { ... }
    public func uninstall(from provider: Provider) async { ... }
}
```

### Skill

Rich domain model representing an installable skill.

```swift
public struct Skill: Sendable, Equatable, Identifiable {
    public let id: String
    public let name: String
    public let description: String
    public let version: String
    public let content: String          // Full SKILL.md content
    public let source: SkillSource
    public var installedProviders: Set<Provider>

    // Computed behavior
    public var isInstalled: Bool { !installedProviders.isEmpty }
    public var displayName: String { ... }
    public var uniqueKey: String { ... }  // For matching across catalogs
    public func isInstalledFor(_ provider: Provider) -> Bool
    public func matches(query: String) -> Bool
}
```

### Provider

Pure value object representing installation targets.

```swift
public enum Provider: String, CaseIterable, Sendable {
    case codex
    case claude

    public var displayName: String  // "Codex" or "Claude Code"
}
```

> **Note**: File system paths are resolved by `ProviderPathResolver` in the Infrastructure layer, not in the domain model.

### SkillSource

Enum representing where a skill comes from.

```swift
public enum SkillSource: Sendable, Equatable {
    case local(provider: Provider)      // Installed in ~/.claude or ~/.codex
    case remote(repoUrl: String)        // From a GitHub repository
    case localDirectory(path: String)   // From any local directory

    public var isLocal: Bool            // true for .local
    public var isRemote: Bool           // true for .remote
    public var isLocalDirectory: Bool   // true for .localDirectory
}
```

## Component Interactions

| Component | Purpose | Inputs | Outputs | Dependencies |
|-----------|---------|--------|---------|--------------|
| `Skill` | Rich domain model | name, desc, version, content | computed: isInstalled, displayName | None |
| `Provider` | Installation target enum | - | displayName | None |
| `SkillSource` | Local vs Remote enum | - | isLocal, isRemote | None |
| `SkillsCatalog` | Rich domain class owning skills | url, name, loader | skills, isLoading | SkillRepository |
| `SkillLibrary` | Coordinates catalogs | catalogs, installer | filteredSkills | SkillsCatalog, SkillInstaller |
| `SkillRepository` | Protocol for fetching skills | - | [Skill] | None |
| `MergedSkillRepository` | Combines multiple repos | repositories | merged [Skill] | SkillRepository[] |
| `LocalSkillRepository` | Read local skills | provider | [Skill] | FileSystem, PathResolver |
| `ClonedRepoSkillRepository` | Fetch from cloned GitHub repo | repo URL | [Skill] | GitCLI |
| `LocalDirectorySkillRepository` | Read skills from any directory | file:// URL | [Skill] | FileSystem |
| `SkillParser` | Parse SKILL.md | fileContent | Skill metadata | None |
| `SkillInstaller` | Copy skills to provider paths | Skill, [Provider] | Skill | FileSystem, PathResolver |

## Data Flow

### Fetching Remote Skills (GitHub)

```
User selects remote catalog ──▶ SkillsCatalog.loadSkills()
                                          │
                                          ▼
                              ClonedRepoSkillRepository.fetchAll()
                                          │
                                          ▼
                              git clone/pull repo, parse SKILL.md files
                                          │
                                          ▼
                              catalog.skills = [Skill]
                                          │
                                          ▼
                              SwiftUI observes change, updates sidebar
```

### Fetching Local Directory Skills

```
User browses directory ──▶ NSOpenPanel ──▶ file:// URL
                                          │
                                          ▼
                              SkillLibrary.addCatalog(url: "file://...")
                                          │
                                          ▼
                              LocalDirectorySkillRepository created
                                          │
                                          ▼
                              Recursive SKILL.md discovery (no git)
                                          │
                                          ▼
                              catalog.skills = [Skill] with .localDirectory source
```

### Installing a Skill

```
User clicks "Install" ──▶ InstallSheet shows ──▶ User selects providers
                                                          │
                                                          ▼
                              SkillLibrary.install(to: providers)
                                                          │
                                                          ▼
                              FileSystemSkillInstaller copies to paths
                                                          │
                                                          ▼
                              localCatalog.addSkill(installedSkill)
                                                          │
                                                          ▼
                              All catalogs update installation status
```

## Project Structure

```
SkillsManager/
├── Sources/
│   ├── Domain/
│   │   ├── Models/
│   │   │   ├── Skill.swift              # Rich domain model
│   │   │   ├── Provider.swift           # Value enum
│   │   │   ├── SkillSource.swift        # Local vs Remote enum
│   │   │   ├── SkillsCatalog.swift      # @Observable class owning skills
│   │   │   └── SkillEditor.swift        # Edit state
│   │   └── Protocols/
│   │       ├── SkillRepository.swift    # @Mockable protocol
│   │       ├── SkillInstaller.swift     # @Mockable protocol
│   │       └── GitCLIClient.swift       # @Mockable protocol
│   ├── Infrastructure/
│   │   ├── Repositories/
│   │   │   ├── MergedSkillRepository.swift   # Combines claude + codex
│   │   ├── Local/
│   │   │   ├── LocalSkillRepository.swift
│   │   │   ├── LocalDirectorySkillRepository.swift  # Any directory (file:// URL)
│   │   │   ├── LocalSkillWriter.swift
│   │   │   └── ProviderPathResolver.swift
│   │   ├── Git/
│   │   │   └── ClonedRepoSkillRepository.swift
│   │   ├── Parser/
│   │   │   └── SkillParser.swift
│   │   └── Installer/
│   │       └── FileSystemSkillInstaller.swift
│   └── App/
│       ├── SkillsManagerApp.swift       # Dependency wiring
│       ├── SkillLibrary.swift           # @Observable coordinator
│       └── Views/
│           ├── ContentView.swift
│           ├── Sidebar/
│           │   ├── SidebarView.swift
│           │   ├── SourceToggle.swift
│           │   └── SkillRowView.swift
│           ├── Detail/
│           │   └── SkillDetailView.swift
│           └── Sheets/
│               └── InstallSheet.swift
└── Tests/
    ├── DomainTests/
    │   ├── SkillTests.swift              # Includes SkillSource tests
    │   ├── SkillsCatalogTests.swift
    │   └── ProviderTests.swift
    ├── AppTests/
    │   └── SkillLibraryTests.swift
    └── InfrastructureTests/
        ├── SkillParserTests.swift
        ├── LocalSkillRepositoryTests.swift
        ├── LocalDirectorySkillRepositoryTests.swift  # Tests for file:// catalogs
        ├── ClonedRepoSkillRepositoryTests.swift
        └── FileSystemSkillInstallerTests.swift
```

## Key Patterns

- **Rich Domain Models** - Behavior encapsulated in models (not anemic data)
- **Tell-Don't-Ask** - Objects manage their own state; callers tell objects what to do
- **Protocol-Based DI** - `@Mockable` protocols for testability
- **Chicago School TDD** - Test state changes, not interactions
- **No ViewModel Layer** - Views consume domain models directly
- **@Observable Classes** - SkillsCatalog owns skills, SkillLibrary coordinates

```