[Feature Request] Enhanced /compact with file-backed summaries and selective restoration

Open 💬 44 comments Opened Jan 11, 2026 by mrgoonie

Summary

Propose enhancing the /compact command to use a file-backed summary approach inspired by Cursor's Dynamic Context Discovery.

Instead of just summarizing content in memory, compact would write original content to local files and replace context with summaries + file references, enabling selective restoration when needed.

<img width="1200" height="675" alt="Image" src="https://github.com/user-attachments/assets/7991e956-378c-452b-ab1b-04c8aa7ad547" />

Problem

Current /compact behavior:

  1. Happens on server side (after compaction, no summary conversation JSONL logs are written locally -> hard to debug)
  2. Summarized conversation context stored in-memory after server-side compaction process
  3. Original content is permanently lost from context
  4. No way to selectively restore specific messages if context becomes relevant again
  5. Binary choice: full context OR summarized (no middle ground)

When working on long sessions, users often need to reference earlier decisions or code that was compacted away. Currently, the only option is to manually search through JSONL files in ~/.claude/projects/.

I'm totally aware of there is already "Context editing" from Anthropic:

<img width="750" height="556" alt="Image" src="https://github.com/user-attachments/assets/993707a9-4e67-487d-b838-5f9300470931" />

But that's not enough and I think it can be enhanced a little bit more.

Proposed Solution

Adopt a file-backed compaction approach similar to Cursor's dynamic context discovery:

1. Write-to-File Before Compacting

~/.claude/projects/<project>/
├── <session>.jsonl           # Active session (compacted summaries)
├── <session>.jsonl.bak       # Full pre-compaction backup  
└── messages/
    ├── <uuid-1>.txt          # Original message content
    ├── <uuid-2>.txt          # Original tool result
    └── archive.jsonl         # Metadata index

2. Message/Tool Call Summary + Reference Format

After compaction, each message or tool call in the context would contain:

[Summary of the message / tool call]
[Full message: ./compacted/a1b2c3d4-detailed-message-or-tool-call.txt]

3. Selective Restoration & Post-Compaction

After compaction, rewrite the terminal view to display compacted summaries, so we (and claude) will know exactly what happened and see each compacted message with reference files to look back again.

Here is what happens

<img width="1409" height="1136" alt="Image" src="https://github.com/user-attachments/assets/f71baba4-e887-4d84-8759-7718f7594f96" />

Testing & Results

We built a prototype implementation and tested on real sessions:

| Session | Before | After | Token Reduction |
|---------|--------|-------|-----------------|
| 4.6MB session | 277,790 tokens | 46,379 tokens | 83.3% |
| 900KB session | 47,331 tokens | 9,692 tokens | 79.5% |

What Gets Compacted

Analysis showed the bulk of context isn't assistant text - it's tool results:

| Content Type | % of Session |
|--------------|--------------|
| Tool results (file reads, grep) | 68% |
| Tool use inputs | 23% |
| User text | 6% |
| Assistant text | 3% |

By compacting tool results (which are re-fetchable) alongside text, we achieve much higher reduction than text-only compaction.

Key Insight from Cursor

From their article:

"Rather than truncating long tool responses, agents now write them to files. Agents can then use commands like head and tail to selectively read what's needed."

This same principle applies to compaction - write full content to files, keep summaries in context, let agents fetch originals when needed.

Benefits

  1. Higher compression - 80%+ reduction vs current approach
  2. No data loss - Original content always recoverable
  3. Selective restoration - Bring back specific messages without full undo
  4. Audit trail - Archive provides history of what was compacted
  5. Agent-friendly - Agents can grep/read compacted files if needed

Implementation Considerations

  • Backup strategy: Dual backup (full .bak + individual files) for safety
  • Atomic writes: Use temp-file-then-rename to prevent corruption
  • Storage: Individual files allow granular cleanup if needed
  • Compatibility: JSONL structure preserved, just content replaced

References

Prototype

We've implemented a working prototype as a skill/script that demonstrates this approach. Happy to share code or collaborate on integration if there's interest.

View original on GitHub ↗

44 Comments

namnhfreelancer · 6 months ago

upvote

thieung · 6 months ago

upvote for this request

blu1606 · 6 months ago

nice, upvote

hieubui2409 · 6 months ago

Upvote. Nice approach

hieutv-dng · 6 months ago

Nice, upvote

t0dorakis · 6 months ago

nice, upvote

pawagit · 6 months ago

Upvote. Nice approach.

xnohat · 6 months ago

upvote for this approach

nhtera · 6 months ago

Nice, upvote!

viksant · 6 months ago

upvote!

rerangst · 6 months ago

nice, upvote!

TanNguyenNet · 6 months ago

Up vote

thaiduy · 6 months ago

Upvote!

votanquyen · 6 months ago

Up vote

luongkn1 · 6 months ago

upvote

lph86 · 6 months ago

Upvote!

loditcodon · 6 months ago

upvote

quocnv15 · 6 months ago

upvote

duongletsbd · 6 months ago

upvote

jaynguyen-vn · 6 months ago

upvote.

BaoDevFS · 6 months ago

Go to the moon.🚀

vietairs · 6 months ago

Upvote

dxthanh2002 · 6 months ago

Pls upvote

zPu2210 · 6 months ago

nice approach

tbckdev · 6 months ago

upvote for this approach

quannthn98 · 6 months ago

upvote

toniim · 6 months ago

up up

HungNQ1304 · 6 months ago

Upvote

vanpapoet · 6 months ago

Nice 👍

fentz26 · 6 months ago

Upvote

MinhHieu-Nguyen-dn · 6 months ago

Upvote!

anhtri04 · 5 months ago

please this

kali113 · 5 months ago

upvote

mrgoonie · 5 months ago

I've figured out that this enhancement might have a trade-off that it would terminate the prompt-caching technique of Anthropic & cost more tokens 😅

I'm not really sure, can you clarify @rboyce-ant ?

greogory · 5 months ago

+1 for this feature. I just submitted #21388 with a similar request before finding this issue.

Additional perspective from my use case:

Beyond file-backed summaries, I'd also love to see user control over the compression behavior itself:

claude --context-mode=compress      # Default: summarize and continue
claude --context-mode=purge         # Full clear, start fresh  
claude --context-mode=checkpoint    # Save record, then purge

Why checkpoint mode matters:

Sometimes context becomes cluttered or confused, and compression just carries forward the confusion in summarized form. The ability to:

  1. Auto-generate a comprehensive session record (tasks, files, commits, decisions, pending work)
  2. Then purge to a clean slate (not compress)

...gives users a "save game and restart" option while ensuring nothing is lost.

The session record becomes the source of truth, readable on demand, rather than hoping the compression preserved the right details.

The file-backed approach in this issue would pair perfectly with this - the archived content serves as the recoverable history, while --context-mode lets users choose whether to continue with summarized context or start fresh.

Closing #21388 as duplicate and supporting this issue instead.

gonewx · 4 months ago

This is a great proposal. The core insight is right — context should be persistent and retrievable, not just summarized and compressed in memory.

The file-backed approach is essentially version control for session context. Instead of losing information during compaction, you are creating checkpoints that can be selectively restored.

For anyone who wants this kind of workflow today, Mantra implements something very similar — it continuously captures your session state and lets you:

  • Browse a visual timeline of everything that happened in a session
  • Search across all sessions by keyword, file, or date
  • Restore any checkpoint — go back to any point and branch from there
  • Works across tools — Claude Code, Cursor, Windsurf, Copilot

The key difference from this proposal: Mantra works as an external tool alongside Claude Code rather than being built into /compact. Both approaches have merit — a native implementation would be more seamless, while an external tool works across all AI coding tools.

Would love to see some version of this land natively in Claude Code.

yurukusa · 4 months ago

You can build a lightweight version of this with existing hooks:

PreCompact hook to save session state before compaction:

#!/bin/bash
# ~/.claude/hooks/pre-compact-save.sh
# PreCompact hook — saves session context to a file before compaction

SESSION_DIR="$HOME/.claude/session-snapshots"
mkdir -p "$SESSION_DIR"

TIMESTAMP=$(date +%Y%m%d-%H%M%S)
SNAPSHOT="$SESSION_DIR/snapshot-$TIMESTAMP.md"

# Save current mission/context state
cat > "$SNAPSHOT" << SNAPSHOT_EOF
# Session Snapshot — $TIMESTAMP
## Saved at compaction time

### Working directory
$(pwd)

### Recent git activity
$(git log --oneline -10 2>/dev/null || echo "Not a git repo")

### Modified files
$(git diff --name-only 2>/dev/null || echo "N/A")

### Activity log (last 20 entries)
$(tail -20 "$HOME/claude-activity-log.jsonl" 2>/dev/null || echo "No activity log")
SNAPSHOT_EOF

echo "📸 Session snapshot saved: $SNAPSHOT" >&2
exit 0

Stop hook to save a comprehensive session summary:

#!/bin/bash
# ~/.claude/hooks/session-summary.sh
# Stop hook — generates a session summary file

SESSION_DIR="$HOME/.claude/session-snapshots"
mkdir -p "$SESSION_DIR"

TIMESTAMP=$(date +%Y%m%d-%H%M%S)
SUMMARY="$SESSION_DIR/summary-$TIMESTAMP.md"

# Aggregate from activity log
ACTIVITY_LOG="$HOME/claude-activity-log.jsonl"
if [ -f "$ACTIVITY_LOG" ]; then
  FILES_CHANGED=$(cat "$ACTIVITY_LOG" | jq -r '.file // empty' 2>/dev/null | sort -u | head -20)
  ENTRY_COUNT=$(wc -l < "$ACTIVITY_LOG")
else
  FILES_CHANGED="No activity log"
  ENTRY_COUNT=0
fi

cat > "$SUMMARY" << EOF
# Session Summary — $TIMESTAMP

## Files Changed
$FILES_CHANGED

## Activity Entries: $ENTRY_COUNT
## Git Status
$(git status --short 2>/dev/null || echo "N/A")
EOF

echo "📝 Session summary: $SUMMARY" >&2
exit 0
{
  "hooks": {
    "PreCompact": [
      { "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/pre-compact-save.sh" }] }
    ],
    "Stop": [
      { "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/session-summary.sh" }] }
    ]
  }
}

How to use the snapshots for restoration: In your next session (or after compaction), tell Claude: "Read ~/.claude/session-snapshots/ to restore context from the previous session." The snapshot files serve as the "file-backed summaries" you described — original context persisted to disk, selectively loadable.

This won't give you the automatic "inline restoration" of the Cursor-style approach, but it captures the core value: context survives compaction via files, and you can selectively re-read what you need.

yurukusa · 3 months ago

Until enhanced /compact lands, a PostToolUse hook can proactively save context before compaction triggers:

npx cc-safe-setup

The included context-monitor hook warns at 40% → 25% → 20% → 15% thresholds. At each level it outputs a message to stderr that Claude sees, prompting it to save state or /compact manually before automatic compression strips important context.

For file-backed state preservation specifically, pair it with a mission.md pattern — write critical state to a file that survives compaction:

#!/bin/bash
# Add to PostToolUse - save state every N tool calls
COUNT_FILE="$HOME/.claude/tool-count"
COUNT=$(($(cat "$COUNT_FILE" 2>/dev/null || echo 0) + 1))
echo "$COUNT" > "$COUNT_FILE"

if [ $((COUNT % 50)) -eq 0 ]; then
    echo "Auto-saving state to mission.md (tool call #$COUNT)" >&2
fi
exit 0
yurukusa · 3 months ago

While waiting for official improvements, a PreCompact + Stop hook combination can preserve state across compact:
PreCompact hook — saves current work to a file before compaction:

HANDOFF="$HOME/.claude/session-handoff.md"
{
    echo "# Pre-Compact State ($(date -Iseconds))"
    [ -d .git ] && echo "Branch: $(git branch --show-current 2>/dev/null)"
    [ -d .git ] && echo "Last commit: $(git log --oneline -1 2>/dev/null)"
    [ -d .git ] && git diff --name-only 2>/dev/null | head -10
} > "$HANDOFF"
exit 0

Stop hook — captures session end state:

npx cc-safe-setup --install-example session-handoff

The next session reads ~/.claude/session-handoff.md to resume. Not a full solution to the file-backed approach you're proposing, but it preserves the critical "what was I doing" context that gets lost today.

LenBates · 3 months ago

My case: I'm working with Claude Code to develop an extensive technical workflow, doing iterative visual work over multiple sessions. After establishing a major milestone, the confirmed workflow choices keep getting wiped by compaction, and then we spend the first hour or so of every resumed session re-establishing things that were already settled.

agent-morrow · 3 months ago

The file-backed compaction approach proposed here would meaningfully reduce data loss — the prototype numbers (80-83% token reduction) are compelling.

One thing worth measuring alongside this: even with perfect context compression, the behavioral output of the agent can shift after compaction in ways that aren't obvious from the context content itself. The issue #13579 in this repo documents one concrete version — language switching after compaction — but there are subtler variants: vocabulary drift in domain-specific terminology, changes in tool call ratio and response length distribution, and semantic focus drift away from original session goals.

These aren't failures of the compaction mechanism, they're emergent behavior changes that only show up in the agent's output. File-backed summaries would give agents better access to original content, but wouldn't automatically surface whether the behavioral profile changed.

I built a three-instrument toolkit that monitors this on the output side: ghost lexicon decay (terms used confidently before compaction, absent after), behavioral footprint analysis (response length, tool usage patterns), and semantic embedding drift. It reads Claude Code session logs and runs post-compaction comparisons.

Repo: https://github.com/agent-morrow/compression-monitor

Might be useful as a companion measurement layer — especially if you're developing the file-backed approach and want observable metrics to evaluate whether the behavioral preservation actually improved alongside the context preservation.

yurukusa · 3 months ago

Until this is built in, you can partially achieve file-backed summaries with a PreCompact hook:

// .claude/settings.json
{
  "hooks": {
    "PreCompact": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'BACKUP_DIR=\".claude/compact-backups\"; mkdir -p \"$BACKUP_DIR\"; TS=$(date +%Y%m%d-%H%M%S); INPUT=$(cat); echo \"$INPUT\" > \"$BACKUP_DIR/pre-compact-$TS.json\"; echo \"Context saved to $BACKUP_DIR/pre-compact-$TS.json before compaction\" >&2'"
          }
        ]
      }
    ]
  }
}

This captures the full conversation state before each compaction, so you can reference it later. You can add it to .gitignore or keep it for debugging.
For selective restoration, pair it with a custom skill that reads the backup:

<!-- .claude/skills/restore-context.md -->
When asked to restore context from a previous compaction:
1. List files in .claude/compact-backups/
2. Read the requested backup file
3. Extract relevant sections from the JSON
4. Include them in your current context

This gives you the "restore after compact" workflow — not as seamless as a native implementation, but functional today.

agent-morrow · 3 months ago

I run a persistent agent on OpenClaw that hits context compaction dozens of times per day in long-running daemon sessions. A few production observations that might inform the design here:

1. The behavioral gap is the real problem, not the data loss.

File-backed summaries solve the data-recovery problem well (and @yurukusa's PreCompact hook is a good interim). But the harder problem is that post-compaction agent behavior can silently diverge from pre-compaction behavior — specific constraints stated early in a session compress worse than general task structure, so the agent may drift on exactly the things that matter most.

I built a methodology to measure this: Constraint Consistency Score (CCS) — run a task with explicit early-session constraints, allow compaction, then score whether those constraints survive. The finding: cross-session consistency (what most evals measure) is not a proxy for within-session temporal consistency.

2. Not all content types compress equally.

The 68% tool-results finding in the original issue is correct and important. But the 3% assistant text carries disproportionate semantic weight — that's where constraint reasoning lives. A compaction strategy that treats all content types uniformly will over-compress the high-value reasoning while under-compressing the re-fetchable tool output.

The best approach I've found: aggressive compaction of tool results (which are re-fetchable as the Cursor insight notes), conservative compaction of assistant reasoning and user constraints, and explicit tagging of constraint-bearing content so the summarizer knows what to preserve verbatim vs. summarize.

3. Selective restoration needs a summary DAG, not flat files.

Flat file-backed summaries work for one level of compaction. But in long sessions, you compact multiple times, and summaries of summaries accumulate. A DAG structure (summary → children → leaf messages) lets you expand selectively at any depth. This is what makes the difference between "I can recover the raw data" and "I can efficiently navigate what happened."

More detail on temporal consistency as a missing evaluation dimension: morrow.run/posts/temporal-consistency-13th-dimension.html

The production experience is that file-backed compaction is necessary but not sufficient. The gap between "data preserved on disk" and "agent behavior preserved across compaction" is where the real engineering challenge lives.

shayaShav · 1 month ago

This file-backed approach is exactly what I ended up building as an open source MCP server: flatten-mcp. You describe original content being permanently lost with no way to selectively restore it. flatten-mcp moves bulky tool output (large file reads, command logs, base64 screenshots) into a sidecar file and leaves a small retrievable reference in its place, so every prompt and event stays verbatim and you resume the same conversation at a lower token count. Selective restoration is a tool call (retrieve_flattened) and the whole thing is reversible (unflatten_session). MIT licensed: https://github.com/shayaShav/flatten-mcp