About
This skill performs a read-only integrity check on a Claude Code agent's memory store to verify reachability and budget compliance. It detects issues like orphaned files, broken links, and truncation limit violations against the 200-line/25KB caps. Developers should run it during session starts, after repository changes, or as a periodic health check before relying on memory contents.
Quick Install
Claude Code
Recommendednpx skills add pjt222/agent-almanac -a claude-code/plugin add https://github.com/pjt222/agent-almanacgit clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/verify-memory-integrityCopy and paste this command in Claude Code to install this skill
Documentation
Verify Memory Integrity
Read a Claude Code memory store and report whether it is reachable and within budget — without changing a byte of it. A store-identity resolution and eight checks cover the two truncation caps, orphaned topic files, dangling and degraded references, cross-reference resolution, catalog conformance, topic-file size, and recoverability.
manage-memory and prune-agent-memory both mutate the store. This skill is the instrument they
are measured with: run it before either one for a baseline, and again afterward to prove the
mutation stranded nothing. An instrument that edits its subject cannot measure a change.
When to Use
- At the start of a session, before trusting anything the memory index claims
- Before and after an index compaction — to record what was reachable while it still was, then to prove nothing was stranded. Compaction is the operation the caps make mandatory, and it is also the operation that breaks reachability
- After a repository rename or move, which invalidates paths inside memory entries
- When a memory directory has grown past a few dozen topic files and nobody has audited the links
- As a periodic health check, on the same cadence as
prune-agent-memory
Do NOT use to fix anything. This skill never writes to the store. Hand its report to
manage-memory (to relink or extract) or prune-agent-memory (to delete) and re-run it afterward.
Inputs
| Parameter | Type | Required | Description |
|---|---|---|---|
memory_dir | path | Yes | The store to verify, typically ~/.claude/projects/<project>/memory/. Never hardcode it: autoMemoryDirectory in any settings scope and CLAUDE_CODE_PROJECT_DIR_NAME both relocate it |
report_path | path | No | Where the report is written (default: a path under $TMPDIR). Must be outside memory_dir |
topic_max_bytes | number | No | Per-project topic-file size threshold for check 7. No default — see that step |
name_prefixes | list | No | Filename prefixes that check 5 may strip when resolving (default: feedback-, project-, reference- — hyphen form, because the block normalizes _ to - before it strips) |
Read-Only Contract
No Write, no Edit, no rm, no mv, no redirect into the store. allowed-tools omits the
mutating tools deliberately and no step below writes inside memory_dir, which is what makes the
skill safe every session and its output usable as a before/after baseline.
Each check appends verdict lines to one report file outside the store, and the run exits
non-zero if any line begins FAIL. Steps run as separate tool calls, so shell state does not
persist: re-export the report path and the store path in each call rather than relying on a trap or
an earlier assignment. The report skeleton, its exit-code rules and the fail-closed guard on a
missing report are in references/EXAMPLES.md.
Procedure
Step 0: Resolve the store before measuring it
Every number below reads whichever directory this step names, so name it first. The
project-directory slug transformation changed between 2026-03-22 and 2026-04-16: an underscore in a
project path used to be preserved and is now converted to a hyphen. So memory written before the
change lives under a slug the harness will never open again, and two project paths differing only by
_ versus - now collide onto one store.
# Report the RESOLVED path, plus any sibling store differing only in _ vs -.
DIR=<memory-dir> # .../projects/<slug>/memory
STORE=$(cd "$DIR" && pwd -P) && echo "STORE $STORE"
SLUG=$(basename "$(dirname "$STORE")"); ROOT=$(dirname "$(dirname "$STORE")")
KEY=$(printf '%s' "$SLUG" | tr '_' '-') # both spellings collapse to one key
for d in "$ROOT"/*/; do
alt=$(basename "$d")
[ "$alt" = "$SLUG" ] || [ "$(printf '%s' "$alt" | tr '_' '-')" != "$KEY" ] \
|| [ ! -d "$ROOT/$alt/memory" ] \
|| echo "SIBLING $ROOT/$alt/memory — a second store differing only in _ vs -"
done
Scan and normalize; do not substitute. Building the candidate with ${SLUG//-/_} looks equivalent
and silently kills the direction that matters — measured on two real sibling pairs, and explained in
references/EXAMPLES.md.
Expected: One STORE line naming the absolute path actually measured, and no SIBLING line.
On failure: Append FAIL store identity and stop before check 1. Unreachable is
indistinguishable from empty, so a budget and an orphan count are both perfectly accurate readings
of the wrong store. Determine which store the session reads, then re-run from here.
Step 1: Measure the dual-cap budget
MEMORY.md is truncated on load at 200 lines or 25KB, whichever comes first (per the Claude
Code memory documentation). Measure both and act on the larger fraction:
usage = max(size / 25000, lines / 200) — warn at 0.80, rewrite target 0.70.
Above ~124 characters of content per line the size cap binds first — 125 units once the line
separator is counted, since 200 lines carry 199 separators. At the ~150-character entry this skill
targets — a derivation here, not a documented recommendation — the real budget is ~166 lines, not
200. Never report a line count alone, and always name which cap binds.
Before quoting the paragraph above, read what in it is documented and what is derived: references/EXAMPLES.md.
What the size cap counts (measured, not documented). The cap is applied to UTF-16 code units —
JavaScript String.length — rather than UTF-8 bytes or Unicode code points. For any text inside
the Basic Multilingual Plane — ASCII, Latin-1 accents, CJK — the character count is the unit
count, so a character count is exact for most real indexes. It diverges in two places: a byte
count over-reports on any non-ASCII content (up to 3x on CJK, which is why a wc -c check can
demand a prune the loader does not need), and a character count under-reports on astral
characters such as emoji, where one character costs two units. Measured on Claude Code v2.1.238
(Windows) and 2.1.237 (Linux) and reported in anthropics/claude-code#82056, August 2026. Treat
as version-volatile: the two documented numbers are the contract, this is how the current
implementation counts.
size = sum(2 if ord(c) > 0xFFFF else 1 for c in text) # UTF-16 code units
Three further measured properties (Claude Code 2.1.237–2.1.241, linux-x64/WSL2, tool use
disabled; derivation in references/EXAMPLES.md): truncation is whole-line,
so first line dropped names a line dropped entirely rather than cut mid-way; carriage returns
count, so a CRLF index has a smaller line budget than the same content with LF; and being past the
crossover says only which cap will bite first, not that anything is being truncated yet. State the
boundary as measured across that range, never as a constant.
# Dual-cap budget. Reads bytes and decodes ONCE: Python's text mode deletes CR
# characters, which silently changes the string the loader actually measures.
IDX=<memory-dir>/MEMORY.md
python3 - "$IDX" <<'PY'
import re, sys
raw = open(sys.argv[1], 'rb').read()
full = raw.decode('utf-8', 'replace')
# Only the content that LOADS counts toward either limit. YAML frontmatter and
# block-level HTML comments are stripped before the index is loaded and are
# excluded from the measurement; a comment INSIDE a fenced code block is not —
# it is preserved and counted (measured, see the skill text). Stripping it too
# under-reports, which hides a truncation that is already happening.
text = re.sub(r'\A---\r?\n.*?\r?\n---[ \t]*\r?\n', '', full, flags=re.S)
kept, fence, cmt = [], False, False
for ln in text.split('\n'):
if ln.lstrip().startswith('```'):
fence = not fence
elif not fence and (cmt or ln.lstrip().startswith('<!--')):
cmt = '-->' not in ln
continue
kept.append(ln)
text = '\n'.join(kept)
units = lambda s: sum(2 if ord(c) > 0xFFFF else 1 for c in s) # UTF-16 code units
lines = text.count('\n') + (0 if text.endswith('\n') else 1)
size = units(text)
lf, sf = lines / 200, size / 25000
# Track BOTH caps and take the minimum. A loop that tests only the size cap and
# checks the line cap in its else-branch reports every large file as size-bound.
acc = cut_size = 0
for i, line in enumerate(text.split('\n'), 1):
acc += units(line) + 1
if acc > 25000:
cut_size = i
break
cut_line = 201 if lines > 200 else 0
cuts = [c for c in (cut_size, cut_line) if c]
binds = 'size' if cut_size and (not cut_line or cut_size <= cut_line) else 'lines' if cut_line else 'neither'
print(f"lines {lines}/200 = {lf:.1%} size {size}/25000 = {sf:.1%}")
print(f"USAGE {max(lf, sf):.1%} -> " + ("OVER CAP - the tail is dropped on load" if max(lf, sf) >= 1.0
else "COMPACT NOW (target 70%)" if max(lf, sf) >= 0.80 else "OK"))
print(f"binds: {binds}" + (f"; first line dropped: {min(cuts)}" if cuts else ""))
print(f"mean {size / lines:.0f} units/line — the size cap binds first above 125")
print(f"utf-8 bytes {len(raw)}; not loaded, so not counted: {units(full) - size} unit(s)")
print(f"astral chars {sum(1 for c in text if ord(c) > 0xFFFF)}")
PY
Measurement-basis note. The block measures what LOADS: frontmatter and block-level HTML comments are stripped, because the loader strips them before applying the limits. A comment inside a fenced code block is not stripped — measured, and it counts against the cap like any other content (how). Getting either half wrong is a silent misread in a different direction: measuring raw over-reports, and one store of four measured here read 70.4% of cap raw against 68.7% loaded; stripping fenced comments under-reports, and hides a truncation already happening.
Expected: Both fractions with both denominators, a binds: verdict naming which cap would cut
first (neither while both still have headroom), the mean units per line against the crossover,
and USAGE under 80%.
On failure: At USAGE >= 0.80 append FAIL dual-cap and hand the store to manage-memory with
a rewrite target of 70% of the binding cap. At USAGE >= 1.0 the tail is already invisible on
load — record first line dropped before anyone edits the file, because the next write moves it.
Step 2: Detect orphaned topic files
Only the index is loaded automatically, so a topic file nothing links to is unreachable — and nothing about its own contents will ever reveal that.
# Reachability: the index is the only file loaded automatically, so a topic file
# that nothing links to is not deprioritized — it is invisible.
DIR=<memory-dir>
python3 - "$DIR" <<'PY'
import os, re, sys
d = sys.argv[1]
text = open(os.path.join(d, 'MEMORY.md'), 'rb').read().decode('utf-8', 'replace')
# HTML comments are stripped before the index reaches the model, and the
# stripped content is excluded from the load limits: a note left in one is
# invisible to the reader, and buys nothing by being cheap.
text = re.sub(r'<!--.*?-->', '', text, flags=re.S)
EXAMPLES = {'file.md', 'example.md', 'topic-name.md'} # format-documentation targets
linked = {os.path.basename(m) for m in re.findall(r'\]\(([^)#\s]+\.md)', text)} - EXAMPLES
on_disk = {f for f in os.listdir(d) if f.endswith('.md') and f != 'MEMORY.md'}
orphans, dangling = sorted(on_disk - linked), sorted(linked - on_disk)
size = lambda names: sum(os.path.getsize(os.path.join(d, n)) for n in names)
tot = size(on_disk) or 1
print(f"topic files {len(on_disk)}; linked {len(linked & on_disk)}")
print(f"ORPHANS {len(orphans)} = {len(orphans)/max(len(on_disk),1):.1%} of files, {size(orphans)/tot:.1%} of bytes")
print(f"DANGLING {len(dangling)} (linked, absent on disk)")
for n in orphans: print(f" orphan {n}")
for n in dangling: print(f" dangling {n}")
PY
Five rules this block honors, each learned from a real miss. They govern how its output is read as much as how it is written, and steps 3, 4 and 6 each pick one up:
- Exclude template/example link targets — a format-documentation line such as
- [Title](file.md) — hookotherwise reports as dangling forever, and a check that cries wolf trains its operator to ignore it. - A prose mention is not reachability. Require an exact filename match on a real link target. Report near-matches separately as degraded references; never count them as reachable.
- HTML comments in the index are not a mitigation. They are stripped before the index reaches the model, so a curator note in one is written into a void. Being stripped, it is also excluded from both load limits — it is free, and unread, which is the worst combination for a note whose whole purpose is to be seen. A note that must survive has to be a plain markdown line. (Before v2.1.211 the raw file was measured, so such a note did also consume budget.)
- Parse frontmatter, do not grep it. A
^type:regex misses a field nested undermetadata:and reports a conformance failure that does not exist. - Report both denominators, labeled. File share and byte share are different numbers, never interchangeable — a store can be 40% orphaned by file count and 5% by bytes.
Expected: ORPHANS 0, with both denominators printed and labeled. topic files equals linked.
On failure: Append FAIL orphans with the file list and both percentages. Do not delete — an
orphan is as likely to be a valuable file whose index line a compaction dropped. manage-memory
relinks; prune-agent-memory decides deletion.
Step 3: Resolve dangling links
Step 2's DANGLING list is the sole verdict source for broken links — never add a second extractor
that can disagree with it. This step adds the reading: every entry is either a real break or a
format-documentation target belonging in the EXAMPLES set (rule 1).
# DIAGNOSTIC ONLY — Step 2 holds the verdict. Lists in-scope suspects: every
# target that is not a flat `*.md`. Full link-form census in EXAMPLES.md.
grep -oE '\]\([^)]+\)' <memory-dir>/MEMORY.md | tr -d ']()' \
| grep -vE '^[^/]+\.md$|^#|://' \
|| echo "LINK FORMS all flat *.md — no sub-path, anchor or URL targets"
Anchor-only and URL targets are out of scope. A sub-path target is in scope and a likely break: the store is flat, so a link carrying a directory component usually survived a move.
Expected: DANGLING 0 after every format-documentation target has been accounted for by the
EXAMPLES set, and no sub-path targets.
On failure: Append FAIL dangling with the list. For a documentation example, extend EXAMPLES
in the Step 2 block rather than suppressing the check: an exclusion list is auditable, a disabled
check is not.
Step 4: Report degraded references
A filename that appears in the index only as prose or inline code is not a weak link, it is not a link (rule 2). It reads as reachable to a human scanning the index and is invisible to the mechanism that makes files reachable. Counted separately, never as reachable — the files are already in Step 2's orphan list, and this step explains why they looked fine.
# Degraded references: named in the index, never as a link target.
python3 - <memory-dir> <<'PY'
import os, re, sys
d = sys.argv[1]
text = open(os.path.join(d, 'MEMORY.md'), encoding='utf-8', errors='replace').read()
text = re.sub(r'<!--.*?-->', '', text, flags=re.S)
linked = {os.path.basename(m) for m in re.findall(r'\]\(([^)#\s]+\.md)', text)}
prose = set(re.findall(r'[\w.\-]+\.md', re.sub(r'\]\([^)]*\)', '', text)))
on_disk = {f for f in os.listdir(d) if f.endswith('.md') and f != 'MEMORY.md'}
degraded = sorted((prose - linked) & on_disk)
print(f"DEGRADED {len(degraded)} (named in the index, not a link target; NOT reachable)")
for n in degraded: print(f" degraded {n}")
PY
Expected: DEGRADED 0, and the count never added to linked anywhere in the report.
On failure: Append FAIL degraded with the list. The repair is one character class — turn the
mention into a markdown link — but it is manage-memory's repair, not this skill's.
Step 5: Resolve cross-references across naming conventions
Two naming conventions coexisting in one store — hyphen versus underscore, prefix retained versus stripped — produced a measured 13% of link targets that no exact match resolved (pjt222/agent-almanac#407). That is a convention split, not a typo rate, and the two need different responses. Normalization tells you which you have; it never makes an unresolved target reachable.
# Normalization is diagnosis, not repair. A target that resolves only after
# normalizing is still a broken link at load time.
python3 - <memory-dir> <<'PY'
import os, re, sys
d, PREFIXES = sys.argv[1], ('feedback-', 'project-', 'reference-') # see name_prefixes input
def norm(name):
n = re.sub(r'\.md$', '', name.lower()).replace('_', '-')
for p in PREFIXES:
if n.startswith(p): n = n[len(p):]
return n
text = re.sub(r'<!--.*?-->', '', open(os.path.join(d, 'MEMORY.md'),
encoding='utf-8', errors='replace').read(), flags=re.S)
linked = {os.path.basename(m) for m in re.findall(r'\]\(([^)#\s]+\.md)', text)}
on_disk = {f for f in os.listdir(d) if f.endswith('.md') and f != 'MEMORY.md'}
index, unresolved = {}, []
for f in on_disk: index.setdefault(norm(f), []).append(f)
for t in sorted(linked - on_disk):
hits = index.get(norm(t), [])
print(f" {'NORMALIZES' if hits else 'UNRESOLVED'} {t}" + (f" -> {', '.join(sorted(hits))}" if hits else ""))
if not hits: unresolved.append(t)
print(f"CONVENTIONS {len({'underscore' if '_' in f else 'hyphen' for f in on_disk})} in use")
print(f"UNRESOLVED {len(unresolved)}/{len(linked)} = {len(unresolved)/max(len(linked),1):.1%} of link targets")
PY
Expected: UNRESOLVED 0. NORMALIZES entries are still failures — they name the fix, they are
not the fix.
On failure: Append FAIL unresolved with the count and rate. A store at CONVENTIONS 2 with a
non-zero rate needs normalizing to one convention before individual links are chased — fixing them
one at a time re-creates the split on the next write.
Step 6: Check catalog conformance
Parse the frontmatter, do not grep it (rule 4): a ^type: regex misses a field nested under
metadata: and invents a conformance failure that does not exist. An absent frontmatter block is
not a failure — files predating the field are legitimate and are reported as no-frontmatter.
An unparsable one is. And a check that cannot run reports SKIPPED, never PASS.
# Frontmatter is PARSED. Inability to measure is not a passing verdict.
python3 - <memory-dir> <<'PY'
import os, re, sys
try:
import yaml
except ImportError:
print("SKIPPED catalog conformance: PyYAML unavailable. Install it or check by hand.")
sys.exit(0)
d, TYPES = sys.argv[1], {'user', 'feedback', 'project', 'reference'}
read = lambda n: open(os.path.join(d, n), encoding='utf-8', errors='replace').read()
for f in sorted(x for x in os.listdir(d) if x.endswith('.md') and x != 'MEMORY.md'):
m = re.match(r'---\r?\n(.*?)\r?\n---\r?\n', read(f), flags=re.S)
if not m:
print(f" no-frontmatter {f}"); continue # legitimate: predates the field
try:
fm = yaml.safe_load(m.group(1)) or {}
except yaml.YAMLError as exc:
print(f" FAIL unparsable {f}: {exc}"); continue
kind = fm.get('type') or (fm.get('metadata') or {}).get('type') # nested, not ^type:
if kind is not None and kind not in TYPES:
print(f" FAIL unknown type {f}: {kind!r}")
entry, matched = re.compile(r'^\s*[-*]\s+\[[^\]]+\]\(([^)#\s]+\.md)\)\s*(.*)$'), 0
for hit in filter(None, map(entry.match, read('MEMORY.md').splitlines())):
matched += 1
desc = hit.group(2).lstrip('—-: ').strip()
if not 10 <= len(desc) <= 300:
print(f" FAIL description {hit.group(1)}: {len(desc)} chars")
print(f"CATALOG ENTRIES CHECKED {matched}") # 0 here is a broken check, not a clean index
PY
The catalog-entry regex matches only single-link lines; a compound line is skipped rather than guessed at, which under-reports and never invents a failure. That is why the block prints how many entries it checked — a regex matching nothing prints no failures, and a check that discovered nothing is not a check that passed.
Expected: No FAIL lines, and CATALOG ENTRIES CHECKED well above zero. no-frontmatter
entries are listed but are not failures.
On failure: Append FAIL catalog with the list. A SKIPPED line is itself a reportable
result — record it so a later reader does not read the absence of failures as a pass.
Step 7: Check topic-file size hygiene
The threshold is project-configured. Do not substitute an internal Claude Code read budget here: undocumented internals move between releases and go stale silently — the number keeps printing, it just stops being true. Only Step 1's two caps are documented, and they do not cover topic files, which are read on demand and in full.
# No default. A per-project number an operator chose beats an internal one
# copied from a release note.
TOPIC_MAX_BYTES=${TOPIC_MAX_BYTES:?set a per-project threshold; there is no documented default}
find <memory-dir> -maxdepth 1 -name '*.md' ! -name 'MEMORY.md' -printf '%s\t%f\n' \
| awk -F'\t' -v cap="$TOPIC_MAX_BYTES" \
'$1 > cap { printf " oversize %s (%d bytes)\n", $2, $1; n++ }
END { printf "OVERSIZE %d of %d topic files over %d bytes\n", n, NR, cap }'
Expected: OVERSIZE 0, or a short list an operator recognizes as deliberate.
On failure: Append WARN oversize, not FAIL. An oversize topic file costs read time on the
one session that opens it; an oversize index costs every session — not the same defect, so not the
same verdict.
Step 8: Check recoverability
Memory files do not expire: Claude Code excludes projects/<project>/memory/ from the
cleanupPeriodDays retention sweep (default 30 days, minimum 1), so the index and its topic files
stay until someone edits or deletes them. That is why this check exists rather than a reason to skip
it: no retention copy exists to fall back on, so a bad overwrite is unrecoverable unless the store
is under version control or has a tombstone path. Most have neither.
DIR=<memory-dir>
git -C "$DIR" rev-parse --show-toplevel >/dev/null 2>&1 \
&& echo "VCS yes ($(git -C "$DIR" rev-parse --show-toplevel))" \
|| echo "VCS no — an overwrite in this store is unrecoverable"
ls -d "$DIR"/.archive "$DIR"/../memory-archive 2>/dev/null \
|| echo "ARCHIVE none — no tombstone path for deleted topic files"
Expected: At least one of version control or an archive path, recorded in the report either way.
On failure: Append WARN unrecoverable. Do not create either one here — that is a write. Report
it, and require a copy of the store before any mutating run against it.
Validation
- Nothing inside
memory_dirwas created, modified, or deleted;report_pathis outside it - Step 0 printed the resolved
STOREpath and reported any_-versus--sibling store - Index budget is within both caps (
max(size / 25000, lines / 200) < 0.80), reported as both numbers, with thebinds:verdict and the mean units per line - Step 1's provenance and measurement-basis notes were read before any figure was quoted
- Step 2 reported orphan share as file share and byte share, each labeled
- Every dangling entry is either a real break or an accounted-for
EXAMPLEStarget - Degraded references were counted separately and never added to
linked - Unresolved cross-references were counted;
NORMALIZESentries were not treated as resolved - Frontmatter was parsed, not grepped;
CATALOG ENTRIES CHECKED> 0;SKIPPEDis a non-verdict - Check 7 ran against a project-configured threshold, not a hardcoded internal constant
- Recoverability was recorded before any mutating skill was pointed at the store
- The run exited non-zero if and only if the report contains a
FAILline
Common Pitfalls
- Reporting a line count alone: the size cap binds first above ~125 units per line, so a comfortable
129/200can sit at 74.6% of the real budget. Print both, name which binds. - Using
max(len(raw), chars)as a fail-safe hedge: fail-safe in direction, and measured over-reporting 2.44x on a CJK index — a checker acting on it demands a prune of 117 lines that actually load (pjt222/agent-almanac#407, comment). Reasonable while the unit was unknown; it is now known. - Counting a prose mention as reachable: only an exact filename match on a real link target makes a topic file loadable; a near-match is a degraded reference and belongs in its own column.
- Suppressing a noisy check instead of extending its exclusion list: a check that cries wolf gets ignored, but a disabled check is not auditable. Extend
EXAMPLES; never delete the check. - Writing the report into the memory directory: it breaks the read-only contract, and the next run reports the report as an orphan.
- Reading
SKIPPEDas a pass: a check that could not run produced no evidence about its subject — the same distinction as a red CI check that found something versus one that could not execute. - Treating a
NORMALIZEShit as a fix: normalization diagnoses a convention split; the link is still broken at load time until someone edits the index. - Pinning an undocumented internal number: only the 200-line and 25KB caps are documented; anything else copied from a release note goes stale silently — it keeps printing.
Examples
Worked runs, the full report template, the link-form census, and the before/after compaction pairing are in references/EXAMPLES.md.
What Verification Does Not Buy
- A write succeeding tells you nothing about whether the memory will ever be read again. Verify reachability, not write success — every session, because the operation that breaks reachability (compaction) is the one the caps make mandatory.
- Nothing here is enforced at write time — every guarantee is verified when the skill last ran, not an invariant (why).
Related Skills
- manage-memory — the repair side: relinks orphans, extracts oversize sections, compacts the index this skill measures
- prune-agent-memory — the deletion side; bracket a prune pass with this skill so its collateral is measured, not assumed
- repair-broken-references — general broken-link repair for the dangling and unresolved targets reported here
- catalog-collection — the cataloging discipline behind check 6: every item described, every description conforming
- preserve-materials — preservation framing for check 8; no version control and no tombstone path means no preservation copy
- write-claude-md — CLAUDE.md is loaded in full and is not subject to these caps; content that keeps overflowing the index often belongs there
GitHub Repository
Frequently asked questions
What is the verify-memory-integrity skill?
verify-memory-integrity is a Claude Skill by pjt222. Skills package instructions and resources that Claude loads on demand, so Claude can perform verify-memory-integrity-related tasks without extra prompting.
How do I install verify-memory-integrity?
Use the install commands on this page: add verify-memory-integrity to Claude Code as a plugin, or clone its repository into your skills directory, then restart Claude so it picks up the skill.
What category does verify-memory-integrity belong to?
verify-memory-integrity is in the Design category.
Is verify-memory-integrity free to use?
Yes. verify-memory-integrity is listed on AIMCP and free to install.
Related Skills
Use the executing-plans skill when you have a complete implementation plan to execute in controlled batches with review checkpoints. It loads and critically reviews the plan, then executes tasks in small batches (default 3 tasks) while reporting progress between each batch for architect review. This ensures systematic implementation with built-in quality control checkpoints.
This skill dispatches a code-reviewer subagent to analyze code changes against requirements before proceeding. It should be used after completing tasks, implementing major features, or before merging to main. The review helps catch issues early by comparing the current implementation with the original plan.
This skill provides a comprehensive guide for developers to connect MCP servers to Claude Code using HTTP, stdio, or SSE transports. It covers installation, configuration, authentication, and security for integrating external services like GitHub, Notion, and custom APIs. Use it when setting up MCP integrations, configuring external tools, or working with Claude's Model Context Protocol.
This skill helps developers choose between Claude Code Web and CLI interfaces based on task analysis, then enables seamless session teleportation between these environments. It optimizes workflow by managing session state and context when switching between web, CLI, or mobile. Use it for complex projects requiring different tools at various stages.
