add-provider
Assists developers in building new AI providers by structuring architecture and test-driven implementation logic.
Install
mkdir -p .claude/skills/add-provider && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/7648" && unzip -o skill.zip -d .claude/skills/add-provider && rm skill.zipInstalls to .claude/skills/add-provider
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Guide for adding new AI providers to ClaudeBar using TDD patterns. Use this skill when:
(1) Adding a new AI assistant provider (like Antigravity, Cursor, etc.)
(2) Creating a usage probe for a CLI tool or local API
(3) Following TDD to implement provider integration
(4) User asks "how do I add a new provider" or "create a provider for X"Key capabilities
- →Implements new AI provider integrations using TDD
- →Creates usage probes for CLI tools and local APIs
- →Registers providers in the ClaudeBar application
- →Defines visual identity for new providers
How it works
The skill guides the developer through a five-phase TDD process, from parsing tests to registration and visual identity setup.
Inputs & outputs
When to use add-provider
- →Integrate new AI service providers
- →Create usage probes for CLI tools
- →Implement provider integration using TDD
About this skill
Add Provider to ClaudeBar
Add new AI providers following established TDD patterns and architecture.
Architecture Overview
Full architecture: docs/ARCHITECTURE.md
| Component | Location | Purpose |
|---|---|---|
AIProvider | Sources/Domain/Provider/ | Rich domain model with isEnabled state |
UsageProbe | Sources/Infrastructure/CLI/ | Fetches quota from CLI/API |
| Tests | Tests/InfrastructureTests/CLI/ | Parsing + behavior tests |
TDD Workflow
Phase 1: Parsing Tests (Red → Green)
Create Tests/InfrastructureTests/CLI/{Provider}UsageProbeParsingTests.swift:
import Testing
import Foundation
@testable import Infrastructure
@testable import Domain
@Suite
struct {Provider}UsageProbeParsingTests {
static let sampleResponse = """
{ /* sample API/CLI response */ }
"""
@Test func `parses quota into UsageQuota`() throws {
let data = Data(Self.sampleResponse.utf8)
let snapshot = try {Provider}UsageProbe.parseResponse(data, providerId: "{provider-id}")
#expect(snapshot.quotas.count > 0)
}
@Test func `maps percentage correctly`() throws { /* ... */ }
@Test func `parses reset time`() throws { /* ... */ }
@Test func `extracts account email`() throws { /* ... */ }
@Test func `handles missing data gracefully`() throws { /* ... */ }
}
Phase 2: Probe Behavior Tests (Red → Green)
Create Tests/InfrastructureTests/CLI/{Provider}UsageProbeTests.swift:
import Testing
import Foundation
import Mockable
@testable import Infrastructure
@testable import Domain
@Suite
struct {Provider}UsageProbeTests {
@Test func `isAvailable returns false when not detected`() async {
let mockExecutor = MockCLIExecutor()
given(mockExecutor).execute(...).willReturn(CLIResult(output: "", exitCode: 1))
let probe = {Provider}UsageProbe(cliExecutor: mockExecutor)
#expect(await probe.isAvailable() == false)
}
@Test func `isAvailable returns true when detected`() async { /* ... */ }
@Test func `probe throws appropriate error when unavailable`() async { /* ... */ }
@Test func `probe returns UsageSnapshot on success`() async { /* ... */ }
}
Phase 3: Implement Probe
Create Sources/Infrastructure/CLI/{Provider}UsageProbe.swift:
import Foundation
import Domain
public struct {Provider}UsageProbe: UsageProbe {
private let cliExecutor: any CLIExecutor
private let networkClient: any NetworkClient
private let timeout: TimeInterval
public init(
cliExecutor: (any CLIExecutor)? = nil,
networkClient: (any NetworkClient)? = nil,
timeout: TimeInterval = 8.0
) {
self.cliExecutor = cliExecutor ?? DefaultCLIExecutor()
self.networkClient = networkClient ?? URLSession.shared
self.timeout = timeout
}
public func isAvailable() async -> Bool {
// Detect if provider is available (binary exists, process running, etc.)
}
public func probe() async throws -> UsageSnapshot {
// 1. Detect/authenticate
// 2. Fetch quota data
// 3. Parse and return UsageSnapshot
}
// Static parsing for testability
static func parseResponse(_ data: Data, providerId: String) throws -> UsageSnapshot {
// Parse response into domain models
}
}
Phase 4: Create Provider
Choose Repository Type (ISP):
- Simple provider (no special config) → Use base
ProviderSettingsRepository - Provider with config → Create sub-protocol extending base (see ISP section below)
Create Sources/Domain/Provider/{Provider}Provider.swift:
import Foundation
import Observation
@Observable
public final class {Provider}Provider: AIProvider, @unchecked Sendable {
public let id: String = "{provider-id}"
public let name: String = "{Provider Name}"
public let cliCommand: String = "{cli-command}"
public var dashboardURL: URL? { URL(string: "https://...") }
public var statusPageURL: URL? { nil }
/// Whether the provider is enabled (persisted via settingsRepository)
public var isEnabled: Bool {
didSet {
settingsRepository.setEnabled(isEnabled, forProvider: id)
}
}
public private(set) var isSyncing: Bool = false
public private(set) var snapshot: UsageSnapshot?
public private(set) var lastError: Error?
private let probe: any UsageProbe
private let settingsRepository: any ProviderSettingsRepository // Or your sub-protocol
public init(probe: any UsageProbe, settingsRepository: any ProviderSettingsRepository) {
self.probe = probe
self.settingsRepository = settingsRepository
// Default to enabled for most providers (set defaultValue: false for opt-in providers)
self.isEnabled = settingsRepository.isEnabled(forProvider: "{provider-id}")
}
public func isAvailable() async -> Bool {
await probe.isAvailable()
}
@discardableResult
public func refresh() async throws -> UsageSnapshot {
isSyncing = true
defer { isSyncing = false }
do {
let newSnapshot = try await probe.probe()
snapshot = newSnapshot
lastError = nil
return newSnapshot
} catch {
lastError = error
throw error
}
}
}
Phase 5: Register Provider
Add to Sources/App/ClaudeBarApp.swift:
let settingsRepository = JSONSettingsRepository.shared
let repository = AIProviders(providers: [
ClaudeProvider(probe: ClaudeUsageProbe(), settingsRepository: settingsRepository),
// ... existing providers
{Provider}Provider(probe: {Provider}UsageProbe(), settingsRepository: settingsRepository),
])
For providers with special settings (ISP pattern):
// ZaiProvider uses ZaiSettingsRepository (sub-protocol)
ZaiProvider(
probe: ZaiUsageProbe(settingsRepository: settingsRepository),
settingsRepository: settingsRepository // Same instance, casted to ZaiSettingsRepository
)
// CopilotProvider uses CopilotSettingsRepository (sub-protocol with credentials)
CopilotProvider(
probe: CopilotUsageProbe(settingsRepository: settingsRepository),
settingsRepository: settingsRepository // Same instance, casted to CopilotSettingsRepository
)
Add visual identity in Sources/App/Views/Theme.swift:
// In AppTheme.providerColor(for:scheme:)
case "{provider-id}": return /* your color */
// In AppTheme.providerName(for:)
case "{provider-id}": return "{Provider Name}"
// In AppTheme.providerSymbolIcon(for:)
case "{provider-id}": return "/* SF Symbol name */"
// In AppTheme.providerIconAssetName(for:)
case "{provider-id}": return "{Provider}Icon"
Domain Model Mapping
Map provider responses to existing domain models:
| Source Data | Domain Model |
|---|---|
| Quota percentage | UsageQuota.percentRemaining (0-100) |
| Model/tier name | QuotaType.modelSpecific("name") |
| Reset time | UsageQuota.resetsAt (Date) |
| Account email | UsageSnapshot.accountEmail |
Error Handling
Use existing ProbeError enum:
ProbeError.cliNotFound("{Provider}") // Binary/process not found
ProbeError.authenticationRequired // Auth token missing/expired
ProbeError.executionFailed("message") // Runtime errors
ProbeError.parseFailed("message") // Parse errors
ISP: Creating Provider-Specific Repository Sub-Protocols
If your provider needs special configuration or credentials, create a sub-protocol following ISP:
Step 1: Define Sub-Protocol in Domain
Add to Sources/Domain/Provider/ProviderSettingsRepository.swift:
/// {Provider}-specific settings repository, extending base ProviderSettingsRepository.
public protocol {Provider}SettingsRepository: ProviderSettingsRepository {
// Configuration
func {provider}ConfigPath() -> String
func set{Provider}ConfigPath(_ path: String)
// Credentials (if needed)
func save{Provider}Token(_ token: String)
func get{Provider}Token() -> String?
func has{Provider}Token() -> Bool
}
Step 2: Implement in Infrastructure
Add to Sources/Infrastructure/Storage/JSONSettingsRepository.swift:
// MARK: - {Provider}SettingsRepository
extension JSONSettingsRepository: {Provider}SettingsRepository {
public func {provider}ConfigPath() -> String {
store.read(key: "{provider}.configPath") ?? ""
}
public func set{Provider}ConfigPath(_ path: String) {
store.write(value: path, key: "{provider}.configPath")
}
}
Step 3: Update Provider and Probe
// Provider
private let settingsRepository: any {Provider}SettingsRepository
// Probe (if needs settings)
public init(settingsRepository: any {Provider}SettingsRepository) {
self.settingsRepository = settingsRepository
}
Existing Examples:
ZaiSettingsRepository- config path + env varCopilotSettingsRepository- env var + GitHub credentials
Reference Implementation
See references/antigravity-example.md for a complete working example showing:
- Full parsing test suite
- Probe behavior tests with mocking
- Probe implementation with process detection
- Provider class pattern
Provider Icon
See references/provider-icon-guide.md for creating provider icons:
- SVG template with rounded rectangle background
- PNG generation at 1x/2x/3x sizes
- Asset catalog setup
- ProviderVisualIdentity extension
Checklist
- Parsing tests created and passing
- Probe behavior tests created and passing
- Probe implementation complete
- Provider class created
- Provider registered in ClaudeBarApp
- Visual identity added to Theme.swift (color, name, icons)
- Provider ico
Content truncated.
When not to use it
- →When not following the established TDD architecture
Limitations
- →Requires adherence to specific repository patterns
- →Requires manual creation of icon assets
How it compares
It enforces a strict TDD workflow and architectural pattern, ensuring new providers are testable and consistent with existing ones.
Compared to similar skills
add-provider side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| add-provider (this skill) | 1 | 5mo | No flags | Advanced |
| implement-feature | 1 | 7mo | Review | Advanced |
| new-api-support | 1 | 6mo | Review | Intermediate |
| api-test-generator | 1 | 9mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by tddworks
View all by tddworks →You might also like
implement-feature
tddworks
Guide for implementing features in ClaudeBar following architecture-first design, TDD, rich domain models, and Swift 6.2 patterns. Use this skill when: (1) Adding new functionality to the app (2) Creating domain models that follow user's mental model (3) Building SwiftUI views that consume domain models directly (4) User asks "how do I implement X" or "add feature Y" (5) Implementing any feature that spans Domain, Infrastructure, and App layers
new-api-support
nalexn
Add introspection support for a SwiftUI API (view type, modifier, or View extension function). Use when the user wants to add support for a new SwiftUI entity to ViewInspector.
api-test-generator
mikopbx
Генерация полных Python pytest тестов для REST API эндпоинтов с валидацией схемы. Использовать при создании тестов для новых эндпоинтов, добавлении покрытия для CRUD операций или валидации соответствия API с OpenAPI схемами.
ios-simulator-skill
conorluddy
21 production-ready scripts for iOS app testing, building, and automation. Provides semantic UI navigation, build automation, accessibility testing, and simulator lifecycle management. Optimized for AI agents with minimal token output.
build-iphone-apps
glittercowboy
Build professional native iPhone apps in Swift with SwiftUI and UIKit. Full lifecycle - build, debug, test, optimize, ship. CLI-only, no Xcode. Targets iOS 26 with iOS 18 compatibility.
xcodebuildmcp
cameroncooke
Official skill for XcodeBuildMCP. Use when doing iOS/macOS/watchOS/tvOS/visionOS work (build, test, run, debug, log, UI automation).