Many teams keep their important documents in Git, where changes get reviewed and every version is kept. The people who read those documents often work in Notion instead. So somebody copies each document over by hand, the two copies drift apart, and after a few months nobody can say which one is current.
notion_publish is a command-line tool that publishes Markdown files from a Git repository into Notion and then keeps those pages up to date. Git stays the authoritative copy. Notion shows a current version of it.
It was built for a security and compliance corpus, where an auditor can reasonably ask which Notion page corresponds to a given policy, and where "somebody pasted it in last spring" is not a good answer.
Publish a file. --parent takes a page ID, a Notion URL, or the exact name of a database:
$ notion-publish policies/access-control.md --parent 'Policies' --link
Published policies/access-control.md to database "Policies" (2efab123-...)
https://app.notion.com/p/Access-Control-Policy-3cfab123cd45818b9a72c2bd16e85a62
--link writes a file called notion-publish-manifest.yml, which records the page each document became. You commit that file. From then on, one command brings every page up to date:
$ notion-publish republish
Updated policies/incident-response.md to database "Policies" (2efab123-...)
https://app.notion.com/p/Incident-Response-Policy-...
12 documents: 11 unchanged, 1 updated
Before publishing anything, you can ask what has moved apart:
$ notion-publish status
/repo/notion-publish-manifest.yml -- 12 tracked
Changed locally (1)
policies/access-control.md
Changed in Notion (1)
policies/incident-response.md
https://app.notion.com/p/...
10 in sync, 1 changed locally, 1 changed in Notion
status exits with code 3 when something needs a person to look at it, so it also works as a check in continuous integration.
Notion does not publish an official Ruby SDK. The client it maintains is for JavaScript.
Ruby has a dozen unofficial Notion gems, and they address two different problems. Most are API clients that wrap the HTTP endpoints, and the widely used ones have not seen a release in some time: notion-ruby-client last shipped in October 2023, notion-sdk-ruby in June 2022, and notion in January 2021. Notion reorganized its data model in September 2025, when a database became a container holding one or more data sources, and the schema and rows moved to the data source. A client written before that models an API that no longer works the same way.
The gems that do handle Markdown run in the other direction. notion_to_md exports pages from Notion into Markdown, and notion_rails renders Notion blocks as HTML inside a Rails application. Both are useful. Neither publishes into Notion, and neither keeps a record of what was published, which is the part that makes a second run safe instead of duplicating everything.
The conversion works differently here as well. Tools in this area usually build Notion's block JSON themselves, which means carrying a Markdown parser and keeping it in step with Notion's block types. notion_publish sends the Markdown and lets Notion parse it, using the Markdown parameter Notion's own API accepts. Tables, nested lists, task lists, and fenced code arrive correctly because Notion did that work. It is also why the gem has no runtime dependencies at all: the client is Net::HTTP from the Ruby standard library.
Requires Ruby 3.2 or later.
gem install notion_publish
The source code, the full usage reference, and the issue tracker are on GitHub: github.com/outsidecto/notion-publish.
MIT licensed. This project is not affiliated with or endorsed by Notion Labs, Inc.