diff --git a/blog/feed.xml b/blog/feed.xml
index 55c4125..4f0dcc7 100644
--- a/blog/feed.xml
+++ b/blog/feed.xml
@@ -4,7 +4,7 @@
https://alexanderwhitestone.com/blog/
- 2026-03-19T01:42:22Z
+ 2026-03-19T01:45:33ZAlexander Whitestone
diff --git a/scripts/aw-post b/scripts/aw-post
index 1a1961a..3b1c186 100755
--- a/scripts/aw-post
+++ b/scripts/aw-post
@@ -2,51 +2,104 @@
# aw-post — Quick-post a scroll from the command line
#
# Usage:
-# aw-post "Title of the Post"
-# aw-post "Title" < body.md
-# echo "Post body here" | aw-post "Title"
+# aw-post "Title" # Create empty post, open for editing
+# aw-post "Title" < body.md # Pipe body from stdin
+# echo "Post body" | aw-post "Title" # Pipe body from stdin
+# aw-post --file thoughts.md # Post from a file (title from first line)
+# aw-post --from-x "Tweet text here" # Port an X/Twitter post
#
-# Creates a new markdown file in blog/posts/ with frontmatter,
-# then rebuilds the blog index, post pages, and RSS feed.
+# Creates a markdown file in blog/posts/, rebuilds the blog.
set -euo pipefail
REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)"
BLOG_DIR="${REPO_DIR}/blog/posts"
-
-if [ $# -lt 1 ]; then
- echo "Usage: aw-post \"Title of the Post\""
- echo " Pipe or redirect body content via stdin."
- exit 1
-fi
-
-TITLE="$1"
DATE=$(date +%Y-%m-%d)
-SLUG=$(echo "$TITLE" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-')
-FILENAME="${DATE}-${SLUG}.md"
-FILEPATH="${BLOG_DIR}/${FILENAME}"
-if [ -f "$FILEPATH" ]; then
- echo "Error: $FILEPATH already exists"
- exit 1
-fi
+slugify() {
+ echo "$1" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-' | head -c 60
+}
-# Read body from stdin if available
-BODY=""
-if [ ! -t 0 ]; then
- BODY=$(cat)
-fi
+create_post() {
+ local title="$1"
+ local body="$2"
+ local slug
+ slug=$(slugify "$title")
+ local filename="${DATE}-${slug}.md"
+ local filepath="${BLOG_DIR}/${filename}"
-cat > "$FILEPATH" << EOF
+ if [ -f "$filepath" ]; then
+ echo "Error: $filepath already exists"
+ exit 1
+ fi
+
+ cat > "$filepath" << EOF
---
-title: "${TITLE}"
+title: "${title}"
date: ${DATE}
---
-${BODY}
+${body}
EOF
-echo "Created: ${FILEPATH}"
+ echo "Created: ${filepath}"
+ python3 "${REPO_DIR}/scripts/build.py"
+}
-# Rebuild the blog
-python3 "${REPO_DIR}/scripts/build.py"
+# Parse arguments
+case "${1:-}" in
+ --file)
+ # Post from a file — title from first non-empty line
+ if [ -z "${2:-}" ] || [ ! -f "${2:-}" ]; then
+ echo "Usage: aw-post --file "
+ exit 1
+ fi
+ BODY=$(cat "$2")
+ # Extract title: first line starting with # or first non-empty line
+ TITLE=$(echo "$BODY" | grep -m1 '^#' | sed 's/^#* *//' || echo "$BODY" | grep -m1 '.' || echo "Untitled")
+ if [ -z "$TITLE" ]; then
+ TITLE="Untitled"
+ fi
+ # Strip the title line from body if it was a markdown header
+ BODY=$(echo "$BODY" | sed '1{/^#/d;}')
+ create_post "$TITLE" "$BODY"
+ ;;
+
+ --from-x)
+ # Port an X/Twitter post — the text becomes both title and body
+ if [ -z "${2:-}" ]; then
+ echo "Usage: aw-post --from-x \"Tweet text here\""
+ exit 1
+ fi
+ TEXT="$2"
+ # Title: first 60 chars, cleaned up
+ TITLE=$(echo "$TEXT" | head -1 | cut -c1-60 | sed 's/[[:space:]]*$//')
+ create_post "$TITLE" "$TEXT"
+ ;;
+
+ --help|-h)
+ echo "aw-post — Quick-post a scroll to The Scrolls"
+ echo ""
+ echo "Usage:"
+ echo " aw-post \"Title\" Create a post (body from stdin)"
+ echo " aw-post --file thoughts.md Post from a markdown file"
+ echo " aw-post --from-x \"Tweet text\" Port an X/Twitter post"
+ echo " aw-post --help Show this help"
+ ;;
+
+ "")
+ echo "Usage: aw-post \"Title of the Post\""
+ echo " See: aw-post --help"
+ exit 1
+ ;;
+
+ *)
+ # Standard mode: title as arg, body from stdin
+ TITLE="$1"
+ BODY=""
+ if [ ! -t 0 ]; then
+ BODY=$(cat)
+ fi
+ create_post "$TITLE" "$BODY"
+ ;;
+esac