CJ Mosure
Engineering

Things I only want to explain once

May 4, 2026 · 6 min read · By C.J. Mosure

An agent's working memory ends when the conversation does. Everything I told it yesterday is gone the next morning: that I shop at HEB, that the news digest pipeline uses RSSHub for YouTube feeds, that I never want seafood in a recipe. That's fine for one-off questions. It becomes friction the moment I'm working with the agent on my own things: my homelab, my Notion, my projects with their specific quirks. I get tired of saying the same things every time.

The first fix most people reach for is CLAUDE.md, which Claude Code reads on every conversation. Stuff your facts in there and they propagate. But CLAUDE.md is undifferentiated: it loads in full every time, grows until it's both expensive and noisy, and rewards you for putting everything important up top while burying the rest. Skills are the alternative.

A skill is one markdown file. It starts with YAML frontmatter, and the rest is whatever the agent needs to know to do a specific thing:

yaml
---
name: tandoor
description: Manages recipes, meal plans, and shopping lists in a self-hosted Tandoor instance. Use when the user wants to generate or edit recipes, plan meals for the week, or build a grocery list. Cooking context is one person shopping at HEB — default servings=1 and prefer ingredients/units that match HEB stock.
---

The description is the only thing the agent sees ahead of time. It reads every available skill's description against what you're asking, picks the matches, and loads the body of those skills into context. Get the description wrong and the skill is invisible no matter how good the body is.

text
SKILL.md
├── frontmatter        ← always visible to the agent for matching
│   ├── name
│   └── description    ← only thing the agent sees before loading

└── body               ← loaded into context only when description matches
    ├── instructions
    ├── workflows
    └── (optional) reference.md, scripts/

I keep mine in a small repo that doubles as a Claude Code plugin:

text
skills/
├── .claude-plugin/
│   └── plugin.json           # plugin manifest
├── global/
│   └── CLAUDE.md             # version-controlled global instructions
└── skills/
    ├── engineering/
    ├── productivity/
    │   └── writing/
    │       └── SKILL.md
    ├── personal/
    │   ├── ai-news/
    │   │   └── SKILL.md
    │   └── tandoor/
    │       ├── SKILL.md
    │       ├── reference.md
    │       └── scripts/
    │           └── tandoor.sh
    └── misc/

The plugin manifest points at the four category directories. Adding a new skill means dropping a folder with a SKILL.md inside one of them. The plugin auto-discovers it on the next load:

json
{
  "name": "cjmosure-skills",
  "version": "0.1.0",
  "skills": [
    "./skills/engineering/",
    "./skills/productivity/",
    "./skills/personal/",
    "./skills/misc/"
  ]
}

Three skills are in mine right now, each solving a different kind of problem.

The first kind is procedural knowledge. ai-news manages the AI news digest I built. Adding a new YouTube channel involves finding the channel ID (which is not the handle, has to start with UC, and lives in the page source), building an RSSHub URL with that ID, and creating a row in a Notion database with the right properties set correctly. The skill encodes all of that. When I tell Claude "add this channel to my news sources," the description triggers, the body loads with the steps and the database schema, and the work happens. Without the skill, I'd be re-explaining the procedure every time.

The second kind is durable preferences. tandoor is the skill behind my self-hosted recipe manager. Most of what makes a recipe useful to me has nothing to do with the recipe itself: one-person servings, HEB grocery store, no seafood, no mustard, imperial units. These are facts about how I cook, not about any specific dish. Once they're in the skill, every recipe the agent generates respects them. The skill also includes a wrapper script that handles auth, so the agent can hit the Tandoor API directly without me re-explaining the bearer token.

The third kind is a behavioral overlay. writing activates whenever I'm producing prose: markdown files, docs, blog posts. It removes AI writing patterns like em dashes, rule-of-three padding, "key" as an adjective, and sycophantic openers. The interesting thing about this skill is that its description tells the agent to apply it proactively, not wait to be asked. Every blog post I publish, including this one, has been through it.

The discipline that holds the library together is brevity. Each SKILL.md stays under about 100 lines. Anything longer gets split into reference.md (loaded only when the body needs more depth) or scripts/ (executable helpers the body can reference). The body of a skill loads into context, and context isn't free. The 100-line cap is a forcing function: if a skill grows past it, that's a signal to split or to drop content that isn't pulling its weight.

The other discipline is description quality. The agent decides whether to load a skill by matching its description against what you're doing. A generic description ("manages tasks") triggers either too often or not at all. A specific description ("manages CJ's daily AI news digest — add sources, audit the source list, review digest pages — sources live in the Notion AI News Sources database") triggers exactly when needed. Writing the description is the actual work. The body is the implementation; the description is the API.

What I didn't expect, before having a few skills in place, is the compounding effect. Each skill on its own isn't dramatic. A few minutes saved per task, a few sentences of context I don't have to retype. But once enough of them cover enough of your domain, the agent feels different. It knows where your data lives, what tools you use, what you prefer. You stop re-explaining yourself, which means shorter questions get useful answers. The skill library is a plugin made of you.


∗ ∗ ∗
May 4
Automation to parse all AI news on the web and summarize
I built an automated daily AI news digest. Every hard problem was plumbing.
May 4
Each rule has a reason
My global CLAUDE.md, the failure modes each rule was written for, and the loops that keep it current.