Skip to main content

Turn meeting transcripts into a temporal context graph for coding agents.

Project description

Meeting → Context Graph

Turn meeting transcripts into a temporal context graph that a coding agent reads to write and update code. Each meeting updates the same graph.json, and git history records how decisions evolved.

Meetily (capture + transcribe, free)  ─►  context_graph CLI  ─►  graph.json (git)  ─►  coding agent

Why a graph, not just notes

Every node has a status (active / superseded / deprecated) and a supersedes list. When a later meeting reverses a decision, the old node is marked superseded and a new active node links to it via a SUPERSEDES edge. So the graph always shows current truth and what changed.

Setup

pip install meetmind                 # core CLI
pip install "meetmind[all]"          # + Slack bot, graph images, doc/PDF ingest, embeddings
export GROQ_API_KEY=...               # free key from console.groq.com  (PowerShell: $env:GROQ_API_KEY="...")

A shared Groq key ships as a fallback, so meetmind works out of the box for light use. Set your own GROQ_API_KEY to avoid the shared rate limit.

Usage

# --- recommended: pull straight from Meetily's local DB (recording -> transcript) ---
meetmind meetily-list                 # see recent Meetily meetings
meetmind ingest --meetily             # ingest the LATEST Meetily meeting
meetmind ingest --meetily-id <id>     # ingest a specific Meetily meeting

# --- batch: catch up on many meetings at once (oldest first, one commit each) ---
meetmind ingest --new                 # every Meetily meeting not yet in the graph
meetmind ingest --since 2026-07-01    # meetings created on/after a date
meetmind ingest --since 2026-07-01 --new   # both filters combined
meetmind ingest --all                 # every Meetily meeting

# --- other input sources ---
meetmind ingest transcripts/m1.txt --meeting-id 2026-07-12-kickoff
meetmind ingest --paste "we'll use REST and Postgres" --meeting-id m1
meetmind ingest --audio meeting.mp3 --meeting-id m1   # Groq Whisper fallback

meetmind ingest ... --dry-run   # preview changes, no write/commit
meetmind show                    # print current active nodes
meetmind delta                   # git diff of last meeting's changes

# render the graph from the terminal (no Slack needed)
meetmind viz --out graph.png                 # PNG
meetmind viz --format mermaid --out g.mmd    # Mermaid text
meetmind viz --format dot --active-only      # DOT, hide superseded

# check graph integrity (dangling edges, supersedes cycles, duplicate concepts)
meetmind validate

# export the ACTIVE-only spec for the coding agent (grouped by feature)
meetmind export --format md --out spec.md
meetmind export --format json --out spec.json

# scope to a separate project graph -> context-graphs/<name>.json
meetmind ingest samples/m1-kickoff.txt --meeting-id m1 --project payments
meetmind export --project payments

# multi-project meeting: split ONE transcript across per-project graphs automatically
meetmind ingest big-meeting.txt --meeting-id m1 --route

Multi-project meetings (routing)

When one meeting discusses several projects, --route makes the extractor label each node with a project and fans the nodes out into separate context-graphs/<project>.json files — each with its own temporal history, supersession, and export spec. Known projects are discovered from the existing graph files, so labels stay consistent meeting to meeting; a genuinely new project name auto-creates its graph. Cross-cutting items go to general.

Cross-project dependencies are preserved: an edge between nodes in different projects (e.g. Billing DEPENDS_ON an Auth decision) is stored in the source project's graph as a namespaced reference auth:decision-api-graphql, surfaced in that project's export spec (so the coding agent sees the dependency) and exempt from validation's dangling-edge check.

In the Slack bot, set CG_ROUTE_PROJECTS=1 and the bot routes each uploaded meeting by content, replying with a per-project breakdown + one graph image per project touched (instead of assuming the channel = the project).

Entity resolution (how meetings merge without duplicating)

When a later meeting revises a decision, the pipeline decides NEW vs DUPLICATE vs CHANGE (supersede) using, in order:

  1. Explicit supersession — the extractor is shown the current active nodes and emits supersedes: [id] when a statement replaces one. Most reliable.
  2. Embedding similarity (optional) — if sentence-transformers is installed (or GEMINI_API_KEY is set) nodes are matched semantically, so req-user-login and req-authentication-flow can still merge. pip install sentence-transformers to enable; without it the system falls back to string/concept matching (no error).
  3. String/concept matching — id-prefix + token overlap. Always available.

Use export to hand the coding agent a clean current-state spec (no history), and validate in CI to catch a corrupt graph before an agent acts on it.

Meetily integration (recording → transcript)

Meetily records system+mic audio locally and transcribes it for free — no meeting bot needed. It stores everything in a SQLite database, which this CLI reads read-only:

OS Database path
Windows %APPDATA%\com.meetily.ai\meeting_minutes.sqlite
macOS ~/Library/Application Support/com.meetily.ai/meeting_minutes.sqlite
Linux ~/.local/share/com.meetily.ai/meeting_minutes.sqlite

The path is auto-detected; override with --meetily-db PATH if needed. With --meetily the meeting-id is auto-derived from the meeting's date + title (e.g. 2026-07-12-design-review), so you don't pass --meeting-id. Speaker source is labeled You: (mic) / Others: (system audio).

Meetings need not be live. A previously-recorded call works two ways: (1) import the recording into Meetily (its audio-import feature transcribes it into the same DB, then --meetily picks it up), or (2) point the CLI straight at the file with --audio old-meeting.mp3 (Groq Whisper transcribes it, no Meetily needed).

Other inputs: pasted minutes (--paste), a plain transcript file, or the built-in Groq Whisper fallback for a raw audio file (--audio).

Slack bot (audio in → graph image out)

Let anyone on the team drop a meeting recording into a channel and get the context graph back as a rendered image — no CLI needed.

User uploads meeting.wav ─► bot transcribes (Groq) ─► ingest ─► posts changelog
                                                              └─► uploads graph PNG

Mentions: @bot graph (post the image), @bot show (list active nodes), @bot delta (git diff since last meeting).

Run it (Socket Mode — no public URL needed)

pip install "meetmind[bot]"              # includes slack-bolt, requests
export SLACK_BOT_TOKEN=xoxb-...           # bot token
export SLACK_APP_TOKEN=xapp-...           # app-level token, scope connections:write
export GROQ_API_KEY=...
export CG_GRAPH_PATH=graph.json           # optional
meetmind-bot

Slack app setup: enable Socket Mode; subscribe to events message.channels and app_mention; bot scopes app_mentions:read, channels:history, files:read, files:write, chat:write (add groups:history for private channels). Invite the bot to the channel.

Graph rendering

The image is rendered by context_graph/viz.py:

  • Graphviz (preferred, fully offline) — install the system binary (choco install graphviz on Windows, apt install graphviz, brew install graphviz); the graphviz pip package wraps it.
  • mermaid.ink (automatic fallback if dot isn't found) — renders via a free web service. ⚠️ This sends the graph to an external host; install Graphviz to keep confidential meetings local.

Encoding: node color = status (green active / grey superseded / amber open question), shape = type (Decision ◆, Requirement ▢, Constraint ⬡, …), and SUPERSEDES edges are red dashed. Check viz.available_renderer() to see which backend is active.

Contract for the coding agent

Read graph.json and treat it as follows:

  • Current requirements = every node with "status": "active". Obey these.
  • Ignore nodes with "status": "superseded" or "deprecated" as current truth — but use them to know what to remove or replace.
  • OpenQuestion nodes are NOT decided — do not assume an answer; flag them.
  • What changed since last meeting = git diff HEAD~1 HEAD -- graph.json (or meetmind delta). A node flipping to superseded plus a new active node linked by a SUPERSEDES edge = "replace the old implementation with the new one."
  • Edges tell you structure: IMPLEMENTS, DEPENDS_ON, BLOCKS, SUPERSEDES, DECIDED_IN, RELATES_TO.

Node shape

{
  "id": "decision-api-style",
  "type": "Decision",
  "title": "API uses GraphQL",
  "content": "Switch the public API from REST to GraphQL.",
  "status": "active",
  "source_meeting": "2026-07-19-review",
  "created_at": "2026-07-19T10:00:00+00:00",
  "supersedes": ["decision-api-rest"],
  "confidence": 0.9,
  "owner": "Priya"
}

Scope (v1)

Included: transcript/paste/audio input, Groq extraction, temporal merge with supersession, JSON graph + git history, CLI.

Deferred: MCP server, Neo4j/Graphiti engine, meeting bot, embedding-based dedup, GUI. See the plan file for rationale.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

meetmind-0.1.1.tar.gz (49.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

meetmind-0.1.1-py3-none-any.whl (47.9 kB view details)

Uploaded Python 3

File details

Details for the file meetmind-0.1.1.tar.gz.

File metadata

  • Download URL: meetmind-0.1.1.tar.gz
  • Upload date:
  • Size: 49.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for meetmind-0.1.1.tar.gz
Algorithm Hash digest
SHA256 ce23307a0c89fda0eb139462df992a1f2aa984b473eca305f872d1ec2485e472
MD5 427225eef357d28a1ca81c9613e7b1e9
BLAKE2b-256 271670d079d3b94a46e0cea43824a1b10cfb8ce6ac2708b905525d2cf71d3adf

See more details on using hashes here.

File details

Details for the file meetmind-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: meetmind-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 47.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for meetmind-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 93ff18714cf64131ec98a15a2aa9f2388f9e6337bc39d1f8260a46af1ebcc6ab
MD5 862c93f21032189fadc87115ea9bf6a9
BLAKE2b-256 c1b0856c88565991bdb11109b94d6759ea25f36d40a76aa320468000f9794d66

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page