@cli-blog/cli
v0.1.3
Published
Official Cli Blog command-line tool for publishing, automation, and offline demos.
Maintainers
Readme
@cli-blog/cli
Official command-line tool for the Cli Blog API.
Homepage · Documentation · CLI Docs · API Reference · Agent Skill · GitHub
What Is This?
@cli-blog/cli lets developers, teams, CI jobs, and AI agents publish and manage Cli Blog content from a terminal. It wraps the public /v1 content API with commands for posts, authors, media, categories, tags, locales, sitemap XML, feed XML, revisions, and slug redirects.
After install, run commands with cli-blog:
cli-blog posts list --demo --jsonInstall
Global install with npm:
npm install -g @cli-blog/cliGlobal install with Bun:
bun add -g @cli-blog/cliGlobal install with pnpm:
pnpm add -g @cli-blog/cliRun without installing with npx:
npx @cli-blog/cli posts list --demo --jsonRun without installing with Bun:
bunx @cli-blog/cli posts list --demo --jsonRun without installing with pnpm:
pnpm dlx @cli-blog/cli posts list --demo --jsonConfigure a private API key for trusted publishing:
cli-blog config set --api-key "$CLI_BLOG_PRIVATE_KEY"Or set an environment variable, which is usually best for CI:
CLI_BLOG_API_KEY=cli_blog_sk_...Configuration precedence is:
--api-key.CLI_BLOG_API_KEY.- Saved config from
cli-blog config set.
Prefer environment variables or a secret manager for private keys. Avoid passing private keys through --api-key because shell history and local process inspection may expose command arguments.
Try It Without Setup
Demo mode is fully offline. It returns deterministic San Francisco sample content without config, API keys, network requests, file reads, uploads, writes, or destructive prompts.
cli-blog posts list --demo --json
cli-blog posts create --demo --title "A developer's guide to San Francisco" --json
cli-blog feed get --demoRun the same demo commands without installing:
npx @cli-blog/cli posts list --demo --json
bunx @cli-blog/cli posts create --demo --title "A developer's guide to San Francisco" --json
pnpm dlx @cli-blog/cli feed get --demoUse --demo on any command that should return sample output instead of calling the API.
Command Guide
Global options work on every command:
| Option | Description |
| --- | --- |
| --api-key <key> | API key override. Prefer CLI_BLOG_API_KEY for private keys. |
| --demo | Return offline demo content without setup. |
| --json | Print formatted JSON for successful JSON responses. |
| --yes | Skip confirmation prompts for destructive real API commands. |
| --help | Print CLI help. |
| --version | Print the CLI version. |
Posts
| Command | Use it for | Common options |
| --- | --- | --- |
| posts list | List posts. | --status, --locale, --limit, --search, --sort, --direction, --fields, --include, author/category/tag filters. |
| posts get <id-or-slug> | Fetch one post. | --locale, --fields, --include. |
| posts create | Create a post. | --title, --body, --body-markdown, --status, --locale, author/category/tag/media IDs, SEO options. |
| posts update <id-or-slug> | Update a post. | Same editable fields as create, plus --expected-version. |
| posts publish <id-or-slug> | Publish a post. | --expected-version, --published-at, --locale. |
| posts schedule <id-or-slug> | Schedule a post. | --scheduled-at or --at, --expected-version, --locale. |
| posts delete <id-or-slug> | Delete/archive a post. | --locale, --yes. |
List posts:
cli-blog posts list \
--status published \
--locale en-US \
--fields summary,seo \
--include authors,categories,tags,media \
--limit 20 \
--jsonExpected result shape:
{
"object": "list",
"data": [
{
"id": "post_123",
"object": "post",
"title": "A developer's guide to San Francisco",
"slug": "developers-guide-to-san-francisco",
"status": "published",
"authors": [{ "id": "author_123", "object": "author", "public_name": "Maya Chen" }]
}
],
"has_more": false,
"next_cursor": null
}Create and publish:
cli-blog posts create \
--title "A developer's guide to San Francisco" \
--body-markdown ./post.md \
--author-ids author_123 \
--category-ids term_category_123 \
--tag-ids term_tag_123 \
--seo-title "A developer's guide to San Francisco" \
--json
cli-blog posts publish post_123 --expected-version 1 --jsonExpected publish result shape:
{
"id": "post_123",
"object": "post",
"status": "published",
"slug": "developers-guide-to-san-francisco",
"version": 2
}Post filters:
--status draft|in_review|scheduled|published|archived
--locale en-US # optional; omit to use your organization's default locale.
--search "coffee"
--sort published_at|created_at|updated_at|relevance
--direction asc|desc
--author-id author_123
--author-slug maya-chen
--category-id term_category_123
--category-slug san-francisco
--tag-id term_tag_123
--tag-slug city-notes
--fields summary,content,seo,workflow,metadata
--include authors,categories,tags,media,translationsPost create/update fields:
--title <text>
--slug <slug>
--body <markdown-or-path> # optional.
--body-markdown <markdown-or-path> # optional.
--excerpt <text>
--status draft|in_review|scheduled|published|archived
--published-at <iso>
--scheduled-at <iso>
--expected-version <number>
--author-ids <id,id>
--category-ids <id,id>
--tag-ids <id,id>
--featured-media-asset-id <id>
--metadata '{"source":"ci"}'SEO options for posts, categories, and tags:
--seo-title <text>
--seo-description <text>
--canonical-url <url>
--focus-keyphrase <text>
--seo-keywords <word,word>
--robots-index=true|false
--robots-follow=true|false
--open-graph-title <text>
--open-graph-description <text>
--open-graph-media-asset-id <id>
--twitter-title <text>
--twitter-description <text>
--twitter-media-asset-id <id>
--schema-type <type>Authors
| Command | Use it for | Options |
| --- | --- | --- |
| authors list | List public authors. | --limit. |
| authors get <id-or-slug> | Fetch one author. | None. |
| authors create | Create an author. | --public-name, --name, --slug, --bio, --avatar-media-id, --website-url, --metadata. |
| authors update <id-or-slug> | Update an author. | Same fields as create. |
| authors delete <id-or-slug> | Delete an author. | --yes. |
cli-blog authors create \
--public-name "Maya Chen" \
--bio "Field notes from San Francisco" \
--website-url "https://example.com/authors/maya-chen" \
--jsonExpected result shape:
{
"id": "author_123",
"object": "author",
"public_name": "Maya Chen",
"slug": "maya-chen",
"bio": "Field notes from San Francisco"
}Media
| Command | Use it for | Options |
| --- | --- | --- |
| media list | List media assets. | --limit. |
| media get <id> | Fetch one media asset. | None. |
| media upload --file <path> | Upload a local file. | --file, --filename, --alt-text, --caption, --content-type, --metadata. |
| media update <id> | Update media metadata. | --alt-text, --caption, --metadata. |
| media delete <id> | Delete media. | --yes. |
cli-blog media upload \
--file ./bay-walk.png \
--alt-text "Morning light over San Francisco Bay" \
--caption "A local image for a San Francisco story." \
--jsonExpected result shape:
{
"id": "media_123",
"object": "media_asset",
"url": "https://cdn.example.com/media/bay-walk.png",
"original_filename": "bay-walk.png",
"alt_text": "Morning light over San Francisco Bay",
"mime_type": "image/png"
}Categories And Tags
| Command | Use it for | Options |
| --- | --- | --- |
| categories list / tags list | List terms. | Optional: --locale, --include translations, --limit. |
| categories get <id-or-slug> / tags get <id-or-slug> | Fetch one term. | Optional: --locale, --include translations. |
| categories create / tags create | Create a term. | Required: --name. Optional: --slug, --locale, --description, --translation-of-id, SEO options. |
| categories update <id-or-slug> / tags update <id-or-slug> | Update a term. | Same fields as create, optional --locale. |
| categories delete <id-or-slug> / tags delete <id-or-slug> | Delete a term. | --locale, --yes. |
cli-blog categories create --name "San Francisco" --locale en-US --json
cli-blog tags create --name "City Notes" --locale en-US --jsonExpected result shape:
{
"id": "term_123",
"object": "taxonomy_term",
"taxonomy_type": "category",
"locale": "en-US",
"name": "San Francisco",
"slug": "san-francisco"
}Locales
cli-blog locales list --jsonExpected result shape:
[
{ "tag": "en-US", "name": "English (United States)", "language": "English", "region": "United States" },
{ "tag": "es-MX", "name": "Spanish (Mexico)", "language": "Spanish", "region": "Mexico" }
]Revisions And Redirects
cli-blog posts revisions list post_123 --json
cli-blog posts revisions get post_123 rev_123 --json
cli-blog posts redirects get old-san-francisco-guide --locale en-US --jsonExpected result shape:
{
"object": "slug_redirect",
"from_slug": "old-san-francisco-guide",
"to_slug": "developers-guide-to-san-francisco",
"post_id": "post_123",
"status_code": 301
}Sitemap And Feed
cli-blog sitemap get --locale en-US > sitemap.xml
cli-blog feed get --locale en-US > feed.xmlThese commands print XML unless --json is used on commands that return JSON.
Demo Mode Examples
Demo mode works across the public command surface:
cli-blog posts list --demo --json
cli-blog posts create --demo --title "A developer's guide to San Francisco" --json
cli-blog authors create --demo --public-name "Maya Chen" --json
cli-blog media upload --demo --file ./missing.png --json
cli-blog categories create --demo --name "San Francisco" --json
cli-blog tags create --demo --name "City Notes" --json
cli-blog posts revisions list demo_post_sf_guide --demo --json
cli-blog posts redirects get old-san-francisco-guide --demo --json
cli-blog sitemap get --demo
cli-blog feed get --demoThe media upload --demo command does not read the file path. It returns a sample media object so you can test output parsing before setting up real storage or keys.
AI Agent Skill
If you want an AI coding agent to add Cli Blog to an application, use the Cli Blog agent skill. It includes guidance for choosing the API, SDK, or CLI, plus framework patterns for common app stacks.
Errors
Failed commands print a single cli-blog: message to stderr and exit with code 1. Successful commands exit 0.
Common cases:
| Error | When to expect it | What to do |
| --- | --- | --- |
| Missing API key | You ran a real API command without config or CLI_BLOG_API_KEY. | Run cli-blog config set --api-key <key> or set CLI_BLOG_API_KEY. |
| Unknown command | The command family or action is not supported. | Run cli-blog --help and check the command spelling. |
| Missing resource ID or slug | A command such as posts get, posts update, or authors delete needs an ID/slug. | Pass the resource ID or slug after the action. |
| Invalid --expected-version number | A numeric flag received non-numeric input. | Pass a valid number. |
| API 401 / 403 | The key is missing, invalid, public-only, or missing permission for the action. | Use the right organization key type and scope. |
| API 404 | The resource ID or locale-scoped slug was not found. | Check the ID, slug, and --locale. |
| API 409 | The --expected-version value is stale. | Fetch the latest post, then retry with the current version. |
Use --json when you want successful output to be machine-readable. Errors intentionally stay on stderr.
Security
- Never expose private API keys in browsers, mobile apps, or other untrusted clients.
- Use public keys for published-content reads.
- Use private keys only in trusted shells, CI, servers, or agent environments.
- Saved config is restricted to the current OS user after every write.
- Destructive commands require confirmation unless
--yesis passed. - Runtime dependencies are limited to the first-party
@cli-blog/nodepackage.
