Private meeting intelligence for macOS.
Record, transcribe, identify speakers, extract decisions and actions, and build project memory — with Local AI as the default boundary.
Why ClosedRoom · Features · How to use it · Run it · Privacy model · Architecture · Feature registry
| Private by default | Intelligence, not just transcripts | Memory across meetings |
|---|---|---|
| Sensitive meeting data stays on your Mac by default. Cloud providers are explicit choices, never silent fallbacks. | ClosedRoom turns conversations into speaker-aware transcripts, actions, decisions, risks, questions and editable notes. | Meeting outputs become reusable project context instead of disappearing inside isolated transcripts. |
A meeting should become useful memory, while the default trust boundary stays on your Mac.
ClosedRoom is built around the full path from capture to reusable operational memory rather than transcription alone.
| Capability | What you get |
|---|---|
| Local meeting capture | Record microphone and system audio on macOS, preserve recoverable artifacts, and save the meeting before expensive inference starts. |
| Local transcription | Transcribe on-device with MLX Whisper or Nemotron ASR, with persisted jobs and reusable results. |
| Speaker-aware transcripts | Separate speakers locally with FluidAudio and keep speaker clusters stable across review and recalculation. |
| Structured meeting intelligence | Turn a transcript into summaries, actions, decisions, risks, open questions and meeting notes through a structured analysis pipeline. |
| Verifiable, editable notes | Review generated actions and decisions against source context, correct them, and preserve user edits across reloads and regenerated revisions. |
| Project memory | Reuse meeting outputs across a project so decisions, risks, commitments and updates do not disappear inside isolated transcripts. |
ClosedRoom can also add optional enrichment without making the core workflow depend on it: conservative visual speaker attribution, richer diagnostics, provider alternatives and deeper analysis paths.
The user mental model is deliberately simple:
Record → Transcribe → Understand → Remember
Under that simple flow, ClosedRoom saves the meeting before expensive AI work, enriches the transcript without making optional stages mandatory, keeps generated notes reviewable, and carries useful outputs into Today and Project memory.
Image placeholder: A compact four-stage product journey showing Record → Transcribe → Understand → Remember. Use real ClosedRoom UI fragments for each stage rather than an abstract architecture diagram. The final stage should visibly connect multiple meetings into Project memory.
| Today | Recording | Meeting intelligence |
|---|---|---|
![]() |
![]() |
![]() |
| Meetings, actions, decisions, risks and context | A focused capture flow with optional advanced controls | Transcript, speakers, sources and structured analysis |
| Project memory | Deep-dive actions |
|---|---|
![]() |
![]() |
| Cross-meeting status, decisions, risks and updates | Operational detail extracted from meeting intelligence |
A normal ClosedRoom workflow does not require choosing models, audio devices or inference parameters before every meeting.
- Start and record a meeting. Add a title or project if useful, grant the required macOS capture permissions, and let ClosedRoom write audio progressively so the meeting remains recoverable.
- Stop and transcribe. ClosedRoom finalizes the recording first, then runs the default local ASR path as a persisted, observable job.
- Turn the transcript into meeting intelligence. Structured analysis produces the summary, actions, decisions, risks and other reusable outputs shown in the main workspace.
- Review and edit. Generated items stay human-reviewable; corrections are persisted instead of being silently replaced on refresh or regeneration.
- Reuse the result. Today and Project workspaces carry decisions, commitments, risks and context across meetings instead of treating each transcript as an isolated file.
Optional visual intelligence can be enabled for a specifically selected macOS window. It may contribute evidence for naming existing speaker clusters, but audio diarization remains the source of who spoke when and uncertain identity mappings abstain rather than pretending certainty.
During native recording, the compact overlay can also save a manual full-display screenshot as local meeting evidence. The image is timestamped against the recording clock, reopens from the transcript/notes at that point, and stays separate from spoken evidence. This action is manual rather than continuous, and remote-provider selection does not silently send the screenshot outside the Mac.
Visual evidence may support naming an existing speaker cluster; it never replaces audio diarization, and low-confidence mappings remain unknown.
ClosedRoom is local-first, not local-only.
The default product path keeps the sensitive meeting workflow on the Mac. Cloud providers exist as explicit choices, not silent fallbacks.
| Area | Default | Optional alternative |
|---|---|---|
| Recording | Local macOS capture | — |
| Speech-to-text | Local MLX Whisper / Nemotron | Speechmatics when explicitly selected |
| Speaker diarization | Local FluidAudio on supported Macs | Speechmatics when explicitly selected |
| Meeting analysis | Local Korgis runtime | Gemini when explicitly selected |
| Visual speaker evidence | Local selected-window frames + local VLM path | Disabled unless explicitly enabled |
| Persistence | Local filesystem + SQLite | No implicit remote persistence |
This is a product boundary, not a marketing label: provider selection, runtime ownership and failure states are explicit so a local failure does not silently move meeting content to a cloud API.
The default trust boundary stays on the user's Mac; cloud providers sit outside it and are used only when explicitly selected.
ClosedRoom separates the meeting product from reusable Local AI runtime concerns.
ClosedRoom macOS app / React workspace
│
▼
Loopback FastAPI boundary
│
┌───────┼────────┐
│ │ │
Recording Jobs Local persistence
│ │ │
└───────┼────────┘
│
┌────────┴─────────┐
│ │
Local ASR / diarization Korgis
│ │
transcript + speakers LLM / VLM runtime
└──────────┬────────┘
▼
Meeting / Project memory
The key ownership split is:
- ClosedRoom owns the user problem: capture, meetings, transcripts, speaker state, structured notes, user edits, project memory, persistence and product UX.
- Korgis owns reusable Local AI runtime infrastructure: model loading, backend selection, runtime lifecycle, text/vision inference, logs and diagnostics. The current integration still uses the internal
local-llm-serverpackage/runtime identity where required by the implementation. - Native helpers own platform-specific capture and diarization work behind explicit process boundaries.
For durable ownership and extension rules, read docs/architecture.md.
Meeting intelligence is a pipeline, so one optional enrichment should not invalidate everything that came before it.
ClosedRoom therefore distinguishes the core meeting artifact from optional stages:
- a recording is finalized before transcription;
- a usable transcript can survive diarization or visual-intelligence degradation;
- visual speaker attribution can abstain;
- diagnostics record effective backends, warnings and failure causes;
- jobs are persistent, cancellable and recoverable where the workflow requires it;
- invalid or stale structured-note edits are surfaced as explicit conflicts instead of being silently remapped.
This is one of the main engineering goals of the project: Local AI should behave like a product system, not like a successful-demo-only pipeline.
ClosedRoom is currently an active-development, source-built macOS project. A public downloadable GitHub Release is not published yet, so the supported path today is to run or build the project from source.
- macOS
- Apple Silicon recommended and required for some MLX / FluidAudio paths
- Python
>=3.10,<3.14 - Homebrew for the repository setup script
ffmpeguvrecommended- local model storage appropriate for the ASR / LLM models you choose
Cloud credentials are not required for the default local path.
git clone https://github.com/daniele21/closedroom.git
cd closedroom
./setup.sh
./run.shThen open:
http://127.0.0.1:1236
The repository still uses the internal Python package / CLI name local-asr-server / local-asr for the local backend. That is an implementation boundary inside the ClosedRoom product, not a separate repository to clone.
local-asr serve \
--model mlx-community/nemotron-3.5-asr-streaming-0.6b \
--recordings-dir ~/Recordings/local-asr \
--port 1236For development with reload:
UV_CACHE_DIR=.cache/uv uv run local-asr serve --reload./build.sh --no-dmg
# => dist/ClosedRoom.appClosedRoom keeps its installed/runtime identity stable across product versions: the app bundle is ClosedRoom.app, the display name is ClosedRoom, and the default bundle identifier is com.closedroom.app. Root VERSION owns the product SemVer embedded in the bundle and used by versioned DMGs/releases; individual finalized artifacts add build ID + source revision without changing the app identity.
For repeated local testing with stable macOS TCC permissions, use one persistent code-signing identity and install the same bundle name each time:
export CLOSEDROOM_SIGN_IDENTITY="ClosedRoom Local Development"
./build.sh --no-dmg --install
# => /Applications/ClosedRoom.appA trusted self-signed Code Signing identity is sufficient for same-Mac development. Public distribution still requires the production Developer ID + notarization path. The packaged application includes the native capture helper and FluidAudio diarization helper; target-Mac behavior still requires applicable real-environment validation.
ClosedRoom already implements the core meeting-intelligence workflow, but it remains under active development.
Current boundaries worth knowing:
- the product is focused on macOS, with the strongest local inference path on Apple Silicon;
- local FluidAudio diarization requires supported macOS / hardware and remains an enrichment rather than a prerequisite for transcription;
- visual intelligence is disabled by default and only observes a window explicitly selected by the user;
- automatic speaker naming is conservative and may intentionally leave a speaker unnamed;
- Speechmatics and Gemini are opt-in providers and move selected meeting data outside the local trust boundary;
- no public binary GitHub Release is available yet;
- model quality, latency, memory and thermal behavior should be treated as environment/model dependent unless backed by representative recorded evidence.
ClosedRoom is not a guarantee of perfect transcription, speaker identity or meeting understanding. Human review remains part of the product model.
Experimental Korgis Consumer SDK transport: ClosedRoom can opt into the role-bound Python SDK for Nemotron text analysis only, while continuing to own its existing runtime sidecar. The default stays on the pinned legacy client; the standalone SDK is now pinned in the opt-in korgis-sdk extra and included by source-built macOS bundles, while real-model/native qualification remains open. See developer setup and compatibility boundaries.
| Area | Main paths | Responsibility |
|---|---|---|
| Product UI | frontend/src/ |
Today, recording, meeting, project, settings and guided workflows |
| API / composition | src/local_asr_server/server.py, app_services.py |
FastAPI boundary, route wiring and long-lived services |
| Recording / capture | recordings.py, native helpers, audio_router.py |
Progressive capture, recovery, macOS audio and optional visual frames |
| Transcription / diarization | transcriptions.py, asr_provider.py, speaker_diarization_helper/ |
ASR providers, transcript persistence and speaker clustering |
| Meeting intelligence | analysis jobs, templates, structured notes | Structured meeting outputs, source references, edits and revisions |
| Local model runtime | Korgis + internal local-llm-server integration |
Local LLM/VLM lifecycle and inference |
| Persistence | catalog.py, settings and paths |
SQLite catalog, artifacts, configuration and durable state |
| macOS app | menubar.py, window.py, ClosedRoom.spec, build scripts |
WKWebView shell, menu bar, bundling and packaging |
Start with AGENTS.md for engineering ownership and docs/features.md for the business/technical feature registry.
# setup
./setup.sh
(cd frontend && pnpm install --frozen-lockfile)
# repository checks
python3 scripts/verify_repository.py
# tests
UV_CACHE_DIR=.cache/uv uv run python -m unittest discover -s test -v
# build
bash scripts/build_artifact.sh --no-dmgCanonical commands and validation stages live in .engineering/commands.json.
The browser workspace, WKWebView shell and diagnostics use the same loopback API boundary.
curl -c /tmp/closedroom.cookies http://127.0.0.1:1236/v1/session
curl http://127.0.0.1:1236/healthFor endpoint-level behavior, provider options, speaker recalculation, analysis pipelines and diagnostics, see docs/features.md and docs/architecture.md.
ClosedRoom uses dev → main as its canonical branch flow. Ordinary feature and fix work branches from dev and returns to dev through a pull request; main is the stable promotion line.
See CONTRIBUTING.md for the development and validation model, and SECURITY.md for security reporting.
ClosedRoom is part of Daniele Moltisanti's Local AI work: build real products on top of reusable Local AI infrastructure, measure what works, and keep Local, Hybrid and Cloud as explicit architectural choices rather than accidental dependencies.
Within that ecosystem, ClosedRoom applies Local AI to a real sensitive workflow, while Korgis provides reusable execution and control infrastructure.
Its role in that mission is concrete: prove that sensitive meeting workflows can become useful, persistent AI-assisted memory while keeping the default data boundary under the user's control.
ClosedRoom is available under the MIT License.







