ainvil is a Go-based command-line tool for standardizing, processing, and exporting data from multiple pendant recording sources.
It supports merging different export formats into a consistent JSON structure for easy archiving, search, and downstream processing.
-
Import ChatGPT meeting transcripts from plain
.txt
files -
Process text exports from Omi and Bee pendant formats (more to come!)
-
Fetch and export lifelogs from the Limitless API
-
Unified, consistent JSON schema
-
Organized date-based output folders
-
Incremental sync: auto-detects last saved lifelog and fetches only new entries
-
Extensible design for new source types
CHATGPT
You can export transcripts from ChatGPT meeting recordings as plain
.txt
files. Just drop them into a folder and runainvil chatgpt --source path/to/folder --out path/to/output
.
LIMITLESS
For the limitless pendant, it is easy. Just use Ainvil to connect to the API using the baseurl and your API token
OMI
The Omi is a bit more involved. You can export a number of ways, but the most efficient I have found is to subscribe to the Google Drive plugin and just grab the source files from there. I am sure there are better, more efficient ways (especially is you use your own backend) are out there, please share your ideas!
BEE
The Bee is the most tedious. You have to go into each day, click into each transcript, then choose "Save To File" and save it somewhere. for simplicity you can just save them to an iCloud drive, so you can grab them on your computer. Not ideal, but works for now
├── LICENSE
├── README.md
├── cmd
│ ├── bee.go
│ ├── chatgpt.go
│ ├── limitless.go
│ ├── omi.go
│ ├── root.go
│ └── version.go
├── common
│ ├── models.go
│ ├── parser_bee.go
│ ├── parser_chatgpt.go
│ ├── parser_limitless.go
│ ├── parser_omi.go
│ ├── processor.go
│ └── utils.go
├── go.mod
├── go.sum
├── main.go
├─ out/
(generated JSON output)
├─ source/
(source files)
Clone the repo:
git clone https://github.com/sottey/ainvil.git
cd ainvil
Build:
go build -o ainvil
Or install directly:
go install github.com/sottey/ainvil@latest
After building, you can run:
./ainvil [command] [flags]
Each command writes standardized JSON files under:
out/
YYYY/
MM/
DD/
[sourceType]_[ID].json
Process Omi pendant .txt
files into standardized JSON.
ainvil omi --source ./omi_exports --out ./out
Flags:
--source
(required): Directory containing.txt
files.--out
: Output root directory (default./out
).
Process Bee pendant .txt
files into standardized JSON.
ainvil bee --source ./bee_exports --out ./out
Flags:
--source
(required): Directory containing.txt
files.--out
: Output root directory (default./out
).
Fetch lifelogs from the Limitless API.
ainvil limitless --token YOUR_API_KEY --url API_ENDPOINT --out ./out
Flags:
--token
(required): Your Limitless API key.--url
(required): Base API URL.--start
: Start date (RFC3339). Optional. If omitted, tool auto-detects last saved date from existing JSON.--end
: End date (RFC3339). Optional.--out
: Output root directory (default./out
).
Example with incremental sync:
ainvil limitless --token YOUR_API_KEY --url https://api.limitless.ai/v1/logs
If you omit --start
, it will scan existing output for the most recent saved lifelog and fetch only newer ones.
out/
2025/
05/
30/
omi_abc123.json
2025/
05/
30/
bee_xyz456.json
2025/
05/
30/
limitless_789def.json
Each JSON contains a standardized structure:
{
"id": "...",
"sourceType": "...",
"startTime": "...",
"endTime": "...",
"title": "...",
"overview": "...",
"transcript": "...",
"contents": [
{ "type": "heading1", "content": "..." },
...
],
"exportDate": "...",
"exportVersion": "ainvil 2.0.0",
"sourceFile": "..."
}
- Config file support (Viper)
- --dry-run mode for previews
- Logging levels (--verbose / --quiet)
- Index file generation
- List / Show subcommands
- Unit tests for parsing
Run locally:
go run main.go [command] [flags]
Format code:
go fmt ./...