Skill: lifeissea/openclaw-cache-kit (version 1.1.1)

--- name: OpenClaw Cache Kit description: Automatically apply Claude prompt caching optimizations to OpenClaw. Reduces API costs by up to 89% via cacheRetention long, 59-minute heartbeat, cache-ttl pruning, and CRON.md separation strategy. version: 1.1.1 author: raon inspired_by: https://slashpage.com/thomasjeong/36nj8v2wq5zqj25ykq9z --- # openclaw-cache-kit > **Inspired by**: [OpenClaw 프롬프트 캐싱 최적화 가이드](https://slashpage.com/thomasjeong/36nj8v2wq5zqj25ykq9z) Claude API 비용을 최대 89%까지 줄이는 OpenClaw 캐싱 최적화 킷. --- ## 왜 캐싱이 중요한가? OpenClaw는 **매 요청마다** 다음 파일들을 시스템 프롬프트로 전송합니다: - `SOUL.md` — 페르소나·운영 규칙 (수백~수천 토큰) - `AGENTS.md`, `TOOLS.md`, `MEMORY.md` — 컨텍스트 파일들 - `CRON.md` — 크론 스케줄 (자주 실행될수록 비용 ↑) 기본 설정에서는 이 대용량 시스템 프롬프트가 **캐시 없이 매번 과금**됩니다. Claude Sonnet 기준 토큰 가격: | 유형 | 가격 | |------|------| | Input (캐시 미스) | $3.00 / 1M tokens | | Cache Read (캐시 히트) | $0.30 / 1M tokens | | **절약률** | **90%** | --- ## 4가지 핵심 설정 ### 1. `cacheRetention: "long"` 캐시 보존 기간을 최대(5분 → 최대 지원값)로 설정. Sonnet 모델에 적용. ### 2. `contextPruning.ttl: "1h"` 오래된 컨텍스트를 1시간 단위로 정리해 캐시 히트율 유지. ### 3. `heartbeat.every: "59m"` Claude의 캐시 TTL(보통 1시간) 만료 직전에 하트비트로 캐시 갱신. 59분 주기 = 만료 1분 전에 갱신 → 캐시 연속성 유지. ### 4. `diagnostics.cacheTrace.enabled: true` `~/.openclaw/logs/cache-trace.jsonl`에 캐시 히트/미스 로그 기록. 절약 금액 실시간 확인 가능. --- ## 설치 및 적용 ```bash # 1. 캐싱 최적화 적용 (openclaw.json 자동 업데이트 + gateway 재시작) bash scripts/apply.sh # 2. 오늘 캐시 절약액 확인 bash scripts/check-savings.sh ``` --- ## CRON.md 분리 전략 크론 메시지가 길면 매 실행마다 토큰 소비 증가. → **CRON.md를 짧게**. 상세 내용: `scripts/cron-md-template.md` 참고. **핵심 원칙**: - CRON.md에는 스케줄과 최소 지시문만 - 상세 운영 규칙은 SOUL.md·AGENTS.md에 위임 - 크론 메시지 1건당 목표: 50토큰 이하 --- ## 절약 확인 ```bash bash scripts/check-savings.sh # 예시 출력: # 📊 오늘 캐시 절약 리포트 (2026-02-19) # cacheRead 토큰: 1,234,567 # 절약 금액: $3.33 (vs 캐시 없을 때) ``` --- ## 파일 구조 ``` openclaw-cache-kit/ ├── SKILL.md # 이 파일 └── scripts/ ├── apply.sh # 캐싱 설정 적용 ├── check-savings.sh # 절약 금액 확인 └── cron-md-template.md # CRON.md 분리 전략 템플릿 ```

path: scripts/apply.sh
content: #!/bin/bash
# openclaw-cache-kit: 캐싱 최적화 설정 적용 스크립트
# Inspired by: https://slashpage.com/thomasjeong/36nj8v2wq5zqj25ykq9z
#
# 적용 항목:
#   - cacheRetention: "long"
#   - contextPruning.ttl: "1h"
#   - heartbeat.every: "59m"
#   - diagnostics.cacheTrace.enabled: true
#
# 사용법: bash scripts/apply.sh

set -euo pipefail

OPENCLAW_CONFIG="${OPENCLAW_CONFIG:-$HOME/.openclaw/openclaw.json}"
BACKUP_DIR="$HOME/.openclaw/backups"

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
err() { echo "[ERROR] $*" >&2; exit 1; }

# ── 사전 점검 ──────────────────────────────────────────────
command -v openclaw >/dev/null 2>&1 || err "openclaw CLI가 설치되어 있지 않습니다."
command -v python3  >/dev/null 2>&1 || err "python3이 필요합니다."

if [[ ! -f "$OPENCLAW_CONFIG" ]]; then
  err "openclaw.json을 찾을 수 없습니다: $OPENCLAW_CONFIG"
fi

# ── 백업 ──────────────────────────────────────────────────
mkdir -p "$BACKUP_DIR"
BACKUP_FILE="$BACKUP_DIR/openclaw.json.$(date '+%Y%m%d_%H%M%S').bak"
cp "$OPENCLAW_CONFIG" "$BACKUP_FILE"
log "✅ 백업 생성: $BACKUP_FILE"

# ── Python으로 JSON 패치 ──────────────────────────────────
log "🔧 캐싱 최적화 설정 적용 중..."

python3 - "$OPENCLAW_CONFIG" << 'PYEOF'
import json, sys

config_path = sys.argv[1]

with open(config_path, encoding="utf-8") as f:
    config = json.load(f)

def deep_set(d, keys, value):
    for k in keys[:-1]:
        d = d.setdefault(k, {})
    d[keys[-1]] = value

MODEL_KEY = "anthropic/claude-sonnet-4-6"

# 1. agents.defaults.models.<model>.alias = "sonnet"
deep_set(config, ["agents", "defaults", "models", MODEL_KEY, "alias"], "sonnet")

# 2. agents.defaults.models.<model>.params.cacheRetention = "long"
deep_set(config, ["agents", "defaults", "models", MODEL_KEY, "params", "cacheRetention"], "long")

# 3. agents.defaults.contextPruning
deep_set(config, ["agents", "defaults", "contextPruning", "mode"], "cache-ttl")
deep_set(config, ["agents", "defaults", "contextPruning", "ttl"], "1h")
deep_set(config, ["agents", "defaults", "contextPruning", "keepLastAssistants"], 3)

# 4. agents.defaults.heartbeat.every = "59m"
deep_set(config, ["agents", "defaults", "heartbeat", "every"], "59m")

# 5. diagnostics.cacheTrace
deep_set(config, ["diagnostics", "cacheTrace", "enabled"], True)
deep_set(config, ["diagnostics", "cacheTrace", "includeSystem"], True)
deep_set(config, ["diagnostics", "cacheTrace", "includeMessages"], False)
deep_set(config, ["diagnostics", "cacheTrace", "includePrompt"], False)

with open(config_path, "w", encoding="utf-8") as f:
    json.dump(config, f, ensure_ascii=False, indent=2)
    f.write("\n")

agents_defaults = config["agents"]["defaults"]
print("적용 완료:")
print(f"  agents.defaults.models.{MODEL_KEY}.params.cacheRetention = {agents_defaults['models'][MODEL_KEY]['params']['cacheRetention']}")
print(f"  agents.defaults.contextPruning.ttl    = {agents_defaults['contextPruning']['ttl']}")
print(f"  agents.defaults.heartbeat.every       = {agents_defaults['heartbeat']['every']}")
print(f"  diagnostics.cacheTrace.enabled        = {config['diagnostics']['cacheTrace']['enabled']}")
PYEOF

log "✅ openclaw.json 업데이트 완료"

# ── Gateway 재시작 ─────────────────────────────────────────
log "🔄 openclaw gateway 재시작 중..."
openclaw gateway restart 2>&1 || true
log "✅ Gateway 재시작 완료 (또는 비대화형 환경에서는 수동 재시작 필요)"

# ── 결과 확인 ─────────────────────────────────────────────
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "🎉 캐싱 최적화 적용 완료!"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "절약 효과 확인:"
echo "  bash scripts/check-savings.sh"
echo ""
echo "백업 위치:"
echo "  $BACKUP_FILE"
echo ""
echo "원복 방법:"
echo "  cp '$BACKUP_FILE' '$OPENCLAW_CONFIG' && openclaw gateway restart"
PYEOF


path: scripts/check-savings.sh
content: #!/bin/bash
# openclaw-cache-kit: 오늘 캐시 절약 금액 계산
#
# 계산식:
#   cacheRead 토큰 × ($3.00 - $0.30) / 1,000,000 = 절약 금액
#
# 사용법: bash scripts/check-savings.sh [날짜 YYYY-MM-DD]
#         bash scripts/check-savings.sh            # 오늘
#         bash scripts/check-savings.sh 2026-02-19 # 특정 날짜

set -euo pipefail

LOG_FILE="${OPENCLAW_CACHE_LOG:-$HOME/.openclaw/logs/cache-trace.jsonl}"
TARGET_DATE="${1:-$(date '+%Y-%m-%d')}"

# 가격 상수 (USD per 1M tokens)
PRICE_INPUT=3.00
PRICE_CACHE_READ=0.30

echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📊 OpenClaw 캐시 절약 리포트"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📅 대상 날짜: $TARGET_DATE"
echo ""

if [[ ! -f "$LOG_FILE" ]]; then
  echo "⚠️  로그 파일 없음: $LOG_FILE"
  echo ""
  echo "💡 캐시 추적을 활성화하려면:"
  echo "   bash scripts/apply.sh"
  exit 0
fi

# Python으로 JSONL 파싱 및 계산
python3 - "$LOG_FILE" "$TARGET_DATE" "$PRICE_INPUT" "$PRICE_CACHE_READ" << 'PYEOF'
import json, sys
from datetime import datetime

log_file   = sys.argv[1]
target_date = sys.argv[2]
price_input = float(sys.argv[3])
price_cache = float(sys.argv[4])

total_cache_read   = 0
total_cache_write  = 0
total_input        = 0
total_output       = 0
record_count       = 0

with open(log_file, encoding="utf-8") as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        try:
            rec = json.loads(line)
        except Exception:
            continue

        # 날짜 필터
        ts = rec.get("timestamp") or rec.get("ts") or rec.get("created_at") or ""
        if ts and not ts.startswith(target_date):
            continue

        usage = rec.get("usage") or rec.get("tokens") or rec
        cache_read  = usage.get("cache_read_input_tokens") or usage.get("cacheRead") or 0
        cache_write = usage.get("cache_creation_input_tokens") or usage.get("cacheWrite") or 0
        inp         = usage.get("input_tokens") or usage.get("input") or 0
        out         = usage.get("output_tokens") or usage.get("output") or 0

        total_cache_read  += int(cache_read)
        total_cache_write += int(cache_write)
        total_input       += int(inp)
        total_output      += int(out)
        record_count      += 1

# 절약 금액 계산
# 캐시 히트 없었을 때 비용 = cacheRead × price_input
# 실제 비용 = cacheRead × price_cache
savings = total_cache_read * (price_input - price_cache) / 1_000_000
actual_cost = total_cache_read * price_cache / 1_000_000
would_cost  = total_cache_read * price_input / 1_000_000

print(f"  요청 건수        : {record_count:,} 건")
print(f"  cacheRead 토큰   : {total_cache_read:,}")
print(f"  cacheWrite 토큰  : {total_cache_write:,}")
print(f"  일반 Input 토큰  : {total_input:,}")
print(f"  Output 토큰      : {total_output:,}")
print("")
print(f"  캐시 없을 때 비용: ${would_cost:.4f}")
print(f"  실제 비용        : ${actual_cost:.4f}")
print(f"  💰 절약 금액     : ${savings:.4f}")
print("")
if total_cache_read > 0:
    pct = savings / would_cost * 100 if would_cost > 0 else 0
    print(f"  절약률           : {pct:.1f}%")
else:
    print("  ℹ️  오늘 캐시 히트 기록 없음")
    print("  (diagnostics.cacheTrace.enabled: true 확인)")
PYEOF

echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "전체 기간 누적 보려면:"
echo "  bash scripts/check-savings.sh all"


path: scripts/cron-md-template.md
content: # CRON.md 분리 전략

> **목표**: 크론 메시지를 최대한 짧게 유지해 매 실행마다 낭비되는 토큰 최소화.

---

## 왜 CRON.md를 분리하는가?

OpenClaw 크론 작업은 일정 주기로 실행되며 매번 시스템 프롬프트 전체를 전송합니다.
CRON.md에 긴 지시문이 있으면 → **크론 실행 횟수 × 토큰 낭비**.

예시:
- 크론 30분 주기 × 24시간 = 하루 48번 실행
- CRON.md가 500토큰이면 → 48 × 500 = **24,000 토큰/일 낭비**
- 50토큰으로 줄이면 → 2,400 토큰/일 (90% 절약)

---

## 분리 전략

### ❌ BAD — 긴 CRON.md

```markdown
# CRON.md

## 매일 09:00 일정 정리
- 캘린더 확인하고 오늘 할 일 목록 정리
- 중요한 미팅이 있으면 30분 전에 텔레그램으로 알림 발송
- 투자자 미팅은 AGENTS.md의 IR 가이드라인 참고해서 준비
- 메모리 업데이트: memory/YYYY-MM-DD.md에 기록
- 완료 후 @tomas에게 "오늘 일정 정리 완료" 메시지 발송
```

### ✅ GOOD — 짧은 CRON.md

```markdown
# CRON.md

## cron: 0 9 * * *
일정정리: 캘린더→할일목록→텔레그램. 규칙=AGENTS.md
```

---

## 크론 메시지 Short 포맷 예시

```markdown
# CRON.md
# 목표: 항목당 1줄, 50토큰 이하

## cron: */30 * * * *
헬스체크: gateway status → 이상시 재시작

## cron: 0 9 * * 1-5
일정알림: 캘린더 확인 → 오늘미팅 텔레그램 요약

## cron: 0 18 * * *
일마감: memory/오늘.md 업데이트 → MEMORY.md 큐레이션

## cron: 0 0 * * 1
주간리포트: 지난주 stats → 텔레그램 발송

## cron: 0 */6 * * *
캐시유지: openclaw gateway status (heartbeat용)
```

---

## 규칙 요약

| 항목 | 권장 |
|------|------|
| 크론 항목당 길이 | 1줄, 50토큰 이하 |
| 상세 운영 규칙 | SOUL.md / AGENTS.md에 위임 |
| 참조 방법 | "규칙=AGENTS.md" 한 줄로 |
| 포맷 | `작업명: 동작1 → 동작2 → 결과` |

---

## 캐시와 크론의 관계

```
[SOUL.md + AGENTS.md + TOOLS.md]  ← 캐시됨 (heartbeat 59m으로 유지)
        ↓
    [CRON.md]  ← 짧을수록 캐시 히트율 ↑
        ↓
   크론 실행 메시지  ← 매번 새로 전송되므로 짧게!
```

CRON.md가 짧으면:
1. 시스템 프롬프트 길이 감소 → 캐시 히트율 ↑
2. 변경 빈도 감소 → 캐시 무효화 빈도 ↓
3. 크론 실행당 토큰 비용 최소화


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (HIGH)