DEV Community

Lily
Lily

Posted on • Originally published at dev.to

Teaching Claude Code to Write and Grow Its Own Skills: A Self-Replicating Agent Environment

Last time I wrote about splitting Claude Code's memory into four layers. This is the follow-up: a setup where Claude Code itself discovers "reusable procedures" and accumulates them as skills over time.

After running this for a few months, ~/.claude/skills/auto/ now holds 64 auto-generated skills. In this article I'll cover the design of that self-replication, the mechanisms that prevent overproduction, and the generation curve I observed while operating it.

The problem: rebuilding the same procedure from scratch every time

Claude Code is capable, but across sessions it forgets "how I got around this error last time." How to fix launchd's exit 78, the steps to bake a favicon with png-to-ico, how to trim the RSC payload in Next.js — these procedures I should have already solved once were being rebuilt from scratch every single time.

I could hand-write additions to CLAUDE.md, but that turns into a "whoever notices, writes it" workflow, and that doesn't last. So I flipped the idea around and decided to make Claude do the work of finding the procedures too.

Design: two-tier generation + Curator

Skill generation is split into two tiers.

Tier Timing Cost Owner
In-session generation Any time during work Free / instant Claude itself, following CLAUDE.md instructions
Nightly batch generation Daily cron at 3:30 Consumes Max quota skill-harvest.sh (claude -p headless)

Then a Curator (skill-curate.sh) runs weekly to periodically organize the accumulated skills. The key is separating generation and organization into different processes.

Tier 1: in-session generation (free / instant)

CLAUDE.md says this (excerpt).

## スキル自己生成(auto-skills)

作業の中で再利用価値のある手順を見つけたら、頼まれなくても自分でスキル化する。
ただし乱造はしない。

### 生成トリガー(いずれか該当時のみ)
- 5回以上ツールを使う非自明なタスクを最後までやり切った
- エラー・行き止まりにぶつかった後、動く回避策を見つけた
- ユーザーにアプローチを修正された(同じ修正を繰り返さないため)
- 再利用できる手順・コマンド列・ワークフローを発見した
Enter fullscreen mode Exit fullscreen mode

The crux is "but don't overproduce," plus narrowing the triggers down to four. Without writing this, Claude turns everything into a skill and the space fills up with noise almost immediately.

Tier 2: nightly batch generation (catching what was missed)

Procedures that never got written down during a session get picked up from the conversation logs by a nightly batch. The skill-harvest.sh pipeline looks like this.

  1. Read .harvest-watermark (the previous processing position)
  2. Extract the diff after the watermark from the conversation logs (raw/conversations/*.md)
  3. Extract frequent patterns headless via claude -p (only adopt those appearing more than 5 times)
  4. Deduplicate against all 64 existing skills by kebab-name
  5. Monitor token usage with a cost-guard hook; abort if the threshold is exceeded
  6. Write out new candidates to <name>/SKILL.md with three sections: frontmatter + Procedure / Pitfalls / Verification
  7. Trigger the Curator at the end to retire old skills
  8. Update the watermark and append to the log

claude -p is the headless invocation I mentioned in the previous article. It runs on the Max quota, so API-key charges are zero.

Isolated namespace: why split things into auto/

Auto-generated skills do not go in the same place as hand-written skills or plugin-bundled skills. They're pushed into an isolated namespace, ~/.claude/skills/auto/. Two reasons.

  • npx skills update -g only manages lock-registered skills. The ones in auto/ aren't added to the lock → they don't get wiped by the daily update.
  • The Curator only targets things that are "under auto/ and author: auto" → it never touches hand-written or bundled skills.

That author: auto is the Curator's target-detection key, and it's required in the frontmatter.

---
name: <kebab-case>
description: <発火条件を具体的に>
author: auto          # ← Curatorの対象判定キー。必須
created: <YYYY-MM-DD>
version: 1.0.0
status: active        # active | stale(Curatorが自動設定)
---
Enter fullscreen mode Exit fullscreen mode

Organizing: the Curator "never deletes — only proposes"

Left ungoverned, skills rot. The Curator runs weekly like this.

  • Before running, take a tar.gz snapshot into .snapshots/
  • Unused for 30 days → demote to status: stale
  • Unused for 90 days → move to .archive/ (never actually deleted — restorable by command)
  • Consolidation of duplicates and low-quality skills is written to .curator-proposals.md as proposals only (not applied automatically)

:::message
Not letting the Curator auto-delete is the core of the safe design. "Untouched for 30 days" doesn't necessarily mean the skill is bad (you just haven't done that kind of work). So it stops at demotion and archival, leaving the final call to a human.
:::

What I learned from operating it

Generation is concentrated early, then tapers off

Looking at the distribution of created:, in the first three days after introduction (5/28–30) 28 skills were verbalized in one burst, after which the pace dropped to a few per day. This matches intuition — the "unverbalized procedures" accumulated in the past get released early, and after that only newly encountered procedures get added.

12 created: 2026-05-30
 9 created: 2026-05-29
 7 created: 2026-06-09
 6 created: 2026-06-11
 5 created: 2026-06-10
 5 created: 2026-05-28
Enter fullscreen mode Exit fullscreen mode

"Don't overproduce" actually works

Here's this morning's harvest log.

会話ログを精査した結果、以下の理由から該当なし。
- Codex CLI のセットアップ → codex-cli-setup が既存
- /insights を CLAUDE.md に反映 → insights-to-claude-md が既存
- カード債務の支払い優先順位 → 個人の財務状況に依存、再利用手順に非該当
該当なし
[2026-06-15 04:11:21] harvest done (exit 0, created=0)
Enter fullscreen mode Exit fullscreen mode

created=0. It rejected duplicates of existing skills, rejected one-off content tied to personal circumstances, and terminated normally with 0 generated. This is proof that the "don't overproduce" design can process a miss as a correct miss. If it generated recklessly here, those 64 would balloon to 200 and turn to noise fast.

Pitfalls I hit

From the Pitfalls sections of actual skills, the ones that mattered.

  • claude -p hits the token cap when the full system prompt loads → suppress with MAX_THINKING_TOKENS=10000
  • Forgetting to advance the watermark and re-extracting the same log → always check the log's last completed offset
  • Grepping on kebab-name alone misses fuzzy duplicates → description embedding comparison is room for improvement (not implemented)
  • launchd fires at 3:30, but the job is skipped while the mac is asleep → recommend pmset wake on schedule
  • Loading all MCP servers headless makes startup slow → keep a harvest-only minimal config at a separate path

Minimal setup: if you're starting today

You don't need the full pipeline. Just adding one block to CLAUDE.md gets Tier 1 running.

  1. Create ~/.claude/skills/auto/
  2. Write in CLAUDE.md: "When you find a reusable procedure, turn it into a skill yourself. But don't overproduce," plus the four trigger conditions
  3. Require author: auto in the frontmatter (a marker for organizing later)

That alone means skills grow a little with every piece of work. You can add the nightly batch and the Curator later, once skills have accumulated and you feel like organizing them — that's soon enough.

Summary

  • Split skill generation into two tiers: in-session (free) and nightly batch (catching what was missed)
  • Spell out don't overproduce in the prompt and narrow the triggers. A 0-generated miss is normal
  • Isolate auto-generation in auto/, and make author: auto the Curator's target key
  • The Curator never deletes — only demotes, archives, and proposes. The final call stays with a human
  • Start with a single block in CLAUDE.md

Next time I'll write about how these skills grew too numerous and Claude Code itself got heavy — the audit that cut context injection from 228KB to 48KB.


Written by **Lily* — I ship iOS apps and automate my content stack with Claude Code.
Follow along: Portfolio · X · GitHub*

Top comments (0)