# Xp Update

> Writes knowledge infusions from the current session into .xp/db.jsonl. Use it with /xp-update at the end of a session or whenever the user explicitly asks for it.

- Skill: `opahimmel/xp-update` (Agent Skill)
- Install (CLI): `npx skillmds@latest add opahimmel/xp-update`
- Raw SKILL.md: https://api.skillmd.com/api/skills/opahimmel/xp-update/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: opahimmel (https://skillmd.com/u/opahimmel)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/opahimmel/xp-update

---


# xp-update

Write directly, then show the marker snippet. No exploring. Session knowledge only.

## Precondition

`.xp/db.jsonl` must exist. If not → call `/xp-index` first.

## Purpose

The XP-System is a semantic blueprint of the codebase. Each entry describes a
labeled symbol so that a new agent, after one grep, understands within 30
seconds what it is, what it's connected to, and what isn't in the code.

Not exception knowledge. Baseline knowledge.

## Process

### 1. What gets entered?

Every symbol that was tagged with an `@xp` marker in this session, or already
carries one whose note is outdated or incomplete.

An entry answers three questions:

| Question | What belongs in it |
|-------|---------------|
| **What is it?** | Semantic role, not syntax — what the symbol means in the system |
| **What does it connect to?** | Direct dependencies, consumers, related concepts in the system |
| **What isn't in the code?** | Implicit contracts, naming discrepancies, edge cases, traps |

### 2. Filter

| Check | Result |
|---------|---------|
| Already in db.jsonl? (`grep "slug" .xp/db.jsonl`) | Upsert — old line gets replaced |
| Entry outdated / irrelevant? | Actively delete the line (upsert without appending) or omit it |
| Would the note add nothing beyond the readable code? | Add it anyway — semantic role + connections still count |

### 3. Write the entry (upsert)

**Format:**
```json
{"id": "domain:slug", "keywords": ["natural-language", "search", "terms"], "note": "Semantic role. Connections + why. Traps or implicit contracts.", "files": ["src/relevant.ts"], "file_hash": "abc123", "updated": "YYYY-MM-DD"}
```

`keywords` — natural-language terms from how the task was described, not code
symbols. Goal: `grep -i "ordering"` hits the entry `sequencer:resolve-chain`.
At least 3, at most 8 keywords per entry.

**Determine the file hash:**
```bash
git hash-object src/relevant.ts
```

**Upsert — replace existing id, append new ones:**
```bash
python3 -c "
import json, sys
new = json.loads(sys.argv[1])
lines = [l for l in open('.xp/db.jsonl') if json.loads(l)['id'] != new['id']]
lines.append(json.dumps(new, ensure_ascii=False) + '\n')
open('.xp/db.jsonl', 'w').writelines(lines)
" '<JSON>'
```

No appending without checking first. No `status: obsolete`. No duplicates.

**The note — density over completeness:**

Everything in one or two sentences. Three aspects, no filler.

❌ `"Shape is an interface in types.ts"` — syntax, not semantics
❌ `"Refactored Shape today"` — session diary
✅ `"Central canvas data structure — stored in the DB as canvas_object (naming discrepancy). ShapeNormalizer must run before every render call, or it crashes. Consumers: RenderEngine, ExportService."` — role + connections + trap
✅ `"Single entry point for all API errors — handling elsewhere is not caught. Connects to Logger and ResponseBuilder. Naming convention: E_USER_ prefix for user-facing errors."` — semantics + topology + contract

### 4. Split vs. merge

One entry = one precise hit. Cramming multiple facts into one note creates
exactly the noise the XP-System is meant to avoid: someone searching for
`_frameAssignments` would otherwise also get `name-migration` context along
with it.

**Split when:**
- the facts can become true/done independently of each other (one can be
  finished while the others aren't)
- a user would plausibly search for only one of the facts, not all of them

**Merge when:**
- the facts are inseparable — neither makes sense without the other
- one fact without the other would be misleading

**Cluster term:** when several slugs belong to the same effort, add a shared
term to all their keyword arrays (e.g. `"frame-labels-rollout"`). A broad
search then hits all of them; a precise search hits only one. No `depends_on`
field needed — the domain prefix in the id (`frame-labels:`) acts as an
implicit cluster when grepping.

### 5. Display

Show all new or changed entries.

