# CLAUDE.md

## Overview

Notion workspace management toolkit for database organization, schema migration, and bulk operations.

## Quick Start

```bash
pip install -r scripts/requirements.txt

# Schema migration
python scripts/schema_migrator.py --source [DB_ID] --target [DB_ID] --dry-run

# Async bulk operations
python scripts/async_organizer.py --database [DB_ID] --action cleanup
```

## Semantic Search

```bash
# Default browse mode (terminal table)
python scripts/notion_search.py "AI agents in 2026"

# JSON output for piping
python scripts/notion_search.py "AI agents" --json | jq '.[].id'

# Constrain to specific databases
python scripts/notion_search.py "MCP" --databases f8f19ede-32bd-43ac-9f60-0651f6f40afe

# Property filter (Notion's filter shape — passed verbatim to data_sources.query)
python scripts/notion_search.py "MCP" --databases ID \
  --filter '{"property": "Status", "status": {"equals": "Done"}}'

# Compound filter (and/or)
python scripts/notion_search.py "MCP" --databases ID \
  --filter '{"and": [{"property": "Status", "status": {"equals": "Done"}}, {"property": "Topic", "multi_select": {"contains": "AI"}}]}'

# Fast mode (skip LLM stages)
python scripts/notion_search.py "exact term" --no-rerank --no-expand
```

The search runs four stages:

1. **Expand** — Claude Haiku generates up to 5 query variants (synonyms + cross-language KR↔EN)
2. **Search** — Notion API searched per variant; results unioned + deduped at 30 candidates
3. **Enrich** — title, properties, and 200-char excerpt fetched per candidate
4. **Rerank** — Claude Haiku scores candidates against the *original* query; top N returned

Results are cached for 24h (SHA256 of query + candidate IDs). Bypass with `--no-cache`.

### Requirements

| Env var | Purpose |
|---------|---------|
| `NOTION_API_KEY` (or legacy `NOTION_TOKEN`) | Notion integration token |
| `ANTHROPIC_API_KEY` (optional) | Use Claude SDK directly. If missing, the skill falls back to `claude -p` CLI. |

## Scripts

| Script | Purpose |
|--------|---------|
| `schema_migrator.py` | Migrate data between databases with property mapping |
| `async_organizer.py` | Async bulk operations (cleanup, restructure, archive) |

## Schema Migrator

```bash
# Dry run (preview changes)
python scripts/schema_migrator.py \
  --source abc123 \
  --target def456 \
  --mapping mapping.json \
  --dry-run

# Execute migration
python scripts/schema_migrator.py \
  --source abc123 \
  --target def456 \
  --mapping mapping.json
```

### Mapping File Format

```json
{
  "properties": {
    "OldName": "NewName",
    "Status": "Status"
  },
  "transforms": {
    "Date": "date_to_iso"
  }
}
```

## Async Organizer

```bash
# Cleanup empty/stale pages
python scripts/async_organizer.py --database [ID] --action cleanup

# Archive old pages
python scripts/async_organizer.py --database [ID] --action archive --days 90

# Restructure hierarchy
python scripts/async_organizer.py --database [ID] --action restructure
```

## Rate Limits

| Limit | Value |
|-------|-------|
| Requests/second | 3 max |
| Items per request | 100 max |
| Retry on 429 | Exponential backoff |

## Configuration

Environment variables:
```bash
# Preferred (matches 32-notion-writer)
NOTION_API_KEY=secret_xxx

# Legacy fallback also accepted
# NOTION_TOKEN=secret_xxx
```

The scripts read `NOTION_TOKEN` first, then fall back to `NOTION_API_KEY`. Use `NOTION_API_KEY` for new setups so the same `.env` works across all Notion skills.

## Notes

- Always use `--dry-run` first for destructive operations
- Large operations (1000+ pages) use async with progress reporting
- Scripts implement automatic rate limiting

## Roadmap (Phase 3)

The current scripts cover schema migration and async bulk ops. Two larger goals are parked for a future iteration:

### Goal 1 — Metadata-aware page move/integration

Search source pages, compare their property metadata against a target database schema, and move/migrate while transforming property values to fit. Beyond the existing `schema_migrator.py` (which expects a hand-written mapping file), this would:

- Auto-suggest property mappings using name + type similarity
- Surface unmappable properties before the move (no silent data loss)
- Support cross-database moves (not just same-schema migrations)

### Goal 2 — Notion as personal RAG source

Treat Notion as a small, personal knowledge base for AI agents:

- Search pages by query across databases, filter by property
- Merge results into a single context (with source citations back to page URLs)
- Summarize / distill via LLM into agent-ready snippets
- Export as JSONL or markdown for fine-tuning or RAG indexing

This dovetails with `90-reference-curator` (which does the same for web sources) — Phase 3 would make Notion a first-class source type for that pipeline.
