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
| Option | Applies to | Notes |
|---|---|---|
--json | All commands | Machine-readable stdout. Errors are written to stderr as JSON when possible. |
--api-url <url> | All commands | Override the default API host, https://api.opendocs.cc. |
-h, --help | All commands | Show command help. |
-V, --version | Root command | Show CLI version. |
Environment variables:
| Variable | Notes |
|---|---|
OPENDOCS_API_KEY | API key used by opendocs login and commands in headless environments. |
OPENDOCS_API_URL | Default API URL override for local/staging environments. |
Exit behavior
| Exit code | Meaning |
|---|---|
0 | Command succeeded. For batch commands, all items succeeded. |
| Non-zero | Command 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:
| Flag | Notes |
|---|---|
--key <key> | API key to validate and store. |
--json | Print 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:
| Flag | Notes |
|---|---|
--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-public | Required with --visibility public. |
--tags <tags> | Comma-separated tags. Max 20 tags per post. |
--export <format> | Export successful publishes to pdf or docx. |
--json | Recommended for agents. |
Limits:
| Limit | Value |
|---|---|
| Markdown size per file | 1 MB |
| Files per CLI invocation | 500 |
| Documents per publish API batch | 25, auto-chunked by the CLI |
| Local images per document | 30 |
| Local image size | 10 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:
| Flag | Notes |
|---|---|
--post-id <id-or-slug> | Required. |
--title <title> | Override the title. |
--visibility <level> | Optional. Omit to preserve current visibility. |
--confirm-public | Required 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:
| Flag | Notes |
|---|---|
--page <n> | Defaults to 1. |
--limit <n> | Defaults to 20, max 100. |
--tag <tag> | Filter by normalized tag. |
--all | List 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:
| Flag | Notes |
|---|---|
--output <path> | Destination file. Defaults to <slug>.md. |
--stdout | Print 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:
| Flag | Notes |
|---|---|
-f, --format <format> | pdf or docx. |
-o, --output <path> | File path for one export; directory for batch export. |
--stdout | Binary stdout. Single post only. |
--landscape | Landscape 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
| Error | Recovery |
|---|---|
auth_expired | Create a new API key and run opendocs login --key .... |
document_limit | Upgrade, unpublish old docs, or publish only the files that fit. |
doc_too_large | Split the Markdown file. |
too_many_files | Split a >500-file publish into multiple invocations. |
too_many_posts | Split export batches into groups of 10. |
confirm_public_required | Re-run with --confirm-public only after explicit consent. |
confirm_required | Add --yes for delete in non-interactive contexts. |
not_a_member | Run opendocs workspace list --json, choose an available slug, then switch. |
image_upload_failed | Fix or remove the local image reference and retry. |
export_failed | Retry opendocs export; the publish usually already succeeded. |