Turn Microsoft OneNote notebooks into clean Markdown your AI agents can actually use.
onenote-md exports OneNote notebooks, sections, pages, metadata, and best-effort assets into a stable Markdown directory for tools like OpenClaw, GBrain, and other local-first agent memory systems.
OneNote is useful for capturing years of notes, but AI agents work better with portable, plain-text, file-based context. This project bridges that gap:
OneNote → Microsoft Graph → Markdown tree → GBrain/OpenClaw/agent memoryPrototype, but functional:
- Microsoft Graph delegated device-code auth
- list notebooks, sections, and pages
- export/sync pages to Markdown
- GBrain-friendly output preset
- YAML frontmatter with source IDs, URLs, timestamps, and content hashes
- best-effort image/resource download
- manifest-based incremental sync
- packaged OpenClaw skill wrapper
git clone https://github.com/adamdaum/onenote-md.git
cd onenote-md
npm install
npm run build
cp .env.example .envSet your Microsoft app registration client ID:
export ONENOTE_MD_CLIENT_ID="<application-client-id>"
export ONENOTE_MD_TENANT_ID="common" # optionalSign in and inspect OneNote:
node dist/cli.js auth login
node dist/cli.js auth status
node dist/cli.js list notebooksExport everything visible to the signed-in account:
node dist/cli.js sync --out ./exports/onenote --preset gbrainImport into GBrain if available:
gbrain import ./exports/onenoteRequired delegated Microsoft Graph permissions:
User.ReadNotes.Readoffline_access
No client secret is required. This is a public-client CLI using delegated auth.
# Local readiness
node dist/cli.js doctor
# Auth
node dist/cli.js auth login
node dist/cli.js auth status
node dist/cli.js auth logout
# Discovery
node dist/cli.js list notebooks
node dist/cli.js list sections --notebook-id "<notebook-id>"
node dist/cli.js list pages --section-id "<section-id>"
# Export/sync
node dist/cli.js sync --out ./exports/onenote --preset gbrain
node dist/cli.js sync --notebook "Personal" --out ./exports/onenote --preset gbrain
node dist/cli.js sync --section-id "<section-id>" --out ./exports/onenote --preset gbrain
# Safe smoke test
node dist/cli.js sync --out ./exports/onenote --preset gbrain --limit 5 --dry-run
# Regenerate unchanged pages after converter changes
node dist/cli.js sync --out ./exports/onenote --preset gbrain --force
# Skip asset download
node dist/cli.js sync --out ./exports/onenote --preset gbrain --no-assetsWith --preset gbrain:
exports/onenote/
manifest.json
sources/
onenote/
<notebook>/
<section>/
<date-title>.md
assets/
...Example Markdown frontmatter:
---
type: source_note
source: onenote
notebook: Personal Notes
section: AI Ideas
title: Project Idea
created: '2026-04-01T12:00:00Z'
modified: '2026-04-24T18:00:00Z'
onenote_page_id: ...
onenote_web_url: ...
content_hash: sha256:...
tags:
- onenote
- imported
---See examples/sample-gbrain-export for sanitized example output.
See docs/GBRAIN_OPENCLAW_WORKFLOW.md.
Packaged OpenClaw skill:
dist-skills/onenote-md-ingest.skillSkill source:
skills/onenote-md-ingest/For converter development without Microsoft auth:
node dist/cli.js convert fixtures/sample-page.html \
--title "Project Idea" \
--notebook "Personal Notes" \
--section "AI Ideas" \
--preset gbrain \
--out ./examples/sample-gbrain-exportnpm install
npm run checknpm run check runs TypeScript build and Vitest tests.
- This is not a full OneNote backup/restore tool.
- Asset handling is best-effort and depends on Microsoft Graph resource URLs in returned page HTML.
- Deleted/moved OneNote pages are not pruned from existing exports yet.
- Handwriting/OCR behavior has not been deeply tested.
- GBrain import is documented/wrapped, not embedded as a runtime dependency.
docs/PROJECT_BRIEF.mddocs/RESEARCH_SPIKE_001.mddocs/MICROSOFT_AUTH.mddocs/GBRAIN_OPENCLAW_WORKFLOW.mddocs/RELEASE_CHECKLIST.md
MIT © Adam Daum. Built by Adam Daum / Weststack, LLC.