Notion dbops
Skill NovateStudioGit/novate-studio-skills/knowledge-ops/notion-dbops
57 agent skills for Claude Code — creative production, paid growth, copywriting, ecommerce, email marketing & knowledge ops. By Novate Studio.
npx -y skills add NovateStudioGit/novate-studio-skills --skill notion-dbopsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Lossless bulk data operations on Notion databases — MERGE two DBs into one, or PURGE a set of rows, with zero accidental data loss. Triggered by `/notion-dbops` or natural language like "merge these two Notion databases", "consolidate these DBs", "delete all the old rows", "wipe the legacy leads", "purge this CRM", "clean up this Notion database". Uses the move-pages + in_trash primitive (the Notion MCP has no direct row-delete), the search drain-loop to enumerate rows, and fetch-to-verify survivors. NOT /notion-cleanup (page/layout tidy), NOT /notion-import, NOT /notion-tracker or /notion-dashboard (build views). This is the careful, loss-averse bulk move/merge/delete engine. See memory feedback-data-safety-merges + drive-mcp-sheets-limits.
SKILL.md
4.7 KB, ~1.0k tokens by cl100k_base, as published. Nobody here has run it
/notion-dbops — lossless Notion bulk data-ops (merge OR purge)
The Notion MCP cannot delete an individual page/row directly (update-page has no in_trash; only whole data sources can be trashed). The workaround that makes both MERGE and PURGE safe and reversible is move-pages → in_trash, plus a reliable way to enumerate the rows. This skill codifies that. Apply memory feedback-data-safety-merges throughout: lose nothing, confirm the plan, migrate non-destructively, verify counts, delete recoverably.
Core primitives (both modes)
- Enumerate via the search drain-loop.
notion-searchwithdata_source_urlis the only listing path and caps at 25 results (semantic, can miss). So: search (broad generic query) → act on that batch → search again (the acted-on rows are gone, new ones surface) → repeat until search returns empty. Never assume one search is complete. - Identify the keep-set explicitly before any destructive move — by page-id (collect ids of rows to KEEP, e.g. the ones you just created have a distinct id prefix) or a marker property. Filter the keep-set OUT of every move batch.
- Move with
notion-move-pages— up to 100 ids per call,new_parent= adata_source_id. Re-parenting is lossless (page body preserved); schema mismatch is fine. - Trash with
notion-update-data-sourcein_trash: true— sends the whole data source (and its rows) to Notion trash, recoverable 30 days. - Verify survivors with
notion-fetchon a keep-row id — the search index lags right after bulk moves and returns empty transiently, sofetch(by id) is the trustworthy check.
Mode A — PURGE (delete a row set)
Use when the user wants rows gone (e.g. "wipe all the old leads") but you must NOT touch the keep-set.
- Confirm the plan + keep-set with the user (which rows die, which survive). Note they're recoverable for 30 days.
notion-create-databasea throwaway bin DB (e.g.ZZZ-Trash-<topic>, minimalName TITLEschema).- Drain-loop: search the source data source → collect ids → drop any keep-set ids →
move-pagesthe rest into the bin's data_source_id → search again → repeat until empty. notion-fetchone keep-row to confirm it's intact in the source DB.notion-update-data-sourcein_trash: trueon the bin data source. Done — only the moved rows are trashed; source DB id + inline embeds untouched.- Report: N purged, M kept, recoverable 30 days.
Mode B — MERGE (consolidate two DBs into one)
Use when two DBs should become one with zero record loss.
- Probe both data sources for row counts + schemas. Pick the richer schema as canonical (the destination).
- Reconcile schema deltas FIRST — especially text→select/multi_select: this API does NOT auto-create select options on a page update (it errors).
ALTERthe destination column to ADD every needed option (include all existing option names so current values are preserved) BEFORE moving. move-pagesall rows from the secondary into the canonical data source (drain-loop if >100; lossless, keeps page body).- Clean up the stray auto-created
"<col> 1"column the move can create (DROP it after copying values if needed). - Verify counts: secondary = 0, canonical = original + moved. Use the drain-loop search to confirm the secondary is empty.
in_trash: truethe emptied secondary data source (recoverable).- Report: counts before/after, options added, anything left for manual review.
Guardrails
- Confirm before trashing. Destructive + bulk → state the plan and the keep-set, get a yes, then act (it's reversible via trash but still confirm).
- Never trust a single search for completeness — drain to empty.
- Verify a survivor by fetch, not search (index lag).
- Bare orphan pages (not in a DB) still can't be trashed via MCP — surface those for the user's one-click manual delete.
- Do this in the main loop, not via parallel subagents (memory
feedback-no-fanout-for-external-writes).