A command-line tool to import your Daylio journal entries into a self-hosted Memos instance.
Before importing, enable "Display edited time" in Memos so that historical entry dates are shown in the timeline and calendar:
Settings → System → Display with updated time (toggle on)
Without this, all imported memos will appear with today's date in the timeline, even though the correct original date is stored internally.
| Daylio data | Memos result |
|---|---|
| Entry note text | Memo content body |
Entry title (note_title) |
First line of memo content |
| Entry date & time | Memo displayTime (set at creation + confirmed via PATCH) |
| Activities / tags | #tagname hashtags appended to content |
| Mood | #mood-rad / #mood-good / #mood-meh / #mood-bad / #mood-awful hashtag |
| HTML formatting in notes | Converted to Markdown (<b> → bold, <br> → newline, etc.) |
| All imported entries | #daylio-import marker tag |
- Photos / assets — entries with attached photos are imported as text only; a warning is printed for each affected entry.
- Goals — Daylio's goal-tracking data has no equivalent in Memos.
- Python 3.8 or later
- A running Memos instance with API access
- Your Memos API token (Settings → API Tokens)
git clone https://github.com/jshields-ca/daylio-to-memos-import.git
cd daylio-to-memos-import
pip install -r requirements.txt- Open Daylio on your phone
- Go to More → Backup & Restore → Export (or Advanced Backup)
- Save the
.dayliofile and transfer it to your computer
python import.py --daylio backup.daylio \
--memos-url https://memos.example.com \
--token YOUR_MEMOS_API_TOKEN| Flag | Default | Description |
|---|---|---|
--daylio FILE |
(required) | Path to the .daylio backup file |
--memos-url URL |
(required) | Base URL of your Memos instance |
--token TOKEN |
$MEMOS_TOKEN |
Memos API bearer token |
--visibility |
PRIVATE |
Visibility of imported memos: PRIVATE, PROTECTED, or PUBLIC |
--dry-run |
off | Preview what would be imported without making any API calls |
--skip-mood |
off | Omit the #mood-X hashtag from memo content |
--skip-tags |
off | Omit Daylio activity tags as hashtags from memo content |
--skip-empty |
off | Skip entries that have no note or title (mood/check-in only entries) |
--delay SECONDS |
0.5 |
Pause between API calls — use 0 to disable |
| Flag | Default | Description |
|---|---|---|
--state-file PATH |
daylio-import-state.json |
Path to the local state file that tracks imported entries across runs |
--ignore-state |
off | Import all entries regardless of the state file (state file is still updated) |
--no-state |
off | Disable state tracking entirely — no dedup, no state file read or written |
| Flag | Default | Description |
|---|---|---|
--delete-imported |
off | Delete all memos tagged #daylio-import from Memos. Interactive — requires typing YES to confirm. --daylio is not required when this flag is used. Combine with --dry-run to preview what would be deleted. |
1. Preview with --dry-run
python import.py --daylio backup.daylio \
--memos-url https://memos.example.com \
--token YOUR_TOKEN \
--dry-runPrints every entry's content and timestamp without touching your Memos instance. Review the output to confirm tags, moods, and formatting look correct before committing.
2. Enable "Display edited time" in Memos
Go to Settings → System and enable Display with updated time. This ensures the timeline and calendar show the original Daylio entry dates instead of the import date.
3. Run the real import
python import.py --daylio backup.daylio \
--memos-url https://memos.example.com \
--token YOUR_TOKENAll entries are imported oldest-first as PRIVATE memos by default. A local state file (daylio-import-state.json) is created to prevent duplicates if you re-run.
4. Verify in Memos
Search for #daylio-import in Memos to see all imported entries. Check a few entries to confirm the dates, tags, and content look correct.
If you need to undo an import or start fresh:
# Preview what would be deleted (no changes made)
python import.py --memos-url https://memos.example.com \
--token YOUR_TOKEN \
--delete-imported --dry-run
# Actually delete (interactive — prompts for YES confirmation)
python import.py --memos-url https://memos.example.com \
--token YOUR_TOKEN \
--delete-importedYou will also be offered the option to clear the local state file so you can re-import cleanly.
The state file (daylio-import-state.json by default) tracks which entries have been imported by their Daylio timestamp. On subsequent runs, already-imported entries are automatically skipped. The summary line shows how many were skipped:
Import complete: 502 succeeded, 0 failed, 360 skipped (empty), 0 skipped (already imported).
To force a full re-import (e.g. after deleting all memos and clearing the state file):
python import.py --daylio backup.daylio \
--memos-url https://memos.example.com \
--token YOUR_TOKEN \
--no-stateexport MEMOS_TOKEN=your_token_here
python import.py --daylio backup.daylio --memos-url https://memos.example.comMemos uses two steps to set historical entry dates:
- POST
/api/v1/memos— creates the memo withdisplayTimeset to the original Daylio entry date - PATCH
/api/v1/{memo_name}— confirmsdisplayTimevia the API update mask
If the PATCH step fails for any reason, you will see a WARN message in the output. The memo is still imported; only the display date may show as today's date in that case.
Note: Memos must be configured to show
displayTimein the timeline. Enable "Display with updated time" in Settings → System to ensure the original Daylio dates appear rather than the server import time.
If entries fail with an HTTP 400 "content too long" error, increase Memos's content length limit: Settings → System → Content length limit (byte) — set to 15000 or higher.
- No bulk import API in Memos — entries are created one-by-one; large imports may take several minutes
- Photo/asset import not supported — only the text content of entries is imported
- Timestamp display requires a Memos setting — enable "Display with updated time" in Memos → Settings → System
MIT — see LICENSE
Created by jshields-ca · scootr.ca
Found a bug or have a feature request? Please open a GitHub issue. Pull requests are welcome — see the issues list for ideas, or open one to discuss your change before submitting.
This script was developed with the assistance of AI tools (Claude by Anthropic) for code generation, debugging, and testing. All code has been reviewed and tested against a live Memos instance.