Skip to content

Feature Request: experimental.session.pre-compact Hook for Plugin-Controlled Context Transition #24958

Closed as not planned

Description

@AnterCreeper

Feature Request: experimental.session.pre-compact Hook —— Plugin-Controlled Context Transition

Summary

Add a new plugin hook experimental.session.pre-compact that triggers before context compaction, giving plugins a complete autonomous cycle with full tool access. This enables structured context transition where plugins can perform data migration, state preservation, or any cleanup before OpenCode compresses the conversation.

Why This Hook Is Valuable

Origin: A Real-World Problem

This request originates from building opencode-noema, an AI autonomous memory system plugin. During long sessions, AI accumulates critical understandings in scratchpad files. When context compacts, the AI cannot archive anything because:

  • tools: {} is enforced during compaction
  • summary: true blocks all tool calls

The result: valuable cognitive work is lost in compression.

The Core Problem (Universal)

This isn't unique to memory systems. OpenCode's compaction is a destructive operation — once executed, detailed conversation history is permanently replaced by a summary. Currently, plugins can only inject text into the summary prompt via experimental.session.compacting, but cannot:

  • Execute tools during compaction (tools: {} enforced)
  • Perform structured data migration
  • Preserve state outside of context

This limits plugin capabilities across many categories and forces unreliable workarounds.

The Solution: A Pre-Compact Hook

A pre-compact hook gives plugins a dedicated cycle before destruction:

[Normal Conversation] → [Pre-Compact: Plugin Autonomous] → [Compact: OpenCode Summarizes]
                            ↑                                    ↓
                     Full tool access                     Pure text generation
                     Structured operations                 Lossy compression

Key principle: Separation of Phases

  • Pre-compact phase: Plugin performs structured operations (data migration, cleanup, checkpointing)
  • Compact phase: OpenCode performs lossy compression (summary generation)

Use Cases (Why This Hook Matters)

1. AI Memory & Knowledge Management

Plugin type: Cognitive memory systems (e.g., opencode-noema)

Scenario: AI accumulates understanding during long sessions. Before context is compressed:

  • Read scratchpad entries
  • Archive key insights to persistent memory files
  • Delete processed entries
  • Preserve cognitive continuity across sessions

Without hook: AI must "remember" to archive during conversation (unreliable) or rely on flat summary text (lossy).

2. Workflow State Checkpoints

Plugin type: Task/workflow management plugins

Scenario: Long-running tasks (builds, migrations, data processing) span multiple context windows:

  • Save intermediate results to files
  • Record progress state
  • Preserve decision history
  • Allow resumption from structured checkpoint (not flat summary)

Without hook: Workflow state is lost in summary compression. Resuming requires reconstructing state from unstructured text.

3. Debugging & Diagnostic Preservation

Plugin type: Debugging assistants, error trackers

Scenario: Complex debugging sessions accumulate:

  • Error traces
  • Hypothesis notes
  • Test results
  • Variable states

Before compaction:

  • Save structured diagnostic data
  • Preserve error patterns for future reference
  • Maintain investigation trail

Without hook: Debugging context is compressed into generic "investigated issue" summary, losing critical details.

4. Collaborative Session Handoff

Plugin type: Multi-agent coordination, session sharing

Scenario: Sessions are transferred between agents or users:

  • Export structured session state
  • Preserve agent decisions and reasoning
  • Maintain shared knowledge base
  • Enable seamless handoff without context loss

Without hook: Handoff relies on summary quality, which may miss critical agent-specific context.

5. Audit & Compliance Logging

Plugin type: Enterprise/compliance plugins

Scenario: Critical decisions or sensitive operations need audit trails:

  • Log decisions before they're compressed
  • Preserve approval chains
  • Maintain compliance records
  • Ensure accountability

Without hook: Audit data is embedded in summary text (unstructured, unreliable for compliance).

6. Context-Aware Cleanup

Plugin type: Resource management, temporary file handlers

Scenario: Sessions generate temporary artifacts:

  • Clean up temp files before context loss
  • Persist valuable artifacts to permanent storage
  • Release resources
  • Maintain workspace hygiene

Without hook: Cleanup must happen during normal conversation (distracting) or be forgotten.

7. Incremental Learning Systems

Plugin type: ML/AI training assistants

Scenario: Iterative model training or fine-tuning:

  • Save training checkpoints
  • Record hyperparameter decisions
  • Preserve evaluation metrics
  • Maintain experiment trail

Without hook: Training history is compressed, losing structured experiment data.

Architecture Value

Extends OpenCode's Plugin Ecosystem

This hook transforms OpenCode from a passive execution environment into an active lifecycle platform:

Current:  Plugin reacts to events (file edited, message sent)
Proposed: Plugin participates in lifecycle (pre-compact, compact, post-compact)

Benefits for OpenCode:

  1. More powerful plugins: Plugins can perform complex state management
  2. Better user experience: Users get reliable persistence without manual intervention
  3. Ecosystem growth: Enables plugin categories that were previously impossible (memory, workflow, audit)
  4. Competitive advantage: Other AI coding agents lack this level of plugin lifecycle control

Clean Separation of Concerns

┌─────────────────────────────────────────────────────────────┐
│  Pre-Compact (Plugin-controlled)                            │
│  ├─ Tools: FULL ACCESS                                       │
│  ├─ Goal: Structured operations, data migration             │
│  └─ Result: Data preserved outside context                  │
├─────────────────────────────────────────────────────────────┤
│  Compact (OpenCode-controlled)                              │
│  ├─ Tools: NONE                                              │
│  ├─ Goal: Lossy compression, summary generation             │
│  └─ Result: Compressed context for continuation             │
└─────────────────────────────────────────────────────────────┘

Why separation matters:

  • Compact summary should be pure text generation (no side effects)
  • Pre-compact should be structured operations (tools, file I/O)
  • Mixing them creates security risks and unreliable behavior

Proposed Solution

Hook API

{
    "experimental.session.pre-compact": async (input, output) => {
        // INPUT:
        {
            sessionID: string,         // Current session
            auto: boolean,             // true=auto-compact, false=user /compact
            parentID: MessageID,       // Compaction trigger message
            messages: MessageV2[],     // Current conversation history
        }
        
        // OUTPUT:
        {
            shouldRun: boolean,        // default: false — whether to run pre-compact
            prompt?: string,           // Custom prompt for pre-compact round
        }
    }
}

Behavior

  1. Default (shouldRun: false): Zero impact. Compact proceeds normally.
  2. When shouldRun: true:
    • OpenCode creates assistant message: mode: "pre-compact" (NOT summary)
    • AI receives prompt and full tool access
    • AI executes tools (write, edit, read, etc.)
    • After completion, OpenCode proceeds to normal compact
    • Pre-compact message remains in history (audit trail)

Implementation Sketch

File: packages/opencode/src/session/compaction.ts

In processCompaction, before existing compact logic:

// ===== PRE-COMPACT PHASE (NEW) =====
const preCompact = yield* plugin.trigger(
    "experimental.session.pre-compact",
    { sessionID: input.sessionID, auto: input.auto, parentID: input.parentID },
    { shouldRun: false, prompt: undefined }
)

if (preCompact.shouldRun) {
    const preMsg = createAssistantMessage({
        mode: "pre-compact",  // NOT summary
        // ... standard fields ...
    })
    
    const preProcessor = yield* processors.create({ assistantMessage: preMsg, ... })
    
    const preResult = yield* preProcessor.process({
        // ... standard fields ...
        tools: availableTools,  // Full tools, not empty!
        messages: [
            ...modelMessages,
            { role: "user", content: [{ type: "text", text: preCompact.prompt }] }
        ],
        // ...
    })
    
    // Always proceed to compact
}
// ===== END PRE-COMPACT =====

// ===== COMPACT PHASE (EXISTING) =====
const compacting = yield* plugin.trigger("experimental.session.compacting", ...)
// ... rest of compact logic ...

Design Decisions

  1. Opt-in by default: shouldRun: false ensures zero impact on existing users
  2. Full tool access: Pre-compact round uses complete tool set (not tools: {})
  3. Not summary mode: mode: "pre-compact" prevents tool call interception
  4. Always proceeds: Even if pre-compact errors, compact continues (no deadlock)
  5. Preserves history: Pre-compact message stays in session (audit trail)

Performance

Metric Impact Mitigation
Extra LLM round +1 API call Only when shouldRun: true
Token cost Prompt + tool outputs Plugin controls scope
Latency +1 round-trip Acceptable for critical operations

Recommendation: Plugins should only enable for manual /compact, not auto-compact.

Backward Compatibility

  • Plugins without hook: Zero impact (hook is optional)
  • Existing compact behavior: Unchanged
  • API: Purely additive, no breaking changes
  • Performance: No overhead when disabled

Why Not Alternatives?

Alternative 1: Allow tools during compact

Pass tools to compact processor instead of tools: {}.

Rejected: Mixes data migration with summary generation. Side effects could corrupt summary quality. Violates compact's "pure text generation" principle.

Alternative 2: Post-compact event

Use session.compacted event.

Rejected: After compact, detailed context is lost. AI must reconstruct state from file system (inefficient, error-prone).

Alternative 3: Embed in summary

Require AI to include operations in summary text.

Rejected: Summary length is limited. Non-structured. Remains in context (pollutes future conversation). Unreliable.

Conclusion

This hook transforms OpenCode's compaction from a destructive operation into a managed lifecycle transition. It enables:

  • Reliable persistence for memory and state management plugins
  • Structured data migration before lossy compression
  • Plugin ecosystem growth in categories previously impossible
  • Clean architecture with separation of concerns

The hook is:

  • Simple: One hook, one cycle, opt-in
  • Safe: Zero impact when disabled, errors don't block compact
  • Powerful: Full tool access enables complex operations
  • Universal: Benefits all plugin categories, not just memory systems

Labels: enhancement, plugin-system, hook-api, architecture, ecosystem
Priority: High (enables new plugin categories)
Related: opencode-noema, workflow-management, debugging-assistants

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Apr 29, 2026
  2. github-actions commented on Apr 29, 2026

    @github-actions
    Contributor

    This issue doesn't fully meet our contributing guidelines.

    What needs to be fixed:

    • The title must start with [FEATURE]: for feature requests
    • The issue is missing the required verification checkbox confirming the feature hasn't been suggested before
    • The description appears to be AI-generated (extremely long, structured with tables, diagrams, and exhaustive sections) — please replace with a concise, human-written description of the problem and proposed solution

    Please edit this issue to address the above within 2 hours, or it will be automatically closed.


    This issue might be a duplicate of existing issues. Please check:

    If you believe this was flagged incorrectly, please let a maintainer know.

  3. AnterCreeper commented on Apr 29, 2026

    @AnterCreeper
    Author

    The above information is auto-generated by AI, however I think the detailed information is provided. Thanks you for understanding, and welcome for discussion!

  4. github-actions commented on Apr 29, 2026

    @github-actions
    Contributor

    This issue has been automatically closed because it was not updated to meet our contributing guidelines within the 2-hour window.

    Feel free to open a new issue that follows our issue templates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

coreAnything pertaining to core functionality of the application (opencode server stuff)

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions