# The .chit bundle

A `.chit` file is how a meeting leaves Chitmonk without losing anything, and how one gets back in. It is an ordinary ZIP archive with a manifest and, for each meeting, the complete log of what happened in it. Importing a bundle reproduces the meeting exactly.

People make one with **Export**, then **Chitmonk bundle (.chit)** on a meeting, or **Export all** in the library for every meeting at once. They bring one in with **Import** in the library. The app accepts `.chit` and `.zip`.

Two files to keep next to this page: the [JSON Schema](/chit.schema.json) and a [sample bundle](/sample.chit).

## What is inside

```text
manifest.json                 what the bundle holds, with a checksum for each file
meetings/<meeting-id>.json    one per meeting: its complete event log
audio/<meeting-id>.<ext>      only if the person chose to include kept audio
```

Nothing else may be in the archive. See [what import checks](#what-import-checks).

## manifest.json

```json
{
  "format": "chitmonk-bundle",
  "version": 1,
  "exportedAt": "2026-10-09T23:01:57.490Z",
  "app": "Chitmonk docs sample",
  "meetings": [
    {
      "id": "01927f3a-0000-7000-8000-000000000001",
      "path": "meetings/01927f3a-0000-7000-8000-000000000001.json",
      "schema": 1,
      "events": 24,
      "sha256": "99c95bda1481d34ad33ced61eb87a9aea036c9fa97fed8028cca46214a4ca898"
    }
  ]
}
```

| Field | Type | Meaning |
| --- | --- | --- |
| `format` | string | Always `chitmonk-bundle` |
| `version` | integer | Version of this container. Currently `1` |
| `exportedAt` | string | When it was written, as an ISO 8601 time |
| `app` | string | What wrote it. Chitmonk writes its own version; write the name of your tool |
| `meetings` | array | One entry per meeting, at most 4,000 |
| `meetings[].id` | string | The meeting's id (a lowercase UUID) |
| `meetings[].path` | string | Exactly `meetings/<id>.json` |
| `meetings[].schema` | integer | Version of the event shapes in that file. Currently `1` |
| `meetings[].events` | integer | How many events the file holds |
| `meetings[].sha256` | string | SHA-256 of that file's exact bytes, in lowercase hex |
| `meetings[].audio` | object | Optional: `path`, `mime`, `bytes`, `sha256` of the audio file |

## A meeting file

```json
{ "schema": 1, "events": [ ... ] }
```

`events` is the meeting: an append-only list, oldest first. The current title, the transcript, who spoke, the action items are all worked out by replaying it. [The event log](/chit/events/) lists every event and the rules for replaying.

## Audio

Audio is in a bundle only when the person kept the audio for that meeting and ticked "Include the retained audio" when exporting. It is one file per meeting, stored without compression, named for its type:

| `mime` starts with | Extension |
| --- | --- |
| `audio/webm` | `.webm` |
| `audio/mp4` | `.m4a` |
| `audio/ogg` | `.ogg` |

Chitmonk records Opus at about 14 MB per hour. Line times in the event log are positions in this recording.

## Limits

| What | Limit |
| --- | --- |
| Files in the archive | 4,000 |
| One JSON file, unpacked | 64 MiB |
| One audio file | 512 MiB |
| Everything, unpacked | 1 GiB |
| Events in one meeting | 500,000 |
| Any one piece of text (a title, a line, a note) | 20,000 characters |

## Versions

There are two numbers and they change for different reasons. `version` in the manifest is the container: the file layout described on this page. `schema` is the shape of the events.

- A bundle with a **newer** `version` or `schema` than the app knows is refused, with a message to update the app. It never guesses.
- A meeting with an **older** `schema` is upgraded as it is read. The file is not changed.
- Fields the app does not know are kept and written back out, so a bundle survives a round trip through an older or newer tool.

Both are `1` today.

## What import checks

In this order, and it stops at the first failure. Nothing is saved from a bundle that fails.

1. **Only expected files.** Every entry must be `manifest.json`, `meetings/<uuid>.json` or `audio/<uuid>.<ext>`. A folder stored as an entry of its own counts as an unexpected file, and so do the `__MACOSX` files some tools add. *"That bundle contains files Chitmonk does not expect, so it was not imported."*
2. **Size.** The limits above. *"That bundle is larger than Chitmonk will import."*
3. **A manifest it recognises.** Valid JSON with `format` set to `chitmonk-bundle`. *"That file is not a Chitmonk bundle Chitmonk can read."*
4. **A version it knows.** *"That bundle was made by a newer Chitmonk. Update the app, then import it again."*
5. **Every listed meeting is there and intact.** The file exists at `meetings/<id>.json` and its SHA-256 matches. *"That bundle is damaged: its contents do not match its own checksums."*
6. **Every event is valid.** Known type, right fields, `meetingId` equal to the meeting's id, and the first event is `MeetingCreated`. An event type the app does not know fails here, with the same message as step 3.
7. **No voice data.** An event carrying a key named `embedding`, `embeddings`, `voiceprint`, `prototype`, `pcm` or `audio`, at any depth, is refused. Voice fingerprints are never stored or exported, and the app will not take them in either.
8. **Audio, if listed, is there and intact.** The same message as step 5.

## What import does

- A meeting the device does not have is added under the id it came with.
- A meeting the device already has, with exactly the same events, is skipped.
- A meeting with the same id but different events is added as a **separate copy**, with a new id and "(imported copy)" after its title. Nothing already on the device is ever overwritten or merged.
