bcbd1bdb22
Integ / changes (push) Has been skipped
Pre-commit / pre-commit (push) Failing after 1s
CLI exit codes / changes (push) Has been skipped
Test (Install) / changes (push) Has been skipped
Test (Python) / changes (push) Has been skipped
Test (TypeScript) / changes (push) Has been skipped
CLI exit codes / cli-gate (push) Has been cancelled
Test (Install) / test-install-gate (push) Has been cancelled
Integ / integ-gate (push) Has been cancelled
Test (Python) / test-python-gate (push) Has been cancelled
Test (TypeScript) / test-typescript-gate (push) Has been cancelled
Test (Install) / python-minimal (3.12) (push) Has been cancelled
Test (Install) / python-minimal (3.11) (push) Has been cancelled
Test (Install) / python-extra (agno, mirage.agents.agno) (push) Has been cancelled
Test (Install) / python-extra (chroma, mirage.resource.chroma) (push) Has been cancelled
Test (Install) / python-extra (pdf, mirage.core.filetype.pdf) (push) Has been cancelled
Integ / integ (push) Has been cancelled
Integ / integ-database (push) Has been cancelled
Integ / integ-database-ts (push) Has been cancelled
Integ / integ-data (push) Has been cancelled
Integ / integ-ssh (push) Has been cancelled
Integ / integ-ssh-ts (push) Has been cancelled
Test (Python) / audit (push) Has been cancelled
Test (TypeScript) / test (push) Has been cancelled
Test (TypeScript) / python-fs-shim (push) Has been cancelled
CLI exit codes / Python CLI (push) Has been cancelled
CLI exit codes / TypeScript CLI (push) Has been cancelled
CLI exit codes / Cross-language snapshot interop (push) Has been cancelled
Test (Python) / test (push) Has been cancelled
Test (Python) / import-isolation (deepagents, openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Python) / import-isolation (deepagents, pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Integ / integ-ts (push) Has been cancelled
Integ / integ-fuse (push) Has been cancelled
Test (Install) / python-extra (databricks, mirage.resource.databricks_volume) (push) Has been cancelled
Test (Install) / python-extra (deepagents, mirage.agents.langchain) (push) Has been cancelled
Test (Install) / python-extra (email, mirage.resource.email) (push) Has been cancelled
Test (Install) / python-extra (fuse, mirage.fuse.mount) (push) Has been cancelled
Test (Install) / python-extra (hdf5, mirage.core.filetype.hdf5) (push) Has been cancelled
Test (Install) / python-extra (hf, mirage.resource.hf_buckets) (push) Has been cancelled
Test (Install) / python-extra (lancedb, mirage.resource.lancedb) (push) Has been cancelled
Test (Install) / python-extra (langfuse, mirage.resource.langfuse) (push) Has been cancelled
Test (Install) / python-extra (mongodb, mirage.resource.mongodb) (push) Has been cancelled
Test (Install) / python-extra (nextcloud, mirage.resource.nextcloud) (push) Has been cancelled
Test (Install) / python-extra (openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Install) / python-extra (openhands, mirage.agents.openhands, 3.12) (push) Has been cancelled
Test (Install) / python-extra (parquet, mirage.core.filetype.parquet) (push) Has been cancelled
Test (Install) / python-extra (postgres, mirage.resource.postgres) (push) Has been cancelled
Test (Install) / python-extra (pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Test (Install) / python-extra (qdrant, mirage.resource.qdrant) (push) Has been cancelled
Test (Install) / python-extra (redis, mirage.resource.redis) (push) Has been cancelled
Test (Install) / python-extra (s3, mirage.resource.s3) (push) Has been cancelled
Test (Install) / python-extra (ssh, mirage.resource.ssh) (push) Has been cancelled
Test (Install) / ts-minimal (push) Has been cancelled
269 lines
8.5 KiB
Plaintext
269 lines
8.5 KiB
Plaintext
---
|
|
title: Notion
|
|
icon: book
|
|
description: Mount Notion pages as a virtual filesystem.
|
|
---
|
|
The Notion resource exposes a Notion workspace as a virtual filesystem
|
|
mounted at a prefix such as `/notion/`.
|
|
|
|
For API key setup, see [Notion Setup](/python/setup/notion).
|
|
|
|
## Config
|
|
|
|
```python
|
|
import os
|
|
|
|
from mirage import MountMode, Workspace
|
|
from mirage.resource.notion import NotionConfig, NotionResource
|
|
|
|
config = NotionConfig(api_key=os.environ["NOTION_API_KEY"])
|
|
resource = NotionResource(config=config)
|
|
ws = Workspace({"/notion": resource}, mode=MountMode.WRITE)
|
|
```
|
|
|
|
| Field | Required | Default | Description |
|
|
| ---------- | -------- | ------------------------------ | ----------------------- |
|
|
| `api_key` | yes | | Notion integration token |
|
|
| `base_url` | no | `https://api.notion.com/v1` | API base URL |
|
|
|
|
## Filesystem Layout
|
|
|
|
```text
|
|
/notion/
|
|
pages/
|
|
<page-title>__<page-id>/
|
|
page.json
|
|
<child-page-title>__<child-id>/
|
|
page.json
|
|
...
|
|
databases/
|
|
<database-title>__<database-id>/
|
|
database.json
|
|
<row-page-title>__<page-id>/
|
|
page.json
|
|
...
|
|
```
|
|
|
|
Example:
|
|
|
|
```text
|
|
/notion/
|
|
pages/
|
|
Project-Roadmap__a1b2c3d4/
|
|
page.json
|
|
Q1-Goals__e5f6g7h8/
|
|
page.json
|
|
Q2-Goals__i9j0k1l2/
|
|
page.json
|
|
Meeting-Notes__m3n4o5p6/
|
|
page.json
|
|
databases/
|
|
Tasks__4a3b21915e77/
|
|
database.json
|
|
Write-proposal__62212c5affe6/
|
|
page.json
|
|
Build-dashboards__f988c5a145ef/
|
|
page.json
|
|
Roadmap__2c4d6a7f5bf3/
|
|
database.json
|
|
```
|
|
|
|
The `pages/` hierarchy mirrors Notion's standalone page tree. The
|
|
`databases/` hierarchy lists databases shared with the integration and
|
|
then the row pages returned by querying each database. Each database
|
|
directory contains `database.json` with the database metadata and its
|
|
typed property schema (the columns), but not the rows themselves; the
|
|
rows are the row-page directories alongside it, so `ls` the database
|
|
directory to enumerate them. Each page directory contains a `page.json`
|
|
file with the page metadata and content. Child pages appear as nested
|
|
directories.
|
|
|
|
`page.json` carries the page metadata (`page_id`, `title`, `url`,
|
|
timestamps, `parent_type`/`parent_id`, `created_by`/`last_edited_by`),
|
|
a `markdown` field with the page body rendered as Markdown, and the raw
|
|
`blocks`. Blocks with children embed them recursively under a
|
|
`children` key, and the Markdown renders nested blocks with
|
|
indentation.
|
|
|
|
`database.json` carries the database metadata (`database_id`, `title`,
|
|
`url`, timestamps, `parent`, `archived`, `is_inline`) and `properties`,
|
|
the database's typed column schema. It does not embed the rows; read a
|
|
row's `page.json` for its content, since a database row is itself a page
|
|
with `parent_type` of `database_id`.
|
|
|
|
### database.json
|
|
|
|
The database's identity plus its typed column schema (Notion's own
|
|
property objects), with no rows inline. `ls` the database directory to
|
|
enumerate row pages:
|
|
|
|
```json
|
|
{
|
|
"database_id": "2c4d6a7f-5bf3-8036-bed2-d1c95826f76b",
|
|
"title": "Item",
|
|
"url": "https://www.notion.so/2c4d6a7f5bf38036bed2d1c95826f76b",
|
|
"created_time": "2025-12-09T23:36:00.000Z",
|
|
"last_edited_time": "2026-04-15T12:30:00.000Z",
|
|
"parent": { "type": "workspace", "workspace": true },
|
|
"archived": false,
|
|
"is_inline": false,
|
|
"properties": {
|
|
"Name": { "id": "title", "type": "title", "title": {} },
|
|
"Number": { "id": "e%5BNQ", "type": "number", "number": { "format": "number" } },
|
|
"Date": { "id": "%3BgQq", "type": "date", "date": {} }
|
|
}
|
|
}
|
|
```
|
|
|
|
To create a row, `notion-page-create` with a `database_id` parent and a
|
|
`properties` object whose keys match this schema.
|
|
|
|
### page.json
|
|
|
|
A page (including a database row). Notion blocks render to `markdown`
|
|
and stay available raw under `blocks`:
|
|
|
|
```json
|
|
{
|
|
"page_id": "2c4d6a7f-5bf3-8022-826b-ed4700254ed2",
|
|
"title": "item_0",
|
|
"url": "https://www.notion.so/item_0-2c4d6a7f5bf38022826bed4700254ed2",
|
|
"created_time": "2025-12-09T23:36:00.000Z",
|
|
"last_edited_time": "2025-12-09T23:44:00.000Z",
|
|
"parent_type": "database_id",
|
|
"parent_id": "2c4d6a7f-5bf3-8036-bed2-d1c95826f76b",
|
|
"archived": false,
|
|
"created_by": "faa6ebe0-0686-466d-96b3-2480ddda715b",
|
|
"last_edited_by": "faa6ebe0-0686-466d-96b3-2480ddda715b",
|
|
"markdown": "",
|
|
"blocks": []
|
|
}
|
|
```
|
|
|
|
## Cache
|
|
|
|
Uses `IndexCacheStore` for page metadata. No separate content
|
|
cache - file content caching is handled by the workspace `IOResult`
|
|
mechanism.
|
|
|
|
## Example
|
|
|
|
```python
|
|
import asyncio
|
|
import os
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
from mirage import MountMode, Workspace
|
|
from mirage.resource.notion import NotionConfig, NotionResource
|
|
|
|
load_dotenv(".env.development")
|
|
|
|
config = NotionConfig(api_key=os.environ["NOTION_API_KEY"])
|
|
resource = NotionResource(config=config)
|
|
|
|
|
|
async def main():
|
|
ws = Workspace({"/notion": resource}, mode=MountMode.WRITE)
|
|
|
|
# List top-level pages
|
|
r = await ws.execute("ls /notion/pages/")
|
|
print(await r.stdout_str())
|
|
|
|
# List shared databases and rows in a database
|
|
r = await ws.execute("ls /notion/databases/")
|
|
print(await r.stdout_str())
|
|
|
|
# Read a page
|
|
r = await ws.execute(
|
|
'cat "/notion/pages/Project-Roadmap__a1b2c3d4/page.json"'
|
|
)
|
|
print(await r.stdout_str())
|
|
|
|
# Search across all pages
|
|
r = await ws.execute('grep "deadline" /notion/pages/')
|
|
print(await r.stdout_str())
|
|
|
|
# Tree view
|
|
r = await ws.execute("tree -L 2 /notion/")
|
|
print(await r.stdout_str())
|
|
|
|
# Search pages with the Notion search API
|
|
r = await ws.execute('notion-search --query "Roadmap" --limit 5')
|
|
print(await r.stdout_str())
|
|
|
|
# Create a new page
|
|
r = await ws.execute(
|
|
'notion-page-create --json \'{"parent":{"page_id":"a1b2c3d4"},'
|
|
'"properties":{"title":[{"text":{"content":"New Page"}}]}}\''
|
|
)
|
|
print(await r.stdout_str())
|
|
|
|
# Append content to an existing page
|
|
r = await ws.execute(
|
|
'notion-block-append --params \'{"block_id":"a1b2c3d4"}\''
|
|
' --json \'{"children":[{"type":"paragraph","paragraph":'
|
|
'{"rich_text":[{"text":{"content":"Appended paragraph"}}]}}]}\''
|
|
)
|
|
print(await r.stdout_str())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|
|
```
|
|
|
|
## Shell Commands
|
|
|
|
Standard commands available on the mounted Notion tree:
|
|
|
|
| Command | Notes |
|
|
| --------------- | ------------------------------------------ |
|
|
| `ls` | List pages and child pages |
|
|
| `cat` | Read page.json content |
|
|
| `head` / `tail` | First/last N lines |
|
|
| `grep` / `rg` | Search across pages |
|
|
| `jq` | Query page JSON fields |
|
|
| `wc` | Line/word/byte counts |
|
|
| `stat` | File metadata |
|
|
| `find` | Recursive search with `-name`, `-maxdepth` |
|
|
| `tree` | Directory tree view |
|
|
|
|
Resource-specific commands:
|
|
|
|
### `notion-page-create`
|
|
|
|
Create a new page under a parent page. Prints the new page normalized as JSON.
|
|
|
|
| Option | Required | Description |
|
|
| -------- | -------- | ---------------------------------------------------------------------- |
|
|
| `--json` | yes | Page body with `parent` (required) and `properties`, per the Notion API |
|
|
|
|
In the TypeScript SDK this command takes `--parent <parent-path>` and
|
|
`--title "title"` instead of a raw `--json` body.
|
|
|
|
### `notion-block-append`
|
|
|
|
Append content blocks to an existing page. Prints the refreshed page as JSON.
|
|
|
|
| Option | Required | Description |
|
|
| ---------- | -------- | ------------------------------------------------- |
|
|
| `--params` | yes | JSON object with the target `block_id` (page ID) |
|
|
| `--json` | yes | JSON object with the `children` blocks to append |
|
|
|
|
### `notion-comment-add`
|
|
|
|
Add a comment to a page. Prints the created comment as JSON.
|
|
|
|
| Option | Required | Description |
|
|
| -------- | -------- | ---------------------------------------------------- |
|
|
| `--json` | yes | Comment body with `parent` (required) and `rich_text` |
|
|
|
|
### `notion-search`
|
|
|
|
Search pages with the Notion search API.
|
|
|
|
| Option | Required | Description |
|
|
| --------- | -------- | ---------------------------- |
|
|
| `--query` | yes | Search query |
|
|
| `--limit` | no | Max results (default 20) |
|