- Initial thoughts
- The foundation: sinedied's devto-cli
Content enrichment
- Diagrams as code with Kroki
- Automatic table of contents
- ANSI-styled terminal output
Bulk operations
- Smart file renaming
- Article badges generation
- Broken link checking
Environment
- Organization publishing
- Proxy support for corporate environments
- Wrapping up
- Further reading
If you write articles on dev.to using markdown files and Git, there's a CLI that might save you a few headaches. I added a bunch of features to a fork of it. Here's what came out.
Initial thoughts
The DEV Weekend Challenge asks to build something for a community. Mine happens to be the people writing technical articles right here on dev.to — the ones who keep a folder full of markdown files and occasionally wonder why they didn't just use the browser editor. Occasionally.
There's an existing CLI called devto-cli that handles the heavy lifting of publishing markdown to dev.to. I forked it and added a few things I kept wishing it had.
The foundation: sinedied's devto-cli
devto-cli by Yohan Lasorsa is a Node.js CLI that turns local markdown files into dev.to articles. No browser editor, no copy-pasting. Just your text editor and Git.
It relies on a personal public github repo for assets such as images.
It handles:
Article creation from templates with front matter
Push to dev.to via the API
Stats for published articles
GitHub-hosted images with automatic URL rewriting- A GitHub Action for automated publishing
Solid tool. I just kept running into small things it didn't cover, so I forked it and got to work.
Content enrichment
These features transform what you write into richer content on dev.to.
Diagrams as code with Kroki
Write a diagram in your markdown:
<!-- diagram-name: shell-runner-well-sized-before-optimization -->
'''mermaid
%%{init: {'theme':'forest'}}%%
gantt
title Shell Executor - Well-Sized Server (Before Extreme Optimization)
dateFormat X
axisFormat %s
section Waiting
Sufficient capacity :active, wait, 0, 1s
section Server
Resource allocation :active, prep, after wait, 1s
section OS
Native system (no container) :active, env, after prep, 1s
section Source Code
Git fetch (local reuse) :active, git, after env, 2s
section Cache
Restore (local filesystem) :active, cache, after git, 2s
section Artifacts
Download artifacts :done, art, after cache, 3s
section Execution
Scripts :done, exec, after art, 10s
section Termination
Upload cache (local) :active, save1, after exec, 1s
Upload artifacts (GitLab network) :done, save2, after save1, 4s
'''
Run:
dev diaggen my-article.md
The CLI sends the block to Kroki, gets back an image, and saves it locally. After committing the image to your assets repo, dev push replaces the code block with an image link pointing to GitHub — dev.to never sees the mermaid source. But your local source is preserved, letting you fix the diagram when needed. Supports mermaid, PlantUML, BlockDiag, and many others.
See 13 diagrams generated this way in GitLab Runners: Which Topology for Fastest Job Execution?
Automatic table of contents
Add two markers anywhere in your article:
<!-- TOC start -->
<!-- TOC end -->
Then:
dev push --update-toc my-article.md
The CLI scans headings and generates anchored links between the markers. The current article uses it.
ANSI-styled terminal output
Choosing colors in a displayed log is a must. The CLI converts a simple pseudo-ANSI syntax into styled HTML blocks.
In your markdown, use {{TAG}} to start a color. The {{/}} closing tag is optional — without it, the color continues until the next tag or end of block. This means multiline content stays colored naturally:
'''ansi
{{RED}}The quick brown fox{{BOLD_RED}} jumps over the lazy dog
{{GREEN}}The quick brown fox{{BOLD_GREEN}} jumps over the lazy dog
{{YELLOW}}The quick brown fox{{BOLD_YELLOW}} jumps over the lazy dog
{{ORANGE}}The quick brown fox{{BOLD_ORANGE}} jumps over the lazy dog
{{BLUE}}The quick brown fox
{{BOLD_BLUE}}jumps over the lazy dog
{{MAGENTA}}The quick brown fox{{BOLD_MAGENTA}} jumps over the lazy dog
{{CYAN}}The quick brown fox{{BOLD_CYAN}} jumps over the lazy dog
{{WHITE}}The quick brown fox{{BOLD_WHITE}} jumps over the lazy dog
{{GRAY}}The quick brown fox{{BOLD_GRAY}} jumps over the lazy dog
{{BG_RED}}The quick brown fox{{/}} jumps over the lazy dog
{{BG_GREEN}}The quick brown fox{{BG_YELLOW}} jumps over the lazy dog
{{BG_ORANGE}}The quick brown fox
jumps over the lazy dog
{{BG_BLUE}}The quick brown fox{{BG_MAGENTA}} jumps over the lazy dog
{{BG_CYAN}}The quick brown fox{{BG_WHITE}} jumps over the lazy dog
{{BG_GRAY}}The quick brown fox{{/}} jumps over the lazy dog
'''
After dev push, this renders as a properly colored terminal block on dev.to — 9 base colors × 3 variants (plain, bold, background). No closing tag needed: colors flow until the next tag, even across lines. All colors are overridable via .env variables (ANSI_RED=#ff6161, etc.).
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox
jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox
jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
Bulk operations
Run one command, affect all your articles at once.
A shared footer file (e.g. "Further reading" links) kept in sync across all articles. Update the footer file once, then push all — the CLI finds the # Further reading marker in each article and replaces everything below it with the shared footer content:
dev push --update-toc "*.md"
Smart file renaming
When an article title changes, the filename should follow:
dev rename "*.md"
🦊 GitLab CI: A Battle-Tested Mono-Repo CI/CD Architecture
GITLAB_mono-repo-architecture.md → GITLAB_ci-battle-tested-mono-repo-ci-cd-architecture.md
🔍 Every Developer Should Review Code — Not Just Seniors
MISC_every-developer-should-review-code.md → MISC_every-developer-review-code-seniors.md
Strips emoji, filters 80+ English stop words (a, the, and, how…), keeps the first 5 significant words, preserves the date/category prefix.
Article badges generation
Generate visual badges for a GitHub profile README:
dev badges --jpg "*.md"
Each badge overlays the article's cover image with its title, publication date, view count, and reading time. Articles are auto-grouped by category (extracted from filename prefix) and sorted by date within each group.
The most viewed articles get golden stars ⭐ — popularity is measured relative to the 2nd most viewed article (to avoid one viral post skewing everything). ≥90% of that reference = 3 stars, ≥50% = 2, ≥25% = 1. Stars and stats refresh on every run.
Produces a _ARTICLES.md file with badge images linking to each article. Here's my GitLab section:
Embed the file in a pinned article and all your articles become browsable from one place. Badges stay up to date with every dev badges run.
Broken link checking
Before publishing:
dev checklinks my-article.md
Catches dead URLs before readers do. Smart enough to treat HTTP 403/429 as "probably fine" (bot blocking, not a dead link). Also validates cover image and canonical URL from front matter. Works on all articles at once with dev checklinks "*.md".
Environment
Configure once, forget about it.
Organization publishing
One line in .env:
DEVTO_ORG=zenika
The CLI adds organization: zenika to the front matter and resolves the org ID automatically on push.
Proxy support for corporate environments
export HTTPS_PROXY=http://proxy.company.com:8080
dev push
All API calls, Kroki requests, and link checks go through the proxy. Self-signed certificates handled too.
Wrapping up
This fork started as a one-line proxy fix and kept growing from there. Every feature was added because I needed it, not because it looked good on a feature list.
It's open source at github.com/bcouetil/devto-cli. If you write on dev.to with markdown files, it might be useful. Or not — the browser editor is fine too. Probably.
Illustrations generated locally by Draw Things using Flux.1 [Schnell] model
Further reading
This article was enhanced with the assistance of an AI language model to ensure clarity and accuracy in the content, as English is not my native language.


















SOCIAL SHARE CARD GENERATOR