The Dev.to CLI that uses 98% of the API. Competitors use 20%.
🚀 Getting Started | 📖 Commands | ⚙️ Configuration | 🤝 Contributing
📺 Watch the full demo on YouTube | 📝 Read the article series on Dev.to
devpub is a command-line tool for developers who write on Dev.to. Write articles in your favorite editor, version control them with Git, publish with one command, and track analytics, all from the terminal.
It uses 98% of the Dev.to API surface, including endpoints no other tool touches: semantic search, ML-powered content concepts, and full analytics.
🏆 Why devpub?
Existing Dev.to tools are either abandoned, broken, or only cover basic publishing. devpub is different:
| Feature | devpub | devto-cli | slinkity | dev-to-git |
|---|---|---|---|---|
| Publish from CLI | ✅ | ✅ | ❌ | ❌ |
| Pull articles to local | ✅ | ❌ | ❌ | ✅ |
| Terminal analytics | ✅ | ❌ | ❌ | ❌ |
| Semantic search | ✅ | ❌ | ❌ | ❌ |
| Trend discovery | ✅ | ❌ | ❌ | ❌ |
| Article validation | ✅ | ❌ | ❌ | ❌ |
| Rate limiting | ✅ | ❌ | N/A | ❌ |
| Actively maintained | ✅ | ❌ (2y stale) | ❌ | ❌ (3y stale) |
📦 Installation
pip install devpub
From source:
git clone https://github.com/simplynadaf/devpub.git
cd devpub
pip install -e .
Requirements: Python 3.10 or higher.
🚀 Quick Start
# 1. Set your API key (get it at https://dev.to/settings/extensions)
export DEVPUB_API_KEY=your_key_here
# 2. Initialize a project
devpub init
# 3. Create your first article
devpub new "My Article Title"
# 4. Edit the article in your editor, then publish
devpub push -f articles/my-article-title.md
# 5. Check how it's performing
devpub stats
📖 Commands
✍️ Writing
| Command | Description |
|---|---|
devpub init |
Initialize a devpub project (creates .devpub/ config and articles/ directory) |
devpub new "Title" |
Create a new article from a template |
devpub new "Title" -t tutorial |
Use a specific template (default, til, tutorial, comparison, experience) |
devpub validate |
Check articles for issues before publishing |
devpub validate -f path.md |
Validate a specific file |
🚀 Publishing
| Command | Description |
|---|---|
devpub push -f article.md |
Publish or update a specific article |
devpub push --all |
Push all articles in your project |
devpub push --dry-run |
Preview what would be published |
devpub pull |
Download your published articles from Dev.to |
devpub pull --all |
Include drafts |
devpub status |
Show sync state (local vs Dev.to) |
devpub upload cover.png |
Upload images and get their Dev.to URLs |
devpub upload *.png --markdown |
Print ready-to-paste Markdown image tags |
📊 Analytics
| Command | Description |
|---|---|
devpub stats |
Lifetime totals (views, reactions, comments, followers) |
devpub stats --referrers |
Traffic sources |
devpub stats --followers |
Follower engagement |
devpub dashboard |
Complete analytics with top articles table |
🔍 Discovery
| Command | Description |
|---|---|
devpub trends |
Trending topics on Dev.to right now |
devpub search "query" |
Keyword search for articles |
devpub search "query" --semantic |
AI-powered search by meaning (not just keywords) |
devpub comments <article_id> |
Read the threaded comments on an article (read-only) |
🔧 Utilities
| Command | Description |
|---|---|
devpub whoami |
Show your Dev.to profile |
devpub doctor |
Check API connectivity and config |
devpub --version |
Show version |
⚙️ Configuration
devpub looks for your API key in this order:
- Environment variable:
DEVPUB_API_KEYorDEVTO_API_KEY - Project-level:
.devpub/.env - Global:
~/.devpub/.env
🔑 Get your API key at: https://dev.to/settings/extensions
🖼️ Image uploads
devpub upload is the one command your API key cannot power: the Forem API V1 has
no image endpoint, so devpub posts to the same session-authenticated endpoint the
web editor uses. That needs two extra values:
DEVPUB_SESSION_COOKIE=... # the _Devto_Forem_Session cookie
DEVPUB_CSRF_TOKEN=... # content of <meta name="csrf-token">
Both are visible in DevTools on https://dev.to/new while logged in. Run
devpub upload once without them and it prints where to click.
⚠️ These are login credentials, not a scoped key. Keep them in
.devpub/.env(gitignored bydevpub init) and expect to re-copy them when they expire -- uploads start failing with a 401 or 403 when they do.
📁 Project Structure
After devpub init, your project looks like:
my-blog/
.devpub/
.env # Your API key (gitignored)
config.yml # Project settings
articles/
my-post.md # Your articles with frontmatter
📝 Article Frontmatter
---
title: "Your Article Title"
published: false
description: "Brief description for SEO"
tags: python, tutorial, beginners
cover_image: https://example.com/image.png
series: "My Series Name"
canonical_url: https://myblog.com/original-post
---
Your article content in Markdown...
🧪 Project Status
devpub is in beta. Core functionality works and is tested against the live Dev.to API, but:
- ⚠️ The API surface is large and some edge cases may not be handled
- ⚠️ Error messages could be more specific in some situations
- ⚠️ Performance for accounts with 500+ articles could be improved
We follow semantic versioning. Until v1.0, minor versions may include breaking changes (documented in CHANGELOG.md).
🤝 Contributing
We welcome contributions of all kinds! See CONTRIBUTING.md for details.
Quick version:
git clone https://github.com/simplynadaf/devpub.git
cd devpub
pip install -e ".[dev]"
pytest
Ways to contribute
- 🐛 Report bugs -- open an issue
- 💡 Request features -- open an issue
- 🔧 Fix bugs -- check good first issues
- 📝 Improve docs -- README, docstrings, examples
- ✅ Add tests -- especially for edge cases
Before submitting a PR
- Fork the repo and create a branch
- Make your changes
- Run
pytestandruff check src/ tests/ - Open a PR with a clear description
🔒 Security
If you discover a security vulnerability, please report it responsibly. See SECURITY.md for details. Do not open a public issue for security vulnerabilities.
📄 License
MIT -- use it however you want.
🙏 Acknowledgments
- Built on the Forem API that powers Dev.to
- CLI powered by Click
- Terminal output by Rich
- HTTP by httpx
Made with ❤️ by Sarvar Nadaf
⭐ If devpub saves you time, consider giving it a star!
Metadata
Release files for devpub 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| devpub-0.4.0.tar.gz | 306.7 kB | Without provenance | Details for devpub-0.4.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| devpub-0.4.0-py3-none-any.whl | Python 3 | none | any | Details for devpub-0.4.0-py3-none-any.whl |
Total release size: 342.0 kB
Release files / devpub-0.4.0.tar.gz
| Download URL | devpub-0.4.0.tar.gz |
|---|---|
| Size | 306.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0f24afd9355472303f583ef70aa41f1116658b751c3fe1950a91f077cda6c9fc
|
|
BLAKE2b-256 checksum How to use checksums |
9dcb861d967fb731086f6ed1fe5c8ebd4dc7bc302e26a9bf6d163450e7b1ee3e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Release files / devpub-0.4.0-py3-none-any.whl
| Download URL | devpub-0.4.0-py3-none-any.whl |
|---|---|
| Size | 35.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1bbd0b5665c95b948924c37e18695e89d9633321cf528e87ff80a5a17f2ffd9e
|
|
BLAKE2b-256 checksum How to use checksums |
ce1d6fb6289766cdeeb4f05b912e60baff4e570bf7543a2ca138cb3d1f706624
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Security for devpub 0.4.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.