Skip to main content

HexCore

PyPI PyPI Downloads Python License

📖 Full documentation · 🐙 Repository · 🟦 TypeScript client for Darwin

A reusable core for Python applications built on hexagonal architecture, DDD, CQRS and background tasks. HexCore ships the abstractions (entities, repositories, unit of work, buses) and the infrastructure every project otherwise rewrites: the SQL session layer, the FastAPI factories, the worker runner, the dynamic cron, identity, and the testing utilities.

The design goal is that the happy path takes zero configuration: create_app() with no arguments gives you a usable app, init_engine() with no arguments gives you a production-correct engine.

🇪🇸 ¿Preferís español? La documentación está completa en los dos idiomas: docs/es/.

# main.py — a complete HexCore app
from hexcore.fastapi import build_lifespan, create_app, SqlEngineStep

app = create_app(
    lifespan=build_lifespan(SqlEngineStep()),
    routers=[users_router, tickets_router],
)
# worker.py — the complete worker, with cron, mutual death and SIGTERM
import hexcore.cqrs as cqrs

await cqrs.run_procrastinate_worker(
    procrastinate_app,
    queues=["default", "reactive"],
    scheduler=cqrs.DynamicScheduler(repo, enqueuer, lock_provider=lock),
    on_startup=[lambda: cqrs.seed_cron_jobs(CRON_JOBS)],
)

📚 Documentation

→ docs/ — 🇬🇧 English · 🇪🇸 español

English Español
Installation and extras installation instalacion
Quickstart quickstart inicio-rapido
Configuration configuration configuracion
SQL layer sql sql
Repositories and entities repositories repositorios
FastAPI utilities fastapi fastapi
CQRS architecture cqrs cqrs
Queues and workers queues-and-workers colas-y-workers
Scheduled tasks cron cron
Event Sourcing event-sourcing event-sourcing
Testing testing testing
CLI cli cli
Darwin (identity) darwin/ darwin/
API reference reference referencia
Versions and migration versions-and-migration versiones-y-migracion
Typing typing tipado

Installation

pip install hexcore

Requires Python ≥ 3.12. HexCore pulls in no heavy dependencies: everything that is not the core lives in extras, and the modules that need them only import them when you use them.

pip install "hexcore[api,sql,procrastinate]"
pip install "hexcore[darwin-sqlalchemy]"
pip install "hexcore[all]"
Group Extras
Core api, sql, mongo, redis, rabbitmq, procrastinate, celery
Identity darwin, darwin-sqlalchemy, darwin-beanie, darwin-magic-link, darwin-two-factor, darwin-oauth, darwin-impersonate, darwin-passkey, darwin-organization
Everything all

The full table, with what each one enables, is in installation · instalación.

import hexcore.cqrs works with no extras at all: name resolution is lazy, so hexcore.cqrs.SqlAlchemyCronJobRepository only requires [sql] at the moment you ask for it.


The four imports

There is one facade module per task. They re-export the public surface without moving anything: the long paths keep resolving to the same object.

import hexcore.fastapi as hx     # create_app, build_lifespan, providers, middlewares, health
import hexcore.cqrs as cqrs      # Command, Query, handlers, decorators, buses, worker, cron
import hexcore.sql as sql        # init_engine, session_scope, uow_scope, Base, query DTOs
import hexcore.darwin as darwin  # IdentityConfig, configure_identity, build_identity_router

The facades expose only the canonical names. The historical I* aliases were removed in 7.0 — see Removed API.


What you get, at a glance

You need API Extra
A wired-up FastAPI app hx.create_app(), hx.AppFeatures api
Orchestrated startup and shutdown hx.build_lifespan() + steps api
SQL engine and sessions sql.init_engine(), sql.PoolSettings sql
A session or UoW outside a request sql.session_scope(), sql.uow_scope() sql
Health checks that actually probe hx.register_health_routes() api
Rate limiting hx.rate_limit() api
SSE / WebSocket / connection caps hx.sse_stream(), hx.connection_slot() api
Commands, queries and events cqrs.Command, cqrs.Query, cqrs.HandlerRegistry —
Running work in the background cqrs.background_command, cqrs.background_task —
The worker entrypoint cqrs.run_cqrs_worker(), cqrs.run_procrastinate_worker() —
Cron you can edit without a restart cqrs.DynamicScheduler, cqrs.SqlAlchemyCronJobRepository sql
Distributed locks cqrs.RedisLockProvider, cqrs.PostgresLockProvider redis / sql
Identity and authentication darwin.configure_identity(), darwin.build_identity_router() darwin + storage
Testing all of the above hexcore.testing —

Darwin: the identity module

Registration, email verification, sign-in, sessions with rotating refresh, revocation, audited impersonation, and a plugin system that adds second factor, OAuth, magic links, passkeys and organizations without the core knowing about them.

from hexcore.darwin import (
    IdentityConfig,
    build_identity_router,
    configure_identity,
    identity_startup_steps,
)
from hexcore.fastapi import AppFeatures, SqlEngineStep, build_lifespan, create_app

configure_identity(IdentityConfig())

app = create_app(
    features=AppFeatures(auth_context=True, csrf=True),
    lifespan=build_lifespan(SqlEngineStep(), *identity_startup_steps()),
    routers=[build_identity_router()],
)

⚠️ If you use SQL, the most important thing to read before deploying is the Alembic section: storage · almacenamiento. A plugin missing from your env.py makes alembic revision --autogenerate emit op.drop_table for its tables.


Project templates (CLI)

hexcore init my_project --template hexagonal
hexcore init my_project --template vertical-slice
  • hexagonal → src/domain, src/application, src/infrastructure.
  • vertical-slice → src/features, src/shared/{domain,application,infrastructure}.

Both generate a root config.py and leave Alembic configured. See CLI · CLI.


Versions and support

Series Status What it means
11.x ✅ Active The only supported one. Receives features and fixes. Removes everything 11.0 had promised to remove — see the table below — and fixes the plugin startup steps that broke boot.
10.x ⛔ Deprecated Darwin gains username sign-in, an optional email, a resolver for roles and scopes, a persisted key store, and startup checks that refuse the development defaults in production. Migrating to 11.x means dropping the names removed there; the deprecation warnings named each replacement.
9.x ⛔ Deprecated Adds the event store and Event Sourcing, and leaves a single event bus port. The schema change is not mechanical: see the storage guide.
8.x ⛔ Deprecated Ships Darwin. Migrating to 9.x is mechanical: the two deprecated names still resolve and warn.
7.x ⛔ Deprecated Removes the pre-5.0 surface and fixes the CORS and rate-limiting defects. No Darwin: it shipped before the module landed on master.
6.x ⛔ Deprecated No longer receives fixes. Contains the CORS and rate-limiting security defects fixed in 7.0, and the pre-5.0 aliases still present.
5.x ⛔ Deprecated Same API surface as 6.x.
4.x ⛔ Deprecated Partial application: missing the Celery event-loop fix, the facades, and the aligned documentation.
3.x ⛔ Deprecated Partial application: has the P0/P1 fixes but none of the FastAPI factories.
2.x ⛔ Deprecated Contains silent bugs fixed in 5.x: the worker re-enqueued instead of executing, the cron skipped or duplicated runs, and a Redis outage switched off the entire cron.
1.x ⛔ Deprecated No support of any kind.

Everything before 10.0 is deprecated. Migrate to 10.x. The detail of each series, the silent 2.x bugs and the step-by-step guides are in versions and migration · versiones y migración.

Removed API and its replacement

The v1/v2 aliases were deprecated since 5.0 — two full majors of notice — and were removed in 7.0. The replacement is mechanical: they are renames, not behavior changes.

Removed in 7.0 (was v1/v2) Use instead
ICommandBus, IQueryBus, IEventBus AbstractCommandBus, AbstractQueryBus, AbstractEventBus
ICommandHandler, IQueryHandler AbstractCommandHandler, AbstractQueryHandler
IMiddleware AbstractMiddleware
ISerializer AbstractSerializer
IEventDispatcher AbstractEventBus
EventBus.register() / .dispatch() AbstractEventBus.subscribe() / .publish()
ServerConfig.event_dispatcher ServerConfig.event_bus
SQLAlchemyCommonImplementationsRepo SqlAlchemyRepository
BeanieODMCommonImplementationsRepo BeanieRepository
NoSqlUnitOfWork BeanieUnitOfWork
reset_sqlalchemy_engine() dispose_engine()
MiddlewareConfig Removed in 3.0. It was dead code: never read.

The 9.0 and 10.0 deprecations were removed in 11.0, on the schedule each warning announced. The replacement is mechanical in every case: the old name kept working, and warned, for a full major.

Removed in 11.0 Use instead Deprecated since
hexcore.domain.events.EventBus hexcore.domain.cqrs.buses.AbstractEventBus 9.0
hexcore.infrastructure.events.events_backends.memory.InMemoryEventBus hexcore.cqrs.InMemoryEventBus 9.0
hexcore.domain.auth (the whole package) hexcore.darwin 10.0
hexcore.domain.auth.PermissionsRegistry, hexcore.PermissionsRegistry hexcore.darwin.RoleRegistry 10.0
hexcore.domain.auth.TokenClaims, hexcore.TokenClaims hexcore.darwin.AccessTokenClaims 10.0
IdentityService.sign_in(email=...) IdentityService.sign_in(identifier=...) 10.0

TokenClaims and AccessTokenClaims were never interchangeable — different fields, different invariants, and TokenClaims had no sid, so a session issued with it could not be revoked. That is why the old name returned the old object and warned instead of aliasing to the new one, and it is why porting is a rewrite of the claims you build, not a rename.

Passing event_dispatcher= to ServerConfig fails with an error that says what to use, rather than being silently ignored: pydantic discards keyword arguments it does not know, and keeping the default bus without noticing would surface much later as "my events never arrive".

If you are still on 6.x, run your tests with warnings visible to see what you have left to migrate:

python -m pytest -W "default::DeprecationWarning"

Contributing

  1. Code of conduct — read the Code of Conduct before interacting.

  2. Branches — fork and create a branch (feat/name, fix/name, docs/name).

  3. Tests — every fix lands with at least one test that fails before and passes after:

    uv sync --extra all --group dev
    uv run python -m pytest -q
    

    CI fails if any test is skipped: a skip means an extra is missing, and we would be reporting green without having run half the suite.

  4. Typecheck — uv run pyright hexcore. The verdict comes from the ratchet, not the exit code: see typing · tipado.

  5. Style — PEP8. Comment the why, not the what.

  6. Commits — Commitizen: feat:, fix:, docs:, refactor:, and ! for breaking changes. The version bump and the CHANGELOG are automatic on merge to master.

  7. PRs — describe the problem, the reproduction, the solution and why that option.

Full detail in CONTRIBUTING.md.

The agent skill

skills/hexcore/ is a Claude Code skill covering both packages — this one and the TypeScript client. It reads the installed package instead of remembering it, and audits a project for the framework's silent failure modes rather than just describing them. Its prose is under the same CI gate as the documentation, so a rename here turns it red.

To use it in a project that consumes HexCore, copy that directory into the project's .claude/skills/. Details in skills/README.md.


References

Metadata

Release files for hexcore 11.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hexcore 11.2.0
File Size Uploaded
hexcore-11.2.0.tar.gz 937.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hexcore 11.2.0
File Interpreter ABI Platform
hexcore-11.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.7 MB

Release files / hexcore-11.2.0.tar.gz

Download URL hexcore-11.2.0.tar.gz
Size 937.0 kB
Tags Source
SHA-256 checksum
How to use checksums
c651977a393a8df67b4750f48c76a3672631a997e5a73cb35125bee5a7b680a3
BLAKE2b-256 checksum
How to use checksums
ae331ca60716a4eefbc2b574100a60aa800122aee386d869f6df9224e1389179
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.

Transparency log

Release files / hexcore-11.2.0-py3-none-any.whl

Download URL hexcore-11.2.0-py3-none-any.whl
Size 756.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6f6898fb3fb4f5436e6b6aa4dcc832442cc3c3d23c5f37dce89133b362055cc7
BLAKE2b-256 checksum
How to use checksums
1c01e291f4b778a60e21809970a9194572150551a6b13242a22b0339042b560f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.

Transparency log

Release history Release notifications | RSS feed

11.3.0

2 release files

This release

11.2.0 This release

2 release files

11.1.0

2 release files

11.0.3

2 release files

11.0.2

2 release files

10.3.0

2 release files

10.2.0

2 release files

10.1.0

2 release files

10.0.0

2 release files

9.7.4

2 release files

9.7.3

2 release files

9.7.2

2 release files

9.7.1

2 release files

9.7.0

2 release files

9.6.0

2 release files

9.5.0

2 release files

9.4.0

2 release files

9.3.0

2 release files

9.2.1

2 release files

9.0.1

2 release files

9.0.0

2 release files

8.0.0

2 release files

7.0.0

2 release files

6.2.1

2 release files

6.2.0

2 release files

6.1.0

2 release files

6.0.2

2 release files

6.0.1

2 release files

6.0.0

2 release files

5.0.0

2 release files

4.0.0

2 release files

3.0.0

2 release files

2.5.0

2 release files

2.4.0

2 release files

2.3.0

2 release files

2.2.0

2 release files

2.1.0

2 release files

2.0.6

2 release files

2.0.5

2 release files

2.0.4

2 release files

2.0.3

2 release files

2.0.2

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.8.0

2 release files

1.7.0

2 release files

1.6.8

2 release files

1.6.7

2 release files

1.6.6

2 release files

1.6.5

2 release files

1.6.4

2 release files

1.6.3

2 release files

1.6.2

2 release files

1.6.1

2 release files

1.6.0

2 release files

1.5.1

2 release files

1.5.0

2 release files

1.4.2

2 release files

1.4.1

2 release files

1.4.0

2 release files

1.3.2

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page