Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 12:30:44 +08:00

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) |