CLI reference
Global syntax
Section titled “Global syntax”loofah [--base DIR] [--vault-path DIR] [--json] <command>| Option | Environment variable | Behavior |
|---|---|---|
--base DIR | LOOFAH_BASE | Use DIR as the vault directory. |
--vault-path DIR | LOOFAH_VAULT_PATH | Use an explicit vault directory. |
--json | None | Emit a versioned JSON response or machine-readable JSON error. |
--vault-path takes precedence over --base. Without either option, the CLI uses Loofah’s platform application-data directory, following the vault_path redirect in its global.json when the vault has been relocated.
Session commands
Section titled “Session commands”meetings remains a compatibility alias for sessions. Plain-text invocations emit a deprecation warning when the alias is used; --json output remains machine-readable.
| Command | Options | Result |
|---|---|---|
sessions list | --query TEXT, --limit 1..200, --offset NUMBER, --tag NAME, --untagged | Meetings ordered by the application query layer. Defaults to 20 results. --tag filters to meetings carrying that tag (case-insensitive); repeatable, and all given tags must match. --untagged keeps only meetings without tags and cannot be combined with --tag. Each meeting’s JSON includes its normalized tags. |
sessions search [QUERY] | --speaker TEXT, --kind title|note|summary|transcript, --limit 1..50, --offset NUMBER | Full-text hits across titles, notes, summaries, and transcript words, newest meetings first. Requires a query and/or --speaker; --speaker limits hits to meetings where that person spoke. --kind is repeatable and defaults to all. |
sessions get ID | None | Metadata, canonical note, summaries, and action items. |
sessions new | --title TEXT (required), --note FILE, --created-at RFC3339, --started-at RFC3339, --ended-at RFC3339, --tag NAME, --author NAME, --skill NAME | Creates a meeting note in the vault and prints its id. --note seeds the note body from FILE, or from stdin when FILE is -. --created-at backdates the meeting on the timeline and in its folder name — useful when importing historical notes; --started-at and --ended-at set the meeting’s start and end. All three take an RFC 3339 timestamp such as 2024-05-01T09:00:00Z (offsets are normalized to UTC); invalid values are rejected before anything is written. --tag is repeatable and both tags the meeting and registers new tags in the vault’s tag list. --author records who wrote the note in the meeting’s metadata; when writing on behalf of someone other than the vault owner (an agent, for example claude-code), always set it — the app marks such meetings as not written by the owner. Left unset, the note counts as the vault owner’s own. --skill additionally records the skill used to produce the note (for example meeting-summarizer); it requires --author and is omitted when no skill was involved. |
sessions note ID | --kind note|summary|all, --set FILE, --append FILE | The selected note documents. Defaults to note. With --set or --append (mutually exclusive, and incompatible with --kind), replaces or extends the note body from FILE or stdin (-); fails when the meeting does not exist. |
sessions transcript ID | None | The full transcript as [HH:MM:SS] Speaker: ... lines, one per speaker turn. |
sessions tag add ID TAG... | None | Adds one or more tags to the meeting and registers new ones in the vault’s tag registry. Tags are normalized (trimmed, # stripped, lowercased) and stored deduplicated and sorted; adding a tag the meeting already has is a no-op. Prints the meeting’s resulting tag list. |
sessions tag remove ID TAG... | None | Removes one or more tags from the meeting. Removing an absent tag is a no-op, and removed tags stay in the vault’s tag registry. Prints the meeting’s resulting tag list. |
sessions path ID | None | Prints the absolute path of the meeting’s session directory. |
sessions attach ID FILE | --name NAME | Stores FILE as a note attachment of the meeting and prints the resulting attachment id. --name overrides the stored filename (defaults to the file’s name). Notes reference attachments as  with the id URL-encoded; the printed attachment id is authoritative — it may differ from the input name when an existing attachment of the same name forces a deduplicated one. |
sessions export ID | --format markdown|json, --output FILE, --force | A complete meeting export, including transcripts. Defaults to Markdown on stdout. Existing files require --force, which is only valid together with --output. |
Tags command
Section titled “Tags command”loofah tags listLists every tag registered in the vault’s tags.json, one name per line (--json returns each tag’s id and name). The registry is append-only: tags stay listed after the last meeting carrying them loses the tag.
Import command
Section titled “Import command”loofah import recording.m4a --title "Weekly sync"loofah import recording.m4a --transcribeloofah import recording.m4a --into MEETING_IDCreates a meeting from an audio file and prints its id. The audio is converted to the vault’s 16 kHz MP3 format, exactly as the desktop app’s import does, so a running app picks the meeting up automatically. Accepts wav, mp3, ogg, mp4, m4a, flac, webm, and aac files; --title defaults to the audio file’s name.
--created-at, --started-at, and --ended-at take RFC 3339 timestamps (normalized to UTC, rejected before anything is written when invalid) and set the new meeting’s metadata — --created-at backdates it on the timeline and in its folder name, which is what you want when importing a historical recording. --author NAME records who created the meeting; agents importing on a user’s behalf should always set it, and --skill NAME additionally records the skill used, if any (see sessions new). Because they describe a new meeting, all of these are rejected together with --into.
With --into MEETING_ID, the audio is imported into that existing meeting instead of creating a new one — for example a note created earlier with sessions new. The meeting keeps its title (--title is rejected together with --into), and the command fails without touching anything when the meeting does not exist or already has a recording; the CLI never replaces existing audio.
With --transcribe, the imported audio is transcribed immediately (see the transcribe command below). When transcription fails after a successful import, the command still reports the meeting id — plain output prints the id, --json adds a transcript_error object to data — and exits non-zero.
Transcribe command
Section titled “Transcribe command”loofah transcribe MEETING_IDTranscribes the meeting’s audio recording on-device with the speech-to-text model configured in the desktop app and replaces the meeting’s transcript, exactly as the app’s own batch transcription does. Prints the new transcript id (--json returns the meeting id plus a transcript object). Progress is written to stderr. The app’s audio retention setting is honored: with retention set to “none”, the recording is deleted as soon as the transcript is saved, just like in the app.
The command fails with a clear message and a non-zero exit code when the meeting or its audio is missing, when no speech-to-text model is configured, when the configured provider or model is not supported by the CLI (only on-device soniqo-* models are), or when the model has not been downloaded yet — the CLI never downloads models, so open the desktop app once to download it. On-device transcription requires macOS on Apple Silicon.
JSON response contract
Section titled “JSON response contract”Successful --json responses contain:
| Field | Meaning |
|---|---|
schema_version | CLI JSON contract version. Currently 1. |
command | Stable command identifier such as meetings.list. |
data | Command result. |
pagination | Page metadata when the command is paginated. |
Pagination includes offset, limit, returned, optional total, and optional next_offset.
Doctor command
Section titled “Doctor command”loofah --json doctorChecks the resolved vault path and read access to its sessions without changing meeting data.
It exits with status 0 when ready is true and status 1 when ready is false.
Inside a vault it also restores the root AGENTS.md agent guide when the file is missing or stale.
MCP command
Section titled “MCP command”loofah mcpStarts the read-only MCP server over stdio. Do not write other output to the server’s stdout.
Help and version
Section titled “Help and version”loofah --helploofah sessions --helploofah sessions list --helploofah --version