Skip to main content

CLI reference

The OpenDocs CLI is the supported integration layer for AI agents, scripts, and humans working from Markdown files.

npm install -g @opendocs.cc/cli
opendocs login --key od_live_xxxxx

For non-interactive agents and CI, prefer:

export OPENDOCS_API_KEY=od_live_xxxxx
opendocs whoami --json

Global options

OptionApplies toNotes
--jsonAll commandsMachine-readable stdout. Errors are written to stderr as JSON when possible.
--api-url <url>All commandsOverride the default API host, https://api.opendocs.cc.
-h, --helpAll commandsShow command help.
-V, --versionRoot commandShow CLI version.

Environment variables:

VariableNotes
OPENDOCS_API_KEYAPI key used by opendocs login and commands in headless environments.
OPENDOCS_API_URLDefault API URL override for local/staging environments.

Exit behavior

Exit codeMeaning
0Command succeeded. For batch commands, all items succeeded.
Non-zeroCommand failed, or a batch completed with at least one failed item.

In --json mode, successful commands write one JSON object to stdout. Errors write a JSON object to stderr when the CLI can classify the failure:

{ "error": "document_limit", "message": "Your free plan has 0 slots left." }

opendocs login

Authenticate and store local config in ~/.config/opendocs/config.json.

opendocs login --key od_live_xxxxx
OPENDOCS_API_KEY=od_live_xxxxx opendocs login

Do not run bare opendocs login from an agent. Without --key or OPENDOCS_API_KEY, it waits for an interactive hidden prompt.

Useful flags:

FlagNotes
--key <key>API key to validate and store.
--jsonPrint the saved account/workspace state as JSON.

JSON shape:

{
"success": true,
"apiUrl": "https://api.opendocs.cc",
"userId": "usr_123",
"username": "ada",
"workspaceId": "ws_123",
"workspaceName": "Acme Docs",
"workspaceSlug": "acme-docs"
}

opendocs whoami

Show the authenticated account and active workspace.

opendocs whoami --json

JSON shape:

{
"userId": "usr_123",
"onboarding": {
"username": "ada",
"workspace": {
"id": "ws_123",
"name": "Acme Docs",
"slug": "acme-docs"
}
},
"quota": {
"documents": {
"plan": "pro",
"limit": null,
"used": 42,
"remaining": null
}
}
}

Agents should use this before publishing when they need to confirm the active workspace or quota.

opendocs publish

Publish one or more Markdown files.

opendocs publish doc.md --json
opendocs publish docs/*.md --tags api-docs --json
opendocs publish ./vault --tags obsidian-import --json
opendocs publish report.md --export pdf --json

Flags:

FlagNotes
--title <title>Override title. Single-file only.
--slug <slug>Request a custom slug. Single-file only.
--visibility <level>private, workspace, or public. Defaults to workspace.
--confirm-publicRequired with --visibility public.
--tags <tags>Comma-separated tags. Max 20 tags per post.
--export <format>Export successful publishes to pdf or docx.
--jsonRecommended for agents.

Limits:

LimitValue
Markdown size per file1 MB
Files per CLI invocation500
Documents per publish API batch25, auto-chunked by the CLI
Local images per document30
Local image size10 MB each

Folder inputs are scanned recursively. The CLI publishes .md files and skips .obsidian, .trash, .git, and node_modules, which makes Obsidian vault imports a single command.

Single-file JSON:

{
"postId": "post_123",
"slug": "launch-note",
"url": "/acme-docs/launch-note",
"title": "Launch note",
"tags": ["launch"]
}

Batch JSON:

{
"total": 2,
"succeeded": 2,
"failed": 0,
"results": [
{
"success": true,
"file": "docs/intro.md",
"postId": "post_123",
"slug": "intro",
"url": "/acme-docs/intro",
"title": "Intro"
}
]
}

Publish-plus-export JSON includes an export block with local output paths:

{
"postId": "post_123",
"url": "/acme-docs/report",
"export": {
"format": "pdf",
"path": "report.pdf"
}
}

opendocs update

Create a new version of an existing published post while keeping the same URL.

opendocs update revised.md --post-id launch-note --json

--post-id accepts either the UUID or slug.

Flags:

FlagNotes
--post-id <id-or-slug>Required.
--title <title>Override the title.
--visibility <level>Optional. Omit to preserve current visibility.
--confirm-publicRequired when changing to public.
--tags <tags>Replace tags with this comma-separated list.

JSON shape:

{
"postId": "post_123",
"versionId": "ver_456",
"versionNumber": 4,
"slug": "launch-note",
"title": "Launch note",
"visibility": "workspace",
"tags": ["release"]
}

opendocs list

List posts authored by the signed-in user.

opendocs list --json
opendocs list --all --limit 100 --json
opendocs list --tag api-docs --json

Flags:

FlagNotes
--page <n>Defaults to 1.
--limit <n>Defaults to 20, max 100.
--tag <tag>Filter by normalized tag.
--allList across all workspaces. Default is active workspace only.

JSON shape:

{
"posts": [
{
"id": "post_123",
"title": "Launch note",
"slug": "launch-note",
"visibility": "workspace",
"isPublished": true,
"workspaceId": "ws_123",
"workspaceSlug": "acme-docs",
"tags": ["release"],
"updatedAt": "2026-04-25T12:00:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 1,
"totalPages": 1
},
"scope": "workspace",
"workspaceSlug": "acme-docs"
}

opendocs get

Inspect one post by UUID or slug.

opendocs get launch-note --json

JSON shape:

{
"post": {
"id": "post_123",
"slug": "launch-note",
"title": "Launch note",
"url": "/acme-docs/launch-note",
"visibility": "workspace",
"isPublished": true,
"versionNumber": 4,
"tags": ["release"]
}
}

opendocs pull

Download the current raw Markdown for a post.

opendocs pull launch-note
opendocs pull launch-note --output docs/launch-note.md
opendocs pull launch-note --stdout

Flags:

FlagNotes
--output <path>Destination file. Defaults to <slug>.md.
--stdoutPrint Markdown to stdout. Useful for agents.

opendocs export

Export one or more published posts to PDF or DOCX.

opendocs export launch-note --format pdf
opendocs export intro guide api --format pdf --output ./exports

Flags:

FlagNotes
-f, --format <format>pdf or docx.
-o, --output <path>File path for one export; directory for batch export.
--stdoutBinary stdout. Single post only.
--landscapeLandscape PDF.
--accent-color <hex>Override export accent color.

Batch export accepts up to 10 post IDs/slugs per command.

opendocs visibility

Change who can read a post without uploading new Markdown.

opendocs visibility launch-note private
opendocs visibility launch-note workspace
opendocs visibility launch-note public --confirm-public

Levels: private, workspace, public.

opendocs unpublish

Hide a post without deleting its content or version history.

opendocs unpublish launch-note

Unpublishing is reversible by publishing again, and it frees a Free-plan document slot because quota counts only currently published posts.

opendocs delete

Permanently delete a post.

opendocs delete launch-note --yes

Use --yes or -y from agents and scripts. Without it, non-interactive contexts fail with confirm_required before making a network call.

opendocs workspace list

List workspaces the account belongs to.

opendocs workspace list --json
opendocs workspace ls --json

JSON shape:

{
"workspaces": [
{
"id": "ws_123",
"name": "Acme Docs",
"slug": "acme-docs",
"role": "owner"
}
],
"activeSlug": "acme-docs"
}

opendocs workspace use

Switch the active workspace in local CLI config.

opendocs workspace use acme-docs --json
opendocs workspace switch acme-docs --json

JSON shape:

{
"success": true,
"workspaceId": "ws_123",
"workspaceName": "Acme Docs",
"workspaceSlug": "acme-docs"
}

Switching is local only. It does not affect the dashboard's active workspace.

opendocs agent

Print static, package-bundled instructions for AI agents. This command does not require login and does not fetch remote content.

opendocs agent # concise, high-signal reference
opendocs agent --full # full bundled SKILL.md
opendocs agent --api # API-only reference
opendocs agent --cli # CLI-only reference

With --json, the response shape is:

{
"variant": "api",
"version": "0.1.x",
"content": "# OpenDocs Public API Agent Reference\n..."
}

opendocs logout

Remove local credentials.

opendocs logout

Common CLI errors

ErrorRecovery
auth_expiredCreate a new API key and run opendocs login --key ....
document_limitUpgrade, unpublish old docs, or publish only the files that fit.
doc_too_largeSplit the Markdown file.
too_many_filesSplit a >500-file publish into multiple invocations.
too_many_postsSplit export batches into groups of 10.
confirm_public_requiredRe-run with --confirm-public only after explicit consent.
confirm_requiredAdd --yes for delete in non-interactive contexts.
not_a_memberRun opendocs workspace list --json, choose an available slug, then switch.
image_upload_failedFix or remove the local image reference and retry.
export_failedRetry opendocs export; the publish usually already succeeded.