Skip to content

sessionStart and sessionEnd hooks fire per-prompt instead of per-session in interactive mode #991

Closed

Description

@torumakabe

Describe the bug

In interactive mode, sessionStart and sessionEnd hooks are triggered for each prompt/response cycle, not when the interactive session actually starts and ends. According to the documentation, these hooks should execute "when a new agent session begins" and "when the agent session completes or is terminated."

Affected version

0.0.383

Steps to reproduce the behavior

  1. Create hooks.json with sessionStart and sessionEnd hooks that log to a file
  2. Start Copilot CLI in interactive mode: copilot
  3. Submit a prompt (e.g., "Display the current time")
  4. Check the log file - observe sessionStart and sessionEnd entries
  5. Submit another prompt within the same interactive session
  6. Check the log file again - observe additional sessionStart and sessionEnd entries

Expected behavior

  • sessionStart should fire once when the interactive session begins (copilot command executed)
  • sessionEnd should fire once when the interactive session ends (user exits with /exit or Ctrl+D)
  • For per-prompt logging, userPromptSubmitted hook should be used instead

Additional context

  • Operating system: Linux
  • CPU architecture: x86_64
  • Shell: zsh
{
    "version": 1,
    "hooks": {
        "sessionStart": [{"type": "command", "bash": ".github/hooks/scripts/session-start.sh"}],
        "sessionEnd": [{"type": "command", "bash": ".github/hooks/scripts/session-end.sh"}]
    }
}

Activity

  1. added theissue type on Jan 16, 2026
  2. ssfdre38 commented on Jan 17, 2026

    @ssfdre38

    Solution Available: Session Lifecycle Plugin

    I've built a plugin that provides proper session start/end tracking!

    Plugin: session-lifecycle

    Live now: https://github.com/barrersoftware/copilot-plugins-registry/tree/master/plugins/session-lifecycle

    What it does:

    • ✅ Tracks ACTUAL session boundaries (not per-prompt)
    • ✅ onActualSessionStart fires once when session truly starts
    • ✅ onActualSessionEnd fires once when session truly ends
    • ✅ Message counting across entire session
    • ✅ Session-scoped data storage

    How to use

    import { PluginClient } from '@barrersoftware/copilot-plugins';
    
    const client = new PluginClient();
    await client.start();
    const session = await client.createSession();
    
    // Install plugin
    await session.sendAndWait({ message: '/plugins install session-lifecycle' });
    
    // Session start fires ONCE (not per prompt)
    // Session end fires ONCE (when session actually ends)

    Example Output

    🔵 ═══ ACTUAL SESSION START ═══
       Session ID: abc123
       Started: 2026-01-17T08:00:00.000Z
    
    ... (many prompts)...
    
    🔴 ═══ ACTUAL SESSION END ═══
       Duration: 325.42s
       Messages sent: 47
       Ended: 2026-01-17T08:05:25.420Z
    

    For Developers

    You can extend the plugin for custom session logic:

    class MySessionPlugin extends SessionLifecyclePlugin {
      async onActualSessionStart(context) {
        await initializeDatabase();
        this.setSessionData('user', 'daniel');
      }
    
      async onActualSessionEnd(context, durationMs) {
        const user = this.getSessionData('user');
        await saveSessionReport(user, durationMs);
      }
    }

    Why a plugin?

    This is a workaround while the GitHub team works on fixing the hook behavior in the CLI. The plugin:

    • Provides proper session tracking NOW
    • Useful for analytics, metrics, and session-based logic
    • Will become obsolete if/when GitHub fixes the native hooks (that's OK!)

    Testing

    Would love feedback! Perfect for anyone building session analytics or needing proper lifecycle tracking.


    Package: @barrersoftware/copilot-plugins
    Registry: https://github.com/barrersoftware/copilot-plugins-registry

  3. VildMedPap commented on Mar 31, 2026

    @VildMedPap

    How on earth is this still not resolved?

  4. added
    area:sessionsSession management, resume, history, session picker, and session state
    on Apr 6, 2026
  5. demorgi commented on Apr 7, 2026

    @demorgi

    Hey @stephentoub @andyfeller any timeline on this getting resolved?

  6. self-assigned this
    on Apr 7, 2026
  7. stephentoub commented on Apr 8, 2026

    @stephentoub

    This should be fixed in the next copilot CLI build.

  8. added a commit that references this issue on Apr 10, 2026
    abdcb96
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:sessionsSession management, resume, history, session picker, and session state

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions