Unified CLI
Global options such as --json, --cookies, and --publication-url must
appear before the command.
Create an unpublished draft
substack drafts create post.md
The title comes from the first Markdown heading, then the filename if the file
has no heading. Use --title to override it.
Export a draft to Markdown
Print a read-only Markdown backup to standard output:
substack drafts export 12345
Write it to a UTF-8 file:
substack drafts export 12345 --output backup.md
The command refuses to replace an existing file unless --force is present.
It fetches the draft but performs no server writes. Content without a supported
Markdown representation is emitted as a versioned opaque HTML comment instead
of being silently discarded.
Update a draft from Markdown
Preview the generated update without writing to Substack:
substack drafts update 12345 revised-post.md --dry-run --yes
Apply it after review:
substack drafts update 12345 revised-post.md --yes
Updates preserve unsupported editor nodes exported as
python-substack-node:v1 markers and editor image attributes preserved in
python-substack-image:v2 markers. The command refuses to remove or alter
those nodes by default. --allow-unsupported-change and
--allow-image-replacement are available only with --yes for intentional
modifications or unmatched image replacements.
Draft updates also verify the revision fingerprint exported in
python-substack-revision:v1 markers. If remote draft changes occurred after
export, the update fails closed to prevent overwriting remote work. Dry-run
updates (--dry-run --yes) report specific mismatch details. Markdown files
lacking revision metadata are treated as unprotected updates. Pass
--allow-conflict --yes (or --force --yes) to explicitly override conflicts
or apply unprotected updates. The CLI uses its authenticated API client while
rendering, so local images can upload even during a dry run.
Select a publication
List every publication available to the authenticated account:
substack publications list
Select one for a single command:
substack --publication-url https://example.substack.com drafts list
Schedule an existing draft
Pass an ISO 8601 timestamp with a timezone offset or Z:
substack drafts schedule 12345 --at 2030-01-02T09:00:00+01:00
Remove the schedule without deleting the draft:
substack drafts unschedule 12345
Stable JSON for automation
substack --json drafts list --limit 10
substack --json drafts export 12345
The command writes a JSON object containing drafts, count, filter,
offset, and limit. Errors are also JSON when --json is present.
Export JSON contains action, draft_id, markdown, and
unsupported_nodes.
Publish and delete
substack drafts publish 12345 --no-send
substack drafts delete 12345 --yes
Publishing and deletion require confirmation. JSON and noninteractive
workflows must pass --yes. Publishing runs Substack’s prepublish check first.
See safety and publishing behavior.
The original console scripts remain supported. See
legacy CLI commands.