Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Indroic/HexCore/llms.txt

Use this file to discover all available pages before exploring further.

HexCore ships a typer-based CLI that accelerates the repetitive parts of a DDD project: scaffolding new projects from opinionated templates, generating domain module boilerplate, managing Alembic migrations, and running your test suite. This page covers every command, its flags, and example terminal output.

Entry Point

The CLI is exposed as the hexcore command after installing the package. You can also drive it from a manage.py file in your project root:
manage.py
from hexcore.infrastructure.cli import app as CLI

if __name__ == "__main__":
    CLI()
# Equivalent invocations:
hexcore --help
python manage.py --help

Commands

hexcore init

Scaffolds a new project directory from one of two structural templates.
hexcore init <project_name> [--template hexagonal|vertical-slice]
project_name
argument
required
The name of the project to create. A directory with this name is created in the current working directory. Fails if the directory already exists.
--template / -t
option
default:"hexagonal"
Structural template to use. Accepted values: hexagonal or vertical-slice.
Creates the classic layered hexagonal architecture layout:
my_project/
├── src/
│   ├── domain/
│   ├── application/
│   └── infrastructure/
│       └── database/
│           ├── models/
│           └── documents/
├── tests/
│   └── domain/
├── alembic/
├── alembic.ini
├── config.py
├── manage.py
└── .gitignore
config.py is pre-populated with repository_discovery_paths pointing at src.infrastructure.repositories.
What init does automatically:
1

Create directories

All directories are created with __init__.py files so they are importable Python packages from the start.
2

Write base files

README.md, .gitignore, manage.py, and config.py are generated with sensible defaults.
3

Configure Alembic

Runs alembic init alembic, patches alembic.ini with the correct version_locations, and patches alembic/env.py to import your models, set target_metadata = Base.metadata, and pull the database URL from LazyConfig.
4

Format with Ruff

Runs ruff format over the new project for consistent code style.
Example output:
$ hexcore init my_project --template hexagonal

Initializing project at: /home/user/my_project (template: hexagonal)
Directory created: /home/user/my_project/src/domain
Directory created: /home/user/my_project/src/application
Directory created: /home/user/my_project/src/infrastructure
Directory created: /home/user/my_project/src/infrastructure/database/models
Directory created: /home/user/my_project/src/infrastructure/database/documents
Directory created: /home/user/my_project/tests/domain
File created: /home/user/my_project/README.md
File created: /home/user/my_project/.gitignore
File created: /home/user/my_project/manage.py
File created: /home/user/my_project/config.py

¡Proyecto 'my_project' inicializado exitosamente en /home/user/my_project con template 'hexagonal'!

hexcore create-domain-module

Generates all boilerplate files for a new domain module inside src/domain/<name>/.
hexcore create-domain-module <name>
name
argument
required
The module name. Must be a valid Python identifier (no hyphens, no spaces). The value is lower-cased internally. Example: users, billing, inventory.
Files created:
FileContents
__init__.pyEmpty package marker
repositories.pyAbstract I<Name>Repository(IBaseRepository[<Name>]) interface
services.pyStub <Name>Service(BaseDomainService) class
value_objects.pyCommented example of a Pydantic value object
events.pyCommented example of an EntityCreatedEvent subclass
enums.pyEmpty
exceptions.pyEmpty
A matching test directory is also created at tests/domain/<name>/ with an __init__.py and a blank test_<name>_entities.py file. Example output:
$ hexcore create-domain-module billing

Creating domain module 'billing' at: /home/user/my_project/src/domain/billing
Directory created: /home/user/my_project/src/domain/billing
  -> File created: src/domain/billing/__init__.py
  -> File created: src/domain/billing/repositories.py
  -> File created: src/domain/billing/services.py
  -> File created: src/domain/billing/value_objects.py
  -> File created: src/domain/billing/events.py
  -> File created: src/domain/billing/enums.py
  -> File created: src/domain/billing/exceptions.py
Creating test module 'billing' at: tests/domain/billing
Directory created: /home/user/my_project/tests/domain/billing
  -> File created: tests/domain/billing/__init__.py
  -> File created: tests/domain/billing/test_billing_entities.py

¡Domain module 'billing' created successfully!

Suggested next steps:
1. Define your main entities in 'src/domain/billing/entities.py'.
2. Define repository interfaces in 'src/domain/billing/repositories.py'.
3. Write tests in 'tests/domain/billing/test_billing_entities.py'.
Generated repositories.py (example for billing):
src/domain/billing/repositories.py
from __future__ import annotations
import abc
from uuid import UUID

from hexcore.domain.repositories import IBaseRepository
from .entities import Billing


class IBillingRepository(IBaseRepository[Billing]):
    """
    Repository interface for the Billing entity.
    """
    pass
Generated services.py:
src/domain/billing/services.py
from __future__ import annotations
import typing as t
from hexcore.domain.services import BaseDomainService


class BillingService(BaseDomainService):
    """
    Domain service for the billing module.
    Orchestrates operations that don't fit naturally in a single entity.
    """
    def __init__(self):
        # Inject repositories and other services here.
        pass

hexcore make-migrations

Generates a new Alembic migration file by comparing your SQLAlchemy models against the current database schema.
hexcore make-migrations <description>
description
argument
required
A human-readable label for the migration. Becomes the -m argument to alembic revision. Use snake_case or a short sentence. Example: "add users table".
Internally runs:
alembic revision --autogenerate -m '<description>'
Example:
$ hexcore make-migrations "add billing table"

Executing migration command: alembic revision --autogenerate -m 'add billing table'
  Generating /home/user/my_project/src/infrastructure/database/migrations/versions/3f4a1b2c_add_billing_table.py ...  done
Alembic cannot detect all schema changes automatically (e.g. column type changes on some databases, custom constraints, or enum renames). Always review the generated migration file before committing it.

hexcore migrate

Applies all pending Alembic migrations to the database.
hexcore migrate
This command takes no arguments. Internally runs:
alembic upgrade head
Example:
$ hexcore migrate

Executing migration command: alembic upgrade head
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> 3f4a1b2c, add billing table
The database URL is read from ServerConfig.sql_database_url via the LazyConfig integration that was injected into alembic/env.py by hexcore init. Make sure sql_database_url is set in config.py or via the HEXCORE_CONFIG_MODULE environment variable before running migrations.

hexcore test

Runs your test suite with pytest.
hexcore test [path] [--extra-args <args>]
path
argument
default:"test"
Path or directory to pass to pytest. Defaults to test/. Pass a specific file or directory to narrow the run.
--extra-args
option
default:"\"\""
Additional arguments forwarded verbatim to pytest. Useful for -k, -x, -v, --cov, etc. Wrap the value in quotes if it contains spaces.
Examples:
hexcore test
Example output:
$ hexcore test tests/domain

Running tests in: tests/domain
============================= test session starts ==============================
platform linux -- Python 3.12.0, pytest-8.1.0
collected 12 items

tests/domain/users/test_user_entities.py ....                           [ 33%]
tests/domain/billing/test_billing_entities.py ........                  [100%]

============================== 12 passed in 0.42s ==============================
The command exits with the same exit code as pytest, so it integrates cleanly with CI/CD pipelines.

Build docs developers (and LLMs) love