blog-cli
Agent-friendly CLI for managing a personal blog: create drafts, upload media, generate preview links, publish articles, and manage project tags.
Install
From PyPI:
pip install -U blog-cli
Or install it as an isolated command-line tool:
pipx install blog-cli
uv tool install blog-cli
For development:
git clone https://github.com/tanaka-mambinge/personal-cli
cd personal-cli
uv sync --extra dev
Configure
The CLI stores the server URL, API key, and site URL in its configured keyring backend. On first use it prints a local setup URL; open it in a browser, enter the three values, and submit. The values are validated against the server before they are saved.
For local development, run the CLI through scripts/docker-cli. Docker uses a
persistent container-only credential volume and never mounts the host keyring:
./scripts/docker-cli run article list --type blog
All commands support --json for machine-readable output and --server-url to override the configured API URL for one command. Commands also support --insecure to skip TLS certificate verification when needed for local development.
Check the installed version:
blog-cli version
Articles
Create a blog post
Blog posts are drafts by default:
blog-cli article blog create \
--title "My Post" \
--description "A short summary" \
--markdown "# My Post\n\nHello."
Use a Markdown file instead:
blog-cli article blog create \
--title "My Post" \
--description "A short summary" \
--markdown-file post.md
Create a project
blog-cli article project create \
--title "My Project" \
--description "A short summary" \
--tag python \
--tag agents \
--markdown-file project.md
Projects can also use --pinned and --sort-order.
List and show articles
# List all articles
blog-cli article list
# List published blog posts
blog-cli article list --type blog --status published
# List projects
blog-cli article list --type project
# Show one article
blog-cli article show my-post
Update an article
blog-cli article update my-post --title "A Better Title"
blog-cli article update my-post --description "An updated summary"
blog-cli article update my-post --markdown-file updated-post.md
blog-cli article update my-post --cover-image hero-image
blog-cli article update my-post --clear-cover-image
The update command also accepts --type, --status, --tag, --pinned, --not-pinned, and --sort-order.
Preview and publish
Generate a time-limited preview link:
blog-cli article preview my-post
blog-cli article preview my-post --ttl-hours 4
Override the configured site URL for a preview:
blog-cli article preview my-post --site-url https://preview.example.com
Publish an article explicitly:
blog-cli article publish my-post --published-by agent
Archive or restore an article:
blog-cli article delete my-post
blog-cli article unarchive my-post
Project tags
# List tags on a project
blog-cli article tag-list my-project
# Add tags
blog-cli article tag-add my-project --tag python --tag agents
# Remove a tag
blog-cli article tag-remove my-project --tag agents
ChatGPT / Codex skill
The repository skill lives at skills/blog-cli/SKILL.md. It is loaded by agents from the repository and is not managed through CLI commands.
Media
Upload media using a stable name, then reference that name from article Markdown:
blog-cli media upload --name hero-image ./hero.jpg
Replace an existing file without changing its name:
blog-cli media update --name hero-image ./new-hero.jpg
Soft-delete media:
blog-cli media delete --name hero-image
Markdown references use the media name:

<video controls width="100%" src="demo-video"></video>
The site resolves these names to their full media URLs.
Publishing new CLI versions
The repository includes a GitHub Actions workflow at .github/workflows/publish.yml. It runs when you push a version tag matching v*.*.* and will:
- Install dependencies with uv.
- Run the test suite.
- Build the wheel and source distribution with
uv build --no-sources. - Publish both distributions to PyPI with
uv publish.
After configuring PyPI Trusted Publishing for the GitHub Actions workflow, release a new version with:
uv version --bump patch
git add pyproject.toml uv.lock
git commit -m "Release blog-cli"
git tag v0.2.4
git push origin main --tags
Use the version from pyproject.toml when creating the tag.
Testing
./scripts/docker-cli test
The CLI tests use an in-memory fake API client, run with networking disabled, and reuse Docker's cached dependencies. The CLI architecture is:
blog-cli (httpx) → FastAPI server → MongoDB/GridFS
License
MIT
Release files for blog-cli 0.4.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| blog_cli-0.4.5.tar.gz | 19.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| blog_cli-0.4.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 36.7 kB
Release files / blog_cli-0.4.5.tar.gz
| Download URL | blog_cli-0.4.5.tar.gz |
|---|---|
| Size | 19.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
45d6f43cef5a87177be88b1ede3c3d97506442b6c7d514dfd6aaf3ab672136ab
|
|
BLAKE2b-256 checksum How to use checksums |
a473af9b5ac657f5432a0c521dd27f3f03ee9115ed2a173c672c3212363a7b5a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / blog_cli-0.4.5-py3-none-any.whl
| Download URL | blog_cli-0.4.5-py3-none-any.whl |
|---|---|
| Size | 17.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fe315a389dc0b80859805ba666e8b9f39a87541aa9a145d56e5cd1d2f1a0eb26
|
|
BLAKE2b-256 checksum How to use checksums |
dc6a9eb9e3c82fed11a213b5695482b34bda8158d800090947ce4900d2564b3a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|