Skip to main content

NoteShift (noteshift)

NoteShift exports Notion content to Obsidian-friendly Markdown with predictable filenames, link rewriting, and checkpoint/resume support.

CI PyPI Python Versions codecov

Why it exists

Teams migrating from Notion to Obsidian consistently report four pains:

  1. broken internal links after export
  2. inconsistent filenames and folder layout
  3. long exports failing midway without resume
  4. 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

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.json for resume
  • migration_report.json
  • migration_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)

Source distribution for noteshift 0.2.0
File Size Uploaded
noteshift-0.2.0.tar.gz 18.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for noteshift 0.2.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page