otterai-cli 0.1.2
Unofficial Otter.ai CLI
Requires Python: >=3.10

# otterai-cli

An unofficial command-line interface for [Otter.ai](https://otter.ai).

> **Note:** This project is not affiliated with or endorsed by Otter.ai / Aisense Inc.

## Requirements

- Python 3.10+

## Installation

```bash
uv tool install otterai-cli
```

This makes the `otter` command available globally.

To update to the latest version:

```bash
uv tool upgrade otterai-cli
```

Or run directly without installing:

```bash
uvx --from otterai-cli otter --help
```

## Setup

```bash
otter login
```

Credentials are stored in your OS keychain (macOS Keychain, Windows Credential Locker, etc.) via [keyring](https://pypi.org/project/keyring/), with `~/.otterai/config.json` as fallback.

You can also use environment variables (`OTTERAI_USERNAME`, `OTTERAI_PASSWORD`), which take highest precedence.

### Auth commands

```bash
otter user      # check current user
otter logout    # remove saved credentials
```

## Usage

```bash
otter speeches list                          # list all speeches
otter speeches list --days 7                 # last 7 days
otter speeches list --folder "Work"          # by folder name
otter speeches get SPEECH_ID                 # get speech details + transcript
otter speeches download SPEECH_ID -f txt     # download as txt, pdf, mp3, docx, srt, or md
otter speeches search "keyword" SPEECH_ID    # search within a speech
otter speakers list                          # list all speakers
otter folders list                           # list all folders
```

Run `otter --help` or `otter <command> --help` for more options.

### Important: Speech IDs (otid vs speech_id)

Otter.ai speeches have two identifiers:
- **`speech_id`** (e.g. `22WB27HAEBEJYFCA`) -- internal ID, does **NOT** work with API endpoints
- **`otid`** (e.g. `jqb7OHo6mrHtCuMkyLN0nUS8mxY`) -- the ID used in all API calls

All CLI commands that accept a `SPEECH_ID` argument expect the **otid** value. Use `otter speeches list` to find otids, or `otter speeches list --json | jq '.speeches[].otid'` for just the IDs.

### Speeches

```bash
# List all speeches
otter speeches list

# List with options
otter speeches list --page-size 10 --source owned

# List speeches from the last N days
otter speeches list --days 2

# List speeches in a specific folder (by name or ID)
otter speeches list --folder "CoverNode"

# Get a specific speech
otter speeches get SPEECH_ID

# Search within a speech
otter speeches search "search query" SPEECH_ID

# Download a speech (formats: txt, pdf, mp3, docx, srt, md)
otter speeches download SPEECH_ID --format txt

# Download as markdown (generated locally from transcript data)
otter speeches download SPEECH_ID --format md
otter speeches download SPEECH_ID --format md --output meeting-notes
otter speeches download SPEECH_ID --format md --frontmatter-fields "title,summary,speakers,start_time,end_time,duration_seconds,source,speech_id,folder,folder_id"

# Upload an audio file
otter speeches upload recording.mp4

# Move to trash
otter speeches trash SPEECH_ID

# Rename a speech
otter speeches rename SPEECH_ID "New Title"

# Move speeches to a folder (by name or ID)
otter speeches move SPEECH_ID --folder "CoverNode"
otter speeches move ID1 ID2 ID3 --folder "CoverNode"

# Move to a new folder (auto-create if it doesn't exist)
otter speeches move SPEECH_ID --folder "New Folder" --create
```

#### Markdown frontmatter (`--format md`)

Markdown export includes YAML frontmatter, configurable per download:

```bash
# Use defaults
otter speeches download SPEECH_ID --format md

# Pick exact fields (in your own order)
otter speeches download SPEECH_ID --format md --frontmatter-fields "title,speech_id,summary"

# Disable all frontmatter fields
otter speeches download SPEECH_ID --format md --frontmatter-fields none
```

Default frontmatter fields (in order):
1. `title`
2. `summary`
3. `speakers`
4. `start_time`
5. `end_time`
6. `duration_seconds`
7. `source`
8. `speech_id`
9. `folder`
10. `folder_id`

Available frontmatter fields for `--frontmatter-fields`:
- `title`
- `summary`
- `speakers`
- `start_time`
- `end_time`
- `duration_seconds`
- `source`
- `speech_id`
- `folder`
- `folder_id`
- `otid`
- `created_at`
- `transcript_updated_at`
- `language`
- `transcript_count`
- `process_status`

Notes:
- `--frontmatter-fields` is valid only with `--format md`.
- `speech_id` in frontmatter is the Otter internal `speech_id`; command argument `SPEECH_ID` still expects the `otid`.

### Speakers

```bash
# List all speakers
otter speakers list

# Create a new speaker
otter speakers create "Speaker Name"

# Tag a speaker on transcript segments
otter speakers tag SPEECH_ID SPEAKER_ID
otter speakers tag SPEECH_ID SPEAKER_ID --all
```

### Folders and Groups

```bash
# List folders
otter folders list

# Create a folder
otter folders create "My Folder"

# Rename a folder
otter folders rename FOLDER_ID "New Name"

# List groups
otter groups list
```

### Configuration

```bash
# Show current config
otter config show

# Clear saved config
otter config clear
```

### JSON Output

Most commands support `--json` flag for machine-readable output:

```bash
otter speeches list --json
otter speakers list --json
```

## Development

```bash
uv sync --dev        # install dependencies
uv run pytest        # run tests
```

## Acknowledgements

Based on [gmchad/otterai-api](https://github.com/gmchad/otterai-api) by Chad Lohrli, with CLI functionality from [PR #9](https://github.com/gmchad/otterai-api/pull/9) by [@andrewfurman](https://github.com/andrewfurman).

## License

MIT