Agent skill

Caching

by kid-sid in kid-sid/claude-spellbook

A skill your agent uses when adding or debugging caching in a service — choosing a cache strategy, designing TTLs, preventing stampedes, reasoning about invalidation, or configuring HTTP…

MITAuto-check passedBackend & APIs

Install Caching

skills CLI
$ npx skills add kid-sid/claude-spellbook --skill caching -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install kid-sid/claude-spellbook caching --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/kid-sid/claude-spellbook.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/caching .claude/skills/caching && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
caching
GitHub stars
189
Token cost
~3.4k tokens
SKILL.md length
593 words
Files
1
Skills in repo
52
Repo updated
First seen
Licence
MIT

At a glance

A skill your agent uses when adding or debugging caching in a service — choosing a cache strategy, designing TTLs, preventing stampedes, reasoning about invalidation, or configuring HTTP…

  • Debugging caching in a service — choosing a cache strategy
  • SKILL.md covers When to Activate, Strategy Selection, Cache-Aside (Most Common) and Cache Key Design, plus 9 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
  • Preventing stampedes

What it does

Caching is an agent skill from kid-sid/claude-spellbook. Use when adding or debugging caching in a service — choosing a cache strategy, designing TTLs, preventing stampedes, reasoning about invalidation, or configuring HTTP Cache-Control headers.

Its SKILL.md is about 3.4k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Backend & APIs, covering Caching. It works with Redis. The repository describes itself as: A curated collection of skills, prompts, and workflows that extend Claude's capabilities — your personal grimoire for AI-powered development. The licence is MIT.

When your agent uses it

  • Debugging caching in a service — choosing a cache strategy
  • Preventing stampedes
  • Reasoning about invalidation
  • Configuring HTTP Cache-Control headers

Example prompts

  • “/caching”

Requirements

  • Python 3

What it can do on your machine

Read from SKILL.md and the folder at commit a7c2ac9. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are python, typescript and go).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Caching loads about 3.4k tokens when it runs. Until then it costs about 49 tokens; SKILL.md has 593 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~49
When it runs · the whole SKILL.md, loaded when a task matches
~3.4k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from kid-sid/claude-spellbook at commit a7c2ac9, republished under its MIT licence (© kid-sid). 593 words, ~3,372 tokens.

Download SKILL.mdSave it as .claude/skills/caching/SKILL.md (or your agent's skills folder).
name
caching
description
Use when adding or debugging caching in a service — choosing a cache strategy, designing TTLs, preventing stampedes, reasoning about invalidation, or configuring HTTP Cache-Control headers.

Caching Patterns

Strategies and implementation patterns for application-level, distributed, and HTTP caching.

When to Activate

  • Adding Redis or Memcached to reduce database load or API latency
  • Designing TTL values and cache invalidation strategies
  • Preventing cache stampede on high-traffic keys
  • Configuring HTTP Cache-Control and CDN caching rules
  • Choosing between cache-aside, write-through, or write-behind
  • Debugging stale data, cache poisoning, or thundering herd problems
  • Sizing a cache or deciding what to cache vs. not cache

Strategy Selection

StrategyHowBest For
Cache-aside (lazy)App checks cache first; on miss, loads from DB, populates cacheGeneral-purpose read caching
Write-throughWrite to cache and DB simultaneouslyData that's read immediately after write
Write-behind (write-back)Write to cache; async flush to DBHigh write throughput, tolerance for small loss window
Read-throughCache fetches from DB on miss (cache manages itself)Managed caches (ElastiCache DAX, Momento)
Refresh-aheadProactively refresh before expiryPredictable access patterns, zero-miss latency required

Cache-Aside (Most Common)

python
# Python — cache-aside with Redis
import redis, json, hashlib
from typing import Callable, TypeVar

T = TypeVar("T")
r = redis.Redis(host="redis", port=6379, decode_responses=True)

def get_or_set(key: str, loader: Callable[[], T], ttl: int = 300) -> T:
    cached = r.get(key)
    if cached is not None:
        return json.loads(cached)

    value = loader()
    r.setex(key, ttl, json.dumps(value, default=str))
    return value

# Usage
user = get_or_set(f"user:{user_id}", lambda: db.query(User).get(user_id), ttl=600)
typescript
// TypeScript — cache-aside
import { createClient } from "redis";

const redis = createClient({ url: "redis://redis:6379" });

async function getOrSet<T>(
  key: string,
  loader: () => Promise<T>,
  ttlSeconds = 300,
): Promise<T> {
  const cached = await redis.get(key);
  if (cached) return JSON.parse(cached) as T;

  const value = await loader();
  await redis.setEx(key, ttlSeconds, JSON.stringify(value));
  return value;
}
go
// Go — cache-aside
func (c *Cache) GetOrSet(ctx context.Context, key string, loader func() (any, error), ttl time.Duration) (any, error) {
    val, err := c.redis.Get(ctx, key).Result()
    if err == nil {
        var result any
        json.Unmarshal([]byte(val), &result)
        return result, nil
    }
    if !errors.Is(err, redis.Nil) {
        return nil, err
    }

    data, err := loader()
    if err != nil {
        return nil, err
    }
    b, _ := json.Marshal(data)
    c.redis.SetEx(ctx, key, string(b), ttl)
    return data, nil
}

Cache Key Design

# Pattern: <service>:<entity>:<id>[:<variant>]
user:profile:123
user:orders:123:active
product:detail:sku-456
search:results:<md5(query+filters)>

# BAD: too broad — invalidation nukes unrelated data
cache_key = "users"

# BAD: too granular — misses sharing opportunity
cache_key = f"user_orders_by_{user_id}_status_{status}_page_{page}"

# GOOD: namespace + entity + discriminator
cache_key = f"user:{user_id}:orders:{status}"   # paginate in app, not in key

TTL Design

Data TypeTTL RangeReasoning
User session15–60 min (sliding)Balance UX vs. stale auth
User profile5–15 minInfrequent changes, high read volume
Product catalog1–24 hrChanges only on explicit update
Search results1–5 minAcceptable staleness for non-personalized
Rate limit countersMatch the window (60s, 3600s)Must expire with the window
One-time tokensExact validity periodNo grace period
Computed aggregates1–10 minTrade accuracy for throughput
python
# Sliding TTL for sessions — reset on every access
def get_session(session_id: str) -> dict | None:
    key = f"session:{session_id}"
    data = r.get(key)
    if data:
        r.expire(key, 1800)  # extend on access
        return json.loads(data)
    return None

Cache Stampede Prevention

When a popular key expires, many requests hit the DB simultaneously.

Probabilistic Early Recomputation (XFetch)
python
import math, random, time

def fetch_with_xfetch(key: str, loader: Callable[[], T], ttl: int, beta: float = 1.0) -> T:
    cached_raw = r.get(key)
    if cached_raw:
        entry = json.loads(cached_raw)
        delta = entry["compute_time"]
        remaining_ttl = r.ttl(key)
        # probabilistically recompute before expiry
        if remaining_ttl - beta * delta * math.log(random.random()) < 0:
            cached_raw = None  # trigger recompute
        else:
            return entry["value"]

    start = time.monotonic()
    value = loader()
    compute_time = time.monotonic() - start
    r.setex(key, ttl, json.dumps({"value": value, "compute_time": compute_time}, default=str))
    return value
Mutex Lock (Simpler)
python
import time

def get_with_lock(key: str, loader: Callable[[], T], ttl: int) -> T:
    cached = r.get(key)
    if cached:
        return json.loads(cached)

    lock_key = f"{key}:lock"
    acquired = r.set(lock_key, "1", nx=True, ex=10)  # 10s lock timeout

    if acquired:
        try:
            value = loader()
            r.setex(key, ttl, json.dumps(value, default=str))
            return value
        finally:
            r.delete(lock_key)
    else:
        # Wait and retry — another worker is computing
        time.sleep(0.1)
        return get_with_lock(key, loader, ttl)

Redis Data Structures

python
# String — simple values, counters
r.set("config:feature_x", "enabled")
r.incr("counter:api_calls:2025-06-01")

# Hash — object fields (avoids full serialization for partial updates)
r.hset("user:123", mapping={"name": "Alice", "plan": "pro"})
r.hget("user:123", "plan")
r.hgetall("user:123")

# Set — membership, deduplication
r.sadd("online_users", "user:123", "user:456")
r.sismember("online_users", "user:123")

# Sorted Set — leaderboards, rate limiting with sliding window
r.zadd("leaderboard", {"user:123": 1500, "user:456": 2000})
r.zrevrange("leaderboard", 0, 9, withscores=True)  # top 10

# List — queues, recent activity
r.lpush("recent:user:123", "order:789")
r.ltrim("recent:user:123", 0, 49)  # keep last 50

# Stream — event log with consumer groups (lightweight Kafka alternative)
r.xadd("events:orders", {"event_type": "placed", "order_id": "abc"})

Invalidation Strategies

python
# 1. TTL expiry — simplest, eventual consistency
r.setex(key, 300, value)

# 2. Explicit delete on write — strong consistency
def update_user(user_id: str, data: dict):
    db.update(User, user_id, data)
    r.delete(f"user:profile:{user_id}")  # invalidate immediately
    r.delete(f"user:orders:{user_id}:*")  # careful: KEYS is O(N), use SCAN

# 3. Tag-based invalidation — invalidate groups of keys
def set_with_tag(key: str, value: any, tag: str, ttl: int):
    r.setex(key, ttl, json.dumps(value))
    r.sadd(f"tag:{tag}", key)
    r.expire(f"tag:{tag}", ttl + 60)

def invalidate_tag(tag: str):
    keys = r.smembers(f"tag:{tag}")
    if keys:
        r.delete(*keys)
    r.delete(f"tag:{tag}")

# 4. Cache-aside with versioning — no explicit invalidation needed
def versioned_key(entity: str, entity_id: str) -> str:
    version = r.get(f"version:{entity}:{entity_id}") or "0"
    return f"{entity}:{entity_id}:v{version}"

def invalidate(entity: str, entity_id: str):
    r.incr(f"version:{entity}:{entity_id}")  # old keys naturally expire

Rate Limiting with Redis

python
# Sliding window counter
def is_rate_limited(user_id: str, limit: int = 100, window: int = 60) -> bool:
    key = f"ratelimit:{user_id}"
    now = time.time()
    window_start = now - window

    pipe = r.pipeline()
    pipe.zremrangebyscore(key, 0, window_start)  # remove old entries
    pipe.zadd(key, {str(now): now})              # add current request
    pipe.zcard(key)                              # count in window
    pipe.expire(key, window)
    results = pipe.execute()

    return results[2] > limit

# Token bucket (alternative — smoother bursting)
def consume_token(key: str, rate: float, capacity: int) -> bool:
    lua = """
    local tokens = tonumber(redis.call('GET', KEYS[1])) or tonumber(ARGV[2])
    local last = tonumber(redis.call('GET', KEYS[2])) or tonumber(ARGV[3])
    local now = tonumber(ARGV[3])
    local rate = tonumber(ARGV[1])
    local capacity = tonumber(ARGV[2])
    tokens = math.min(capacity, tokens + (now - last) * rate)
    if tokens >= 1 then
        redis.call('SET', KEYS[1], tokens - 1)
        redis.call('SET', KEYS[2], now)
        return 1
    end
    return 0
    """
    # Use redis.eval() with Lua for atomic token bucket

HTTP Caching

Cache-Control Headers
# Static assets — long cache, versioned URLs
Cache-Control: public, max-age=31536000, immutable   # 1 year; URL changes on update

# API responses — CDN-cacheable, short TTL
Cache-Control: public, max-age=60, s-maxage=300      # browser 1min, CDN 5min

# Authenticated API responses — never CDN-cache
Cache-Control: private, max-age=0, must-revalidate

# Never cache
Cache-Control: no-store

# Revalidate with ETag
Cache-Control: no-cache                               # always revalidate; use ETag
ETag: "abc123"

# Vary header — CDN stores separate copies per value
Vary: Accept-Encoding, Accept-Language
ETags and Conditional Requests
python
from hashlib import md5
from flask import request, jsonify, make_response

@app.get("/api/products/<product_id>")
def get_product(product_id: str):
    product = get_product_from_db(product_id)
    etag = md5(json.dumps(product, sort_keys=True).encode()).hexdigest()

    if request.headers.get("If-None-Match") == etag:
        return "", 304  # Not Modified — no body, saves bandwidth

    response = make_response(jsonify(product))
    response.headers["ETag"] = etag
    response.headers["Cache-Control"] = "public, max-age=60"
    return response

Distributed Cache Pitfalls

# 1. Cache penetration — repeated misses for non-existent keys
Solution: cache null/"not found" with short TTL (30–60s)
r.setex(key, 60, json.dumps(None))

# 2. Cache avalanche — many keys expire simultaneously
Solution: add jitter to TTL
ttl = base_ttl + random.randint(0, base_ttl // 10)

# 3. Hot key — single key receiving disproportionate traffic
Solution: local in-process cache as L1, Redis as L2
from functools import lru_cache
@lru_cache(maxsize=1000)
def get_config(key: str): ...  # millisecond in-process cache

# 4. Large values — serializing/deserializing huge objects
Solution: store field-level with Redis Hash; never cache full result sets > 1MB

# 5. Stale reads after failover
Solution: use Redis Sentinel or Cluster; never rely on single-node without replication

See also: performance, database-design, api-design

Show full SKILL.md (319 more words)Show less

Red Flags

  • Cache stampede on simultaneous key expiry — all requests hit the DB at once when a hot key expires; use probabilistic early expiry, a distributed lock, or staggered TTLs to prevent the pile-on
  • No TTL on cached values — keys accumulate indefinitely and consume memory; every cached value must have an expiry unless explicitly justified as permanent
  • Missing ownership context in cache keys — a key without tenant or user ID can serve one user's data to another; always include the ownership scope in every cache key
  • Write-through without invalidating on write failure — a failed DB write while the cache shows success creates a stale-read window; invalidate the cache key on any write failure
  • In-process LRU cache in a multi-worker service — forked workers maintain separate memory; a cache write in one worker is invisible to others; use Redis for cross-process sharing
  • Cache-Control: no-store on versioned static assets — disabling caching on content-hashed JS/CSS/images forces a full download on every page load; use max-age=31536000, immutable for versioned assets
  • Caching at the wrong layer — caching computed aggregates that are rarely requested wastes memory; cache at the layer closest to the hot query, and measure hit rates before adding any new cache

Checklist

  • Cache keys follow <service>:<entity>:<id> namespace convention
  • TTL values justified per data type — not a single global default
  • Cache-aside pattern implemented; null results cached with short TTL (prevents cache penetration)
  • TTL jitter applied to prevent cache avalanche on mass expiry
  • High-traffic keys protected against stampede (mutex lock or XFetch)
  • Invalidation strategy defined: TTL only, explicit delete on write, or versioned keys
  • Sensitive data (auth tokens, PII) uses private Cache-Control or not cached at all
  • Static assets served with long max-age + immutable + content-hashed URLs
  • Rate limiters use atomic Redis operations (Lua scripts or pipeline)
  • Redis connection pooling configured; not creating new connection per request
  • Cache hit rate monitored; eviction policy set (allkeys-lru or volatile-lru)
  • No KEYS * in production — use SCAN for bulk operations

© kid-sid, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in skills/caching of kid-sid/claude-spellbook.

Open the folder on GitHubat commit a7c2ac9

Compare with similar skills

Caching next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Caching compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Caching this skillkid-sid/claude-spellbook189—~3.4kAutomated safety check: PassMIT
Stripe Projectsfossasia/eventyay1.7k5 repos~2kAutomated safety check: NotesApache-2.0
FoundatioFoundatioFx/Foundatio2.1k—~3.9kAutomated safety check: PassApache-2.0
FastAPI-Redis SDK Developmentredis/fastapi-redis-sdk404—~2.5kAutomated safety check: NotesMIT
Caching Patternsdilolabs/nosia2131 repos~1.9kAutomated safety check: PassMIT
Cachingcodewithmukesh/dotnet-claude-kit7511 repos~1.4kAutomated safety check: PassMIT

Similar skills

  • Stripe Projects

    fossasia/eventyay

    A skill your agent uses when the user wants to provision infrastructure or third-party services using Stripe Projects.

    1.7k GitHub starsUsed in 5 repos~2k tokens
    Backend & APIsAuto-check: notes
  • Foundatio

    FoundatioFx/Foundatio

    A skill your agent uses when working with Foundatio infrastructure abstractions for .NET -- caching, queuing, messaging, file storage, distributed locking, or background jobs.

    2.1k GitHub stars~3.9k tokensUpdated today
    Backend & APIsAuto-check passed
  • FastAPI-Redis SDK Development

    redis/fastapi-redis-sdk

    Official

    Guides development on the fastapi-redis-sdk library itself - its connection lifecycle, dependency-injected caching, and async/sync bridging.

    404 GitHub stars~2.5k tokensUpdated 6 days ago
    Backend & APIsAuto-check: notes
  • Caching Patterns

    dilolabs/nosia

    Implements HTTP caching with ETags, fragment caching, Russian doll caching, and Solid Cache configuration.

    213 GitHub starsUsed in 1 repo~1.9k tokens
    Backend & APIsAuto-check passed
  • Caching

    codewithmukesh/dotnet-claude-kit

    Caching strategies for .NET 10 applications. An agent skill from codewithmukesh/dotnet-claude-kit.

    751 GitHub starsUsed in 1 repo~1.4k tokens
    Backend & APIsAuto-check passed
  • Caching Strategies

    ThibautBaissac/rails_ai_agents

    Implements Rails caching patterns for performance optimization.

    665 GitHub stars~1.4k tokensUpdated 4 mo ago
    Backend & APIsAuto-check passed

More from kid-sid/claude-spellbook

All 52 skills in this repo
  • Accessibility

    kid-sid/claude-spellbook

    A skill your agent uses when building or reviewing UI components for keyboard and screen reader compatibility, adding ARIA to custom widgets, auditing a page for WCAG AA conformance, or preparing…

    189 GitHub stars~3.2k tokensUpdated 2 mo ago
    Auto-check passed
  • Agentex

    kid-sid/claude-spellbook

    A skill your agent uses when building, wiring, or debugging an Agentex agent — choosing agent type, configuring acp.py and manifest.yaml, using adk.messages or adk.state, or resolving…

    189 GitHub stars~2.2k tokensUpdated 2 mo ago
    Auto-check: notes
  • AI Engineer

    kid-sid/claude-spellbook

    A skill your agent uses when building production LLM applications — designing RAG pipelines, choosing vector databases, implementing agent orchestration, optimizing cost, or adding AI safety…

    189 GitHub stars~3.7k tokensUpdated 2 mo ago
    Auto-check passed
  • Angular

    kid-sid/claude-spellbook

    A skill your agent uses when building or refactoring Angular applications — choosing between signals, RxJS, and NgRx for state, configuring routing with guards and lazy loading, optimizing change…

    189 GitHub stars~5k tokensUpdated 2 mo ago
    Auto-check passed
  • API Design

    kid-sid/claude-spellbook

    A skill your agent uses when designing new REST endpoints, reviewing an existing API contract, adding pagination or filtering, planning a versioning strategy, or building a public or partner-facing…

    189 GitHub stars~3.6k tokensUpdated 2 mo ago
    Auto-check passed
  • Auth

    kid-sid/claude-spellbook

    A skill your agent uses when implementing login flows, issuing or validating JWTs, setting up OAuth2/OIDC with a provider, designing role-based or attribute-based access control, securing API…

    189 GitHub stars~3.2k tokensUpdated 2 mo ago
    Auto-check passed

Works with

Categories

Questions about Caching

What does Caching do?

A skill your agent uses when adding or debugging caching in a service — choosing a cache strategy, designing TTLs, preventing stampedes, reasoning about invalidation, or configuring HTTP…. Caching is an agent skill from kid-sid/claude-spellbook. Use when adding or debugging caching in a service — choosing a cache strategy, designing TTLs, preventing stampedes, reasoning about invalidation, or configuring HTTP Cache-Control headers.

When should I use Caching?

Caching fits situations like: debugging caching in a service — choosing a cache strategy; preventing stampedes; reasoning about invalidation; configuring HTTP Cache-Control headers.

How do I install Caching in Claude Code?

Run `npx skills add kid-sid/claude-spellbook --skill caching -a claude-code`. Or copy the skill folder (skills/caching in kid-sid/claude-spellbook) into .claude/skills/caching in your project. Claude Code loads it when a task matches its description.

How do I install Caching in Codex?

Run `npx skills add kid-sid/claude-spellbook --skill caching -a codex`. Or copy the skill folder (skills/caching in kid-sid/claude-spellbook) into .agents/skills/caching in your project. Codex loads it when a task matches its description.

Can I use Caching in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add kid-sid/claude-spellbook --skill caching -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/caching, .gemini/skills/caching, .github/skills/caching and .opencode/skills/caching in your project.

What does Caching need to run?

SKILL.md names no scripts, command-line tools or credentials: Caching is instructions for the agent only. Our summary lists: Python 3.

Does Caching access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Caching safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Caching use?

Caching is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Caching use?

About 3.4k tokens (SKILL.md is roughly 13k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Caching?

Skills that share tags, products or a category with Caching: Stripe Projects (fossasia/eventyay, 1.7k stars), Foundatio (FoundatioFx/Foundatio, 2.1k stars), FastAPI-Redis SDK Development (redis/fastapi-redis-sdk, 404 stars) and Caching Patterns (dilolabs/nosia, 213 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Caching?

kid-sid (a GitHub user) maintains it in kid-sid/claude-spellbook, which has 189 GitHub stars. The repository holds 52 skills in this directory. The repository was last updated on August 5, 2026.

Source: kid-sid/claude-spellbook on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.