Architecture
Overview
axm-init follows a layered architecture with clear separation of concerns:
graph TD
subgraph "User Interface"
CLI["CLI (cyclopts)"]
MCP["MCP Tools"]
end
subgraph "Core Logic"
CheckEngine["CheckEngine"]
Templates["Template Resolution"]
Reserver["PyPI Reserver"]
end
subgraph "Checks"
PyprojectChecks["pyproject checks"]
CIChecks["CI checks"]
ToolingChecks["tooling checks"]
DocsChecks["docs checks"]
StructureChecks["structure checks"]
DepsChecks["deps checks"]
ChangelogChecks["changelog checks"]
WorkspaceChecks["workspace checks"]
end
subgraph "Adapters"
Copier["CopierAdapter"]
PyPI["PyPIAdapter"]
Creds["CredentialManager"]
FS["FileSystemAdapter"]
GH["GitHubAdapter"]
Makefile["MakefileAdapter"]
end
subgraph "External"
CopierEngine["Copier Engine"]
PyPIAPI["PyPI API"]
PyPIRC["~/.pypirc"]
Disk["File System"]
GHCLI["gh CLI"]
end
CLI --> CheckEngine
CLI --> Templates
CLI --> Reserver
MCP --> CheckEngine
MCP --> Templates
CheckEngine --> PyprojectChecks
CheckEngine --> CIChecks
CheckEngine --> ToolingChecks
CheckEngine --> DocsChecks
CheckEngine --> StructureChecks
CheckEngine --> DepsChecks
CheckEngine --> ChangelogChecks
CheckEngine --> WorkspaceChecks
Reserver --> PyPI
Reserver --> Copier
Templates --> Copier
Copier --> CopierEngine
PyPI --> PyPIAPI
Creds --> PyPIRC
FS --> Disk
GH --> GHCLI
Layers
1. CLI (cli.py)
Cyclopts-based commands with input validation and formatted output (text, JSON, agent).
| Command | Function | Description |
|---|---|---|
scaffold |
scaffold() |
Scaffold a new project |
check |
check() |
Score against AXM standard |
reserve |
reserve() |
Reserve PyPI package name |
version |
version() |
Show version |
2. Core Logic (core/)
Business logic independent of I/O:
| Module | Key Symbols | Purpose |
|---|---|---|
checker.py |
CheckEngine, format_report(), format_json(), format_agent() |
Run checks (dynamic discovery via importlib), format output |
templates.py |
TemplateInfo, TemplateType, get_template_path() |
Template catalog, type dispatch (standalone/workspace/member), and resolution |
reserver.py |
ReserveResult, reserve_pypi(), create_minimal_package(), build_package(), publish_package() |
PyPI name reservation workflow and result model |
3. Checks (checks/)
44 checks across 8 categories, each a pure function (Path) → CheckResult:
| Module | Category | # Checks |
|---|---|---|
_utils.py |
(internal) | Shared utilities: _load_toml for TOML parsing, @requires_toml decorator that loads pyproject.toml once and short-circuits with a failure if missing |
pyproject.py |
pyproject | 9 |
ci.py |
CI | 7 |
tooling.py |
tooling | 7 |
docs.py |
docs | 5 |
structure.py |
structure | 7 |
deps.py |
deps | 2 |
changelog.py |
changelog | 2 |
workspace.py |
workspace | 5 |
_workspace.py |
(internal) | Context detection: detect_project_context(), find_workspace_root(), get_workspace_members() |
4. Adapters (adapters/)
Each adapter wraps a single external dependency:
| Adapter | Wraps | Purpose |
|---|---|---|
CopierAdapter / CopierConfig |
copier.run_copy() |
Template-based scaffolding (CopierConfig is the Pydantic input model) |
PyPIAdapter / AvailabilityStatus |
PyPI JSON API | Package name availability check |
CredentialManager |
PYPI_API_TOKEN / ~/.pypirc |
Token retrieval, validation, and persistence (returns False on PermissionError) |
FileSystemAdapter / Transaction |
pathlib |
File operations with rollback (logs warnings on cleanup failures) |
GitHubAdapter / RepoCreateResult |
gh CLI |
Repo creation, secrets, Pages (graceful False when gh is missing) |
detect_makefile_targets() |
Makefile |
Detect available make targets |
patch_all() |
pyproject.toml, Makefile, CI workflows |
Workspace root file patching after member scaffold |
5. Models (models/)
Pydantic models for structured data exchange between layers:
| Model | Module | Purpose |
|---|---|---|
CheckResult |
check.py |
Single check outcome (passed, message, fix) |
CategoryScore |
check.py |
Aggregated score per category |
ProjectResult |
check.py |
Full project check result |
Grade |
check.py |
A–F grade enum |
ScaffoldResult |
results.py |
Outcome of a scaffolding operation |
6. Tools (tools/)
MCP tool wrappers for AI agent integration. All tools satisfy the AXMTool protocol (imported from axm.tools.base).
| Tool | Class | Entry Point |
|---|---|---|
init_check |
InitCheckTool |
axm.tools → check |
init_scaffold |
InitScaffoldTool |
axm.tools → scaffold |
init_reserve |
InitReserveTool |
axm.tools → reserve |
Design Decisions
| Decision | Rationale |
|---|---|
| Hexagonal architecture | Testable core, swappable adapters |
| Pydantic models | Validation, serialization, extra = "forbid" |
| Copier for scaffolding | Jinja2 templates, supports project updates |
src/ layout |
PEP 621 best practice, no import conflicts |
| Pure check functions | Each check is (Path) → CheckResult, easy to test and extend |
| Dynamic check registry | checker.py discovers checks via importlib/inspect, reducing coupling |
| Parallel check execution | ThreadPoolExecutor — checks are I/O-bound and independent |