Skip to content

Add session multiplexing detection#48

Merged
TechNickAI merged 2 commits intomainfrom
feature/session-multiplexing
Apr 1, 2026
Merged

Add session multiplexing detection#48
TechNickAI merged 2 commits intomainfrom
feature/session-multiplexing

Conversation

@TechNickAI
Copy link
Copy Markdown
Owner

Summary

  • New SessionStart hook that detects when 3+ Claude Code sessions are active simultaneously
  • Outputs context re-grounding reminder so responses include explicit repo/branch/task info
  • Designed for multi-window workflows where context switching is constant

Changes

  • plugins/core/hooks/session-multiplexing.sh — new hook script
    • Touches ~/.claude/sessions/{SESSION_ID} on every session start/resume/clear/compact
    • Counts files modified in last 2 hours
    • At 3+ active: injects multi-session reminder
    • Auto-cleans session files older than 24 hours
  • plugins/core/hooks/hooks.json — added SessionStart hook entry

Test plan

  • Start 3+ Claude Code sessions — verify "Multi-session mode" message appears
  • Verify session files created in ~/.claude/sessions/
  • Verify old session files cleaned up after 24h
  • Verify single-session usage produces no extra output

🤖 Generated with Claude Code

SessionStart hook that tracks active Claude Code sessions. When 3+ sessions
are active (modified in last 2 hours), outputs a reminder to include explicit
context in responses — repo name, branch, what we're working on.

Designed for users who juggle multiple windows/repos simultaneously.
Auto-cleans session marker files older than 24 hours.

Inspired by gstack's ELI16 mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@claude
Copy link
Copy Markdown

claude bot commented Apr 1, 2026

PR Review: Add session multiplexing detection

Nice feature idea for multi-window workflows. A few observations:

Bug: Duplicate if/else blocks

The macOS vs Linux detection is dead code — both branches are identical:

if [[ "$OSTYPE" == "darwin"* ]]; then
    ACTIVE_COUNT=$(find "$SESSION_DIR" -type f -mmin -120 2>/dev/null | wc -l | tr -d ' ')
else
    ACTIVE_COUNT=$(find "$SESSION_DIR" -type f -mmin -120 2>/dev/null | wc -l | tr -d ' ')
fi

find -mmin works the same on macOS and Linux (GNU coreutils vs BSD find both support it). Collapse to a single line:

ACTIVE_COUNT=$(find "$SESSION_DIR" -type f -mmin -120 2>/dev/null | wc -l | tr -d ' ')

Minor: SESSION_ID validation could be tighter

jq -r '.session_id // empty' exits cleanly on missing key, but if the session ID contains path traversal characters (e.g. ../../etc/something), touch "$SESSION_DIR/$SESSION_ID" could write outside the session directory. Since this is a hook consuming Claude Code's own JSON, the risk is low, but a simple basename guard would be more defensive:

SESSION_FILE="$SESSION_DIR/$(basename "$SESSION_ID")"
touch "$SESSION_FILE"

Minor: Hook matcher format

The hooks.json entry uses "matcher": "startup|resume|clear|compact". Worth confirming this pipe-delimited regex syntax is what the Claude Code hook system expects for SessionStart — the existing PostToolUse hooks use exact tool names. If SessionStart doesn't support a matcher at all (since it's not tool-based), the matcher field may be ignored or cause unexpected behavior.

Suggestion: Make threshold configurable

The hardcoded 3 threshold is fine for now, but a comment explaining the choice would help (e.g. # 3+ sessions is where context-juggling becomes error-prone). Even a variable at the top would make it easier to tweak.

Overall

The core logic is clean and the use case is real. Fixing the dead code branch and the session file path safety would make this merge-ready.

🤖 Generated with Claude Code

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 47845b9d28

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +3 to +5
"SessionStart": [
{
"matcher": "startup|resume|clear|compact",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove ended sessions from multiplexing count

This tracking logic only runs on SessionStart and never clears a session marker when a session ends, so closed windows are still counted as "active" for up to 2 hours (or 24 hours until cleanup). In practice, if a user opens 3 sessions, closes 2, and then starts another within 2 hours, the hook still reports 3+ active sessions and injects unnecessary guidance. Adding a SessionEnd hook to delete the corresponding marker would make the count reflect truly active sessions.

Useful? React with 👍 / 👎.

- Remove dead code OS detection (both branches were identical)
  find -mmin works the same on macOS and Linux
- Add basename guard against path traversal in SESSION_ID
- Add comment explaining the 3-session threshold choice

Co-Authored-By: Claude <noreply@anthropic.com>
@claude
Copy link
Copy Markdown

claude bot commented Apr 1, 2026

PR Review: Add session multiplexing detection

Nice idea — context grounding in multi-session workflows is a real pain point. The implementation is clean and consistent with the existing todo-persist.sh style. A few things worth addressing before merge:


Potential Bug: SessionStart matcher field

"SessionStart": [
  {
    "matcher": "startup|resume|clear|compact",
    ...
  }
]

Claude Code's SessionStart hook type may not support a matcher field the same way PostToolUse does (where matcher targets tool names). If the matcher is unsupported or requires an exact string rather than a regex, the hook may silently never fire. Worth verifying against the Claude Code hooks docs, and possibly removing the matcher entirely (letting it run on all session starts, which is the intent).


Potential Bug: Unguarded arithmetic comparison

ACTIVE_COUNT=$(find "$SESSION_DIR" -type f -mmin -120 2>/dev/null | wc -l | tr -d ' ')

if [ "$ACTIVE_COUNT" -ge 3 ]; then

If find produces no output and wc -l | tr -d ' ' returns an empty string, the -ge comparison will fail with unary operator expected. Guard it:

if [ "${ACTIVE_COUNT:-0}" -ge 3 ]; then

Minor: Session ID characters could still cause issues

basename "$SESSION_ID" prevents path traversal, but if SESSION_ID contains characters like spaces or newlines (unlikely for UUIDs but worth considering), the touch command could behave unexpectedly. Quoting is already correct ("$SESSION_FILE"), so this is low risk — just noting it.


Minor: Cleanup runs after count (intentional, but worth a comment)

The ordering — touch → count → cleanup — is correct: old files don't inflate the active count. A quick comment noting "cleanup runs after counting to avoid deflating active count" would make the intent obvious to future editors.


Observation: jq dependency

Consistent with todo-persist.sh so this is fine for this repo's conventions. Just noting it for awareness.


What's working well

  • basename sanitization for path traversal is correct and explicit
  • 2>/dev/null on both find calls handles missing directory gracefully
  • wc -l | tr -d ' ' is correctly cross-platform (macOS adds leading spaces)
  • Cleanup after counting is the right ordering
  • Overall structure and style matches existing hooks

Summary: The main risk is the SessionStart matcher behavior — if it silently prevents the hook from running, the feature doesn't work at all. The ACTIVE_COUNT guard is a low-friction fix. Both are small changes, otherwise this looks good to merge.

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

# Threshold: 3+ sessions is where context-juggling becomes error-prone.
# Below 3, a user can reasonably track what each window is doing.
if [ "$ACTIVE_COUNT" -ge 3 ]; then
echo "Multi-session mode: $ACTIVE_COUNT active Claude Code sessions detected. The user is juggling multiple windows — always include explicit context (repo name, branch, what we're working on) when reporting status or completing work."
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hook outputs plain text instead of required JSON format

High Severity

The echo on line 33 outputs a plain text string, but Claude Code's SessionStart hooks expect JSON output containing a hookSpecificOutput with an additionalContext field to inject context into the conversation. Plain text stdout from a SessionStart hook is not treated as conversation context — it triggers a "hook output does not start with {" warning and may produce a "startup hook error" in the UI. The message never reaches Claude, which defeats the entire purpose of the hook. The output needs to be structured as JSON, e.g. {"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"..."}}.

Fix in Cursor Fix in Web

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WONTFIX — incorrect. For SessionStart hooks, stdout is injected directly as context. The Claude Code docs example literally uses echo 'Reminder: ...' plain text. JSON hookSpecificOutput/additionalContext is only required for decision-returning hooks like PreToolUse. The plain echo here is the correct pattern.

@TechNickAI TechNickAI merged commit ee2c435 into main Apr 1, 2026
4 checks passed
@TechNickAI TechNickAI deleted the feature/session-multiplexing branch April 1, 2026 14:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant