ADR-002: CLI Plugin Architecture
Status: Partially Implemented Date: 2024-11-29 (Updated: 2025-12-16) Context: Extend CLI with pluggable features for AI agents, generators, and integrations
Implementation Status (v1.1.0+)
| Component | Status | Evidence |
|---|---|---|
| PluginCommand | ✅ Implemented | commands/PluginCommand.java |
| Plugin SPI | ✅ Implemented | plugin/spi/ package |
| AI Service Abstraction | ⚠️ Planned | Future work |
| Complete Plugin Loader | ⚠️ In Progress | Partial implementation |
Current Capabilities:
- ✅
plugin list- List installed plugins - ✅
plugin install <jar>- Install plugin from JAR - ✅
plugin info <id>- Show plugin details - ✅
plugin init-config- Initialize plugin configuration - ✅ Service Provider Interface (SPI) for extensions
Remaining Work:
- AI service provider abstraction (Claude, OpenAI, local)
- Complete plugin discovery mechanism
- Plugin dependency management
- Hot reload capability
Context
The iDempiere CLI has two distinct use cases:
- Core Development - System tenant functionality for iDempiere plugin development
- Custom Tools - Specialized generators, AI integrations, and external tool connections
A plugin architecture would allow:
- Community contributions without modifying core CLI
- Organization-specific extensions (e.g., AI-powered generators)
- Optional features that not all users need
- Separation of concerns between core and extended functionality
Decision
Implement a plugin system with the following architecture:
Architecture Overview
┌─────────────────────────────────────────────────────────────────┐
│ idempiere-cli │
├─────────────────────────────────────────────────────────────────┤
│ CORE │ PLUGIN API │
│ ────────────────────── │ ────────────────────── │
│ Commands: │ Extension Points: │
│ • doctor │ • CommandProvider │
│ • init │ • GeneratorProvider │
│ • config │ • AnalyzerProvider │
│ • add (column/table/ext) │ • IntegrationProvider │
│ • export │ │
│ │ Services: │
│ Services: │ • AIService (Claude, OpenAI) │
│ • TemplateService │ • MCPService │
│ • IdempiereClient │ • ExternalAPIService │
│ • PluginGenerator │ │
└─────────────────────────────────────────────────────────────────┘
│
┌────────────┴────────────┐
│ Plugin Loader │
└────────────┬────────────┘
│
┌────────────────────────┼────────────────────────┐
│ │ │
┌────┴────┐ ┌────┴────┐ ┌────┴────┐
│ ai-gen │ │ integr │ │ custom │
│ plugin │ │ plugin │ │ plugin │
└─────────┘ └─────────┘ └─────────┘
Plugin Types
1. Generator Plugins
Create Application Dictionary elements using AI or templates.
public interface GeneratorProvider {
String getName();
String getDescription();
// Generate AD elements based on natural language or config
GenerationResult generate(GenerationRequest request);
}
Examples:
ai-print-format- Generate print formats from descriptionai-window- Generate window/tab structure from requirementsai-process- Generate process code from specificationtemplate-report- Generate Jasper reports from templates
2. Integration Plugins
Connect CLI to external systems.
public interface IntegrationProvider {
String getName();
void initialize(IntegrationConfig config);
// Sync data between iDempiere and external system
SyncResult sync(SyncRequest request);
// Notify external system of events
void notify(NotificationEvent event);
}
Examples:
slack-notify- Post plugin build status to Slackjira-sync- Sync issues with iDempiere tasksgithub-release- Publish plugin releases to GitHubjenkins-trigger- Trigger CI/CD pipelines
3. Analyzer Plugins
AI-powered analysis and recommendations.
public interface AnalyzerProvider {
String getName();
// Analyze code/config and provide recommendations
AnalysisResult analyze(AnalysisRequest request);
}
Examples:
code-review- AI code review for pluginsmigration-advisor- Recommend changes for version upgradessecurity-scan- Check for security issuesperformance-check- Identify performance bottlenecks
4. Command Plugins
Add new CLI commands.
public interface CommandProvider {
// Return Picocli command classes to register
List<Class<?>> getCommands();
}
Examples:
deploy- Deploy plugin to remote iDempieredebug- Remote debugging toolsbenchmark- Performance benchmarking
Plugin Discovery
Option A: Directory-Based (Recommended)
~/.idempiere-cli/
├── config.yaml # Global configuration
├── plugins/ # Plugin JARs
│ ├── ai-generator-1.0.0.jar
│ ├── slack-integration-1.0.0.jar
│ └── custom-analyzer-1.0.0.jar
└── cache/ # Plugin cache
Option B: Maven Dependencies
<!-- In project pom.xml or global settings -->
<dependency>
<groupId>org.idempiere.cli.plugins</groupId>
<artifactId>ai-generator</artifactId>
<version>1.0.0</version>
</dependency>
Option C: Git Repositories
# ~/.idempiere-cli/config.yaml
plugins:
- git: https://github.com/org/idempiere-cli-ai-plugin.git
version: v1.0.0
- git: https://github.com/org/custom-generator.git
branch: main
Configuration
Global Configuration
# ~/.idempiere-cli/config.yaml
plugins:
enabled:
- ai-generator
- slack-integration
disabled:
- deprecated-plugin
ai:
provider: claude # claude, openai, local
apiKey: ${CLAUDE_API_KEY}
model: claude-sonnet-4-20250514
integrations:
slack:
webhook: ${SLACK_WEBHOOK_URL}
channel: "#idempiere-dev"
github:
token: ${GITHUB_TOKEN}
repo: org/idempiere-plugins
Per-Project Configuration
# .idempiere-cli.yaml (in project root)
plugins:
ai-generator:
enabled: true
defaultModel: claude-sonnet-4-20250514
templates:
printFormat: custom-template.yaml
AI Integration
AI Service Interface
public interface AIService {
String getName();
// Generate content based on prompt
AIResponse generate(AIRequest request);
// Analyze content
AIAnalysis analyze(String content, AnalysisType type);
// Available models
List<AIModel> getAvailableModels();
}
Supported Providers
| Provider | Models | Use Case |
|---|---|---|
| Claude | claude-sonnet-4-20250514, opus | Complex generation, analysis |
| OpenAI | gpt-4, gpt-3.5 | Quick generation |
| Local | llama, mistral | Offline/private use |
| MCP | Any MCP server | Custom integrations |
MCP Integration
# ~/.idempiere-cli/config.yaml
mcp:
servers:
- name: idempiere-mcp
command: npx
args: ["idempiere-mcp-server"]
- name: custom-generator
command: python
args: ["-m", "custom_mcp_server"]
Example Plugin: AI Print Format Generator
Plugin Structure
ai-print-format-plugin/
├── pom.xml
├── src/main/java/
│ └── org/idempiere/cli/plugins/aiprintformat/
│ ├── AIPrintFormatPlugin.java
│ ├── PrintFormatGenerator.java
│ └── commands/
│ └── GeneratePrintFormatCommand.java
└── src/main/resources/
├── META-INF/services/
│ └── org.idempiere.cli.spi.PluginProvider
└── templates/
└── print-format-prompt.txt
Usage
# Generate print format from description
idempiere-cli ai generate print-format \
--description "Invoice with header, line items, and totals" \
--table C_Invoice \
--output invoice-format.xml
# Generate with specific AI model
idempiere-cli ai generate print-format \
--description "Customer statement" \
--model claude-sonnet-4-20250514 \
--table C_BPartner
Implementation Phases
Phase 1: Plugin Infrastructure
- [ ] Plugin SPI (Service Provider Interface)
- [ ] Plugin loader and lifecycle management
- [ ] Configuration system
- [ ] Plugin CLI commands (
plugin list,plugin install)
Phase 2: Core Plugins
- [ ] AI service abstraction
- [ ] Claude integration
- [ ] Basic print format generator
- [ ] Basic code analyzer
Phase 3: Community Plugins
- [ ] Plugin repository/registry
- [ ] Documentation for plugin development
- [ ] Example plugins
- [ ] Plugin testing framework
Consequences
Positive
- Extensible without modifying core CLI
- Community can contribute specialized tools
- AI features are optional (not bloating core)
- Organizations can develop private plugins
Negative
- Increased complexity in plugin management
- Need to maintain plugin API stability
- Security considerations for loading external code
- Documentation burden for plugin developers
Risks
- Plugin compatibility across CLI versions
- AI API costs for users
- Plugin quality control
Alternatives Considered
1. Monolithic CLI with Feature Flags
- Simpler but not extensible
- All features must be maintained in core
2. Separate CLI Tools
idempiere-cli(core) +idempiere-ai(AI tools)- Fragmentseð user experience
3. External Scripts
- Shell scripts calling CLI
- Limited integration, no shared state