From core-api-consumers
Build and extend Python desktop applications using a strict Core-API-Consumers layered architecture. Use when asked to create a new package or module, add a feature to an existing package, build an API layer, create an MCP server, wire a GUI to an API, scaffold a CLI, restructure code into layers, or review architecture compliance. Covers project scaffolding, layer responsibilities, dependency rules, config-driven design, session management, MCP tool design, GUI threading, error handling, batch processing, testing strategy, and the complete feature-addition workflow from core to all consumer interfaces. Inspired by Clean Architecture and Hexagonal / Ports-and-Adapters patterns.
How this skill is triggered — by the user, by Claude, or both
Slash command
/core-api-consumers:core-api-consumers-architectureThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Build Python desktop + AI-agent applications using three strict layers:
Build Python desktop + AI-agent applications using three strict layers: Core -> API -> Consumers (GUI, CLI, MCP).
Use when the user asks to:
Consumers (outer)
GUI (PyQt5) | CLI (argparse) | MCP (FastMCP)
\ | /
v v v
+--------------------------------------+
| API Layer | <- orchestration
| config | *_ops | session_io |
+--------------------------------------+
|
v
+--------------------------------------+
| CORE Layer | <- pure logic
| models | engines | processing | io |
+--------------------------------------+
Dependencies flow inward only. NEVER violate this.
- Core NEVER imports from API, GUI, CLI, or MCP.
- API NEVER imports from GUI, CLI, or MCP.
- Data flows outward via return values and callbacks — never via imports.
When creating a new package, use this directory layout:
my_package/
├── __init__.py
├── core/
│ ├── __init__.py
│ ├── models.py # Dataclasses / domain entities
│ ├── engines/ # Computational engines (one per domain)
│ ├── processing/ # Signal processing, QC, statistics
│ ├── io/ # File format readers/writers
│ └── utils.py # Pure utility functions
├── api/
│ ├── __init__.py
│ ├── config.py # All configuration dataclasses
│ ├── analysis.py # Main workflow operation functions
│ ├── export.py # Export / report operations
│ ├── session_io.py # Session save/load
│ └── validation.py # Input validation
├── gui/
│ ├── __init__.py
│ ├── main_window.py
│ ├── views/ # Major UI panels (one per tab / screen)
│ ├── dialogs/ # Modal configuration dialogs
│ └── widgets/ # Reusable custom widgets
├── cli/
│ ├── __init__.py
│ └── main.py
├── mcp/
│ ├── __init__.py
│ ├── __main__.py # Entry: python -m my_package.mcp
│ └── server.py # FastMCP tool definitions
└── visualization/ # Optional: plot functions
├── __init__.py
└── plots.py
core/)Pure domain logic. No framework imports. No UI. No network.
| Sub-module | Responsibility |
|---|---|
models.py | Dataclasses for domain entities |
engines/ | Stateless computational algorithms |
processing/ | Signal processing, QC, statistics |
io/ | File format readers/writers |
utils.py | Pure helpers (unit conversion, interpolation) |
Rules: Functions take data in, return data out. No side effects. No global state. Testable with plain pytest.
For detailed code examples, read
references/core-layer.md.
api/)Orchestration and configuration. The single entry point for all consumers.
| Sub-module | Responsibility |
|---|---|
config.py | Dataclass-based configuration objects |
*_ops.py | Operation functions — one per workflow |
session_io.py | Session save/load (serialize to disk) |
validation.py | Input validation before calling core |
Rules:
{"success": bool, "errors": [...], ...}.progress_callback for GUI progress bars (optional, default None).Critical defaults:
Config() must work.For detailed code examples, read
references/api-layer.md.
gui/)PyQt5/6 widgets. Zero business logic. Only event wiring and display.
QThread worker for any call > 100ms.For QThread worker pattern and common pitfalls, read
references/gui-layer.md.
cli/)argparse or click based. Parses arguments -> builds config -> calls API -> prints result. Same API functions as GUI and MCP.
mcp/)FastMCP server exposing API operations as AI-agent-callable tools.
session_id for stateful multi-call workflows.Optional params — only update what is provided.multiprocessing.Pool — it deadlocks stdio transport.For complete MCP server pattern, read
references/mcp-layer.md.
visualization/)Optional sibling. Plot functions take arrays + output path -> return saved file path. Called by API in report/export operations. Never imports from GUI/CLI/MCP.
Always follow this order:
1. CORE -> Add algorithm / data model / loader
2. API -> Add operation function + config fields
3. GUI -> Add widget / dialog that calls the API
4. CLI -> Add subcommand that calls the API
5. MCP -> Add tool that calls the API
Each step is independently testable and deployable. A feature can exist in API+CLI before the GUI is built. MCP can be added without touching core.
For a complete worked example, read
references/feature-workflow.md.
| Layer | Strategy |
|---|---|
| Core | Raise domain-specific exceptions |
| API | Catch all -> return {"success": false, "errors": [...]} |
| GUI | Read errors -> show QMessageBox |
| CLI | Read errors -> print to stderr -> exit(1) |
| MCP | Return error dict -> AI agent reads and adapts |
When quality control rejects too many items, the API should auto-fallback:
For implementation, read
references/error-handling.md.
For multi-item workflows, the API iterates over items calling the single-item
API function. In MCP context, never use multiprocessing.Pool — use
sequential processing or ThreadPoolExecutor.
tests/
├── test_core/ # Unit tests — fast, no I/O, no framework
├── test_api/ # Integration tests — may use tmp_path for files
└── test_mcp/ # Tool tests — call functions with mock data
Core tests are pure. API tests may touch disk. GUI tests are optional (pytest-qt).
api/config.py.ProcessingConfig, QCConfig, PeakConfig, etc.dataclasses.asdict() / recursive config_from_dict().dict.get(key, default) returns None when key EXISTS with value None.
Always guard: cfg.get(k, d) or d for PyQt5 setValue() calls.os.path.join or pathlib.Path — never string concatenation./ and \, normalize for display.When implementing any feature, verify:
core/ with zero framework importsapi/config.py with sensible defaults{"success": bool, "errors": [...]}Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub mersadfathizadeh1995/programming_tools --plugin core-api-consumers