chore: import upstream snapshot with attribution
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
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
This commit is contained in:
@@ -0,0 +1,268 @@
|
||||
---
|
||||
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) |
|
||||
Reference in New Issue
Block a user