> ## Documentation Index
> Fetch the complete documentation index at: https://docs.omnichar.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Read .char files with the Python SDK

> Use omnichar-sdk to open a .char file in Python: get its references in prompt order, prompt text for each model, the trained LoRA, the voice, and build new characters.

`omnichar-sdk` reads `.char` files from Python. It opens a character and returns its parts. It can also build a new `.char`. The source is in the [ComfyUI-Omnichar repository](https://github.com/omnichar/ComfyUI-Omnichar/tree/main/packages/omnichar-sdk).

## Install

```bash theme={null}
pip install omnichar-sdk              # standard library only
pip install 'omnichar-sdk[images]'    # adds Pillow, for decoding and resizing references
```

The base install has no dependencies on purpose. It drops into ComfyUI, A1111, SwarmUI or a batch job without competing with whatever that host has pinned. It never converts images to tensors; that's the host's job. It needs Python 3.10 or newer.

## Open a character

```python theme={null}
from omnichar_sdk import Character

char = Character.open("Ada.char")

char.get_description()                       # the locked description
char.get_references(arch="flux2-klein")      # the reference set compiled for a model, in prompt order
char.get_lora()                              # the trained adapter, with a portability verdict
char.get_prompt(style="ordinal")             # text that binds the character to its positions
char.get_voice()                             # the stored voice clip, or None
char.get_info()                              # name, counts, which models it has payloads for
```

`get_ref_archs()` and `get_lora_archs()` tell you which models the file carries a reference set or an adapter for. The reference sets currently compiled are `flux2-klein`, `minimax-h3` and `fal-ref`.

## References

`get_references()` returns references in the order a prompt addresses them. Each one has a `role` (`face`, `body` or `cloth`), its `width` and `height`, and:

* `bytes()` for the raw image
* `open()` for a Pillow RGB image (needs the `images` extra)
* `fit(size, mode="pad")` to resize onto a fixed size: `pad` letterboxes, `cover` crops, `stretch` distorts

```python theme={null}
for ref in char.get_references(arch="flux2-klein"):
    image = ref.fit((1024, 1024), mode="cover")
```

Filter with `role` or `limit`. `limit` divides the slots between face, body and outfit instead of cutting the end of the list, so a character keeps its wardrobe when a model takes fewer references than the character has. Pass `arch` for a model's compiled set, or leave it out (optionally with `origin`) to read the original references. You can't pass both.

## Prompt text

`get_prompt()` writes text that names the positions the references will occupy. The `style` picks the addressing a model was trained on:

| Style | For | Output starts with |
| - | - | - |
| `ordinal` | FLUX.2 | `Images 1 and 2 show Ada, ...` |
| `token` | MiniMax H3 | `<Picture 1> <Picture 2> show Ada, ...` |
| `at-image` | Seedance | `@Image1 and @Image2 show Ada, ...` |
| `description-only` | A LoRA (no positions) | `Ada, a woman in her thirties ...` |

`first_position` sets the number the first reference gets. Use the same value for the prompt and the reference sheet so they agree on which image is image 1.

## LoRA

`get_lora(arch)` returns the adapter trained for that model, or `None`. With several adapters and no `arch`, it raises instead of guessing.

```python theme={null}
lora = char.get_lora("z-image")
lora.strength        # the strength it was judged at
lora.portability     # PORTABLE, PARTIAL, INCOMPATIBLE or UNMEASURED
lora.reason          # why, in a sentence
lora.save_to("models/loras")
```

Use the recorded `strength`, not 1.0. An overfitted adapter only works turned down. `portability` says whether the adapter's keys match what tools outside Omnichar Studio expect.

## Reference sheets

A reference sheet lays the references out in a numbered grid. The numbers are what a prompt refers to, so the sheet can be checked against the prompt it belongs to. Needs the `images` extra.

```python theme={null}
char.reference_sheet(arch="flux2-klein", first_position=1)  # a Pillow image
char.reference_sheet_png()                                  # PNG bytes
char.save_reference_sheet("out/ada.png")                    # adds .png if missing
```

It takes the same `arch`, `role`, `limit` and `origin` filters as `get_references`, plus `columns`, `cell`, `fit`, `labels` and `background`.

## Voice

`get_voice()` returns `None`, or a voice with `seconds`, `sample_rate`, `read_wav()` (the mono clip a model is given) and `read_sample()` (the clip as recorded).

`wanted()` applies Omnichar's rule for when to send the voice: only when the prompt has dialogue.

```python theme={null}
from omnichar_sdk import wanted

if wanted("auto", prompt):
    text = char.get_prompt(style="token", voice_position=1)
```

The modes are `auto`, `always` and `never`.

## Build a character

`encode_character` writes a new `.char` from `(image, role)` pairs and compiles a reference set for each model, so the result works without a rebuild.

```python theme={null}
from omnichar_sdk import encode_character, write

doc = encode_character("Ada", "A woman with short dark hair.", [(face, "face"), (body, "body")])
write("Ada.char", doc)
```

To add a voice, pass two PCM WAV clips: the sample as recorded, and the mono copy a model hears, which needs at least 3 seconds of sound.

```python theme={null}
from omnichar_sdk import set_voice

set_voice(doc, sample_wav, mono_wav, source_name="ada.wav")
```

> [!NOTE]
>
> The SDK doesn't compute identity vectors, because those need face encoders it doesn't ship. Rendering is unaffected, but Omnichar Studio's continuity score and verify features stay off for that character until Studio re-encodes the file.


## Related topics

- [Read .char files from the command line](/integrations/cli.md)
- [The .char character file](/characters.md)
- [Integrate .char characters into your tools](/integrations/overview.md)
- [About Omnichar](/index.md)
- [Install the Omnichar ComfyUI node](/comfyui/install.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.