# python -m kindgi.pack

> Indexing and serving a Python pack's code.

`kindgi dev` runs both for you; a pack image runs `serve`.

## `python -m kindgi.pack index`

The indexer — a Python pack's `index.json`.

```plaintext
python -m kindgi.pack index --pack-dir . [--output dist/index.json]
                            [--artifact-version 20261001.1] [--published-at <iso>] [--json]
```

The Python counterpart of `kindgi-index`: reads `[tool.kindgi]`, discovers the files under `tools/`, `guardrails/`, `agents/`, `flows/` (or the configured globs), imports each one, collects the primitives it defines, and writes the index (`@kindgi/specs/pack-index.schema.json`) atomically. Byte-deterministic: same source and pinned `--artifact-version` / `--published-at`, same bytes.

Fails loud, but per file: a module that fails to import, defines a primitive of the wrong kind for its folder, or defines nothing is a file error, and the rest of the pack still indexes. A helper module inside a discovery folder starts with `_` (`tools/_db.py`) and is skipped.

## `python -m kindgi.pack serve`

The pack service process.

```plaintext
python -m kindgi.pack serve [--index <path>] [--module-root <dir>] [--host <address>]
```

The process contract of `@kindgi/handler-runtime`'s pack service, so the same supervisor (`kindgi dev`) and the same deployment run either:

- index: `--index`, else `KINDGI_PACK_INDEX`, else `/app/index.json`
- module root: `--module-root`, else the index's directory
- token: `KINDGI_PACK_SERVICE_TOKEN` (required)
- concurrency: `KINDGI_PACK_SERVICE_MAX_CONCURRENCY` (default 32)
- port: `PORT` (default 8080; `0` picks one)
- host: `--host`, else every interface
- env check: `KINDGI_PACK_ENV_CHECK`, `strict` (default) or `warn`

Logs are `kindgi.log` records on stderr (subsystem `pack`), at `KINDGI_LOG_LEVEL` / `KINDGI_LOG_LEVELS`, in `KINDGI_LOG_FORMAT` (`auto`: JSON unless stderr is a terminal): a record per call, and the lifecycle (`listening`, `boot-failed`, …) whatever the levels (`records.py`).

Boot fails (exit 1, a `boot-failed` record listing every problem) when the index can't be read, a module it names is missing, or one fails to import. A name in the index's `env.required` that is unset or empty is logged once (a `missing-env` warning naming it); under `strict` `/readyz` and calls answer 503 naming it, under `warn` the service serves. Once listening it writes a `listening` record with the port. SIGTERM drains in-flight calls (`/readyz` and new calls answer 503) for up to 8 s, then exits 0.
