The current Transcripted app defaults to a Transcripted-named Application Support root:
- app support root:
~/Library/Application Support/Transcripted/ - default capture library:
~/Library/Application Support/Transcripted/captures/
Users can point the capture library at a different folder in Settings via the
transcriptSaveLocation preference. When the current library still has saved
meetings, dictations, or writing, Settings offers to move or copy those captures
to the new folder before switching. Both skip destination name collisions instead of
overwriting. Copy never deletes originals. Move copies first, switches the
library, then sends each copied original to the Trash only if its copy exists
and the original hasn't changed since it was copied; anything else stays in
the old folder. App-owned state, cache, logs, and temp
files always stay under ~/Library/Application Support/Transcripted/.
Dictation artifacts live under:
- root:
<capture-library>/dictations/ - current runtime output: daily markdown files like
Dictations_2026-04-11.md
DictationStoragePaths.transcriptsFolder points directly at the dictations
folder. There is no extra transcripts/ subdirectory in the current app
layout.
Kept dictation audio lives in <capture-library>/dictations/audio/, one file
per take named from its session UUID: <uuid>.m4a, or <uuid>.wav until
background compression finishes (or if it failed). Files are 0600 in a 0700
folder. The day file's Audio: line stores the path relative to the dictations
folder (audio/<uuid>.m4a), so it survives a library move; Move and Copy carry
dictations/audio/*.m4a|*.wav like the day files (audio named by a day file
that stays behind on a name collision stays behind with it). Deleting a
dictation in Home deletes its kept audio once the undo window closes.
DictationAudioArchive (Sources/Dictation/DictationAudioArchive.swift) owns
keep, resolve, compress, and prune. How long audio stays is Settings → Storage →
Keep dictation audio (dictation-audio-keep in AudioStoragePreferences:
Don't keep, 7 days, 30 days (default), Forever); pruning runs at launch and
when the setting changes, and only touches regular files with those names,
never symlinks.
Until the transcript saves, a take's audio stays in the private recovery folder
~/Library/Application Support/Transcripted/state/dictation-audio-recovery/
(app state, not the library). After a successful save it moves into
dictations/audio/ when audio is kept, or is deleted when it isn't. A failed
save leaves it in recovery.
Saved writing lives under:
- root:
<capture-library>/writing/ - runtime output: one Markdown file per local day, like
Writing_2026-09-25.md. The format is indocs/capture-format.md("Writing day files").
The main app writes these day files, never the keyboard. The folder is created
0700 and each file 0600. FileManager.writingSupportDir resolves the folder
(FileManager.writingDirectory(in:) for a library other than the current one),
and mcp-directories.json lists it as writingDirectory. That key is optional:
manifests written before Writing lack it and get rewritten once with it, and
tools that predate it ignore it. Choosing a new capture library prepares
writing/ next to meetings/ and dictations/, and Move and Copy carry
writing/*.md with the same collision and changed-since-copy rules as
dictation day files.
App-owned Writing state stays under Application Support when the capture library moves:
- state root:
~/Library/Application Support/Transcripted/writing/, holding the keyboard socketghost.sock,runtime.lock, the text-freeOutcome Ledger/andWord Diary/(Tilde's plaintext word diary isn't ported; accepted text is saved only by Save my writing), and the encryptedPersonal History/.Outcome Ledger/events.jsonlis cut back to its newest 12 MiB once it passes 24 MiB, which still covers the seven-day window - models:
~/Library/Application Support/Transcripted/models/writing/<id>/model.gguf, excluded from backup. The Writing tab's Delete model empties this folder (never Delete all writing); it refuses the folder if it's a symlink - diagnostics log:
~/Library/Application Support/Transcripted/logs/writing-diagnostics.log, rolled towriting-diagnostics.log.1at 4 MB (one old generation kept)
Closed, secret-scrubbed writing waiting for its day-file save is owned by
~/Library/Application Support/Transcripted/writing/Pending Entries/pending-writing.json.
This private 0600 journal in a 0700 folder stays local when the capture library
moves or goes offline. Publication is replayed by Entry ID so a restart cannot
append the same entry twice. Up to 256 closed entries / 8 MiB may wait; a full or
unavailable recovery store refuses new closed-entry admission rather than dropping
old entries. Save errors stay visible until every pending entry is resolved.
Consent changes, scope narrowing, opt-out and Delete all discard pending writing
intentionally. Raw open entries and scrubber context are never journaled; a
crash/force quit can still lose unfinished writing. When the final open entry
can't be closed into durable ownership, graceful Quit asks first (Keep Open /
Quit Anyway); logout, restart and shutdown go ahead and lose that entry.
Meeting captures live under:
- root:
<capture-library>/meetings/
The meetings capture folder contains user-facing artifacts:
- markdown transcripts:
<capture-library>/meetings/*.md - retained recording audio:
<capture-library>/meetings/audio/*_audio/
After a successful transcript save, app-managed retained .wav audio is
converted to .m4a and the original .wav is removed only after conversion
succeeds. The Storage settings page controls whether retained audio is deleted
after 7 days, 30 days, or never. Markdown transcripts are not removed by audio
retention cleanup.
On launch, Transcripted also performs best-effort compression for existing
retained audio folders that already have matching Markdown transcripts. Failed
audio that is still referenced by the failed-meeting retry queue can also be
compressed in place, with the queue updated to point at the new .m4a files
before the original .wav files are removed. Orphaned audio without a saved
transcript or failed-queue entry is left alone instead of guessing ownership.
App-owned meeting state is stored separately under:
- speaker DB:
~/Library/Application Support/Transcripted/state/speakers.sqlite(WeSpeaker voiceprints); the default ReDimNet2 voiceprint model keeps its ownstate/speakers_redimnet2-b4.sqlite, since voiceprints from different models can't be compared - stats DB:
~/Library/Application Support/Transcripted/state/stats.sqlite - failed queue:
~/Library/Application Support/Transcripted/state/failed_transcriptions.json - queued import journals:
~/Library/Application Support/Transcripted/state/imported_transcription_queue/ - runtime diagnostics marker:
~/Library/Application Support/Transcripted/state/runtime-diagnostics.json - stopped dictation audio:
~/Library/Application Support/Transcripted/state/dictation-audio-recovery/(a private WAV plus.jsonwritten when a dictation stops, deleted once its text is saved; a short failed take's WAV is usually dropped with the error, while a take of 30 s or more keeps it behind a Transcribe It button. At the next launch a leftover under 30 s is deleted; one of 30 s or more, or one whose length can't be read, stays here quietly with nothing asking about it) - dictionary-fix backups:
~/Library/Application Support/Transcripted/state/dictionary-fix-backups/(one folder per "Fix them" from the Corrections list: the original text of each meeting it changed plus areceipt.json; kept 3 days so Undo survives a relaunch, pruned at launch, and dropped when the meeting is deleted from Home). Backups follow the meeting's file name, so renaming a fixed meeting drops its Undo at the next launch; the prune is skipped while the meetings folder is missing (for example on an unmounted drive)
Claude Desktop integration installs the bundled read-only MCP helper under:
- MCP helper:
~/Library/Application Support/Transcripted/mcp/transcripted-mcp - MCP directory manifest:
~/Library/Application Support/Transcripted/mcp-directories.json
The opt-in live meeting helper (Tools/TranscriptedLive) writes outside the app's folder, under
~/Library/Application Support/TranscriptedLive/ (or TRANSCRIPTED_LIVE_DIR):
session.json: the helper's state and current ghost linesmeetings/<id>.jsonl: the rough transcript of each meeting it heard; the helper deletes ones older than 24 h when it starts. Deleting a meeting in the app, moving the capture library and the app's cleanup never touch this folder
Script-installed experimental models (never downloaded by the app) live under:
- Parakeet Ultra:
~/Library/Application Support/Transcripted/models/parakeet-ultra/parakeet-tdt-0.6b-v3/, installed byscripts/models/parakeet-ultra/install.shand only used when itstranscripted-model.jsonmarker is present
The ReDimNet2 voiceprint model ships inside the app
(Transcripted.app/Contents/Resources/redimnet2-voiceprint/Model.mlmodelc). The build copies it
from the shared FluidAudio model cache, where the app also looks when the bundle has none:
~/Library/Application Support/FluidAudio/Models/redimnet2-b4-slim/Model.mlmodelc, put there by
scripts/models/redimnet2/install.sh. The app never downloads it.
Temporary audio scratch paths live under:
- raw recordings:
~/Library/Application Support/Transcripted/tmp/recordings/ - speaker clips:
~/Library/Application Support/Transcripted/tmp/recordings/speaker_clips/
Successful live and imported meeting recordings are copied from scratch into the meeting capture library before scratch cleanup. Failed live meeting transcriptions also copy their available recording audio there while keeping the scratch files available for retry. Explicitly discarded recordings still delete their scratch audio.
These paths are defined on the app side in Sources/Meeting/MeetingStoragePaths.swift
and then injected into TranscriptedCore through CoreStoragePaths.
App-side observability output currently lives under:
- debug log:
~/Library/Application Support/Transcripted/logs/debug.log - events:
~/Library/Application Support/Transcripted/logs/events.jsonl - Writing diagnostics:
~/Library/Application Support/Transcripted/logs/writing-diagnostics.log
The embedded TranscriptedCore logger also writes JSONL under the same logs
directory:
- core pipeline log:
~/Library/Application Support/Transcripted/logs/app.jsonl
CoreStoragePaths.default now uses the same Transcripted-named Application
Support layout:
- meeting captures:
~/Library/Application Support/Transcripted/captures/meetings/ - databases + failed queue:
~/Library/Application Support/Transcripted/state/ - raw audio scratch:
~/Library/Application Support/Transcripted/tmp/recordings/ - logs:
~/Library/Application Support/Transcripted/logs/
The app still injects its own CoreStoragePaths so the meeting capture folder
can follow the user-selected capture library.
The standalone tools do not all resolve paths the same way:
TranscriptedCLIfirst follows the app-selected capture library frommcp-directories.jsonor the app'stranscriptSaveLocationpreference, then falls back to the current Transcripted capture folders, then legacy Draft.../transcripts/, then~/Documents/Transcripted/; explicit--data-dir,--meetings-dir,--dictations-dir, or matching env vars still override thisTranscriptedMCPfirst follows the app-selected capture library frommcp-directories.jsonor the app'stranscriptSaveLocationpreference, then falls back to the current-plus-legacy read order. It keeps its SQLite index under~/Library/Application Support/Transcripted/cache/by default; ifTRANSCRIPTED_DATA_DIRis set, it instead keeps the index in that shared root unlessTRANSCRIPTED_INDEX_DIRis also setTranscriptedQAfollows the app-selected capture library frommcp-directories.jsonor thetranscriptSaveLocationpreference, scans the current and existing legacy fallback capture directories, keeps state/log validation under the app-owned~/Library/Application Support/Transcripted/root, and accepts explicit--path,--dictations-path,--state-dir, and--log-pathoverrides for nonstandard setups