Imported from naoigcat/naoigcat.github.io (
.agents/skills/create-post/SKILL.md). Install upstream withnpx skills add naoigcat/naoigcat.github.io --skill create-post. Copyright stays with the author.
create-post
When the user runs this skill and provides a title (for example: bash-random-number), follow the steps below to create
the file.
Language
- Display title and body: Write the front matter
titlevalue ({display_title}) and all article body content (the Markdown after the closing front matter---) in Japanese. The user may still supply an ASCII/kebab-style slug for{filename_slug}; only the human-facing title and prose must be Japanese.
1. Determine the filename slug
Keep the user-provided title as {title} and introduce a separate variable {filename_slug} for the file name. Store a
value in {filename_slug} by converting the user input to ASCII kebab-case suitable for file names. Apply these rules
when generating it:
- First normalize
{title}with Unicode normalization NFKC. - Convert Japanese and other non-ASCII characters to ASCII as far as possible, using romanization or a transliteration library appropriate to the source language.
- Replace whitespace and runs of delimiter characters with a hyphen (
-). - Convert uppercase Latin letters to lowercase.
- Remove any character that is not a lowercase Latin letter, digit, or hyphen.
- Collapse consecutive hyphens into one, and trim leading and trailing hyphens.
- The final
{filename_slug}must match the regular expression^[a-z0-9-]+$. - If the conversion yields an empty string, treat it as an error and ask the user to re-enter the title. If you adopt a
fallback, state explicitly that you are appending a short random ID to produce
{filename_slug}.
2. Prepare fields
- Display title: Use a separate variable
{display_title}for front matter and display. It must be Japanese phrasing appropriate for the post (if the user gives an ASCII slug likebash-random-number, expand it to a natural Japanese title such asBashでの乱数生成). - Tags: Split
{filename_slug}on hyphens (-) and resolve{tag}from those segments.- The first segment is always the leading tag (this is the primary category, e.g.
git,sort,yaml). It comes first in the final list. - For the remaining segments, add a segment as an additional tag only when that segment is itself a meaningful
tag — typically a tool, platform, language, framework, or other well-known proper noun that already appears as
a tag elsewhere in
_posts/. Skip segments that are merely descriptive words. - Adjacent segments may be joined with a hyphen to form a single tag when together they spell one proper noun
(e.g.
github-copilot). - Render
{tag}as a space-separated list in the order the segments appear. - Examples:
bash-random-number→bash(randomandnumberare descriptive, not separate tags)sh-which-of-debian-utils→bash debian(debianis a platform tag; theshslug prefix maps to the existingbashprimary tag, see the note below)vscode-github-copilot-commit-message-generation→vscode github-copilotsort-bubble→sort(bubbleis descriptive, not a tag)
- When in doubt, prefer fewer tags and do not invent new tags that are not already used elsewhere in
_posts/. - Note: a few first-segment slugs are normalized to a canonical tag name (e.g.
sh-*→bash,objc-*→objective-c). Reuse the same normalization that recent posts use; check sibling posts under_posts/to confirm.
- The first segment is always the leading tag (this is the primary category, e.g.
3. Obtain date and time, then write the file
Capture the current instant immediately before creating the Markdown file — not at the start of the workflow and not
while still drafting body content or other assets. The front matter date and the file path must both reflect when
the post file is actually created.
Convert that instant to Asia/Tokyo (Japan Standard Time, JST). Use a timezone-aware API or library so results are
consistent across environments (for example: TZ=Asia/Tokyo date '+%Y %m %d %Y-%m-%d %H:%M:%S +0900',
Intl.DateTimeFormat with timeZone: 'Asia/Tokyo', date-fns-tz, or moment-timezone).
From that JST instant derive:
{year}: Four-digit Gregorian year (YYYY; example: 2026){month}: Two-digit month (MM; example: 04){day}: Two-digit day (DD; example: 10){date}: The same instant formatted asyyyy-mm-dd HH:MM:SS +0900(example:2026-04-10 22:05:36 +0900)
Create the new Markdown file at:
_posts/{year}/{month}/{year}-{month}-{day}-{filename_slug}.md
- Create parent directories if they do not exist.
- If a file already exists at that path, do not overwrite it without confirmation, or prompt the user to choose a different file name.
- Do not round
{date}to midnight or any other fixed clock time; use the captured second-level timestamp. - If preparation crosses midnight JST, re-capture the instant at write time so the directory, file name, and
dateall agree on the new calendar day.
After the file is written, optionally confirm alignment with the filesystem timestamp (for example on macOS:
stat -f '%SB' -t '%Y-%m-%d %H:%M:%S %z' '<path>'; on Linux: stat -c '%w' '<path>' or stat -c '%y' '<path>' when birth
time is unavailable). If the recorded date differs from the file-creation instant by more than a few seconds, update the
date: line to match the filesystem time (still formatted as yyyy-mm-dd HH:MM:SS +0900 in JST).
Front matter column alignment
For every scalar key: value line in YAML front matter, align values vertically so the first character of each
value sits on column 12 when counting positions from 1 at the row start. The longest key prefix in _posts/ is
sort_demo:; shorter keys pad with spaces immediately after : so every value aligns with rows that define sort_demo.
Concretely, after stripping surrounding whitespace from each scalar value, rebuild each line so the substring beginning
with key: and ending with delimiter spaces occupies exactly eleven characters, then append the trimmed value
(with no extra gap)—the value begins at column 12. Known keys resolve to the spacing counts in the numbered list below. If any
new front matter scalar key exceeds the width of sort_demo:, recompute padding for all scalar keys in that front matter
together so columns still agree.
Posts inherit layout: post from _config.yml (defaults); do not set layout in post front matter.
Mandatory keys layout:
---
title: {display_title}
date: {date}
tags: {tag}
---
When adding optional scalar keys (mathjax, mermaid, sort_demo), include only keys the post needs. If multiple
optional keys are present, list them in alphabetical order (mathjax before mermaid before sort_demo), using the
spacing reference.
title: …
date: …
tags: …
mathjax: true
mermaid: true
sort_demo: true
The fenced block above is illustrative (omit unused keys; wrap with front matter --- delimiters).
Spacing reference (ASCII spaces after colon before each value):
title: 5 spaces.date: 6 spaces.tags: 6 spaces.mathjax: 3 spaces.mermaid: 3 spaces.sort_demo: 1 space.
Optional front matter keys (semantics reminder):
mathjax: true—head.htmlloads the MathJax CDN script so kramdown$$...$$math renders.mermaid: true—head.htmlloads the Mermaid CDN script so Mermaid fenced code blocks render.sort_demo: true—head.htmlloads sort-demo CSS andsort-demo.jswhen using{% include sort-demo.html %}.
Set title to {display_title} and tags to {tag} (the space-separated list resolved in step 2, always starting with
the first segment of {filename_slug}). Write the article body in Japanese.
4. Run markdownlint
When creation or editing of the .md file is complete, run from the workspace root:
mise run lint
If lint reports errors, apply fixes (mise run lint -- --fix "<path-to-file.md>" for auto-fixable rules; edit manually for
the rest) and re-run until mise run lint exits 0. Do not treat the post as finished while markdownlint still reports
errors.
5. Regenerate tag JSON
After markdownlint passes, regenerate committed tag metadata under assets/tags/ from the workspace root:
mise run tags
This task runs scripts/generate-tags-json.swift (Docker + Jekyll export). Docker must be running; if the command fails,
report the exit code and stderr and do not commit until tag JSON is updated successfully.
When the command succeeds, stage any created, updated, or removed files under assets/tags/ together with the new post in
the commit step below.
6. Commit
Before committing the new file, run git rev-parse --is-inside-work-tree to verify you are inside a Git repository. If
not, stop and tell the user to run git init or work in an existing repository.
When running git add and git commit, capture standard error. On failure, report the exit code and error output as-is,
then suggest next steps such as retrying, checking with git status, or running git init if appropriate.
If everything is fine, commit with:
git add _posts/{year}/{month}/{year}-{month}-{day}-{filename_slug}.md assets/tags/
git commit -m "Add post \`{year}-{month}-{day}-{filename_slug}\`"
7. Report completion
Report the path and contents of the created file to the user.