This guide explains how to create new LLM provider plugins for abc-cli.
abc-cli uses a plugin system that allows different LLM providers to be used for command generation. Each provider is a separate Python package that:
- Implements the LLMProvider interface
- Registers itself as an entry point
- Provides configuration schema validation
- Create a new package directory:
mkdir abc-provider-NAME
cd abc-provider-NAME- Create the package structure:
abc-provider-NAME/
├── pyproject.toml
├── README.md
└── abc_provider_NAME/
├── __init__.py
└── llm_provider.py
- Configure pyproject.toml:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "abc-provider-NAME"
version = "2025.09.04" # Match abc-cli version format
description = "NAME LLM provider for abc-cli"
readme = "README.md"
requires-python = ">=3.8"
license = "Apache-2.0"
dependencies = [
"NAME-api-package>=X.Y.Z", # Provider's API package
]
[project.entry-points."abc.llm_providers"]
NAME = "abc_provider_NAME.llm_provider:NAMEProvider"Create a provider class in llm_provider.py that implements the LLMProvider interface:
from abc_cli import LLMProvider
from typing import Dict, Any
class NAMEProvider(LLMProvider):
"""NAME LLM provider."""
def __init__(self, config: Dict[str, str]):
"""Initialize provider with configuration."""
if config.get('provider') != 'NAME':
raise ValueError("Provider must be 'NAME'")
self.api_key = config['api_key']
# Initialize other provider-specific settings
# Initialize API client
def generate_command(
self,
description: str,
context: Dict[str, Any],
system_prompt: str,
) -> str:
"""Generate command using NAME's API."""
# Call the provider's API to generate a command
# Return the command with danger level annotation:
# command
# ##DANGERLEVEL=N## justification
def get_config_schema(self) -> Dict:
"""Get JSON schema for configuration."""
return {
"type": "object",
"properties": {
"provider": {
"type": "string",
"description": "Provider identifier (must be 'NAME')",
"enum": ["NAME"]
},
"api_key": {
"type": "string",
"description": "NAME API key"
},
# Add other provider-specific settings
},
"required": ["provider", "api_key"]
}- Create a test suite:
abc-provider-NAME/
└── tests/
├── conftest.py
└── test_provider.py
- Add test dependencies to pyproject.toml:
[project.optional-dependencies]
test = [
"pytest>=7.0.0",
"pytest-cov>=4.0.0",
]- Create tests that verify:
- Configuration parsing and validation
- Command generation functionality
- Error handling
- Integration with abc-cli core
Users can install your provider using:
pipx inject abc-cli abc-provider-NAMEFor development:
pipx inject abc-cli -e ./abc-provider-NAMEUsers configure your provider in ~/.abc.conf:
[default]
provider = NAME
api_key = {NAME_API_KEY}
# Other provider-specific settings
[name1] # Named configuration
provider = NAME
api_key = {NAME_API_KEY}
model = specific-model-
Error Handling:
- Validate all configuration settings
- Provide clear error messages
- Handle API errors gracefully
-
Testing:
- Mock API calls in tests
- Test error conditions
-
Documentation:
- Document all configuration options
- Provide installation instructions
- Include example configurations
-
Security:
- Never log API keys or sensitive data
- Validate and sanitize all inputs
- Follow provider's security guidelines
See abc_provider_anthropic for a complete example of a provider implementation.