NoteShift (noteshift)
NoteShift exports Notion content to Obsidian-friendly Markdown with predictable filenames, link rewriting, and checkpoint/resume support.
Why it exists
Teams migrating from Notion to Obsidian consistently report four pains:
- broken internal links after export
- inconsistent filenames and folder layout
- long exports failing midway without resume
- low confidence in migration correctness
NoteShift is focused on solving those pains first.
Current capabilities
- Export a Notion page tree to Markdown
- Export Notion data sources/databases through API layer
- Rewrite internal links for Obsidian compatibility
- Preserve and download attachments
- Resume interrupted runs via checkpoint file
- Emit migration report (
migration_report.json+.md) - Optionally emit YAML frontmatter with Notion metadata in each exported page
Documentation
- Docs index:
docs/ - Start here: Getting started
- Library integration: API contract
Installation
Install from PyPI
uv tool install noteshift
# or
pipx install noteshift
Install from source (development)
uv tool install .
uv sync --extra dev --extra test
Authentication
Set a Notion integration token in NOTION_TOKEN.
export NOTION_TOKEN="secret_xxx"
Basic usage
noteshift export \
--page-id "<notion-page-id>" \
--out ./export \
--max-depth 2 \
--overwrite
Frontmatter
Pass --frontmatter to include YAML frontmatter at the top of every exported markdown file:
noteshift export \
--page-id "<notion-page-id>" \
--out ./export \
--frontmatter
Each index.md will begin with a block like:
---
notionId: "abc12345-..."
notionUrl: "https://www.notion.so/..."
createdAt: "2024-01-01T10:00:00.000Z"
updatedAt: "2024-06-15T14:30:00.000Z"
title: "My Page"
---
For pages that live inside a Notion database, supported property types are also included as additional keys (select, multi_select, date, checkbox, number, url, email, phone_number, rich_text). Property names are lowercased and spaces are replaced with underscores.
Frontmatter is off by default so existing exports are unaffected.
Output
A successful run writes:
- Markdown files for exported pages
- downloaded assets in the export tree
.checkpoint.jsonfor resumemigration_report.jsonmigration_report.md
Development
uv sync --extra dev --extra test
uv run ruff format .
uv run ruff check .
uv run mypy src
uv run pytest --cov=noteshift --cov-report=term
Contract tests (pytest-vcr)
Contract tests are deterministic and replay HTTP traffic from sanitized cassettes:
uv run pytest -m contract
To re-record cassettes intentionally, set a real token in your environment and run:
VCR_RECORD_MODE=once uv run pytest -m contract
License
MIT
Metadata
Release files for noteshift 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| noteshift-0.2.0.tar.gz | 18.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| noteshift-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 43.3 kB
Release files / noteshift-0.2.0.tar.gz
| Download URL | noteshift-0.2.0.tar.gz |
|---|---|
| Size | 18.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fdf31ad26ec947485f6b902365230d7b107b64928fdb6096668ae5445b6659fd
|
|
BLAKE2b-256 checksum How to use checksums |
1db5f9dce3c4c941560aef4cd7961ffff25e5cd26c1d05aa47fe9b8e1447f951
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 26, 2026.
Transparency logRelease files / noteshift-0.2.0-py3-none-any.whl
| Download URL | noteshift-0.2.0-py3-none-any.whl |
|---|---|
| Size | 24.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cede87a7170f24625235054be6ba210098f78fd2e38d6fd3276641250d71acb8
|
|
BLAKE2b-256 checksum How to use checksums |
3ef82e7e92d6647bb9f62eff3585b449b909162a4422e6e1fbbad9bbaf4ce193
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 26, 2026.
Transparency log