Publish
Publishing is the core OpenDocs workflow.
opendocs publish my-doc.md
The CLI reads the file from disk, uploads the Markdown, and returns a stable URL.
For agent workflows, ask the agent to save the Markdown file first, then run
the CLI with --json so it can parse the postId, slug, url, and title
without scraping terminal text.
If the Markdown references local images next to the source file, the CLI uploads those images first and rewrites the Markdown to use their OpenDocs URLs. Supported local formats are JPEG, PNG, WebP, GIF, and SVG. Each image can be up to 10 MB, with a maximum of 30 local images per document.
For safety, local image paths must stay inside the directory containing the Markdown file. References that escape that directory are skipped.
What the CLI sends
The current publish flow sends:
markdowntitlewhen you pass--titleslugwhen you pass--slugvisibilityworkspaceIdfrom your stored CLI configprojectIdfrom your active project, or from--projecttagssourcePathconfirmPublicwhen needed
CLI flags
| Flag | Meaning |
|---|---|
--title <title> | Override the document title |
--slug <slug> | Choose a custom URL slug |
--visibility <visibility> | private, workspace, or public |
--tags <tags> | Comma-separated tags |
--project <slug-or-id> | Publish to a specific project instead of the active project |
--confirm-public | Required when publishing publicly |
--export <format> | Also export each successful publish to pdf or docx |
--json | Global flag for machine-readable output |
--api-url <url> | Global flag to override the default API host |
Title and slug behavior
- If you do not pass
--title, the CLI looks for the first# Headingin the file. - If you do not pass
--slug, OpenDocs generates one from the title. - If the slug is already taken in your project, OpenDocs appends a numeric suffix.
- Route words like
tagandprojectsare reserved. If OpenDocs generates one from a title, it suffixes it automatically; explicit reserved--slugvalues are rejected.
Example
opendocs publish api-reference.md \
--slug checkout-api-reference \
--visibility workspace \
--tags api,checkout \
--json
Example JSON response:
{
"postId": "abc123",
"slug": "checkout-api-reference",
"url": "/acme/checkout-api-reference",
"projectSlug": "default",
"title": "Checkout API reference"
}
Agent-friendly pattern
When an agent is doing the work, ask it to save the Markdown file first and then run:
opendocs publish api-reference.md --json
That gives the agent a clean response object to read back to you.
Publish many files
Pass more than one Markdown file and the CLI uses the batch endpoint. One CLI invocation can publish up to 500 files; under the hood, the CLI chunks them into server requests of 25 documents each.
opendocs publish docs/*.md --tags api-docs --json
For Obsidian vaults or larger doc folders, pass the folder itself:
opendocs publish ./vault --tags obsidian-import --json
Folder uploads are recursive. The CLI publishes .md files and skips
.obsidian, .trash, .git, and node_modules.
Batch publishing is the right shape for agents. Do not ask an agent to loop over files one by one; that repeats auth/config/network work and makes errors harder to summarize.
Batch notes:
--titleand--slugare single-file only.--visibility,--tags, and--confirm-publicapply to every file.- Add a shared
--tagsvalue so you can find the group again withopendocs list --tag <tag>. - For a coherent batch, create or switch to a project first:
opendocs project create "Launch docs" --use. - Each server request is capped at 25 documents and each Markdown file is capped at 1 MB.
Publish and export together
Use --export when you want both a shareable URL and a local PDF/DOCX:
opendocs publish report.md --export pdf --json
opendocs publish docs/*.md --export pdf --tags release-q2 --json
The CLI publishes first, then exports each successful post and writes the file next to the source Markdown unless you choose a different export destination. DOCX export requires Pro or Team.
Public publishing
Public publishing must be explicit:
opendocs publish launch-note.md --visibility public --confirm-public
If you omit --confirm-public, the API rejects the request.
Do not use public just because you want to share something internally. Use
workspace for team sharing and reserve public for links that should be
accessible to anyone with the URL.
Next steps
- Learn how updates work in Update and version history
- Learn visibility choices in Visibility overview