新しいfrontmatterフィールド
| フィールド | 説明 |
|---|---|
context: fork | サブエージェント分離実行 |
agent | forkのエージェントタイプ(Explore, Plan等) |
hooks | PreToolUse/PostToolUse/Stopフック |
動的コンテキスト注入
## Context
- Current branch: !`git branch --show-current`
!command“ でスキル送信前にコマンド出力を埋め込める。
descriptionのベストプラクティス
Triggers: キーワードで自動起動条件を明記する。これがClaude自動起動の唯一の判断材料。
"PRをレビューする。Triggers: user says 'レビューして', or when a PR number is mentioned."
Progressive Disclosure
- Level 1: メタデータ(常時ロード、~100トークン)
- Level 2: SKILL.md本文(起動時、<5000トークン推奨)
- Level 3: references/(必要時にRead)
肥大化の犯人
projects/— 会話履歴。最大(数百MB〜GB級)debug/— デバッグログ。数百MBになるfile-history/— ファイル変更履歴。300GB到達の報告あり
対策
settings.json に追加:
{
"cleanupPeriodDays": 20
}
サイズ確認エイリアス:
alias claude-size='du -sh ~/.claude/ && du -sh ~/.claude/* 2>/dev/null | sort -h'
削除可能なディレクトリ
debug/, projects/*, file-history/, stats-cache.json, statsig/
削除不可: settings.json, commands/, skills/, rules/
3つの実装形態
| 形態 | 構成 | 使い分け |
|---|---|---|
| A: スキル単体 | SKILL.md | 対話的 + 軽量処理 |
| B: サブエージェント単体 | agent.md | 非対話、他から呼ばれる |
| C: ラッパーパターン | SKILL.md + agent.md | /command起動 + 重い処理は別コンテキスト |
判断フロー
対話が必要?
├─ Yes → 処理重い? → Yes: C / No: A
└─ No → /command起動したい? → Yes: C / No: B
ポイント
disable-model-invocation: trueは使わない。descriptionのトリガー条件で起動制御する方が柔軟- ラッパーパターンでは SKILL.md は薄く(委譲のみ)、実処理は agent.md に書く
- 軽量処理のagentは
model: haikuでコスト3倍削減
+server.ts = サーバー専用APIエンドポイント
SvelteKitのファイル規約:
| ファイル | 役割 |
|---|---|
+page.svelte | ページUI(ブラウザ) |
+page.server.ts | ページ用サーバー処理 |
+server.ts | 純粋なAPIエンドポイント |
Next.jsとの対応:
| Next.js | SvelteKit |
|---|---|
app/api/xxx/route.ts | src/routes/api/xxx/+server.ts |
Cloudflare環境変数の取得パターン
// +server.ts 内(サーバー専用、フロントに露出しない)
const apiKey = platform?.env?.CLAUDE_API_KEY;
platform.env= Cloudflare Workers の Bindings(環境変数)process.envではなくplatform.envを使うのがCF固有のパターン?.は ローカル開発時にplatformが undefined になる可能性があるため
Zedエディタ複数起動 + 内蔵ターミナルのワークフローだとZellijの利点の大半はカバー済み
| Zellijの売り | Zedで代替可能 |
|---|---|
| プロジェクトごとの分離 | ウィンドウを分けて起動 |
| ペイン分割 | エディタ内ターミナル分割 |
| エディタ+ターミナル同時表示 | 標準機能 |
Zellijが本当に活きる場面
- SSH先での作業 — 接続切れてもセッション生存
- エディタ再起動時 — dev serverなど長時間プロセスがZellijで動いていれば死なない
- エディタ非依存の作業環境 — Zedを使わない日でも環境が残る
macOS + Zed内蔵ターミナルでAltキーを使うには
Zed設定で option_as_meta: true が必要。これがないとAltキーが特殊文字入力になる。
{
"terminal": {
"option_as_meta": true
}
} 問題
git worktree add で一時ディレクトリにブランチをチェックアウトすると、node_modules が存在しないためpre-commitフック(lefthook)が失敗する。
必要な準備
worktreeでgit commitする前に以下が必要:
# 1. ルートの依存
yarn install --frozen-lockfile
# 2. サブディレクトリの依存(monorepo構成の場合)
cd site && yarn install --frozen-lockfile
# 3. Nuxtプロジェクトの場合、ESLint設定が .nuxt/ に依存
cd site && npx nuxt prepare
教訓
- biome: ルートの
node_modulesだけで動く - prettier:
site/node_modulesも必要(tailwind plugin等) - eslint:
.nuxt/eslint.config.mjsが必要 →nuxt prepare必須 - フックが段階的に失敗するので、全部入れてからコミットすると効率的
renderHTMLの0とは
tiptap(ProseMirror)の renderHTML で返す配列の 0 は “hole” と呼ばれ、子要素(コンテンツ)が挿入される位置を示す。
// Mark拡張の例
renderHTML({ HTMLAttributes }) {
// 0 = ProseMirrorの"hole"(子要素が挿入される位置)
return ['a', HTMLAttributes, 0];
}
配列の構造
['タグ名', 属性オブジェクト, 0]
│ │ └─ 子要素の挿入位置(hole)
│ └─ HTML属性
└─ 出力するHTML要素
0 がないとコンテンツが描画されない。Mark(インライン装飾)では必須。
BetterAuthのD1アダプタはDrizzle一択
kysely-d1はCF Workers本番でFailed to initialize database adapterエラー。drizzle-orm + drizzleAdapterが正解。
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { drizzle } from 'drizzle-orm/d1';
import * as authSchema from './auth-schema';
const drizzleDb = drizzle(db, { schema: authSchema });
betterAuth({
database: drizzleAdapter(drizzleDb, { provider: 'sqlite', schema: authSchema }),
});
schema必須 — 渡さないとThe model "verification" was not foundエラー。Drizzleスキーマでuser, session, account, verificationの4テーブルを定義して渡す。
認証必須アプリはSPAモードでよい
SEO不要なアプリでssr: trueは百害あって一利なし。src/routes/+layout.tsにexport const ssr = falseで解決。SSR起因のブラウザAPI問題(window未定義等)が全て消える。
ローカル開発でD1を使うには
svelte.config.jsのplatformProxy設定 + ローカルD1マイグレーション適用が必要:
wrangler d1 execute DB_NAME --local --file ./migrations/0001_initial.sql
vite devでplatform.env.DBがundefinedになる場合、.wrangler/state/v3/にローカルDBが存在しないのが原因。
Astro 5ではContent Collectionsの設定が大きく変わった。
変更点
- 設定ファイル:
src/content/config.ts→src/content.config.ts type: "content"が廃止され、loaderが必須に
// Astro 5
import { defineCollection, z } from "astro:content";
import { glob } from "astro/loaders";
const blog = defineCollection({
loader: glob({ pattern: "**/*.md", base: "./src/content/blog" }),
schema: z.object({
title: z.string(),
date: z.coerce.date(),
}),
});
renderも変更
// 旧: post.render()
// 新: import { render } from "astro:content"
import { render } from "astro:content";
const { Content } = await render(post);
post.slug も廃止され、post.id を使う。
Biome 2.xからSvelteファイルのフォーマットに対応した。biome.jsonで以下のように設定する。
{
"formatter": {
"enabled": true,
"indentStyle": "tab"
},
"files": {
"includes": ["**/*.svelte"]
}
}
ただし、Svelteの<script>タグ内のみがフォーマット対象。テンプレート部分(HTML)は対象外なので注意。
# フォーマット実行
pnpm biome format --write "src/**/*.svelte"