back to posts
#43 Part 7 2026-01-14 10 min

The Command System: Two Commands That Run Everything

How /write-post and /publish-post orchestrate the entire content pipeline

The Command System: Two Commands That Run Everything

My entire publishing workflow is two commands: /write-post and /publish-post. Everything else is orchestration.


The Philosophy

Commands should do one thing well. But that one thing can be complex.

/write-post handles everything about creating content. /publish-post handles everything about deploying it.

Clear separation. No overlap. Run them in sequence or independently.


Command 1: /write-post

Purpose: Create a new blog post from scratch or from an outline.

What it does:

/write-post "Title of My Post"


┌─────────────────────────────────────┐
│ 1. CHECK EXISTING CONTENT           │
│    - Does this post already exist?  │
│    - Is there an outline to use?    │
└─────────────────────────────────────┘


┌─────────────────────────────────────┐
│ 2. GENERATE FRONTMATTER             │
│    - title: from argument           │
│    - date: today's date             │
│    - part: ask or infer             │
│    - readTime: estimate from length │
│    - tags: suggest relevant ones    │
└─────────────────────────────────────┘


┌─────────────────────────────────────┐
│ 3. CREATE FILE                      │
│    - Next available number          │
│    - Slugified title                │
│    - Path: posts/XX-slug.md         │
└─────────────────────────────────────┘


┌─────────────────────────────────────┐
│ 4. DRAFT CONTENT                    │
│    - If outline exists, follow it   │
│    - If not, create structure       │
│    - Match blog voice/style         │
└─────────────────────────────────────┘


┌─────────────────────────────────────┐
│ 5. REVIEW                           │
│    - Show the draft                 │
│    - Ask for changes                │
│    - Iterate until approved         │
└─────────────────────────────────────┘

Example:

User: /write-post "Rate Limiting Without State"

PAI: I found an outline for this topic in outlines-and-drafts/.
     Using that as the foundation.

     Creating: blog-site/src/content/posts/44-rate-limiting-stateless.md

     Frontmatter:
     - title: "Rate Limiting Without State: The MCP Paradox"
     - date: "2026-01-20"
     - part: 4
     - readTime: "12 min"
     - tags: ["mcp", "rate-limiting", "architecture"]

     [Drafts the post...]

     Ready for review. Want me to make any changes?

Command 2: /publish-post

Purpose: Deploy a post to the blog and optionally cross-post to Substack.

What it does:

/publish-post [path-or-number]


┌─────────────────────────────────────┐
│ 1. IDENTIFY THE POST                │
│    - From argument: path or #       │
│    - Or: most recently modified     │
└─────────────────────────────────────┘


┌─────────────────────────────────────┐
│ 2. VALIDATE                         │
│    - Frontmatter complete?          │
│    - Required fields present?       │
│    - Build succeeds?                │
└─────────────────────────────────────┘


┌─────────────────────────────────────┐
│ 3. DEPLOY TO BLOG                   │
│    - git add                        │
│    - git commit                     │
│    - git push                       │
│    - Wait for Cloudflare deploy     │
└─────────────────────────────────────┘


┌─────────────────────────────────────┐
│ 4. CROSS-POST (if requested)        │
│    - Open Substack                  │
│    - Create post                    │
│    - Paste content                  │
│    - Upload image                   │
│    - Publish                        │
└─────────────────────────────────────┘


┌─────────────────────────────────────┐
│ 5. VERIFY                           │
│    - Blog URL live?                 │
│    - Substack URL live?             │
│    - Report results                 │
└─────────────────────────────────────┘

Example:

User: /publish-post 43

PAI: Publishing post #43: "The Command System"

     ✓ Frontmatter valid
     ✓ Build succeeds
     ✓ Git commit: "Add post #43: The Command System"
     ✓ Pushed to origin
     ✓ Cloudflare deploy triggered

     Cross-post to Substack?

User: Yes

PAI: ✓ Substack post created
     ✓ Content pasted
     ✓ Image uploaded
     ✓ Published

     Live at:
     - Blog: https://operationalsemantics.dev/posts/43-blog-meta-command-system
     - Substack: https://myronkoch.substack.com/p/the-command-system

     AutoRAG will index within 10 minutes.

The Outlines Workflow

Posts often start as outlines in outlines-and-drafts/:

outlines-and-drafts/
├── cloudflare-ai-pipeline-series-outline.md
├── blog-meta-tutorial-series-outline.md
├── local-voice-pai-outline.md
└── fire-for-prometheus-outline.md

When /write-post runs, it checks this directory first. If an outline exists for the topic, it uses that structure instead of starting from scratch.

The flow:

Idea → Outline (in outlines-and-drafts/)


         /write-post uses outline


              Draft post


               Review/edit


            /publish-post


         Move outline to published/

Outlines that become posts get moved to outlines-and-drafts/published/ to track what’s been used.


Frontmatter Auto-Completion

The commands handle frontmatter intelligently:

FieldAuto-generated
titleFrom command argument
dateToday’s date
partInferred from content or asked
readTimeCalculated from word count
descriptionSummarized from content
tagsSuggested based on content
authorDefault: “Myron Koch”

If something’s missing or wrong, the command asks before proceeding.


Build Verification

Before committing, /publish-post runs the build:

cd blog-site && npm run build

This catches:

If the build fails, the command stops and shows the error. No broken deploys.


The Git Commit Format

Commits follow a consistent format:

Add post #43: The Command System

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

This makes the git log readable:

60d5377 Add post #43: The Command System
04d2f62 Add post #42: AI-Powered Cross-Posting
94b5187 Add post #41: The Chatbot Architecture
02d2b03 Add post #40: Astro + Cloudflare Pages
9af3057 Add post #39: The Pipeline Vision

Error Handling at Each Phase

PhasePossible ErrorHandling
ValidateMissing frontmatterPrompt to add it
BuildSchema violationShow error, fix, retry
GitMerge conflictAsk for resolution
PushAuth failedPrompt to re-auth
SubstackLogin expiredAsk user to login
UploadFile not foundAsk for correct path
PublishRate limitedWait and retry

Each phase can fail independently. The command reports where it failed and what to do.


Silent vs. Loud Publishing

Two modes:

Silent drop: Publish without promotion

/publish-post 43 --silent

Loud launch: Full promotion

/publish-post 43 --announce

Default is silent. You choose when to make noise.


Batch Operations

For bulk publishing:

/publish-post 39 40 41 42 43 --silent

Publishes all five posts sequentially without email notifications. Useful for backfilling or silent drops.


Command Location

Commands live in the Claude Code skills directory:

~/.claude/
├── commands/
│   ├── write-post/
│   │   └── prompt.md      # /write-post definition
│   └── publish-post/
│       └── prompt.md      # /publish-post definition
└── skills/
    └── substack-images/
        └── SKILL.md       # Image generation workflow

Each command is a prompt file that defines:


Why Commands, Not Scripts

Why not just write bash scripts?

Commands are conversational.

Scripts are rigid.

The command system combines the reliability of automation with the flexibility of an assistant.


Adding New Commands

To add a new command:

  1. Create ~/.claude/commands/your-command/prompt.md
  2. Define the command behavior
  3. It’s immediately available as /your-command

No deployment. No compilation. Just add the file.


Summary

CommandPurposeKey Actions
/write-postCreate contentDraft, frontmatter, review
/publish-postDeploy contentValidate, build, git, cross-post

Two commands. Entire workflow.

The complexity is hidden. The interface is simple.


Next up: When RSS Parsing Ships - The last manual step disappears.