Safe GitOps and infrastructure-as-code for Notion databases and data sources.
notionctl lets teams define Notion schemas as version-controlled YAML, preview changes, detect drift, and safely reconcile Notion from Git. It is designed around the same desired-state workflow used by infrastructure tools: pull → plan → review → apply.
Notion is excellent for collaborative workspaces, but database schemas are often changed manually and are hard to review, reproduce, or audit. notionctl makes the schema declarative:
Git/YAML → validate → plan → review → apply → Notion
↑
drift
Destructive property deletes and type changes are blocked by default.
- Declarative YAML manifests for databases and data sources
- Deterministic diffs and machine-readable JSON plans
- Safe
applywith explicit confirmation - Drift detection between Git and live Notion
- Resource status and connectivity diagnostics
- Migration scaffolding for schema evolution
- Lock/state tracking for stable Notion IDs
- Notion API version pinning
- Retry/backoff for transient API failures
- Environment-specific token selection
- Node.js 20+ and TypeScript
- Unit-tested diff/config/manifest layers
- GitHub Actions CI and npm-ready packaging
npm install -g notionctl
# or
pnpm add -g notionctlFor development:
pnpm install
pnpm checkCreate a Notion integration and share the target database with it, then export the token:
export NOTION_TOKEN=secret_...For separate environments, set NOTIONCTL_ENV and a matching token variable. For example:
export NOTIONCTL_ENV=staging
export NOTION_TOKEN_STAGING=secret_....env is supported for local development and is ignored by Git. Never commit tokens.
notionctl init --database <database-id> --name tasks
notionctl pull
notionctl validate
notionctl plan
notionctl apply --yesTo inspect machine-readable output:
notionctl plan --jsonIf someone edits a managed database directly in Notion:
notionctl driftA drifted resource exits non-zero and reports the same reconciliation plan that apply would use.
| Command | Purpose |
|---|---|
init |
Register a Notion database as a managed resource |
pull |
Export live Notion schema to YAML |
validate |
Validate configuration and manifests |
plan |
Preview changes without mutating Notion |
diff |
Backward-compatible alias for plan |
apply |
Safely reconcile Notion from manifests |
drift |
Detect divergence between Git and Notion |
status |
Summarize managed resources and drift |
doctor |
Diagnose configuration, token, and API access |
migrate |
Create and inspect ordered schema migration files |
apply always computes a fresh plan. It requires --yes when changes exist. Property deletion and property type changes are blocked unless explicitly enabled:
notionctl apply --yes --allow-delete-properties
notionctl apply --yes --allow-type-changePlans have a deterministic ID. You can pin an apply to a previously reviewed plan:
notionctl plan --json
notionctl apply --yes --plan <plan-id>If live Notion state changed, the plan ID changes and the apply is rejected.
A CI workflow is included under .github/workflows/ci.yml. For deployment, provide NOTION_TOKEN as a GitHub Actions secret and run notionctl validate/notionctl plan in pull requests. Keep apply in a protected deployment workflow with an explicit environment approval.
src/
commands.ts CLI and command orchestration
diff.ts desired-vs-live reconciliation planner
apply.ts safe mutation executor
notion.ts resilient Notion API adapter
remote.ts live-state retrieval
manifest.ts YAML manifest IO
schemas.ts Zod schemas and domain types
config.ts config/state/secrets handling
test/ unit tests
migrations/ ordered schema migration notes
.github/workflows/ci.yml
pnpm install
pnpm typecheck
pnpm test
pnpm build- Environment-specific workspace/resource overlays
- First-class migration apply/rollback semantics
- GitHub PR plan comments
- More Notion resource types
- Published documentation site
Please report security issues privately using the repository's security policy rather than opening a public issue. See SECURITY.md.
MIT. See LICENSE.