# Meetings

> Context for working with the Meetings app's data — where a meeting's notes, diagram, transcript-derived tasks, and calendar cache live, what the lifecycle states mean, and how the app's agents are driven. Load when the user asks about a meeting's notes or action items, or when writing/reading files under the meetings app data dir.

- Skill: `kirodotdev/meetings` (Agent Skill)
- Install (CLI): `npx skillmds@latest add kirodotdev/meetings`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kirodotdev/meetings/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: kirodotdev (https://skillmd.com/u/kirodotdev)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/kirodotdev/meetings

---


# Meetings app

The Meetings app transcribes a live meeting and fans each line out to a small
crew of background agents. A **file-backed** agent (`widget_type` `markdown` or
`html`) owns exactly ONE output file and rewrites it in full after every batch.
An agent whose `widget_type` is `chat` has no output file — its output IS its
chat replies, it gets no `OUTPUT_FILE` line, and none of the file rules below
apply to it.

Only a markdown agent's output is user-editable in the app (the editable
minutes), so a markdown agent re-reads its output file before every rewrite —
the user may have edited it since the last write. An `html` output is not
user-editable.

Only one meeting may be active at a time; starting a second answers 409. The
server enforces the lifecycle transition table, not just the UI: `active` and
`paused` may only reach `ended` through `reviewing` (the action-item review
gate), `ended` may be reopened to `active`, and a same-status POST is an
idempotent no-op.

A live translation panel translates each transcript line as it lands, using one
tool-less `kirocrew-lite` call per line in an ephemeral session — deliberately
NOT the agent batch path, because latency is the point. It is sequential per
meeting and drops the oldest pending line when it falls behind, so gaps in
`translations.json` are expected, not a bug.

## Where the data lives

All paths are under `~/.kiro/crew/apps/meetings/data/`:

| Path | What it is |
|---|---|
| `config.json` | app config: the agent roster, the task/calendar provider ids, presets |
| `dictionary.toml` | speech-to-text correction terms (`[[term]]` blocks) |
| `calendar-cache.json` | the last calendar sync's events |
| `task-ledger.json` | tasks filed through the local task provider |
| `meetings/<id>/session.json` | one meeting's metadata (title, status, attendees, attachments, outputs map) |
| `meetings/<id>/tasks.json` | that meeting's extracted action items |
| `meetings/<id>/<agent-id>.md` | a markdown agent's output (e.g. `note-taker.md`) |
| `meetings/<id>/<agent-id>.html` | an HTML agent's output (e.g. `sketch-artist.html`) |
| `meetings/<id>/transcript.jsonl` | the raw transcript, one finalized speech segment per line — read this instead of asking the user to re-summarize |
| `meetings/<id>/translations.json` | per-line translations for the live translation panel |

`<id>` is the meeting id with `:` replaced by `_`. Only `[A-Za-z0-9._-]` is
legal in it — the backend rejects anything else, so do not construct a path from
a raw calendar UID.

## Lifecycle

1. `idle` — the meeting folder exists, nothing is running.
2. `active` — transcription is flowing; agents receive batched lines every ~30s.
3. `paused` — transcription stopped, the session and its queues are intact.
4. `reviewing` — the meeting is over and the user is triaging extracted tasks.
5. `ended` — finished; outputs are final.

## The agents

| Agent | Writes | Notes |
|---|---|---|
| `meetings-note-taker` | `note-taker.md` | structured notes: topics, decisions, action items, open questions |
| `meetings-sketch-artist` | `sketch-artist.html` | one self-contained HTML/Mermaid diagram, revised in place |
| `meetings-task-extractor` | `tasks.json` | always runs; the app's core output |

A file-backed agent's first message carries an `OUTPUT_FILE:` line. Write to that
exact path, character for character, and rewrite the FULL file after every batch —
never accumulate content in memory, because a context limit would lose it. A
`chat` agent gets no such line and writes no file.

Lines prefixed `[chat]` are typed by the user, not transcribed: treat them as
corrections or added context and act on them immediately.

## Providers

Two things are pluggable, and which implementation is active comes from
`config.json`:

- **`task_provider`** — where a reviewed action item is filed. The shipped
  provider is `local`, which appends to `task-ledger.json`.
- **`calendar.provider`** — where upcoming meetings come from. `none` (default,
  meetings are created by hand) or `ics`, which reads the iCalendar document at
  `calendar.source` (a local `.ics` file path, or a published `https://` URL).

To sync the calendar, call `POST /api/apps/meetings/calendar/sync` — do not try
to fetch or parse the calendar yourself. With a provider configured the app also
syncs on its own every `calendar.poll_interval_secs` (default 300) and creates
the meeting directory for an event `calendar.precreate_lead_minutes` (default 15)
before it starts, so an imminent meeting usually already exists as `idle`;
`calendar.auto_sync: false` turns the background poll off, and a lead of `0`
keeps the sync but stops pre-creation.

## Speech-to-text

Transcription uses KiroCrew's own streaming endpoint (`/api/ws/stt`), driven from
the browser. Cloud transcription is optional
(`pip install 'boto3>=1.34,<2' 'amazon-transcribe>=0.6,<1'`); when it is not
installed the app says so and the user can still type into the broadcast bar to
feed the agents.

## Correcting recurring mistranscriptions

When the user complains that a project noun keeps coming through wrong, add a
dictionary term rather than correcting it in the notes:

```
POST /api/apps/meetings/dictionary
{"correct": "DynamoDB", "aliases": ["dynamo db", "dynamo d.b."]}
```

Matching is case-insensitive with word boundaries and the longest alias wins, so
every later meeting gets it right at the point of transcription.

