Skip to content
This repository was archived by the owner on Aug 10, 2026. It is now read-only.

feat: add user, comment, team commands + markdown import/export + page move/duplicate - #1

Open
elyase wants to merge 9 commits into
OverseedAI:mainfrom
elyase:main
Open

elyase wants to merge 9 commits into
OverseedAI:mainfrom
elyase:main

Conversation

@elyase

@elyase elyase commented Jan 25, 2026

Copy link
Copy Markdown

Summary

This PR adds several new features to make onotion a more complete Notion CLI, inspired by features from litencatt/notion-cli and the official Notion MCP server.

New Commands

User Management

  • onotion user list - List all workspace users with pagination
  • onotion user get <user-id> - Get a specific user by ID
  • onotion user me - Get the current bot user

Comments

  • onotion comment list <page-id> - List all comments on a page
  • onotion comment add <page-id> <text> - Add a comment to a page

Teams (Enterprise)

  • onotion team list - List teams/teamspaces (gracefully handles non-enterprise)

Page Operations

  • onotion page import <file.md> - Import markdown file as a new page
  • onotion page export <page-id> - Export page to markdown
  • onotion page move <page-id> --to <parent-id> - Move page to new parent
  • onotion page duplicate <page-id> - Deep copy page with all blocks

New Dependencies

  • notion-to-md - For exporting Notion pages to markdown
  • @tryfabric/martian - For converting markdown to Notion blocks

Technical Details

  • All new commands follow existing patterns (output formats, error handling, streaming)
  • duplicatePage handles complex nested structures (columns, tables, nested blocks)
  • movePage auto-detects parent type (page vs database)
  • Markdown import handles files >100 blocks via batched appends
  • Team command gracefully handles non-enterprise workspaces

Testing

  • pnpm build passes
  • pnpm test - 25 tests pass
  • Tested page import with real markdown file
  • Tested page export round-trip
  • Tested user me with real Notion workspace

Test plan

  1. Install and run onotion user me to verify user commands
  2. Test onotion page import <file.md> -p <parent-id> with a markdown file
  3. Test onotion page export <page-id> to verify markdown output
  4. Test onotion comment list <page-id> on a page with comments

🤖 Generated with Claude Code

Yaser Martinez Palenzuela added 9 commits January 25, 2026 17:46
These libraries enable bidirectional markdown conversion:
- notion-to-md: Export Notion pages to markdown format
- @tryfabric/martian: Convert markdown to Notion block format
New commands:
- `user list` - List all workspace users with pagination support
- `user get <user-id>` - Retrieve a specific user by ID
- `user me` - Get the current bot user information

Features:
- Streaming support with --stream flag for large workspaces
- All standard output formats (table, json, plain, compact)
- Consistent error handling with existing commands
New commands:
- `comment list <page-id>` - List all comments on a page
- `comment add <page-id> <text>` - Add a new comment to a page

Features:
- Full pagination support for pages with many comments
- Streaming support with --stream flag
- All standard output formats (table, json, plain, compact)

This enables CLI-based code review workflows and automated
commenting on Notion pages.
New commands:
- `team list` - List all teams/teamspaces in the workspace

Note: Teams API is enterprise-only. The command gracefully handles
non-enterprise workspaces by displaying a helpful message instead
of throwing an error.
New functions:
- exportPageToMarkdown(pageId, client) - Convert Notion page to markdown
- importMarkdownToBlocks(content) - Convert markdown to Notion blocks

Uses:
- notion-to-md for Notion → Markdown conversion
- @tryfabric/martian for Markdown → Notion block conversion

This enables round-trip markdown workflows where users can export
pages for editing in their preferred editor and re-import changes.
New API functions:
- getUser(userId) - Retrieve a specific user
- listTeams() - List teams (enterprise-only, graceful fallback)
- listComments(blockId) - List comments on a page/block
- createComment(pageId, richText) - Add a comment to a page
- movePage(pageId, newParentId) - Move page to new parent
- duplicatePage(pageId, options) - Deep copy page with all blocks

The duplicatePage function handles complex nested structures:
- Recursively copies all child blocks
- Preserves column layouts and tables
- Copies page icon and cover
- Supports custom title for the duplicate

Also includes helper functions for block type conversion to ensure
proper handling of all Notion block types during duplication.
New page subcommands:

\`page import <file>\`
  - Import a markdown file as a new Notion page
  - Options: --parent, --database, --title, --batch-size, --delay-ms
  - Handles files larger than 100 blocks via batched append

\`page export <page-id>\`
  - Export a Notion page to markdown format
  - Options: --output (file path, defaults to stdout)

\`page move <page-id>\`
  - Move a page to a new parent (page or database)
  - Options: --to <parent-id>
  - Auto-detects parent type (page vs database)

\`page duplicate <page-id>\`
  - Create a deep copy of a page including all blocks
  - Options: --title (custom title for the copy)
  - Preserves nested content, columns, tables, icon, and cover

These commands enable powerful CLI workflows for content management,
backup/restore, and batch operations on Notion pages.
Register the new command modules in the main CLI entry point:
- createUserCommand() for user management
- createCommentCommand() for page comments
- createTeamCommand() for team/teamspace listing

All commands are now available via:
  onotion user [list|get|me]
  onotion comment [list|add]
  onotion team list
These are development artifacts used during implementation:
- reference/ - cloned repos used for API patterns
- PLAN.md - implementation planning document
@hal-shin

Copy link
Copy Markdown
Contributor

Hey @elyase, thanks for the PR — sorry it took so long for me to get around to it, this somehow got lost in my inbox.

The PR has a really nice scope and the duplicate logic around tables and column lists clearly took some work to get right.

That said, there are a couple of things I'd want fixed before merging.

The page import command hardcodes properties.Name when the parent is a database (page.ts:454). Most databases don't use Name as their title property — they use Title, Task, etc. — so this'll 400 for most users. You've already got the right pattern in getTitlePropertyKey for duplicate, would be great to reuse it here.

The bigger one is duplicatePage. Two issues there:

  • DB row properties (select, date, number, relation, etc.) aren't copied — only the title. So duplicating a row in a database silently loses every field except the title.
  • child_page and child_database blocks become placeholder paragraphs reading "Unsupported block type: child_page". I'd rather skip them silently (or log to stderr) than write that into the duplicated page.

A few smaller things:

  • page move dropped -p/--database without an alias — that's a breaking change for anyone using it
  • movePage's try-page-then-catch-as-database pattern means a bad parent ID surfaces the wrong error message
  • @tryfabric/martian pulls in @notionhq/client@1.0.4 (so the SDK gets duplicated) and katex@0.12.0 which is pretty old — worth a pnpm audit
  • RichTextItemRequest is defined in both comment.ts and client.ts, would be nice to extract
  • No tests for the new client.ts code, especially the blockToCreateRequest branches given how much as unknown as casting is in there
  • There are some merge conflicts to resolve

Once the import title-prop and duplicate property/child-page issues are sorted I'm happy to merge. Thanks again, this is a nice addition :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants