Skip to content

Commit 651157d

Browse files
Oliver Baerclaude
andcommitted
feat: add Vibe Coding pipeline for automated blog generation
Implement "Vibe Coding" plugin that transforms session memory files into public-ready blog posts via CI/CD automation. Features: - New /vibe-init skill for one-command infrastructure setup - Python blog generator using Anthropic API (Claude 3.5 Sonnet) - GitHub Actions workflow triggered on .memory/ changes - Automatic PR creation with generated drafts - Comprehensive documentation and user guides Architecture: - Hybrid approach: Claude Code skill + CI/CD pipeline - .github/scripts/blog_gen.py - Main generator (119 lines) - .github/workflows/vibe_publisher.yml - GitHub Actions (56 lines) - skills/vibe-init/skill.md - Plugin skill definition (275 lines) Documentation: - VIBE_CODING.md - Complete user guide (302 lines) - IMPLEMENTATION_SUMMARY.md - Technical architecture (325 lines) - VERIFICATION_CHECKLIST.md - QA verification report - Updated CLAUDE.md, README.md, CLAUDE_TEMPLATE.md Security: - API keys loaded from environment variables only - GitHub Secrets integration for CI/CD - Pull request workflow for review before merge Files created: 10 new files, 4 new directories, 1,077 lines of code Cost: ~$0.03 per blog post using Claude 3.5 Sonnet Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 70b99ce commit 651157d

12 files changed

Lines changed: 1572 additions & 1 deletion

File tree

.github/scripts/blog_gen.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Blog Generator for Vibe Coding Pipeline
4+
Converts .memory/*.md files into polished blog posts using Anthropic API
5+
"""
6+
7+
import os
8+
import sys
9+
from pathlib import Path
10+
from datetime import datetime
11+
import anthropic
12+
from dotenv import load_dotenv
13+
14+
# Load environment variables
15+
load_dotenv()
16+
17+
18+
def get_latest_memory_file():
19+
"""Find the most recent letter file in .memory/"""
20+
memory_dir = Path(os.path.abspath('.memory'))
21+
22+
if not memory_dir.exists():
23+
print("❌ .memory/ directory not found")
24+
sys.exit(1)
25+
26+
# Find all letter_*.md files
27+
letter_files = sorted(memory_dir.glob('letter_*.md'), reverse=True)
28+
29+
if not letter_files:
30+
print("❌ No letter files found in .memory/")
31+
sys.exit(1)
32+
33+
return letter_files[0]
34+
35+
36+
def generate_blog_post(memory_content: str) -> str:
37+
"""Use Anthropic API to convert memory file to blog post"""
38+
api_key = os.getenv('ANTHROPIC_API_KEY')
39+
40+
if not api_key:
41+
print("❌ ANTHROPIC_API_KEY not found in environment")
42+
sys.exit(1)
43+
44+
client = anthropic.Anthropic(api_key=api_key)
45+
46+
prompt = f"""You are a technical blog writer. Convert this development session memory into an engaging, public-ready blog post.
47+
48+
INPUT (Session Memory):
49+
{memory_content}
50+
51+
REQUIREMENTS:
52+
1. Transform technical decisions into narrative insights
53+
2. Keep the "Pain Log" as "Lessons Learned" or "Challenges"
54+
3. Make it readable for a general developer audience
55+
4. Add markdown frontmatter with: title, date, tags, excerpt
56+
5. Use proper markdown formatting with headers, code blocks, lists
57+
6. Maintain technical accuracy but improve readability
58+
59+
OUTPUT FORMAT:
60+
---
61+
title: "[Engaging Title]"
62+
date: {datetime.now().strftime('%Y-%m-%d')}
63+
tags: [relevant, tags, here]
64+
excerpt: "Brief summary of the post"
65+
---
66+
67+
[Blog post content in markdown]
68+
69+
Generate the blog post now:"""
70+
71+
message = client.messages.create(
72+
model="claude-3-5-sonnet-20241022",
73+
max_tokens=4096,
74+
messages=[
75+
{"role": "user", "content": prompt}
76+
]
77+
)
78+
79+
return message.content[0].text
80+
81+
82+
def save_blog_post(content: str, source_file: Path):
83+
"""Save generated blog post to drafts/"""
84+
drafts_dir = Path(os.path.abspath('drafts'))
85+
drafts_dir.mkdir(exist_ok=True)
86+
87+
# Generate filename based on source
88+
timestamp = datetime.now().strftime('%Y-%m-%d')
89+
output_file = drafts_dir / f"blog_{timestamp}_{source_file.stem}.md"
90+
91+
output_file.write_text(content, encoding='utf-8')
92+
print(f"✅ Blog post generated: {output_file}")
93+
return output_file
94+
95+
96+
def main():
97+
"""Main execution flow"""
98+
print("🎨 Vibe Coding: Generating blog post...")
99+
100+
# Get latest memory file
101+
memory_file = get_latest_memory_file()
102+
print(f"📖 Reading: {memory_file}")
103+
104+
# Read content
105+
memory_content = memory_file.read_text(encoding='utf-8')
106+
107+
# Generate blog post
108+
print("🤖 Calling Anthropic API...")
109+
blog_content = generate_blog_post(memory_content)
110+
111+
# Save to drafts
112+
output_file = save_blog_post(blog_content, memory_file)
113+
114+
print(f"✅ Success! Blog post saved to: {output_file}")
115+
print("🚀 Ready for review and publishing!")
116+
117+
118+
if __name__ == "__main__":
119+
main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
anthropic>=0.18.0
2+
python-dotenv>=1.0.0
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Vibe Publisher - Memory to Blog
2+
3+
on:
4+
push:
5+
paths:
6+
- '.memory/**'
7+
workflow_dispatch:
8+
9+
jobs:
10+
generate-blog:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout repository
15+
uses: actions/checkout@v4
16+
with:
17+
fetch-depth: 0
18+
19+
- name: Set up Python
20+
uses: actions/setup-python@v5
21+
with:
22+
python-version: '3.11'
23+
24+
- name: Install dependencies
25+
run: |
26+
python -m pip install --upgrade pip
27+
pip install -r .github/scripts/vibe_requirements.txt
28+
29+
- name: Generate blog post
30+
env:
31+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
32+
run: |
33+
python .github/scripts/blog_gen.py
34+
35+
- name: Create Pull Request
36+
uses: peter-evans/create-pull-request@v6
37+
with:
38+
token: ${{ secrets.GITHUB_TOKEN }}
39+
commit-message: 'feat(blog): generate post from memory session'
40+
title: '📝 New Blog Post from Session Memory'
41+
body: |
42+
## 🎨 Vibe Coding Pipeline
43+
44+
Auto-generated blog post from latest session memory.
45+
46+
**Generated by:** Anthropic Claude API
47+
**Source:** `.memory/` folder
48+
**Output:** `drafts/` folder
49+
50+
### Next Steps
51+
- [ ] Review the generated content
52+
- [ ] Edit for style/branding if needed
53+
- [ ] Move to your blog publishing location
54+
- [ ] Merge when ready
55+
branch: blog-automation-${{ github.run_number }}
56+
delete-branch: true

.memory/letter_example.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Letter to Myself (Session Handoff)
2+
3+
**Date:** 2026-01-29
4+
5+
## 1. Executive Summary
6+
* **Goal:** Implement Vibe Coding pipeline to transform session memories into blog posts
7+
* **Current Status:** Successfully completed implementation with CI/CD integration
8+
9+
## 2. The "Done" List (Context Anchor)
10+
* Created `skills/vibe-init/skill.md` - New skill for pipeline initialization
11+
* Implemented `.github/scripts/blog_gen.py` - Python script using Anthropic API
12+
* Created `.github/workflows/vibe_publisher.yml` - GitHub Actions workflow
13+
* Added `vibe_requirements.txt` with anthropic and python-dotenv dependencies
14+
* Updated CLAUDE.md with Vibe Coding documentation
15+
* Created comprehensive VIBE_CODING.md guide
16+
* Updated README.md and CLAUDE_TEMPLATE.md
17+
18+
## 3. The "Pain" Log (CRITICAL)
19+
* **Tried:** Initial assumption was Python application with `src/` directory
20+
* **Failed:** Repository is actually a Claude Code plugin (markdown/YAML based)
21+
* **Workaround:** Adapted architecture to hybrid approach - Claude Code skill + CI/CD pipeline
22+
* *Note:* The correct architecture respects the existing plugin system while adding CI/CD automation
23+
24+
## 4. Active Variable State
25+
* ANTHROPIC_API_KEY required in GitHub Secrets for automation
26+
* Default model: claude-3-5-sonnet-20241022
27+
* Output directory: `drafts/`
28+
* Trigger path: `.memory/**`
29+
30+
## 5. Immediate Next Steps
31+
1. [x] Create all required files and directories
32+
2. [x] Verify Python syntax and structure
33+
3. [x] Update documentation (README, CLAUDE.md, VIBE_CODING.md)
34+
4. [ ] Test the pipeline with actual API key
35+
5. [ ] Create git commit with all changes

CLAUDE.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
This is a Claude Code plugin called "Letter to Myself" that implements context persistence between Claude sessions. The plugin provides an agent and skill that automatically write structured "Last Will" summaries to a `.memory/` folder, enabling seamless continuity when sessions end, get compacted, or when days pass between work sessions.
8+
9+
## Core Components
10+
11+
### Plugin Structure
12+
- `.claude-plugin/plugin.json` - Plugin manifest defining name, version, and component paths
13+
- `agents/letter-for-my-future-self.md` - Agent persona that handles checkpoint creation
14+
- `skills/save-checkpoint/skill.md` - Skill that writes memory checkpoints to disk
15+
- `skills/vibe-init/skill.md` - Skill that sets up the Vibe Coding CI/CD pipeline
16+
- `CLAUDE_TEMPLATE.md` - Template users copy to their projects to enable the plugin
17+
- `install_agents.sh` - Installation script that sets up the plugin structure
18+
19+
### Vibe Coding Pipeline (NEW)
20+
The plugin now includes a "Vibe Coding" feature that automatically transforms memory files into public-ready blog posts:
21+
- `.github/scripts/blog_gen.py` - Python script using Anthropic API for blog generation
22+
- `.github/scripts/vibe_requirements.txt` - Python dependencies (anthropic, python-dotenv)
23+
- `.github/workflows/vibe_publisher.yml` - GitHub Actions workflow triggered on .memory/ changes
24+
- `drafts/` - Output directory for generated blog posts
25+
26+
### The Memory Protocol
27+
- Memory files are stored in `.memory/` as sequential markdown files (`letter_01.md`, `letter_02.md`, etc.)
28+
- Each file follows a strict template with sections: Executive Summary, Done List, Pain Log, Variable State, Next Steps
29+
- On startup, the agent reads the highest-numbered letter file to restore context
30+
- On checkpoint/exit, the agent generates a new letter with incremented number
31+
32+
## Installation & Usage
33+
34+
### Installing the Plugin
35+
```bash
36+
# Option A: Use the installation script (recommended)
37+
chmod +x install_agents.sh
38+
./install_agents.sh
39+
40+
# Option B: Install as local plugin
41+
claude plugin install . --scope user
42+
```
43+
44+
### Adding to a Project
45+
Copy `CLAUDE_TEMPLATE.md` into the target project as `CLAUDE.md` (or merge if one exists).
46+
47+
### Triggering Checkpoints
48+
The agent activates when users type:
49+
- `/checkpoint`
50+
- `exit` or indicates session is ending
51+
- "wrap up"
52+
53+
### Setting Up Vibe Coding
54+
Initialize the blog generation pipeline by running:
55+
```bash
56+
/vibe-init
57+
```
58+
59+
This creates:
60+
1. Required directories (.memory/, drafts/, .github/scripts/, .github/workflows/)
61+
2. Blog generator script with Anthropic API integration
62+
3. GitHub Actions workflow for automatic blog post generation
63+
4. Python dependencies file
64+
65+
**Required Setup:**
66+
Add `ANTHROPIC_API_KEY` to GitHub repository secrets (Settings → Secrets and variables → Actions)
67+
68+
**How It Works:**
69+
1. Push changes to `.memory/*.md` files
70+
2. GitHub Actions automatically triggers
71+
3. Latest memory file is converted to blog post using Claude
72+
4. Pull request created with generated draft in `drafts/`
73+
5. Review and merge when ready
74+
75+
## Memory Versioning
76+
77+
See `MEMORY_VERSIONING.md` for comprehensive Git workflows:
78+
- **Option A**: Full versioning (recommended for solo projects)
79+
- **Option B**: Clean diffs with `.gitattributes` configuration
80+
- **Option C**: Team workflow with shared/private split
81+
- **Option D**: Security guardrails to prevent secrets in memory
82+
- **Option E**: Keep history clean with filtered logs or orphan branches
83+
- **Option F**: Archiving strategies for long-running projects
84+
85+
Key commands for memory management:
86+
```bash
87+
# Commit memory after session
88+
git add .memory/shared
89+
git commit -m "chore(memory): session handoff"
90+
91+
# Scan for secrets before committing
92+
rg -n --hidden --glob ".memory/**" -e "AKIA[0-9A-Z]{16}" -e "BEGIN( RSA)? PRIVATE KEY" .memory
93+
```
94+
95+
## Architecture Notes
96+
97+
### Plugin Design Philosophy
98+
- **Continuity over context**: Addresses the fundamental limitation of Claude's context window by creating persistent memory
99+
- **Minimal friction**: Automatic checkpoint creation on session end
100+
- **Structured format**: Strict template ensures consistent, actionable handoffs
101+
- **Pain Log emphasis**: Critical section for documenting failures and workarounds to prevent repeated mistakes
102+
103+
### Agent Behavior
104+
The `letter-for-my-future-self` agent operates in two modes:
105+
1. **Normal mode**: Acts as a standard coding assistant
106+
2. **Checkpoint mode**: Triggered by exit signals, stops all work to review conversation history and generate a summary
107+
108+
### Skill Execution
109+
The `save-checkpoint` skill:
110+
1. Creates `.memory/` directory if needed
111+
2. Lists existing letter files to determine next sequential number
112+
3. Writes the generated letter using the Write tool
113+
4. Confirms to user with filename
114+
115+
## File Organization
116+
117+
```
118+
.
119+
├── .claude-plugin/
120+
│ └── plugin.json # Plugin manifest
121+
├── agents/
122+
│ └── letter-for-my-future-self.md # Agent persona definition
123+
├── skills/
124+
│ └── save-checkpoint/
125+
│ └── skill.md # Checkpoint skill definition
126+
├── CLAUDE_TEMPLATE.md # Template for user projects
127+
├── install_agents.sh # Installation script
128+
├── MEMORY_VERSIONING.md # Git workflow guide
129+
├── QUICK_START.md # User installation guide
130+
└── README.md # Project documentation

CLAUDE_TEMPLATE.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,14 @@ This project uses the **Letter to Myself** agent.
66
1. **Startup:** Always check the `.memory/` directory. Read the file with the highest number (e.g., `letter_05.md`) to understand the current state.
77
2. **Shutdown:** Before exiting or when asked to `/checkpoint`, use the `save-checkpoint` tool to write the next sequential letter.
88

9+
## 🎨 Vibe Coding (Optional)
10+
To enable automatic blog post generation from session memories:
11+
12+
1. **One-time setup:** Run `/vibe-init` to install the CI/CD pipeline
13+
2. **Add API key:** Set `ANTHROPIC_API_KEY` in GitHub repository secrets
14+
3. **Automatic:** Every push to `.memory/` triggers blog post generation
15+
16+
See [VIBE_CODING.md](./VIBE_CODING.md) for complete documentation.
17+
918
## 📝 Coding Standards
1019
(Add your normal coding standards here, e.g., TypeScript strict mode, Python PEP8, etc.)

0 commit comments

Comments
 (0)