Invoked skill not re-attached after manual /compact; only the summary's paraphrase survives
Status Open
Reported on v2.1.270
Maintainer reply None cached
Workaround ✓ Mentioned in thread ↓
Activity 3 comments · opened Sep 15, 2026
Summary
The skills docs say compaction re-attaches the most recent invocation of each skill after the summary (first 5,000 tokens each, 25,000 combined). In my session that did not happen after a manual /compact. The only trace of the skill that survived was the compaction summary's paraphrase of it, and the paraphrase lost a detail that mattered.
Environment
- Claude Code 2.1.270, macOS, model claude-fable-5-1
- Session running as a Claude Code background job
- One project skill,
.claude/skills/<name>/SKILL.md, 5,279 bytes (about 1,300 tokens), invoked by me as a slash command at the start of the session
What happened
- I invoked the skill. It ran a long code walkthrough for a few hours.
- I ran
/compact(transcript metadata: trigger "manual", preTokens 213,828, postTokens 8,106). - After the summary, no
invoked_skillsblock or skill content was present. The transcript has no such block at any point after the compaction boundary. - The model continued from the summary's paraphrase of the skill. The skill says to use "a background subagent" for silent file writes. The paraphrase said "background subagents". The model then spawned a new subagent for every write and ended the session with ten idle ones.
Expected
Per https://code.claude.com/docs/en/skills ("Auto-compaction carries invoked skills forward within a token budget"), the skill should have been re-attached after the summary. The skill is small and was the only one invoked, so the budget was not a factor.
Questions and suggestions
- Is re-attach meant to apply to manual
/compactas well as auto-compaction? The doc sentence names only auto-compaction. If manual is excluded on purpose, the doc could say so. - Does session kind matter? This was a background job session.
- Whatever the cause, a skill the user invoked is standing instruction for the session, like CLAUDE.md. A summary's paraphrase is not a safe substitute. If re-attaching the body is unwanted in some modes, at least listing the active skills by path in the summary so the model can re-read them would avoid this class of drift.
Related: #82144, #83306, #85138 (all about how replay behaves once it happens), #74990 (catalog reminder dropped after compaction).
3 Comments
The manual/auto ambiguity you flagged looks real: the skills page names auto-compaction for skill re-attach, while the context window table lists skill re-injection with no trigger qualifier. You can get deterministic behavior today either way. What the current docs say survives compaction:
compact: re-run on both manual and automatic compaction, output added to the compacted context.Three moves, smallest first.
/compact, re-invoke the skill. That is the documented recovery when a skill stops influencing behavior or gets dropped by the budget, and it restores the full body in one line./compact": conversation-only instructions are the ones that disappear, file content is re-read from disk. "A background subagent" vs "background subagents" is exactly the kind of distinction that should not depend on a summary.Stdout lands in context after the summary, so it survives the boundary that ate the skill body. Swap the echo for a script if you want the list generated from disk, and the same hook can live in the skill's frontmatter instead of settings if you want it tied to the skill; skill-defined hooks stay registered for the rest of the session once invoked.
To verify on 2.1.270:
/contextafter a compaction should show the re-attached skill block, and anInstructionsLoadedhook with matchercompactlogs the instruction reload when it fires.<!-- Post as a COMMENT on https://github.com/anthropics/claude-code/issues/94564
(same symptom: "Invoked skill not re-attached after manual /compact").
If you would rather open a new issue, use the title below and paste the same body. -->
<!-- Title, only if filed as a new issue:
Invoked skills are not re-attached after compaction when they were invoked more than ~6-9 hours earlier (manual and auto) -->
Same symptom here, with data that may narrow it down. Elapsed time since the skill was invoked looks like the deciding factor. The trigger (manual vs auto) and the 25,000-token budget do not.
Environment: Claude Code 2.1.219 and 2.1.280–2.1.286, Claude desktop app (Code tab), Windows 11. Project skills plus a few plugin skills. I have not tested 2.1.288+. Its changelog has "Fixed
--resumesometimes dropping files and other context that a compaction had just restored", which may or may not be related.Method: I scanned the session
.jsonltranscripts under~/.claude/projectswith a script. For every compaction I listed:Skilltool calls and/skillcommands), with its age;invoked_skillsattachment after thecompact_boundaryrecord carried it.That covers 7 sessions and 15 compactions that had at least one skill invoked earlier.
Result, counting each skill at the first compaction after its invocation:
| Skill invoked this long before the compaction | Re-attached |
|---|---|
| 0.2–5.6 hours | 21 of 21 |
| 8.7–26.5 hours | 0 of 12 |
/compactand auto-compaction appear on both sides. That answers the question in this issue: manual compaction does re-attach, when the skills are recent.Steps to reproduce (derived from the data above, not yet run as a clean test):
/compact..jsonl. There is noinvoked_skillsattachment after the newcompact_boundary, and the skill's instructions are gone from context.Control: invoke, then
/compactwithin an hour. Theinvoked_skillsattachment is present with the skill.Expected: per the docs (code.claude.com/docs/en/skills, "Skill content lifecycle"), the most recent invocation of each skill is re-attached within the 25,000-token budget, and only the budget drops older skills. Two possibilities:
Today the drop is silent: the model carries on from the summary's paraphrase, which is exactly the drift described in this issue.
Side note on the per-skill limit: the "first 5,000 tokens of each" cut lands at exactly 20,000 characters. Two different skills were each cut at 20,000. So it's an estimate of about 4 characters per token, which for markdown-heavy skills is closer to 10,000 real tokens. That's fine, but worth knowing if you place must-follow instructions near the top of a long skill.
Workaround we use: a
SessionStarthook with matchercompact. It reads the transcript, lists the skills the session invoked, and re-injects each skill's short "must-obey" section asadditionalContext(capped under 10,000 characters). It makes the re-attachment question moot for the parts that matter.The age split in that table has a plainer cause than an age cutoff, and the overnight gaps with the app closed or updated and the session resumed are the tell.
In 2.1.284 the list of invoked skills that compaction re-attaches lives in process memory. Invoking a skill, by slash command or the Skill tool, writes the body into that registry. When a session is resumed, the registry is rebuilt from the transcript, but only from
invoked_skillsattachments that an earlier compaction already wrote. The original invocation records are not scanned. So a skill invoked before any compaction, with a restart in between, is not in the registry when the first compaction runs, and that compaction re-attaches nothing. That fits 0 of 12 on the long gaps, "re-attached nothing" rather than trimmed to budget, and 21 of 21 inside one process. A skill an earlier compaction had already restored does survive a resume, which is why a second compaction in a resumed session can look fine.Manual versus auto never mattered; resume did. Until resume rebuilds the registry from the invocation records, two workarounds: re-invoke the skill right after
--resume, which rewrites the entry, or the SessionStartcompacthook above, which does not depend on the registry. The 2.1.288 resume fix covers files and context a compaction had already restored, a different path.