Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
File renamed without changes.
59 changes: 59 additions & 0 deletions .agents/skills/create-skill/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
name: create-skill
description: Create a new agent skill in .agents/skills. Use when the user wants to add a reusable workflow, instruction pack, or tool-specific capability for agents.
allowed-tools: Read, Write, Edit, Bash(ls:*), Bash(mkdir:*), Bash(find:*)
---

# Create New Agent Skill

Help the user create a new agent skill under `.agents/skills`.

## Process

1. Understand the reusable workflow
- What should the skill help the agent do?
- When should the skill be used?
- Does it need scripts, references, templates, assets, or evals?

2. Design the skill structure
- Use a kebab-case skill directory name.
- Create `.agents/skills/<skill-name>/SKILL.md`.
- Add optional supporting folders only when they are useful.

3. Write the skill
- Include YAML frontmatter with `name` and `description`.
- Make the description trigger-oriented, so the agent knows when to use it.
- Keep instructions operational and specific.
- Put bulky reference material in `references/` and link to it from `SKILL.md`.

## Skill Template

```markdown
---
name: skill-name
description: Use this skill when...
allowed-tools: Read, Write, Edit
---

# Skill Name

Briefly state what this skill enables.

## Workflow

1. First step
2. Second step
3. Third step

## Output

Describe what the agent should produce or do.
```

## Best Practices

- Keep each skill focused on one reusable capability.
- Prefer concrete workflows over broad advice.
- Store long examples, API references, or playbooks in `references/`.
- Add scripts when repeatable work is safer as executable code.
- Include evals when the skill has a quality bar that can be checked repeatedly.
165 changes: 165 additions & 0 deletions .agents/skills/draft-newsletter/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
---
name: draft-newsletter
description: Draft the weekly Buttondown newsletter issue. Use this skill whenever Damian wants to write, draft, or prepare the next newsletter, weekly email, or Buttondown issue. Also use when he mentions "newsletter," "this week's email," "Wednesday email," "Buttondown draft," or anything about preparing the weekly send. This skill handles the full workflow — determining whether the issue should lead with a video or blog post, checking open-source repos for updates, gathering curated links, selecting the right CTA, and writing the draft.
---

# Draft Newsletter

Guide Damian through drafting the weekly Buttondown newsletter issue. The newsletter publishes on Wednesdays and alternates between video-led and blog-post-led weeks.

This is an interactive, multi-step process. You are a collaborator, not an autonomous writer. Gather inputs, surface relevant material, and then draft.

## Before Starting

Read these files to load context:

1. `~/vault/2-Areas/Content Creation/Creator Voice and Positioning.md` — compact creator voice and positioning (required, read every time)
2. `~/vault/2-Areas/Content Creation/Newsletter/References/Voice Profile.md` — newsletter-specific writing voice
3. `~/vault/2-Areas/Content Creation/Newsletter/References/Newsletter Charter.md` — newsletter charter, structure, template
4. `~/vault/2-Areas/Content Creation/Newsletter/References/Content Cadence.md` — the alternating video/blog rhythm
5. `~/vault/2-Areas/Content Creation/Newsletter/References/Lead Generation.md` — available lead magnets and funnels

Also read the two most recent newsletters in `~/vault/2-Areas/Content Creation/Newsletter/Published/` (sort by filename or `publish_date` in frontmatter) to calibrate tone and see what was covered last. Check `~/vault/2-Areas/Content Creation/Newsletter/Backlog.md` for curated links, quick hits, and issue candidates.

## Current Source of Truth

- Newsletter drafts, published issues, backlog, and newsletter-specific references live in `~/vault/2-Areas/Content Creation/Newsletter/`.
- Current YouTube video packages, titles, publish state, descriptions, resources, CTAs, and related child pages live in the Notion `YouTube Production OS` Videos database. Do not use the Obsidian YouTube pipeline as the source of truth for current video context.
- Blog posts, site pages, and publish-ready blog metadata live in the `dgalarza.github.io` repo. On Damian's machine this is usually `~/Code/dgalarza.github.io`; in Emma's runtime use `~/Code/emmav2/workspace/repos/dgalarza.github.io`.
- Vault notes can provide supporting context, prior thinking, and newsletter archive history, but the current video package comes from Notion and the current blog package comes from the website repo.

## Step 1: Determine the Lead Type

Check the most recent newsletter in `~/vault/2-Areas/Content Creation/Newsletter/Published/`. If it led with a YouTube video, this week should lead with a blog post (and vice versa). The alternating pattern from `~/vault/2-Areas/Content Creation/Newsletter/References/Content Cadence.md`:

| Week | Newsletter Lead | Notes |
|------|----------------|-------|
| 1 | YouTube video | Video is the headline, no blog post that week |
| 2 | Blog post | Video still publishes, gets a mention but isn't the headline |

Look at the structure of the last issue — did it open with a `## This week's video` section as the primary content, or did a blog post take the lead? Then alternate.

Tell Damian what you've determined: "Based on the last issue, this week should be **[video-led / blog-post-led]**."

Then collect the current lead material from the right source:

- **If video-led**: Search or fetch the relevant Notion `YouTube Production OS` Videos database record. Use its title, YouTube URL, description/package notes, resources, CTA, and linked child pages when available. If multiple records match or Notion access is unavailable, ask Damian for the exact Notion page or YouTube URL instead of falling back to the Obsidian YouTube pipeline.
- **If blog-post-led**: Locate the leading blog post in the `dgalarza.github.io` repo (`content/posts/`) or ask Damian for the URL/filename if it is not clear. The video still gets a mention, so fetch the current video from the Notion Videos database or ask for the exact Notion page/YouTube URL.

Confirm the lead type and the source records before drafting. If Notion and the repo disagree, treat Notion as authoritative for video details and the repo as authoritative for blog details, then surface the mismatch.

## Step 2: Check Open-Source Repos for Updates

Review recent git activity in both repos to surface anything worth mentioning:

```bash
# Check claude-code-workflows for recent activity
cd ~/Code/claude-code-workflows
git log --oneline --since="7 days ago"
git tag --sort=-creatordate | head -5

# Check agent-skills for recent activity
cd ~/Code/agent-skills
git log --oneline --since="7 days ago"
git tag --sort=-creatordate | head -5
```

If there are noteworthy changes (new releases, new plugins/skills, significant updates), summarize them for Damian. These can go in an "Open Source Updates" section or under "Quick Hits."

If nothing significant happened in the last week, that's fine — skip this section in the newsletter. Don't manufacture updates.

## Step 3: Ask About Curated Links

Use `AskUserQuestion` to ask Damian:

> Do you have any interesting links to share this week? These could be from X/Twitter, Hacker News, blog posts, tool releases, or anything relevant to the audience. Each one gets 2-4 sentences of your take on why it matters.
>
> If you have links, share them and I'll help write the context. If not, we can skip this section.

If Damian provides links, write 2-4 sentences of context for each one following the newsletter voice. These go in the "Curated Links & Tools" section. The context should explain why the link matters to the audience (developers using AI coding tools), not just describe what it is.

## Step 4: Ask About Livestream

Use `AskUserQuestion` to ask:

> Are you doing a livestream this week? If so, what's the date/time, what will you be building, and do you have the stream link?

If yes, include a "Live Stream" section. If no, skip it.

## Step 5: Select the CTA

Every issue needs a call to action. Pick one based on the week's content theme:

| Lead Magnet | Best When... | URL Segment |
|-------------|-------------|-------------|
| Codebase Readiness Assessment | Content touches codebase quality, agent workflows, team adoption | `codebase-readiness` |
| Terminal Cheat Sheet | Content is beginner-friendly or about terminal/CLI | `terminal-cheat-sheet` |
| Coaching/Services | Content shows consulting-level thinking, architecture decisions | Link to `/coaching/` or `/services/` |

The coaching/services soft CTA should **always** appear as the closing line regardless of whether another lead magnet is featured. It's a gentle sign-off, not a hard sell.

If featuring a lead magnet, weave it naturally into the relevant section (not as a separate "ad" block). Use recognizable URL segments so Buttondown automations can tag subscribers who click.

Present the CTA choice to Damian and confirm before drafting.

## Step 6: Draft the Newsletter

Write the draft following this structure. Not every section appears every week — only include what's relevant.

### Structure

1. **Lead section** — Video or blog post (whichever is the headline this week)
2. **Secondary mention** — The other one (video gets a brief mention in blog-post-led weeks, and vice versa)
3. **Livestream announcement** — Only if applicable
4. **Original commentary** — 1-2 sections of exclusive value: behind the scenes, what you're building, open source updates, deeper context
5. **Curated Links & Tools** — 1-3 items with context (only if Damian provided links)
6. **Quick Hits** — Optional 1-3 bullet items for small announcements
7. **Closing CTA** — Reply prompt + soft coaching/services link + "Damian"

### Formatting Rules

- Use `---` horizontal rules between major sections
- YouTube thumbnails use: `[![TITLE](https://img.youtube.com/vi/VIDEO_ID/maxresdefault.jpg)](https://youtu.be/VIDEO_ID)`
- Blog post links should use the full damiangalarza.com URL
- Keep to 500-1000 words total
- Sign off as "Damian" (just the name, no "Best," or "Cheers,")

### Frontmatter

```yaml
---
subject: ""
description: ""
status: draft
---
```

The **subject line** should be specific and concrete — what the reader will learn or see. Not clickbait, not vague. Look at past issues for calibration.

The **description** is the email preview text (the snippet readers see in their inbox before opening). Keep it to 1-2 sentences that tease the key topics covered in the issue. Look at the `description` field in recent newsletters for examples.

### Voice Reminders

- First person ("I built", "I found", "I've been using")
- Direct and concise — no filler
- Professional but conversational
- No hype, no fluff, no excessive enthusiasm
- Honest about what didn't work
- No em dashes — use commas, parentheses, or separate sentences

### Save Location

Save the draft to `~/vault/2-Areas/Content Creation/Newsletter/Drafts/<slug>.md` where the slug is derived from the subject line (lowercase, hyphens, no special characters).

Use the Buttondown API skill to create or update the Buttondown draft after Damian approves the local draft. After the issue is sent, update Buttondown metadata in the vault file and move it to `~/vault/2-Areas/Content Creation/Newsletter/Published/YYYY/`.

## Step 7: Review with Damian

After writing the draft, ask Damian to review it. Call out:

- The lead type and why
- Which CTA you chose and why
- Any sections you skipped and why
- Anything you weren't sure about

Be ready to revise based on feedback. The goal is a draft Damian can publish with minimal edits, not a perfect first pass.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

```bash
# Clone the repo
git clone https://github.com/mvanhorn/last30days-skill.git ~/.claude/skills/last30days
git clone https://github.com/mvanhorn/last30days-skill.git ~/.agents/skills/last30days

# Add your API keys
mkdir -p ~/.config/last30days
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ echo "Edit to add your API keys for enhanced research."

**Step 1: Run the research script**
```bash
python3 ~/.claude/skills/last30days/scripts/last30days.py "$ARGUMENTS" --emit=compact 2>&1
python3 ~/.agents/skills/last30days/scripts/last30days.py "$ARGUMENTS" --emit=compact 2>&1
```

The script will automatically:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Other skills can import the research context in several ways:
### Inline Context Injection
```markdown
## Recent Research Context
!python3 ~/.claude/skills/last30days/scripts/last30days.py "your topic" --emit=context
!python3 ~/.agents/skills/last30days/scripts/last30days.py "your topic" --emit=context
```

### Read from File
Expand All @@ -42,19 +42,19 @@ Other skills can import the research context in several ways:

### Get Path for Dynamic Loading
```bash
CONTEXT_PATH=$(python3 ~/.claude/skills/last30days/scripts/last30days.py "topic" --emit=path)
CONTEXT_PATH=$(python3 ~/.agents/skills/last30days/scripts/last30days.py "topic" --emit=path)
cat "$CONTEXT_PATH"
```

### JSON for Programmatic Use
```bash
python3 ~/.claude/skills/last30days/scripts/last30days.py "topic" --emit=json > research.json
python3 ~/.agents/skills/last30days/scripts/last30days.py "topic" --emit=json > research.json
```

## CLI Reference

```
python3 ~/.claude/skills/last30days/scripts/last30days.py <topic> [options]
python3 ~/.agents/skills/last30days/scripts/last30days.py <topic> [options]

Options:
--refresh Bypass cache and fetch fresh data
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
75 changes: 0 additions & 75 deletions .claude/commands/create-command.md

This file was deleted.

1 change: 0 additions & 1 deletion .claude/skills/buffer

This file was deleted.

1 change: 0 additions & 1 deletion .claude/skills/buttondown

This file was deleted.

2 changes: 1 addition & 1 deletion .config/tmux/tmux.conf
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ set -g @resurrect-strategy-nvim 'session'
set -g @catppuccin_flavor "mocha"
set -g @catppuccin_window_status_style "rounded"

run ~/.tmux/plugins/tmux/catppuccin.tmux
run ~/.config/tmux/plugins/tmux/catppuccin.tmux

set -g @catppuccin_window_text ' #{?#{==:#{window_name},#{pane_current_command}},#{b:pane_current_path},#{window_name}}'
set -g @catppuccin_window_current_text ' #{?#{==:#{window_name},#{pane_current_command}},#{b:pane_current_path},#{window_name}}'
Expand Down
2 changes: 1 addition & 1 deletion .zshrc
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ fi

[[ -f ~/.zshrc.local ]] && source ~/.zshrc.local

. "$HOME/.atuin/bin/env"
[[ -f "$HOME/.atuin/bin/env" ]] && source "$HOME/.atuin/bin/env"

# opencode
export PATH=$HOME/.opencode/bin:$PATH
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ Custom scripts in `.local/bin/`:

## Claude Code

Global [Claude Code](https://docs.anthropic.com/en/docs/claude-code) configuration lives in `.claude/`. This includes a global `CLAUDE.md` with cross-project context, slash commands, and reusable skills (marketing, content strategy, CRO, SEO, and more).
Global [Claude Code](https://docs.anthropic.com/en/docs/claude-code) configuration lives in `.claude/`. Agent skills live in `.agents/skills/` so they can be shared across agents and bootstrapped into `~/.agents/skills/`, then mirrored into `~/.claude/skills/` for Claude Code.

Run the setup script to symlink everything into `~/.claude/`:
Run the setup script to symlink Claude config into `~/.claude/`, public/private agent skills into `~/.agents/skills/`, and compatibility links into `~/.claude/skills/`:

```bash
./setup-claude.sh
Expand All @@ -107,4 +107,5 @@ The script also sets up a `~/vault` symlink to your Obsidian vault for private s
- `.zshrc` at the repo root
- Tool configs under `.config/` (Ghostty, Tmux, Neovim, Starship, AeroSpace)
- Custom scripts in `.local/bin/`
- `.claude/` for Claude Code global config (skills, commands, CLAUDE.md)
- `.claude/` for Claude Code global config (`CLAUDE.md`, settings)
- `.agents/skills/` for reusable public agent skills
Loading