From 1740743328faec6bf5e9d0e4da2cb0af6bcc1e29 Mon Sep 17 00:00:00 2001 From: TinyMind Bot Date: Thu, 9 Apr 2026 07:50:39 +0000 Subject: [PATCH] feat: add tinymind-blog skill for AI agents Add skill for posting thoughts and blog articles to TinyMind via GitHub API. Features: - Post thoughts with optional images - Post blog articles in markdown - Update about page - Upload images - Clean up unused images Supports configurable GitHub repository via TINYMIND_REPO environment variable. --- skills/tinymind/README.md | 54 +++++++++++++ skills/tinymind/SKILL.md | 165 ++++++++++++++++++++++++++++++++++++++ skills/tinymind/cli.sh | 155 +++++++++++++++++++++++++++++++++++ 3 files changed, 374 insertions(+) create mode 100644 skills/tinymind/README.md create mode 100644 skills/tinymind/SKILL.md create mode 100755 skills/tinymind/cli.sh diff --git a/skills/tinymind/README.md b/skills/tinymind/README.md new file mode 100644 index 0000000..3edf41a --- /dev/null +++ b/skills/tinymind/README.md @@ -0,0 +1,54 @@ +# TinyMind Blog Skill + +Post thoughts, blog articles, and update about page to TinyMind (tinymind.me) using GitHub. + +## Quick Start + +```bash +# Set environment variables +export TINYMIND_REPO="your-username/tinymind-blog" + +# Post a thought +./cli.sh thought "Hello world!" + +# Post a blog article +./cli.sh blog "My Post" /path/to/post.md + +# Update about page +./cli.sh about /path/to/about.md + +# Upload an image +./cli.sh upload /path/to/image.png +``` + +## Requirements + +- GitHub CLI (`gh`) authenticated with `repo` scope +- GitHub Personal Access Token with repo access + +## Environment Variables + +| Variable | Description | Default | +|----------|-------------|---------| +| `TINYMIND_REPO` | GitHub repository (format: `user/repo`) | `user/repo` | + +## Commands + +| Command | Description | +|---------|-------------| +| `thought "msg"` | Post a short thought | +| `thought "msg" image.jpg` | Post a thought with image | +| `blog "Title" file.md` | Post a blog article | +| `about file.md` | Update about page | +| `upload image.png` | Upload image, returns URL | + +## Setup + +1. Create a GitHub Personal Access Token with `repo` scope +2. Configure gh CLI: `gh auth login` +3. Set environment variable: `export TINYMIND_REPO="your-username/tinymind-blog"` +4. Authorize TinyMind to access your GitHub repository + +## License + +MIT \ No newline at end of file diff --git a/skills/tinymind/SKILL.md b/skills/tinymind/SKILL.md new file mode 100644 index 0000000..725a60e --- /dev/null +++ b/skills/tinymind/SKILL.md @@ -0,0 +1,165 @@ +--- +name: tinymind +description: Post thoughts, blog articles, and update about page to TinyMind (tinymind.me) using GitHub. Use when managing TinyMind blog content, posting thoughts, writing blog posts, or updating profile images. +--- + +# TinyMind Blog Skill + +Post thoughts, blog articles, and update about page to TinyMind (tinymind.me) using GitHub. + +## Overview + +TinyMind stores all content in a GitHub repository. This skill provides commands to: +- Post a thought (short message) +- Post a blog article (longer format with markdown) +- Update the About page +- Upload and link images +- Clean up unused images + +## Configuration + +Set environment variables: + +```bash +export TINYMIND_USER="your-github-username" +export TINYMIND_REPO="your-username/tinymind-blog" +export TINYMIND_URL="https://tinymind.me" +``` + +## CLI Usage + +### Post a Thought + +```bash +{skillDir}/cli.sh thought "Your message here" +``` + +Example: +```bash +{skillDir}/cli.sh thought "今天天氣真好" +``` + +### Post a Thought with Image + +```bash +{skillDir}/cli.sh thought "Message" /path/to/image.jpg +``` + +### Post a Blog Article + +```bash +{skillDir}/cli.sh blog "Title" /path/to/article.md +``` + +### Update About Page + +```bash +{skillDir}/cli.sh about /path/to/about.md +``` + +### Upload Image + +```bash +{skillDir}/cli.sh upload /path/to/image.png +``` + +## Repository Structure + +``` +your-username/tinymind-blog/ +├── content/ +│ ├── about.md # About page content +│ ├── thoughts.json # Array of thought objects +│ └── blog/ # Markdown blog posts +│ └── post.md +└── assets/ + └── images/ + └── YYYY-MM-DD/ + └── {timestamp}.png +``` + +## File Formats + +### Thoughts (`thoughts.json`) + +```json +[ + { + "id": "1775464679964", + "content": "Your thought here...", + "timestamp": "2026-04-07T08:37:59.964Z" + } +] +``` + +### Blog Post + +```yaml +--- +title: Your Article Title +date: 2026-04-07T10:00:00.000Z +--- + +Your article content in markdown... + +## Section + +More content... +``` + +### About Page + +Simple markdown file. Can include images. + +```markdown +![Image](https://raw.githubusercontent.com/your-username/tinymind-blog/main/assets/images/YYYY-MM-DD/IMAGE_ID.png) + +About content here... +``` + +## Image Workflow + +### Step 1: Upload Image + +```bash +# Download from URL +curl -sk "https://example.com/image.png" -o /tmp/image.png + +# Upload to GitHub +DATE=$(date +%Y-%m-%d) +ID=$(date +%s%3N) +gh api -X PUT repos/${TINYMIND_REPO}/contents/assets/images/${DATE}/${ID}.png \ + -F "content=$(base64 -w0 /tmp/image.png)" \ + -F "message=Upload image" +``` + +### Step 2: Link Image in Content + +Use the raw GitHub URL format: +```markdown +![Alt text](https://raw.githubusercontent.com/${TINYMIND_REPO}/main/assets/images/YYYY-MM-DD/IMAGE_ID.png) +``` + +## Cleaning Unused Images + +Check which images are referenced in content: +```bash +curl -s https://raw.githubusercontent.com/${TINYMIND_REPO}/main/content/about.md | grep -oE 'assets/images/[^)]+\.(png|jpg|jpeg)' +curl -s https://raw.githubusercontent.com/${TINYMIND_REPO}/main/content/thoughts.json | grep -oE 'assets/images/[^)]+\.(png|jpg|jpeg)' +curl -s https://raw.githubusercontent.com/${TINYMIND_REPO}/main/content/blog/*.md | grep -oE 'assets/images/[^)]+\.(png|jpg|jpeg)' +``` + +Delete unused images: +```bash +SHA=$(gh api repos/${TINYMIND_REPO}/contents/assets/images/PATH/IMAGE.png --jq '.sha') +gh api -X DELETE repos/${TINYMIND_REPO}/contents/assets/images/PATH/IMAGE.png \ + -F "message=Remove unused image" -F "sha=$SHA" +``` + +## Notes + +- New thoughts are prepended to the thoughts list +- Images are uploaded to daily folders with timestamp-based IDs +- Timestamps are in ISO 8601 UTC format +- Markdown frontmatter uses `---` delimiters +- Image URLs must use `raw.githubusercontent.com` format \ No newline at end of file diff --git a/skills/tinymind/cli.sh b/skills/tinymind/cli.sh new file mode 100755 index 0000000..d459963 --- /dev/null +++ b/skills/tinymind/cli.sh @@ -0,0 +1,155 @@ +#!/bin/bash + +# TinyMind Blog CLI +# Usage: tinymind-cli thought "message" [image] +# tinymind-cli blog "title" /path/to/markdown.md +# tinymind-cli about /path/to/content.md +# tinymind-cli upload /path/to/image.png + +set -e + +REPO="${TINYMIND_REPO:-user/repo}" +THOUGHTS_FILE="content/thoughts.json" +BLOG_DIR="content/blog" +ABOUT_FILE="content/about.md" +IMAGES_DIR="assets/images" + +command -v gh >/dev/null 2>&1 || { echo "gh CLI required"; exit 1; } + +post_thought() { + local message="$1" + local image="$2" + local timestamp now id img_url sha base64 + + timestamp=$(date -u +%Y-%m-%dT%H:%M:%S.000Z) + now=$(date +%s%3N) + + if [ -n "$image" ]; then + local date_f + date_f=$(date +%Y-%m-%d) + + # Upload image first + local img_content + img_content=$(base64 -w0 "$image") + gh api -X PUT "repos/$REPO/contents/${IMAGES_DIR}/${date_f}/${now}.png" \ + -F "content=$img_content" \ + -F "message=Upload image ${now}" \ + -F "parents=$(gh api "repos/$REPO/git/main" --jq '.sha')" > /dev/null + + img_url="https://raw.githubusercontent.com/$REPO/main/${IMAGES_DIR}/${date_f}/${now}.png" + fi + + sha=$(gh api "repos/$REPO/contents/$THOUGHTS_FILE" --jq '.sha') + + # Get current thoughts and add new one at beginning + local tmp_current tmp_new + tmp_current=$(mktemp) + tmp_new=$(mktemp) + + curl -s "https://raw.githubusercontent.com/$REPO/main/$THOUGHTS_FILE" > "$tmp_current" + + if [ -n "$img_url" ]; then + message="${message}"$'\n\n'"![image]($img_url)" + fi + + jq --arg id "$now" --arg timestamp "$timestamp" --arg content "$message" \ + '[{id: $id, content: $content, timestamp: $timestamp}] + .' "$tmp_current" > "$tmp_new" + + base64=$(base64 -w0 "$tmp_new") + + gh api -X PUT "repos/$REPO/contents/$THOUGHTS_FILE" \ + -F "content=$base64" \ + -F "message=Add thought via tinymind-cli" \ + -F "sha=$sha" + + rm -f "$tmp_current" "$tmp_new" + + echo "Thought posted successfully" +} + +post_blog() { + local title="$1" + local file="$2" + local filename sha base64 slug + + # Create slug from title + slug=$(echo "$title" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -d '[:punct:]') + filename="${slug}.md" + + # Update date in frontmatter + local date_now + date_now=$(date -u +%Y-%m-%dT%H:%M:%S.000Z) + + sed -i "s/^date:.*/date: $date_now/" "$file" + + sha=$(gh api "repos/$REPO/contents/$BLOG_DIR/$filename" --jq '.sha' 2>/dev/null || echo "") + + base64=$(base64 -w0 "$file") + + if [ -z "$sha" ]; then + gh api -X PUT "repos/$REPO/contents/$BLOG_DIR/$filename" \ + -F "content=$base64" \ + -F "message=Add blog post: $title" + else + gh api -X PUT "repos/$REPO/contents/$BLOG_DIR/$filename" \ + -F "content=$base64" \ + -F "message=Update blog post: $title" \ + -F "sha=$sha" + fi + + echo "Blog post '$title' posted successfully" +} + +update_about() { + local file="$1" + local sha base64 + + sha=$(gh api "repos/$REPO/contents/$ABOUT_FILE" --jq '.sha') + base64=$(base64 -w0 "$file") + + gh api -X PUT "repos/$REPO/contents/$ABOUT_FILE" \ + -F "content=$base64" \ + -F "message=Update about page" \ + -F "sha=$sha" + + echo "About page updated successfully" +} + +upload_image() { + local image="$1" + local date_f now img_url img_content + + date_f=$(date +%Y-%m-%d) + now=$(date +%s%3N) + + img_content=$(base64 -w0 "$image") + gh api -X PUT "repos/$REPO/contents/${IMAGES_DIR}/${date_f}/${now}.png" \ + -F "content=$img_content" \ + -F "message=Upload image ${now}" \ + -F "parents=$(gh api "repos/$REPO/git/main" --jq '.sha')" > /dev/null + + img_url="https://raw.githubusercontent.com/$REPO/main/${IMAGES_DIR}/${date_f}/${now}.png" + echo "$img_url" +} + +case "$1" in + thought) + post_thought "$2" "$3" + ;; + blog) + post_blog "$2" "$3" + ;; + about) + update_about "$2" + ;; + upload) + upload_image "$2" + ;; + *) + echo "Usage: $0 thought \"message\" [image]" + echo " $0 blog \"title\" /path/to/markdown.md" + echo " $0 about /path/to/about.md" + echo " $0 upload /path/to/image.png" + exit 1 + ;; +esac \ No newline at end of file