Skip to content

blog-writing-reminder.sh

.claude/hooks/blog-writing-reminder.sh

UserPromptSubmit

Surfaces the blog conventions at the moment they're needed, instead of carrying them always-on. • prompt is about WRITING / drafting a blog post → inject a pointer to the house voice (docs/agents/blog-writing.md) • prompt says "this could make a good blog post" / "blog this" → suggest the to-blog-issue skill, which captures the idea as a Blog post issue Reminder only; Claude decides whether to act. Registered in settings.json under UserPromptSubmit. jq parses the hook's stdin JSON ({prompt: "..."}).

Source

bash
#!/usr/bin/env bash
#
# UserPromptSubmit hook — surfaces the blog conventions at the moment they're
# needed, instead of carrying them always-on.
#
#   • prompt is about WRITING / drafting a blog post  → inject a pointer to the
#     house voice (docs/agents/blog-writing.md)
#   • prompt says "this could make a good blog post" / "blog this" → suggest the
#     `to-blog-issue` skill, which captures the idea as a `Blog post` issue
#
# Reminder only; Claude decides whether to act. Registered in settings.json under
# UserPromptSubmit. jq parses the hook's stdin JSON ({prompt: "..."}).

set -euo pipefail

input="$(cat)"
prompt="$(jq -r '.prompt // empty' <<<"$input")"
[ -n "$prompt" ] || exit 0

# Lowercase once for case-insensitive matching.
lc="$(printf '%s' "$prompt" | tr '[:upper:]' '[:lower:]')"

emit() {
  jq -n --arg ctx "$1" \
    '{hookSpecificOutput: {hookEventName: "UserPromptSubmit", additionalContext: $ctx}}'
  exit 0
}

# Capture trigger — the maintainer is flagging an idea, not asking to write now.
case "$lc" in
  *"good blog post"*|*"blog this"*|*"capture"*"blog"*|*"blog idea"*|*"blog post idea"*)
    emit "The maintainer is flagging a blog-post idea. Run the \`to-blog-issue\` skill: capture it as a single GitHub issue labelled \`Blog post\` (a braindump an agent can later draft from), backlog, no milestone. Surface the draft and confirm before filing. Don't draft the post itself now — the issue is the deliverable."
    ;;
esac

# Writing intent — drafting / editing / restyling an actual post.
if printf '%s' "$lc" | grep -qE 'blog' && \
   printf '%s' "$lc" | grep -qE 'writ|draft|post|style|voice|tone|rewrite|publish|wiki'; then
  emit "This is about writing a blog post. Follow the house voice in docs/agents/blog-writing.md: first-person testimony, a recognisable-scenario hook, varied rhythm (short punches beside longer lines), NO em-dash sentence breaks (use short sentences + colons), contrast, signpost transitions, paragraph closers that land, and an ending that hands agency back rather than summarising. Posts live in harness-dashboard/blog/; build with \`cd harness-dashboard && npm run build\`."
fi

exit 0