Skip to content
Back to skills

Devto

ASecurity

Publish and manage articles on Dev.to (Forem API) from local markdown, using the API key stored in 1Password. Use when the user wants to post, draft, update, publish, unpublish, or list their Dev.to articles, cross-post a blog post or vault note to Dev.to, or mentions dev.to, DEV Community, or the Forem API.

  • 2 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 2, 2026
ai-agentsbashapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 2, 2026

npx -y skills add magnusrodseth/dotfiles --skill devto --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Devto?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Devto
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/magnusrodseth-devto/badge)](https://www.skillsdirectory.com/skills/magnusrodseth-devto)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: devto
description: Publish and manage articles on Dev.to (Forem API) from local markdown, using the API key stored in 1Password. Use when the user wants to post, draft, update, publish, unpublish, or list their Dev.to articles, cross-post a blog post or vault note to Dev.to, or mentions dev.to, DEV Community, or the Forem API.
---

# Dev.to

Publish markdown to Dev.to through the Forem API. Authenticated as `magnusrodseth` (user id `3803258`).

The key lives in 1Password at `op://Private/Dev.to API Key/credential` on the personal account (`my.1password.eu`). **Never read it into a variable that gets printed, never paste it into a URL, never echo it.** `scripts/devto.sh` resolves it per call and keeps it out of stdout.

## The two rules that matter

**Draft first, always.** `published` defaults to `false`. Create the draft, hand the user the edit URL, let them read it rendered in Dev.to's own editor. Publishing is a separate command.

**Publishing is close to irreversible.** The Forem API has **no DELETE endpoint**. Once published, an article mints a public URL that gets crawled, cached and syndicated within minutes. `unpublish` hides it from the site but does not undo distribution. Treat `publish` as outward-facing: confirm explicitly with the user before running it, every time, even if they authorized a publish earlier in the session.

## Commands

```bash
S=~/.claude/skills/devto/scripts/devto.sh

bash $S whoami                              # verify auth
bash $S list [published|unpublished|all]    # your articles, id + title + state
bash $S get <id>                            # one article as JSON

bash $S draft <file.md> [--title T] [--tags "a,b,c"] [--description D] [--canonical URL]
bash $S update <id> <file.md> [same flags]
bash $S publish <id>                        # GATED: confirm with the user first
bash $S unpublish <id>                      # hide a published article
```

`draft` and `update` read the markdown file, strip any YAML frontmatter (see below), and send it as `body_markdown`. Both print the article id and both URLs on success.

## The frontmatter trap

Forem parses YAML frontmatter **inside `body_markdown`** and lets it override the JSON fields. Vault notes and blog posts almost always carry frontmatter with `type:`, `created:`, `tags:`, `related:` and other keys Forem does not understand, which produces a mangled post or a 422.

`scripts/devto.sh` strips a leading `---` block before sending. That is the correct default. If the user genuinely wants Forem-style frontmatter to drive the metadata, pass `--keep-frontmatter` and make sure the block contains only keys Forem accepts (`title`, `published`, `tags`, `series`, `cover_image`, `canonical_url`, `description`).

When publishing a vault note, the publishable text is usually only the part below a `---` separator partway down the file. Read the file and confirm what the article actually starts at rather than assuming the whole file is the post.

## Field rules

- `tags` on **write** is a comma-separated **string**, max **4** tags, lowercase alphanumeric only. On **read** the same data comes back as `tag_list`, an array. Do not send an array.
- `title` is required on create unless frontmatter supplies it.
- `description` is the social and SEO snippet. Keep it under about 150 characters.
- `canonical_url` points at the original when cross-posting, so the source keeps the SEO credit.
- `series` groups posts; a new string starts a new series.
- `main_image` is the cover image URL.

## Responses

`201` created, `200` updated, `401` bad or missing key, `422` unprocessable (usually a bad tag, a duplicate title, or frontmatter Forem could not parse). On `422` the body names the field, so print it rather than guessing.

Full schema, error shapes and less common fields: [REFERENCE.md](REFERENCE.md)

## Sponsored or client work

Dev.to requires disclosure on paid or sponsored posts. If the article is sponsored, confirm the disclosure is in the body before creating the draft, not after. An undisclosed sponsored post risks the account.

Files in this skill

  • SKILL.md4 KB
  • scripts/devto.sh5.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.