Package Control

The Sublime Text package directory, replenished.

NotionSave

Sublime Text plugin to save and close notes to Notion with a durable background queue

Links

Versions

1.0.2 ·
2026-09-30 19:18

More

NotionSave

Adds Save to Notion to Sublime Text's editor context menu, tab context menu, File menu, and Command Palette. Saves the full buffer locally, closes the selected tab without a save prompt, and uploads it to your Notion database in a worker thread.

Targets Sublime Text 2 (build 2221+) with Python 2.6-compatible runtime code; also accommodates Sublime Text 3 and 4. Legacy editor compatibility should be verified on the specific build you use. Requires a curl executable with modern HTTPS/certificate support; there are no Python dependencies.

Install

  1. Download the source ZIP, or clone this repository.
  2. In Sublime Text, choose Preferences → Browse Packages….
  3. Copy the extracted repository into that folder as NotionSave. notion_save_plugin.py must be directly inside Packages/NotionSave/, alongside notion_save/.
  4. Restart Sublime Text.
  5. Open the Command Palette and run Preferences: NotionSave Settings.

Alternatively, download NotionSave.sublime-package from the latest release. Developers can build it with python3 scripts/build_package.py. Put that archive in Sublime's Installed Packages directory, which is next to Packages, then restart. Install either the source folder or the archive, not both.

Connect Notion

Create an internal connection at Notion's integration settings. Enable Read content, Insert content, and Update content. Add the connection to the target database using its ••• → Connections menu.

Run Preferences: NotionSave Settings, enter your token and database URL or ID, then save:

{
    "api_key": "YOUR_NOTION_API_TOKEN",
    "database_id": "YOUR_DATABASE_URL_OR_ID",
    "data_source_id": "",
    "curl_path": "curl"
}

The settings command shows bundled defaults and your editable user settings side by side. Settings are stored in Packages/User/NotionSave.sublime-settings, outside the plugin repository. Leave the bundled settings empty. Instead of api_key, you can set NOTION_API_KEY in the environment inherited by Sublime (GUI-launched apps may not inherit shell variables).

No credentials are needed by the website or Vercel. Never commit your token.

Use

Right-click in the editor or on a tab, then choose Save to Notion. The tab closes after a durable local snapshot; there is no network wait or upload dialog. The status bar reports the result. This command saves the entire buffer, not just the selection.

A saved file uses its filename as the Notion page title. An untitled buffer uses its first nonempty line (or Untitled). Text is stored in paragraph blocks, preserving text and whitespace within the blocks. Markdown syntax stays plain text. Long lines become multiple blocks; the per-buffer limit is 5 MB. Each invocation creates a new page, rather than updating an earlier page.

The source file on disk is not changed or deleted. Unsaved edits are included in the snapshot sent to Notion. Closing a tab does not quit Sublime; uploads run while the app is open. There is a small local disk-write cost before closing, which avoids losing the note if the app or network fails.

Recovery

The queue is stored as plain-text JSON in Packages/User/Notion Save Queue. Queue entries contain the text and destination, never the API token. Successful uploads are removed. Queue files use owner-only permissions on POSIX; on Windows they inherit your user directory permissions.

Connection failures before sending, read failures, and rate limits retry with backoff (up to one hour between attempts). Retry-After is respected across the queue. Authentication/validation failures wait for Retry Uploads.

If a non-idempotent write times out, returns an ambiguous server error, or is interrupted by quitting Sublime, it is marked uncertain and is not automatically retried. Notion may have accepted the request. Check the database, recover the local copy, and only send it again if needed. A partially uploaded large note may already have a page; its ID and confirmed block offset are recorded in the queue file. Exactly-once delivery cannot be guaranteed across a remote write and a local process crash.

Pending jobs resume when Sublime restarts. An upload is not guaranteed to continue after quitting the app.

Website / Vercel

site/index.html is a single static page with embedded CSS and JavaScript, plus a local JetBrains Mono font. It follows the visual style of Adel Dev Tools. The editor preview is an illustrative demo and sends no data.

Import this repository into Vercel, keep the Root Directory at the repository root, and select Other for the framework. vercel.json publishes only site/, with no install/build command or environment variables. The Python plugin, tests, and queue are not deployed. Download links point to the public GitHub repository and release archive.

Preview locally:

python3 -m http.server 8765 --directory site

Package Control

The package name is NotionSave. Version 1.0.0 is submitted to the default channel and awaiting review; until accepted, use the manual installation above. The submission record tracks its status.

License

MIT, copyright 2026 Adel Hamad. The documentation website's bundled JetBrains Mono font uses its separate SIL Open Font License in site/FONT-LICENSE.txt; website assets are excluded from the plugin package.

Development

python3 -m unittest discover -s tests -v
python3 scripts/build_package.py

The suite uses fake Notion responses and Sublime API stubs. It covers durable snapshots, failure recovery, Unicode and request limits, destination resolution, thread behavior, rate-limit handling, secret handling, and saving/closing the correct tab. It does not replace manual testing in actual Sublime Text versions or a live Notion workspace.

Keep notion_save_plugin.py and notion_save/ compatible with Python 2.6. Development scripts and tests use Python 3.10+.

References: Sublime Text 2 API, Notion create page, Notion limits, Package Control submission.

Results

Packages