Install
openclaw skills install @jhauga/make-blog-postWrite up independently reusable code as an informational blog post walkthrough covering one specific purpose. Use when writing or touching a function, method, class, script, or tool that works outside the current project, or when asked to "make a blog post", "write a blog post about this", "draft a
openclaw skills install @jhauga/make-blog-postTurn independently reusable code into an informational blog post that walks a reader through one specific purpose. The post is built here; publishing it anywhere public always waits on the user.
If the code does not qualify (see Step 1), do nothing and do not mention this skill.
These settings control how the rest of the skill is applied. Treat the listed value as the default and change it only when the user says otherwise.
| Setting | Default | Meaning |
|---|---|---|
automation-mode | false | true when running inside an unattended or agent-driven flow. false when a person is present for the exchange. |
post-store-root | host OS entry under Step 3 | The archive root for posts. Resolve the home portion from the environment (%USERPROFILE% on Windows, $HOME on macOS and Linux) rather than hardcoding it. |
allow-in-workspace-storage | true | When true, the post may live inside the current workspace instead of the post store, if the workspace is a fitting home. |
delivery-mode | auto | auto picks the mode per Step 4. direct, staged, or paste pins one mode. |
seo-optimization | auto | auto picks the level per references/seo-optimization.md. full, light, venue, or internal pins one level. off skips SEO entirely. |
Confirmation (Step 8 and Step 9) is not configurable. It applies in both modes.
The code qualifies only when all of these are true:
If any condition is false, stay silent. Do not mention this skill or the post workflow at all.
Before drafting, check the post store (see Step 3) for an existing post covering the same code. If one exists, skip.
dir /s /b "%USERPROFILE%\Documents\blogPosts\*.md"
When a pseudo-blog venue is the destination, also check whether an existing post on the same code already went out to that venue. If one did, skip.
If the user names a destination, use it. Everything below is inference, and inference loses to an instruction.
When no destination was named, read the working context:
| Question | What it means |
|---|---|
| Is this a repository or a loose folder? | A folder with no version control is scratch work. Its posts go to the post store. |
| Is the workspace a blog or site? | A posts folder (_posts/, content/posts/, src/content/blog/), a generator config (_config.yml, hugo.toml, astro.config.mjs), or a body of dated articles. The workspace is the natural home. See references/blog-platforms.md. |
| Is a pseudo-blog venue in play? | The user may publish standalone posts somewhere that is not a blog, such as a gist. See references/pseudo-blog-venues.md. |
| Is the workspace a documentation set? | A docs/ tree or a documentation-only repository. A walkthrough may belong there as a new doc file. |
| Is the workspace an application or library? | The code lives here but the writing does not. Store the post in the post store and consider only a link back (see Step 10). |
| Does the repository sit in an organization folder? | A repository directly under GitHub uses the blogPosts / <category> form. A repository under GitHub / <organization> uses the blogPosts / <organization> / <category> form. |
From that reading, settle two questions and state both answers at Gate 1:
allow-in-workspace-storage is
true, and the post fits the existing structure. Never create a new
documentation area just to hold a post.When the workspace is a blog or site, match its existing posts: same folder, same file extension, same front matter fields, same naming convention. The layout in Step 6 is the fallback for the post store, not an override of a site's own format.
Determine the host OS first, then use only that OS's forms. Never mix forms from two OS blocks in one path.
Windows:
C:\Users\<user>\<blogSite>\<category>\
C:\Users\<user>\Documents\blogPosts\<category>\
C:\Users\<user>\Documents\blogPosts\<organization>\<category>\
macOS:
/Users/<user>/<blogSite>/<category>/
/Users/<user>/Documents/blogPosts/<category>/
/Users/<user>/Documents/blogPosts/<organization>/<category>/
Linux:
/home/<user>/<blogSite>/<category>/
/home/<user>/Documents/blogPosts/<category>/
/home/<user>/Documents/blogPosts/<organization>/<category>/
<blogSite> is a local checkout of a blog or site the user publishes to. Use
that form only when the post is going into an existing site, and place the file
where the site keeps its posts rather than at the site root.
<category> is a short, lowercase, hyphenated name for the code's domain, such
as string-utils, file-io, powershell, or date-time. Reuse an existing
category folder when one fits. Name the post file after what the code does
(e.g. slugify-text.md), not after the project.
/ is macOS and Linux only.\ on Windows and / on macOS and
Linux, in every path this skill writes or reports.%USERPROFILE% or $HOME) over a literal home path.LF
when the target is a site repository that normalizes line endings.<config-dir>.Where the post belongs and how it reaches the user are separate questions. Settle this before Gate 1, because it decides whether a file is written at all.
| Mode | What is produced | When to use it |
|---|---|---|
direct | The post file, written to the resolved destination. | The destination is a path this session can write to, and the user wants it written. |
staged | The post file, written to a staging path, plus a hand-off summary for the user to post manually. | The final destination is one only the user can reach: a hosted platform, an account-bound venue, or any site the user posts to by hand. |
paste | The post rendered in the reply, ready to copy. No file is written. | The user asked to see it, to be given something to paste, or for a draft to read before deciding. |
With delivery-mode set to auto, read the request:
direct.staged.paste.The reply is the deliverable, so it has to survive a single copy with no cleanup.
references/pseudo-blog-venues.md instead.The post is written, but the user does the posting.
Mode does not weaken the gates. Confirmation still comes first, and nothing reaches a public venue without approval.
These rules are absolute and apply to everything that goes into a post.
| # | Rule | Detail |
|---|---|---|
| 1 | Never include credentials or secure data | No API keys, tokens, passwords, secrets, connection strings, private URLs, internal hostnames or IPs, account IDs, environment variable values, file paths revealing user or machine names, or personal information. Substitute an obvious placeholder such as YOUR_API_KEY or https://api.example.com. |
| 2 | Use cliche sample data only | "Hello, World!", John Doe, Jane Smith, user@example.com, foo / bar / baz, 123 Main St, Lorem ipsum, 42, widgets, Acme Corp. |
| 3 | Never use prompt data | Do not copy, paraphrase, or recycle anything from the conversation, the user's request, or the repository's real data. No real names, project names, business terms, file names, or values from the working context. |
| 4 | Rewrite, do not copy | Generalize the code into a clean demonstration: rename project-specific identifiers to generic ones, strip unrelated logic, remove internal dependencies. |
The post explains one specific purpose of the code, framed as an informational walkthrough of how to use it. Include:
Keep it to one post file with one code sample. A walkthrough that needs several files is not a fit for this skill.
title: <Post title>
description: <One sentence stating what the post demonstrates>
slug: <lowercase-hyphenated-slug>
category: <category>
tags: <tag>, <tag>, <tag>
date: <YYYY-MM-DD>
---
<post body in Markdown>
The description is one sentence, written with no project or prompt details. It doubles as the meta description, so keep it between 140 and 160 characters and lead with what the reader gets.
When the workspace is a blog or site, its own front matter fields win over this layout. Map these values onto the fields that site already uses and drop any it does not read.
Read references/seo-optimization.md and apply the level matching the
destination settled in Step 3: full for a published site, light for the
post store, venue for a pseudo-blog venue, internal for a documentation
set. Keywords come from the technology, never from a project, client,
organization, repository, or internal product name.
Do not create or modify any file until the user confirms. Present, in a few lines:
Wait for confirmation. On a decline, stop and write nothing.
In paste mode there is no file to guard, so this gate does not need its own
round trip. State the subject, the destination shape, and the mode in the same
reply that carries the post.
After the post file is written, show the post and get approval before it is published, committed, or pushed anywhere.
automation-mode is true: show the full post content, then ask a
direct yes or no. Take no publishing action on silence or on anything short
of an explicit yes.automation-mode is false: show the full post content and ask for
approval, inviting edits. Apply any requested changes, show the revised post,
and ask again. Publish only on approval.In paste mode the rendered block is this gate: present it, invite edits, and
revise on request. In staged mode this gate closes at the hand-off summary.
Do not treat approval as permission to post on the user's behalf.
Publishing is a file operation. Do not call an external upload or CLI publishing tool from this skill. After Gate 2 approval:
references/pseudo-blog-venues.md, and report the venue
description and file name to use.Committing or pushing the post is a separate action and needs its own request from the user, as is uploading it to a pseudo-blog venue.
After the post is written, decide whether to add a link to it from the repository's documentation.
Add the link when both are true:
docs/ folder, or a doc
comment on the function), andDo not add the link when:
When adding it, place it next to the existing documentation for that code, on one line:
Walkthrough: <post URL or path>
Only if the post was approved and delivered successfully, end the response with exactly:
BLOG POST MADE
Delivered means the file was written in direct mode, the file and hand-off
summary were given in staged mode, or the post was rendered in paste mode.
If the user declines at either gate, say so in one sentence and do not print that line. If writing fails, report the failure in one sentence and do not print that line.
| Issue | Solution |
|---|---|
| Code fails the qualification test | Stay silent. Do not mention this skill or the post workflow at all. |
| Duplicate post found | Skip entirely. Do not create a second post for the same code. |
| Unsure which category folder to use | List existing folders under the post store root and reuse a matching one before creating a new one. |
| Post store root does not exist | Create category folders under an existing root only. If the root itself is missing, stop and ask. |
| Site build rejects the post | Open a neighboring post in the same folder and copy its front matter field set exactly. See references/blog-platforms.md. |
| Front matter renders as body text | The destination does not parse front matter. Reshape the post per references/pseudo-blog-venues.md. |
| Unsure whether to write a file | Ask at Gate 1. Writing an unwanted file is the more annoying error. |
references/blog-platforms.md - detection, posts folder, and front matter
contract for common static site generators and hosted platforms.references/pseudo-blog-venues.md - shaping a post for a venue with no front
matter, with a worked gist example.references/seo-optimization.md - optimization levels, keyword sourcing,
title, slug, headings, tags, linking, and structured data.