IKAREM — industry-grade Python ASGI backend framework with a zero-dependency core. DI, validation, JWT auth, OpenAPI + MCP. pip install ikarem
See the codeZero-dependency Python ASGI framework, built for humans and LLMs.
FastAPI-style DX (DI, validation, OpenAPI, auth) + Django/Nest-style structure (plugins, config, RBAC) + a core that runs on stdlib alone. Pip-installable, zero required dependencies.
pip install -e . # core only, zero dependencies
pip install -e ".[server,test]" # uvicorn + pytest + httpx for dev
pip install -e ".[postgres]" # asyncpg strategy
pip install -e ".[mysql]" # aiomysql strategy
pip install -e ".[sqlserver]" # aioodbc strategy
from ikarem import Ikarem
app = Ikarem(debug=True)
@app.get("/")
async def home(req):
return {"hello": "ikarem"} # dict auto-becomes JSON
@app.get("/users/{uid:int}")
async def get_user(req, uid: int):
return {"uid": uid}
if __name__ == "__main__":
app.run() # needs `pip install ikarem[server]`
python examples/basic.py
# or
ikarem run examples.basic:app --reload
from ikarem import (
BackgroundTasks,
Depends,
Ikarem,
Schema,
CORSMiddleware,
RateLimitMiddleware,
create_token,
require_roles,
)
app = Ikarem(auth_secret="secret")
app.use(CORSMiddleware())
app.use(RateLimitMiddleware(per_minute=120))
class Item(Schema):
name: str
qty: int = 1
def get_prefix():
return "hi"
@app.post("/items")
async def create(req, item: Item, bg: BackgroundTasks, prefix=Depends(get_prefix)):
bg.add(print, f"created {item.name}")
return {"msg": f"{prefix} {item.name}", "qty": item.qty} # validated + coerced
tok = create_token("u1", "secret", roles=["admin"])
@app.get("/admin")
async def adm(req, claims=Depends(require_roles("admin"))):
return {"sub": claims["sub"]} # 401 without token, 403 without role
Built-ins on every app: GET /healthz, GET /metrics,
GET /openapi.json (OpenAPI 3.1 auto-gen), GET /docs (Swagger UI).
ikarem new myapp && cd myapp # auth + sessions + SQLite CRUD (HTML + JSON), tests + Dockerfile
pytest -q && uvicorn app:app
from ikarem import SessionMiddleware, CSRFMiddleware, Field, Schema
app.use(SessionMiddleware()) # signed cookies: req.session["uid"] = ...
app.use(CSRFMiddleware()) # unsafe routes need X-CSRF-Token or _csrf_token field
class Signup(Schema):
email: str = Field(..., email=True, max_length=254)
password: str = Field(..., min_length=8, max_length=128)
class Note(Schema):
text: str = Field(..., min_length=1, max_length=500)
@app.post("/notes")
async def add(req, note: Note): # validates JSON *and* HTML form bodies
form = await req.form() # urlencoded + multipart, UploadFile files,
f = form.get("doc") # 413 past size caps
await f.write(f"/uploads/{f.filename}")
TestClient keeps a cookie jar (login flows just work) and speaks
get/post/put/patch/delete. ikarem check audits handlers, ikarem mcp
serves every route as an LLM tool (plus ikarem://openapi.json and
ikarem://manifest MCP resources), ikarem inspect prints a compact route
manifest for LLM context, and site/llms.txt is the framework manual in one
page. AGENTS.md holds the contributor laws for AI and human agents alike.
from ikarem import Blueprint, MethodView, Templates, abort, flash
api = Blueprint("api", url_prefix="/api")
@api.get("/items/{uid:int}") # own hooks, own errors, url_for("api.x")
async def one(req, uid: int): ...
app.register_blueprint(api) # hooks wrap once — still zero per-request reflection
abort(403, "owner only") # terse errors through the normal pipeline
class Items(MethodView): # one class per resource, full DI per method
async def get(self, req): ...
async def post(self, req, item: Item): ...
app.route("/items", Items.methods())(Items.as_view("items"))
flash(req, "Saved.") # session-backed, shown once in templates
Templates("templates/").response("hi.html", name="amy") # Jinja2 via ikarem[jinja]
Deliberately not taken: context locals (g, global request proxies) and signals —
explicit req params plus plugins and middleware cover that ground without the magic.
from ikarem import Migrator, QueuePlugin, require_scopes, APIKeyAuth, task
from ikarem.db import DatabasePlugin
app.register(DatabasePlugin("postgresql://..."))
app.register(QueuePlugin()) # durable jobs in app.state_queue
@task("welcome") # name -> callable, worker-dispatched
async def welcome(to: str): ...
@app.post("/signup")
async def signup(req):
await req.app.state_queue.enqueue("welcome", {"to": "a@b.co"})
return {"ok": True}, 201
@app.every(300) # or @app.cron("0 2 * * *")
async def nightly(): ...
# await app.start_scheduler() # explicit: nothing runs unless started
ikarem migrate new add_users && ikarem migrate up myapp:app
ikarem worker myapp:app # drain the queue until Ctrl+C
Plus the small ones the checklist demanded: Schema(extra="forbid") sanitization,
XMLResponse/dict_to_xml, escape_html, APIKeyAuth (static keys or async lookup=),
require_scopes() for JWT scopes, require_if() predicate (ABAC-lite).
Out of scope on purpose: full ORM (strategy + validated schemas is the answer) and
OAuth2 dance (JWT bearer covers service auth).
from ikarem import TimeoutMiddleware, ConcurrencyLimitMiddleware, IdempotencyMiddleware, TrustedHostMiddleware
app.use(TimeoutMiddleware(30)) # hung handler -> 503 + Retry-After
app.use(ConcurrencyLimitMiddleware(100)) # bulkhead: fail fast past N in-flight
app.use(IdempotencyMiddleware()) # Idempotency-Key replays, no double charges
app.use(TrustedHostMiddleware(["example.com", ".example.com"]))
Plus Ikarem(max_body_bytes=...) DoS floor, latency fields in /metrics,
atomic SQLite transactions, Room pub/sub for websockets (tested via
TestClient.ws_connect), and a py.typed marker so downstream type checkers
see the real types.
Live proof it all works: ledger/ — a personal-finance app
(auth, dashboard with SVG charts, CRUD, receipt uploads, CSV export, JSON API)
running on stock IKAREM + uvicorn.
Meraki (5 minutes):
-from meraki import Meraki
+from ikarem.meraki_compat import Meraki
Your app runs unchanged (same routes, middleware, 404/405 bodies) on the IKAREM engine — then migrate handler-by-handler. From anywhere else:
docs/MIGRATING_FROM_FASTAPI.mddocs/MIGRATING_FROM_STARLETTE.mddocs/MIGRATING_FROM_LITESTAR.mddocs/MIGRATING_FROM_FLASK.mddocs/MIGRATING_FROM_DJANGO.mddocs/MIGRATING_FROM_MERAKI.mdPlus honest benchmarks: bench/RESULTS.md ·
extension registry: docs/ECOSYSTEM.md ·
20 runnable recipes: docs/COOKBOOK.md ·
install: pip install ikarem.
Footnote: IKAREM started as an answer to Meraki — same decorator shape, working plugins, and everything Meraki's README promised but never shipped. The rivalry is archived; this section is just the moving van.
| Rival feature | IKAREM answer |
|---|---|
| pip package, minimal deps | Zero required deps. uvicorn/asyncpg/etc are optional extras. Core is pure stdlib + ASGI. |
| ASGI + Uvicorn boundary | Strict server boundary: Ikarem exposes __call__(scope, receive, send). Any ASGI server works (uvicorn, hypercorn, daphne). HTTP + WebSocket + lifespan. |
| Central app + lifecycle | Ikarem() + on_startup / on_shutdown + lifespan. Plugins hook in with priority + topological dependency order. |
| Request/Response | Lazy Request (query, headers, cookies, await body()/json()), Response helpers (JSON, text, html, stream, redirect, File). Handlers never touch raw ASGI. |
| Routing | Compiled routes with {param} + {param:int/float/uuid/path} converters, 404 vs 405 distinction, url_for, include_router(prefix), static mounts. |
| Middleware | Onion pipeline, short-circuitable, global + composable: CORS, security headers, rate limiting (429 + Retry-After), request-ID/timing, metrics. |
| Plugins | Plugin protocol (name, requires, priority, register, on_startup/shutdown/request/response). Manager sorts dependencies, detects cycles. |
| Config | Layered Config: defaults < kwargs < dict < IKAREM_* env vars. Typed config.get(key, default, cast=...). |
| Errors | HTTPException hierarchy + @app.exception_handler(ExcType) with MRO most-specific match. Tracebacks only when debug=True. |
| DB Strategy (pg/mysql/sqlite/mssql) | DatabaseConnector async ABC (connect/disconnect/execute/fetch_one/fetch_all/execute_many/transaction). Lazy driver imports. SQLite runs on stdlib today. DatabasePlugin proves the extension model. |
| DI (FastAPI parity) | Depends() with nesting, per-request cache (+ opt-out), sync/async/yield deps, finalizers guaranteed after response send and on the exception path, circular-dep rejection. |
| Validation (Pydantic-lite) | Schema models from type hints: coercion, required/optional, nested models, ValidationError → 400. Zero deps. |
| Auth | Stdlib HS256 JWT (algorithm-confusion resistant, sub required, expiry enforced), pbkdf2 passwords, BearerAuth, require_roles() RBAC. |
| Caching | MemoryCache + @cached (Redis-swappable CacheBackend interface). |
| Background work | BackgroundTasks param — runs after the response is sent, never fails the response. |
| Realtime / files | app.websocket(path) + WebSocket helper; mount_static() + FileResponse. |
| Observability | JSON logging, x-request-id + x-process-time-ms, /healthz, Prometheus-style /metrics. |
208 passed, 3 skipped — framework plus both showcase apps, one command:
python -m pytest tests/ ledger/tests cadence/tests -q
CI runs the same suite on Python 3.10–3.13 × Ubuntu/macOS/Windows, plus a
live-Postgres job, a Docker showcase build, a starter-template smoke job
(ikarem new + template tests), ruff lint + format, and
ikarem check ledger.app:app. Every behavior ships with a test; bugfix PRs
include a regression test.
ikarem/ zero-dep stdlib core (v1.1.0) — optional integrations lazy-load behind extras
app.py Ikarem core + ASGI callable + lifespan + background/cleanup wiring
compiled.py one-time handler plans (no per-request reflection) + check/describe IR
routing.py compiled routes + converters + Did-you-mean 404s
http.py Request (+forms/uploads) + Response family (+cookies)
di.py Depends + nesting + cycle detection + run_cleanups
validation.py Schema models + Field() constraints (zero-dep validation)
auth.py JWT + passwords + Bearer/API-key auth + roles/scopes guards
session.py signed-cookie sessions + CSRF
security.py CORS + security headers + trusted hosts + rate limiting
resilience.py timeouts + bulkheads + idempotency
cache.py CacheBackend + MemoryCache + RedisCache + @cached
db/ DatabaseConnector ABC + sqlite/postgres/mysql/sqlserver + plugin + factory
queue.py durable task queue + QueuePlugin + `ikarem worker`
scheduler.py cron/intervals + SchedulerPlugin
migrations.py versioned migrations + `ikarem migrate`
resources.py app.resource() validated CRUD
blueprints.py prefixed route groups + MethodView (views.py)
middleware.py Middleware base + stack
plugins.py Plugin protocol + dependency-sorted PluginManager
config.py layered Config
errors.py HTTPException hierarchy + handler registry
openapi.py OpenAPI 3.1 builder + /openapi.json + /docs
mcp.py routes-as-MCP-tools + resources + stdio server
websocket.py WebSocket + Room pub/sub + WSRouter
static.py FileResponse + escape-proof static mounts
templating.py Jinja2 via ikarem[jinja] + flashing.py one-shot messages
observability.py logging + request-ID + metrics + /healthz + /readyz + /metrics
cli.py `ikarem run|check|mcp|new|migrate|worker|inspect`
testing.py TestClient (cookie jar, all verbs, WS driving — no server needed)
scaffold.py `ikarem new` starter generator
deprecation.py deprecated() upgrade path + meraki_compat.py drop-in shim
tests/ + ledger/tests + cadence/tests 208-test suite (see Verification)
ledger/ + cadence/ production showcase apps (finance tracker, habit tracker)
examples/basic.py minimal CRUD + DB plugin app
bench/ honest benches (bench_switch.py) + sustained-load proof (load.py)
docs/ COOKBOOK.md (20 runnable recipes) · ECOSYSTEM.md (extension registry) ·
MIGRATING_FROM_MERAKI.md · DEPLOY.md · PLUGINS.md · PHASE1.md (original spec)
site/ static docs site (no build step) + llms.txt framework manual
SECURITY.md — supported versions, how to report
(GitHub private vulnerability reporting; no public issues for vulns).CONTRIBUTING.md — setup, per-PR checks,
the five agent laws (zero-dep core, tests, no per-request reflection,
fix-saying errors, Conventional Commits).CHANGELOG.md — every release cut from
Conventional Commits, Keep-a-Changelog format.1.x keeps the public API backward-compatible —
ikarem/__init__.py exports, ASGI behavior, CLI commands, response shapes.
Minor versions add; breaking changes wait for a major.deprecated(since=, removal=, use_instead=) — upgrades
warn with the version, the removal target, and the replacement.Python
81.4%
HTML
12.7%
CSS
5.1%
IKAREM — industry-grade Python ASGI backend framework with a zero-dependency core. DI, validation, JWT auth, OpenAPI + MCP. pip install ikarem
See the codeZero-dependency Python ASGI framework, built for humans and LLMs.
FastAPI-style DX (DI, validation, OpenAPI, auth) + Django/Nest-style structure (plugins, config, RBAC) + a core that runs on stdlib alone. Pip-installable, zero required dependencies.
pip install -e . # core only, zero dependencies
pip install -e ".[server,test]" # uvicorn + pytest + httpx for dev
pip install -e ".[postgres]" # asyncpg strategy
pip install -e ".[mysql]" # aiomysql strategy
pip install -e ".[sqlserver]" # aioodbc strategy
from ikarem import Ikarem
app = Ikarem(debug=True)
@app.get("/")
async def home(req):
return {"hello": "ikarem"} # dict auto-becomes JSON
@app.get("/users/{uid:int}")
async def get_user(req, uid: int):
return {"uid": uid}
if __name__ == "__main__":
app.run() # needs `pip install ikarem[server]`
python examples/basic.py
# or
ikarem run examples.basic:app --reload
from ikarem import (
BackgroundTasks,
Depends,
Ikarem,
Schema,
CORSMiddleware,
RateLimitMiddleware,
create_token,
require_roles,
)
app = Ikarem(auth_secret="secret")
app.use(CORSMiddleware())
app.use(RateLimitMiddleware(per_minute=120))
class Item(Schema):
name: str
qty: int = 1
def get_prefix():
return "hi"
@app.post("/items")
async def create(req, item: Item, bg: BackgroundTasks, prefix=Depends(get_prefix)):
bg.add(print, f"created {item.name}")
return {"msg": f"{prefix} {item.name}", "qty": item.qty} # validated + coerced
tok = create_token("u1", "secret", roles=["admin"])
@app.get("/admin")
async def adm(req, claims=Depends(require_roles("admin"))):
return {"sub": claims["sub"]} # 401 without token, 403 without role
Built-ins on every app: GET /healthz, GET /metrics,
GET /openapi.json (OpenAPI 3.1 auto-gen), GET /docs (Swagger UI).
ikarem new myapp && cd myapp # auth + sessions + SQLite CRUD (HTML + JSON), tests + Dockerfile
pytest -q && uvicorn app:app
from ikarem import SessionMiddleware, CSRFMiddleware, Field, Schema
app.use(SessionMiddleware()) # signed cookies: req.session["uid"] = ...
app.use(CSRFMiddleware()) # unsafe routes need X-CSRF-Token or _csrf_token field
class Signup(Schema):
email: str = Field(..., email=True, max_length=254)
password: str = Field(..., min_length=8, max_length=128)
class Note(Schema):
text: str = Field(..., min_length=1, max_length=500)
@app.post("/notes")
async def add(req, note: Note): # validates JSON *and* HTML form bodies
form = await req.form() # urlencoded + multipart, UploadFile files,
f = form.get("doc") # 413 past size caps
await f.write(f"/uploads/{f.filename}")
TestClient keeps a cookie jar (login flows just work) and speaks
get/post/put/patch/delete. ikarem check audits handlers, ikarem mcp
serves every route as an LLM tool (plus ikarem://openapi.json and
ikarem://manifest MCP resources), ikarem inspect prints a compact route
manifest for LLM context, and site/llms.txt is the framework manual in one
page. AGENTS.md holds the contributor laws for AI and human agents alike.
from ikarem import Blueprint, MethodView, Templates, abort, flash
api = Blueprint("api", url_prefix="/api")
@api.get("/items/{uid:int}") # own hooks, own errors, url_for("api.x")
async def one(req, uid: int): ...
app.register_blueprint(api) # hooks wrap once — still zero per-request reflection
abort(403, "owner only") # terse errors through the normal pipeline
class Items(MethodView): # one class per resource, full DI per method
async def get(self, req): ...
async def post(self, req, item: Item): ...
app.route("/items", Items.methods())(Items.as_view("items"))
flash(req, "Saved.") # session-backed, shown once in templates
Templates("templates/").response("hi.html", name="amy") # Jinja2 via ikarem[jinja]
Deliberately not taken: context locals (g, global request proxies) and signals —
explicit req params plus plugins and middleware cover that ground without the magic.
from ikarem import Migrator, QueuePlugin, require_scopes, APIKeyAuth, task
from ikarem.db import DatabasePlugin
app.register(DatabasePlugin("postgresql://..."))
app.register(QueuePlugin()) # durable jobs in app.state_queue
@task("welcome") # name -> callable, worker-dispatched
async def welcome(to: str): ...
@app.post("/signup")
async def signup(req):
await req.app.state_queue.enqueue("welcome", {"to": "a@b.co"})
return {"ok": True}, 201
@app.every(300) # or @app.cron("0 2 * * *")
async def nightly(): ...
# await app.start_scheduler() # explicit: nothing runs unless started
ikarem migrate new add_users && ikarem migrate up myapp:app
ikarem worker myapp:app # drain the queue until Ctrl+C
Plus the small ones the checklist demanded: Schema(extra="forbid") sanitization,
XMLResponse/dict_to_xml, escape_html, APIKeyAuth (static keys or async lookup=),
require_scopes() for JWT scopes, require_if() predicate (ABAC-lite).
Out of scope on purpose: full ORM (strategy + validated schemas is the answer) and
OAuth2 dance (JWT bearer covers service auth).
from ikarem import TimeoutMiddleware, ConcurrencyLimitMiddleware, IdempotencyMiddleware, TrustedHostMiddleware
app.use(TimeoutMiddleware(30)) # hung handler -> 503 + Retry-After
app.use(ConcurrencyLimitMiddleware(100)) # bulkhead: fail fast past N in-flight
app.use(IdempotencyMiddleware()) # Idempotency-Key replays, no double charges
app.use(TrustedHostMiddleware(["example.com", ".example.com"]))
Plus Ikarem(max_body_bytes=...) DoS floor, latency fields in /metrics,
atomic SQLite transactions, Room pub/sub for websockets (tested via
TestClient.ws_connect), and a py.typed marker so downstream type checkers
see the real types.
Live proof it all works: ledger/ — a personal-finance app
(auth, dashboard with SVG charts, CRUD, receipt uploads, CSV export, JSON API)
running on stock IKAREM + uvicorn.
Meraki (5 minutes):
-from meraki import Meraki
+from ikarem.meraki_compat import Meraki
Your app runs unchanged (same routes, middleware, 404/405 bodies) on the IKAREM engine — then migrate handler-by-handler. From anywhere else:
docs/MIGRATING_FROM_FASTAPI.mddocs/MIGRATING_FROM_STARLETTE.mddocs/MIGRATING_FROM_LITESTAR.mddocs/MIGRATING_FROM_FLASK.mddocs/MIGRATING_FROM_DJANGO.mddocs/MIGRATING_FROM_MERAKI.mdPlus honest benchmarks: bench/RESULTS.md ·
extension registry: docs/ECOSYSTEM.md ·
20 runnable recipes: docs/COOKBOOK.md ·
install: pip install ikarem.
Footnote: IKAREM started as an answer to Meraki — same decorator shape, working plugins, and everything Meraki's README promised but never shipped. The rivalry is archived; this section is just the moving van.
| Rival feature | IKAREM answer |
|---|---|
| pip package, minimal deps | Zero required deps. uvicorn/asyncpg/etc are optional extras. Core is pure stdlib + ASGI. |
| ASGI + Uvicorn boundary | Strict server boundary: Ikarem exposes __call__(scope, receive, send). Any ASGI server works (uvicorn, hypercorn, daphne). HTTP + WebSocket + lifespan. |
| Central app + lifecycle | Ikarem() + on_startup / on_shutdown + lifespan. Plugins hook in with priority + topological dependency order. |
| Request/Response | Lazy Request (query, headers, cookies, await body()/json()), Response helpers (JSON, text, html, stream, redirect, File). Handlers never touch raw ASGI. |
| Routing | Compiled routes with {param} + {param:int/float/uuid/path} converters, 404 vs 405 distinction, url_for, include_router(prefix), static mounts. |
| Middleware | Onion pipeline, short-circuitable, global + composable: CORS, security headers, rate limiting (429 + Retry-After), request-ID/timing, metrics. |
| Plugins | Plugin protocol (name, requires, priority, register, on_startup/shutdown/request/response). Manager sorts dependencies, detects cycles. |
| Config | Layered Config: defaults < kwargs < dict < IKAREM_* env vars. Typed config.get(key, default, cast=...). |
| Errors | HTTPException hierarchy + @app.exception_handler(ExcType) with MRO most-specific match. Tracebacks only when debug=True. |
| DB Strategy (pg/mysql/sqlite/mssql) | DatabaseConnector async ABC (connect/disconnect/execute/fetch_one/fetch_all/execute_many/transaction). Lazy driver imports. SQLite runs on stdlib today. DatabasePlugin proves the extension model. |
| DI (FastAPI parity) | Depends() with nesting, per-request cache (+ opt-out), sync/async/yield deps, finalizers guaranteed after response send and on the exception path, circular-dep rejection. |
| Validation (Pydantic-lite) | Schema models from type hints: coercion, required/optional, nested models, ValidationError → 400. Zero deps. |
| Auth | Stdlib HS256 JWT (algorithm-confusion resistant, sub required, expiry enforced), pbkdf2 passwords, BearerAuth, require_roles() RBAC. |
| Caching | MemoryCache + @cached (Redis-swappable CacheBackend interface). |
| Background work | BackgroundTasks param — runs after the response is sent, never fails the response. |
| Realtime / files | app.websocket(path) + WebSocket helper; mount_static() + FileResponse. |
| Observability | JSON logging, x-request-id + x-process-time-ms, /healthz, Prometheus-style /metrics. |
208 passed, 3 skipped — framework plus both showcase apps, one command:
python -m pytest tests/ ledger/tests cadence/tests -q
CI runs the same suite on Python 3.10–3.13 × Ubuntu/macOS/Windows, plus a
live-Postgres job, a Docker showcase build, a starter-template smoke job
(ikarem new + template tests), ruff lint + format, and
ikarem check ledger.app:app. Every behavior ships with a test; bugfix PRs
include a regression test.
ikarem/ zero-dep stdlib core (v1.1.0) — optional integrations lazy-load behind extras
app.py Ikarem core + ASGI callable + lifespan + background/cleanup wiring
compiled.py one-time handler plans (no per-request reflection) + check/describe IR
routing.py compiled routes + converters + Did-you-mean 404s
http.py Request (+forms/uploads) + Response family (+cookies)
di.py Depends + nesting + cycle detection + run_cleanups
validation.py Schema models + Field() constraints (zero-dep validation)
auth.py JWT + passwords + Bearer/API-key auth + roles/scopes guards
session.py signed-cookie sessions + CSRF
security.py CORS + security headers + trusted hosts + rate limiting
resilience.py timeouts + bulkheads + idempotency
cache.py CacheBackend + MemoryCache + RedisCache + @cached
db/ DatabaseConnector ABC + sqlite/postgres/mysql/sqlserver + plugin + factory
queue.py durable task queue + QueuePlugin + `ikarem worker`
scheduler.py cron/intervals + SchedulerPlugin
migrations.py versioned migrations + `ikarem migrate`
resources.py app.resource() validated CRUD
blueprints.py prefixed route groups + MethodView (views.py)
middleware.py Middleware base + stack
plugins.py Plugin protocol + dependency-sorted PluginManager
config.py layered Config
errors.py HTTPException hierarchy + handler registry
openapi.py OpenAPI 3.1 builder + /openapi.json + /docs
mcp.py routes-as-MCP-tools + resources + stdio server
websocket.py WebSocket + Room pub/sub + WSRouter
static.py FileResponse + escape-proof static mounts
templating.py Jinja2 via ikarem[jinja] + flashing.py one-shot messages
observability.py logging + request-ID + metrics + /healthz + /readyz + /metrics
cli.py `ikarem run|check|mcp|new|migrate|worker|inspect`
testing.py TestClient (cookie jar, all verbs, WS driving — no server needed)
scaffold.py `ikarem new` starter generator
deprecation.py deprecated() upgrade path + meraki_compat.py drop-in shim
tests/ + ledger/tests + cadence/tests 208-test suite (see Verification)
ledger/ + cadence/ production showcase apps (finance tracker, habit tracker)
examples/basic.py minimal CRUD + DB plugin app
bench/ honest benches (bench_switch.py) + sustained-load proof (load.py)
docs/ COOKBOOK.md (20 runnable recipes) · ECOSYSTEM.md (extension registry) ·
MIGRATING_FROM_MERAKI.md · DEPLOY.md · PLUGINS.md · PHASE1.md (original spec)
site/ static docs site (no build step) + llms.txt framework manual
SECURITY.md — supported versions, how to report
(GitHub private vulnerability reporting; no public issues for vulns).CONTRIBUTING.md — setup, per-PR checks,
the five agent laws (zero-dep core, tests, no per-request reflection,
fix-saying errors, Conventional Commits).CHANGELOG.md — every release cut from
Conventional Commits, Keep-a-Changelog format.1.x keeps the public API backward-compatible —
ikarem/__init__.py exports, ASGI behavior, CLI commands, response shapes.
Minor versions add; breaking changes wait for a major.deprecated(since=, removal=, use_instead=) — upgrades
warn with the version, the removal target, and the replacement.Python
81.4%
HTML
12.7%
CSS
5.1%