commit 681c2e46c0c4608c8a61fb04df69e264e5f531e1 Author: Zhongwei Li Date: Sat Nov 29 17:59:29 2025 +0800 Initial commit diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..53be66c --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,15 @@ +{ + "name": "session", + "description": "v3.17.4 - Advanced session management for Claude Code with intelligent context tracking, automatic snapshots, and git history capture. Features zero-blocking conversation logging, AI-powered analysis, and optimized parallel subagent architecture. Never lose context!", + "version": "3.17.4", + "author": { + "name": "AutomateWith.Us", + "email": "team@automatewith.us" + }, + "commands": [ + "./commands" + ], + "hooks": [ + "./hooks" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..4f0d2ce --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# session + +v3.17.4 - Advanced session management for Claude Code with intelligent context tracking, automatic snapshots, and git history capture. Features zero-blocking conversation logging, AI-powered analysis, and optimized parallel subagent architecture. Never lose context! diff --git a/commands/close.md b/commands/close.md new file mode 100644 index 0000000..a8bc2d7 --- /dev/null +++ b/commands/close.md @@ -0,0 +1,187 @@ +You are managing a session memory system. The user wants to close and finalize the current session. + +**CRITICAL - Command Format:** +All session plugin commands use the `/session:` prefix. DO NOT suggest commands without this prefix. +- โœ… Correct: `/session:list`, `/session:start`, `/session:continue`, `/session:status` +- โŒ Wrong: `/session list`, `/session start`, `/session continue`, `/session status` +Use ONLY the exact command formats specified in this template. + +## Task: Close Session + +Finalize the session by creating a final snapshot, updating metadata, and generating a summary. + +### Step 1: Validate Active Session + +1. Check if `.claude/sessions/.active-session` file exists +2. If NOT exists, show error: + ``` + โŒ Error: No active session to close + + ๐Ÿ’ก Use /session:start [name] to create a new session + ๐Ÿ’ก Or use /session:continue [name] to resume an existing session + ``` + Then STOP. +3. Read the active session name from `.active-session` +4. Verify session directory exists + +### Step 2: Read Current Session Data + +Read `.claude/sessions/{active_session}/session.md` and extract: +- Started timestamp +- Last Updated timestamp +- Goal +- Files Involved +- Milestones (count completed and total) + +### Step 3: Calculate Session Statistics + +1. **Duration**: Calculate time from "Started" to now + - Format: `Xh Ym` (e.g., "4h 35m") + +2. **Snapshot Count**: Count all snapshot files matching `YYYY-MM-DD_HH-MM.md` pattern in session directory + +3. **Files Modified**: Count unique files in "Files Involved" section of session.md + +4. **Todos/Milestones Completed**: Count checked milestones in session.md + +5. **Token Usage**: Get current conversation token usage (from system info or estimate) + - Format as "XXXk" (e.g., "67.4k") + +### Step 4: Generate Final Snapshot + +Create a final snapshot using the same process as `/session:save`: + +1. Generate timestamp filename: `YYYY-MM-DD_HH-MM.md` +2. Capture: + - Conversation summary (what was accomplished in this session) + - Final completed todos + - Final file changes + - Final state + - Session outcome/results + +3. **IMPORTANT**: In the snapshot, add a header line: + ```markdown + # FINAL Snapshot: {session_name} + **Timestamp**: {timestamp} + **Session Closed**: This is the final snapshot before session closure + ``` + +4. Include a "Session Outcome" section: + ```markdown + ## Session Outcome + - Goal: {original_goal_from_session_md} + - Status: {Completed|Partially Completed|In Progress} + - Key Achievements: {list_main_accomplishments} + - Remaining Work: {list_what_still_needs_to_be_done} + ``` + +### Step 5: Update context.md with Final Summary + +1. Read `.claude/sessions/{active_session}/context.md` +2. Add a final entry to the "Summary" section: + ```markdown + ## Session Closure Summary + + **Closed**: {current_timestamp} + **Duration**: {duration} + **Outcome**: {Completed|Partially Completed} + + ### What Was Accomplished + {bullet_list_of_main_accomplishments} + + ### Final State + {description_of_final_state} + + ### Next Steps (if resuming later) + {what_to_do_when_session_is_continued} + ``` +3. Write updated context.md + +### Step 6: Update session.md with Closed Status + +1. Read `.claude/sessions/{active_session}/session.md` +2. Update these fields: + - **Status**: Change from "Active" to "Closed" + - **Closed**: Add current timestamp + - **Last Updated**: Update to current timestamp +3. Write updated session.md + +### Step 7: Clear Active Session + +1. Delete or clear the `.claude/sessions/.active-session` file +2. This marks that no session is currently active + +### Step 8: Display Closing Summary + +Show comprehensive closing summary: + +``` +โœ“ Session '{session_name}' closed +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” +๐Ÿ“Š Session Summary: + Duration: {duration_formatted} + Snapshots: {snapshot_count} + Files modified: {file_count} + Milestones completed: {completed_milestones}/{total_milestones} + Token usage (this conversation): {token_usage_formatted} + +๐ŸŽฏ Goal: {original_goal} + +โœ… Key Achievements: + {list_top_3_to_5_achievements} + +๐Ÿ“ Session saved to: .claude/sessions/{session_name}/ + +๐Ÿ’ก Use /session:continue {session_name} to resume later +๐Ÿ’ก Use /session:list to see all sessions +``` + +### Example Output: + +``` +โœ“ Session 'feature-auth-system' closed +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” +๐Ÿ“Š Session Summary: + Duration: 4h 35m + Snapshots: 5 + Files modified: 12 + Milestones completed: 8/10 + Token usage (this conversation): 67.4k + +๐ŸŽฏ Goal: Implement OAuth2 authentication system + +โœ… Key Achievements: + - Implemented Google OAuth provider integration + - Created authentication middleware + - Added token refresh mechanism + - Built user profile synchronization + - Completed security testing + +๐Ÿ“ Session saved to: .claude/sessions/feature-auth-system/ + +๐Ÿ’ก Use /session:continue feature-auth-system to resume later +๐Ÿ’ก Use /session:list to see all sessions +``` + +### Step 9: Offer Next Steps + +Ask the user: +``` +Session closed successfully. Would you like to: +1. Start a new session (/session:start [name]) +2. Review another session (/session:list) +3. Continue with other work +``` + +--- + +**IMPORTANT**: +- Execute all steps in order +- The final snapshot should be comprehensive - it's the last capture +- Update all metadata files (session.md, context.md) +- Clear active session AFTER all files are updated +- Format output professionally with clear statistics +- Handle errors gracefully (e.g., if session files are missing) +- Token usage should be from current conversation only, not cumulative +- Duration should be accurate based on timestamps +- Provide clear next steps for user diff --git a/commands/continue.md b/commands/continue.md new file mode 100644 index 0000000..3702515 --- /dev/null +++ b/commands/continue.md @@ -0,0 +1,359 @@ +You are managing a session memory system. The user wants to resume an existing session. + +**CRITICAL - Command Format:** +All session plugin commands use the `/session:` prefix. DO NOT suggest commands without this prefix. +- โœ… Correct: `/session:list`, `/session:start`, `/session:continue`, `/session:status` +- โŒ Wrong: `/session list`, `/session start`, `/session continue`, `/session status` +Use ONLY the exact command formats specified in this template. + +## Task: Continue Existing Session + +Parse the session name from the command arguments. The command format is: `/session:continue [name]` + +**OPTIMIZATION**: v3.7.0 uses parallel subagent delegation for 72% token reduction (77k โ†’ 22k tokens). + +### Step 1: Validate Session Exists (CLI) + +Extract the session name from arguments, then run: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js get {session_name} +``` + +If this returns an error (exit code 2), the session doesn't exist. Show: +``` +โŒ Error: Session '{name}' not found +๐Ÿ’ก Use /session:list to see available sessions +๐Ÿ’ก Use /session:start {name} to create a new session +``` +Then STOP. + +The JSON response contains metadata (status, started, snapshotCount, etc.). + +### Step 1.5: Close Previous Active Session (If Different) + +Before continuing the target session, close any currently active session if it's different: + +1. Check if `.claude/sessions/.active-session` exists +2. If it exists: + - Read the current active session name + - If it's different from the target session {session_name}: + - Show: "๐Ÿ“‹ Closing previous session '{previous_session_name}'..." + - Close the previous session status: + ```bash + node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js update-status "{previous_session_name}" "closed" + ``` + - This marks the previous session as closed in `.auto-capture-state` +3. Continue to next step + +**Note**: This ensures clean session transitions with no abandoned active sessions. + +### Step 1.8: Calculate Absolute Paths for Subagents + +Before delegating to subagents, you need to determine absolute paths that subagents will use. + +**IMPORTANT**: Subagents don't inherit the working directory or environment variables from the main conversation. You MUST provide absolute paths explicitly. + +Calculate these values (conceptually - don't run bash commands, just determine the values): +- **Working directory**: Current working directory (you already know this from your environment) +- **Plugin root**: `/Users/prajyot/.claude/plugins/marketplaces/automatewithus-plugins/session` +- **Session path**: `{working_directory}/.claude/sessions/{session_name}` + +You will substitute these absolute paths into the subagent prompts in the next step. + +### Step 2: Delegate Heavy Work to Subagents (Parallel Execution) + +**CRITICAL**: You MUST invoke ALL 3 Task tools in a SINGLE response message. This runs them in parallel and isolates heavy token usage from the main conversation. + +Use the Task tool to spawn 3 parallel subagents with these exact configurations: + +**Subagent 1 - Consolidate Conversation Log:** +- subagent_type: "general-purpose" +- description: "Consolidate conversation log" +- model: "haiku" +- prompt: | + You are working with session: {session_name} + + **Absolute paths for this task:** + - Working directory: {working_directory} + - Plugin root: ${CLAUDE_PLUGIN_ROOT} + - Session path: {session_path} + + Read the prompt file: ${CLAUDE_PLUGIN_ROOT}/prompts/consolidate-log.md + That file contains template placeholders like "{session_name}", "{session_path}", "${CLAUDE_PLUGIN_ROOT}". + Replace all such placeholders with the actual values provided above. + Then execute the resulting instructions. + +**Subagent 2 - Refresh Git History:** +- subagent_type: "general-purpose" +- description: "Refresh git history" +- model: "haiku" +- prompt: | + You are working with session: {session_name} + + **Absolute paths for this task:** + - Working directory: {working_directory} + - Plugin root: ${CLAUDE_PLUGIN_ROOT} + - Session path: {session_path} + + Read the prompt file: ${CLAUDE_PLUGIN_ROOT}/prompts/refresh-git.md + That file contains template placeholders like "{session_name}", "{session_path}", "${CLAUDE_PLUGIN_ROOT}". + Replace all such placeholders with the actual values provided above. + Then execute the resulting instructions. + +**Subagent 3 - Extract Session Goal:** +- subagent_type: "general-purpose" +- description: "Extract session goal" +- model: "haiku" +- prompt: | + You are working with session: {session_name} + + **Absolute paths for this task:** + - Working directory: {working_directory} + - Plugin root: ${CLAUDE_PLUGIN_ROOT} + - Session path: {session_path} + + Read the prompt file: ${CLAUDE_PLUGIN_ROOT}/prompts/extract-goal.md + That file contains template placeholders like "{session_name}", "{session_path}", "${CLAUDE_PLUGIN_ROOT}". + Replace all such placeholders with the actual values provided above. + Then execute the resulting instructions. + +**REMINDER**: All 3 Task invocations MUST be in the SAME response to execute in parallel! + +### Step 3: Process Subagent Results + +After all 3 subagents complete, you'll receive their results. Handle errors gracefully: + +**Consolidation Result**: +- If `success: true` โ†’ Snapshot created successfully +- If `skipped: true` โ†’ No conversation log found (OK, continue) +- If `success: false` โ†’ Log error but continue + +**Git Refresh Result**: +- If `success: true` โ†’ Git history updated +- If `success: false` โ†’ No git repo or error (OK, continue) + +**Goal Extraction Result**: +- If `success: true` โ†’ Use the extracted goal +- If `success: false` โ†’ Use fallback goal from result + +### Step 3.5: Extract Full Snapshot Summary (Complete Context Approach) + +Provide Claude with complete snapshot summary including all topics, decisions, and tasks for full context visibility using Claude Code tools. + +**IMPORTANT**: This step uses Claude Code's Read and Glob tools instead of bash pipelines to avoid parse errors with command substitution. + +**Implementation Steps:** + +1. **Find the latest snapshot file using Glob tool:** + - Pattern: `.claude/sessions/{session_name}/auto_*.md` + - Glob returns files sorted by modification time (newest first) + - Take the first result as the latest snapshot + +2. **If snapshot exists, use Read tool to extract content:** + - Read the snapshot file (first 80 lines should contain all needed sections) + - Extract all snapshot items with titles only: + - **Topics Discussed**: Extract ALL topic titles from "## Topics Discussed" section + - Format: "1. **Category**: Description" + - Extract only the category/title (bold text between ** markers) + - Store as array of titles + - **Decisions Made**: Extract ALL decision titles from "## Decisions Made" section + - Format: "1. **Decision**: Rationale" + - Extract only the decision title (bold text between ** markers) + - Store as array of titles + - **Tasks Completed**: Extract ALL tasks from "## Tasks Completed" section + - Format: "1. Task description" + - Extract full task line (simple numbered list) + - Store as array of tasks + - **Current Status**: Extract status lines from "## Current Status" section + - Look for "- **Progress**:" line and extract text after it + - Look for "- **Next Steps**:" line and extract text after it + - Look for "- **Blockers**:" line and extract text after it + - Store as object with progress, nextSteps, blockers + +3. **Build full snapshot summary output:** + + ``` + ๐Ÿ“‹ Latest: {snapshot_filename} + + Topics Discussed ({count}): + - {topic_1} + - {topic_2} + ... (all topics) + + Decisions Made ({count}): + - {decision_1} + - {decision_2} + ... (all decisions) + + Tasks Completed ({count}): + - {task_1} + - {task_2} + ... (all tasks) + + Current Status: + โ€ข Progress: {progress_text} + โ€ข Next Steps: {next_steps_text} + โ€ข Blockers: {blockers_text} + + ๐Ÿ’ก Read {snapshot_path} for full details + ``` + +4. **Display the summary in Step 6** (after showing the session goal) + +**Graceful Handling**: +- If no snapshot exists โ†’ Skip summary display (OK, fresh session) +- If extraction fails โ†’ Show generic message "See snapshot for details" +- If Read fails โ†’ Silent failure, continue (don't break resume) + +**Why Full Snapshot Summary Works Better**: +- Complete visibility: All topics, decisions, and tasks visible immediately (~300 tokens) +- No information loss: User sees everything without needing to read snapshot file +- Better context continuity: Claude knows full scope of work done +- Improved decision-making: All context available for next steps +- **No bash parse errors** - uses Claude Code tools (Glob, Read) natively + +### Step 4: Activate Session (CLI) + +Run the CLI command to activate the session: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js activate {session_name} +``` + +This updates both the .active-session file and the index. + +### Step 4.5: Update Session Status to Active + +Update the session status in `.auto-capture-state` and index: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js update-status "{session_name}" "active" +``` + +This ensures the session status matches its active state and prevents sync bugs. + +### Step 5: Update Last Updated Timestamp + +Update the "Last Updated" line in session.md to current time using the Edit tool: + +``` +**Last Updated**: {current ISO timestamp} +``` + +### Step 6: Display Summary with Full Snapshot Details + +Show session goal plus complete snapshot summary with all topics, decisions, and tasks for full context visibility. + +**Implementation**: Use Glob and Read tools (from Step 3.5) to extract and display the full summary. + +**Display Format**: +``` +โœ“ Session ready: {goal} + +๐Ÿ“‹ Latest: {snapshot_filename} + +Topics Discussed ({count}): +- {topic_1} +- {topic_2} +... (all topics) + +Decisions Made ({count}): +- {decision_1} +- {decision_2} +... (all decisions) + +Tasks Completed ({count}): +- {task_1} +- {task_2} +... (all tasks) + +Current Status: +โ€ข Progress: {progress_text} +โ€ข Next Steps: {next_steps_text} +โ€ข Blockers: {blockers_text} + +๐Ÿ’ก Read {snapshot_path} for full details + +What's next? +``` + +**Example Output**: +``` +โœ“ Session ready: Implement product permission system + +๐Ÿ“‹ Latest: auto_2025-11-16_05-24.md + +Topics Discussed (8): +- Database Schema Design +- API Endpoint Implementation +- Permission Middleware +- Frontend Components +- Testing Strategy +- Deployment Planning +- Documentation Updates +- Performance Optimization + +Decisions Made (3): +- Use RBAC Model for Permission System +- Implement Middleware-based Authorization +- Store Permissions in PostgreSQL + +Tasks Completed (12): +- Created users, roles, permissions tables +- Implemented role assignment API +- Built permission checking middleware +- Added frontend permission components +- Wrote unit tests for permission logic +- Created integration tests +- Documented API endpoints +- Updated deployment guide +- Fixed TypeScript errors +- Ran build successfully +- Deployed to staging +- Verified permission checks work + +Current Status: +โ€ข Progress: 12 of 12 tasks completed (100%) +โ€ข Next Steps: Deploy to production and monitor +โ€ข Blockers: None + +๐Ÿ’ก Read .claude/sessions/product-permission/auto_2025-11-16_05-24.md for full details + +What's next? +``` + +**Notes**: +- If no snapshot exists, only show "โœ“ Session ready: {goal}" and "What's next?" +- Use Read tool to extract all items (avoids bash parse errors) +- Fallback gracefully if extraction fails (show generic pointer text) + +**IMPORTANT**: +- DO show full snapshot summary (all topics/decisions/tasks) โ† FULL VISIBILITY +- This provides complete context in ~300 tokens โ† WORTH THE COST +- User doesn't need to read snapshot file separately โ† CONVENIENCE +- All relevant context immediately available for decision-making โ† BETTER UX +- User can still read snapshot file for additional details if needed +- The heavy analysis already happened in the subagents +- User can run `/session:status` for detailed view + +--- + +**TOKEN OPTIMIZATION BENEFITS:** +- Current: ~20.3k tokens with full snapshot summary (74% reduction from v3.6.4) + - Full snapshot summary with all topics/decisions/tasks (~300 tokens) + - Complete visibility: All snapshot items visible immediately + - Benefit: Complete context for better decision-making and continuity +- Heavy work (consolidation, git analysis) happens in isolated subagent contexts +- Parallel execution: 3 subagents run simultaneously (~2-4 seconds total) +- Lazy-loaded prompts: Subagents read their own prompts (~1.7k token savings) +- Result: Faster session resume, massive token savings, complete context restoration + +**ERROR HANDLING:** +- If all subagents fail: Still activate session, show generic message "โœ“ Session ready. What's next?" +- If session.md missing: Show corrupted session warning +- If CLI fails: Suggest rebuilding index with `/session:rebuild-index` + +--- + +ARGUMENTS: {name} diff --git a/commands/continue.md.v3.6.4.backup b/commands/continue.md.v3.6.4.backup new file mode 100644 index 0000000..58d286d --- /dev/null +++ b/commands/continue.md.v3.6.4.backup @@ -0,0 +1,199 @@ +You are managing a session memory system. The user wants to resume an existing session. + +## Task: Continue Existing Session + +Parse the session name from the command arguments. The command format is: `/session continue [name]` + +**OPTIMIZATION:** This command uses CLI for validation and metadata (60-70% token reduction). + +### Step 1: Validate Session Exists (CLI) + +Extract the session name from arguments, then run: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js get {session_name} +``` + +If this returns an error (exit code 2), the session doesn't exist. Show: +``` +โŒ Error: Session '{name}' not found +๐Ÿ’ก Use /session list to see available sessions +๐Ÿ’ก Use /session start {name} to create a new session +``` +Then STOP. + +The JSON response contains metadata (status, started, goal, snapshotCount, etc.). + +### Step 2: Read Session Files + +Now read the actual content files (these need full content for context synthesis): + +1. Read `.claude/sessions/{name}/session.md` +2. Read `.claude/sessions/{name}/context.md` (if exists) +3. Get latest snapshot filename from the CLI JSON response (`latestSnapshot` field) +4. If `latestSnapshot` exists, read `.claude/sessions/{name}/{latestSnapshot}` + +### Step 3: Check for Active Session and Transition (NEW - Session Cleanup) + +Before activating the new session, check if there's already a different active session: + +1. Check if `.claude/sessions/.active-session` exists +2. If it exists, read the current active session name +3. If the current active session is **different** from the session being continued: + - Show: "๐Ÿ“‹ Closing previous session '{previous_session_name}'..." + - Update the previous session's `session.md` "Last Updated" timestamp to current time + - This provides clean transition tracking +4. If it's the **same** session, skip this step (just updating timestamp) + +**Note:** The SessionEnd hook will handle final cleanup on Claude Code termination. + +### Step 4: Activate Session (CLI) + +Run the CLI command to activate the session: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js activate {session_name} +``` + +This updates both the .active-session file and the index. + +### Step 5: Update Last Updated Timestamp + +Update the "Last Updated" line in session.md to current time using the Edit tool. + +### Step 6: Synthesize and Display Context Summary + +Using the data from CLI JSON + file contents, show a comprehensive summary: + +``` +โœ“ Loaded session: '{name}' +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” +๐Ÿ“… Started: {started from CLI JSON} +๐ŸŽฏ Goal: {goal from CLI JSON or session.md} +๐Ÿ“ Last update: {lastUpdated from CLI JSON} +โฐ Status: {status from CLI JSON} +๐Ÿ“ธ Snapshots: {snapshotCount from CLI JSON} + +## Recent Context + +{latest_snapshot_conversation_summary if available} + +## Key Files +{list of files from filesInvolved array in CLI JSON} + +## Milestones +{key milestones from session.md with checkboxes} + +## Recent Decisions +{recent decisions from context.md, max 3} + +## Current State +{current state from latest snapshot if available} + +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” +Ready to continue! How would you like to proceed? +``` + +### Step 7: Prepare for Work + +Tell the user: +"I've loaded the full context for session '{name}'. All previous work, decisions, and progress have been restored. What would you like to work on next?" + +--- + +**PERFORMANCE BENEFITS:** +- **Before:** 10-20K tokens, reads session.md + context.md + snapshot + metadata parsing, 3-5s +- **After:** 3-8K tokens, CLI provides metadata instantly, only reads content files, 1-2s +- **Improvement:** ~60-70% token reduction, ~2x faster + +**WHY STILL READ CONTENT FILES:** +- context.md and snapshots contain narrative context needed for synthesis +- Claude needs full context to provide meaningful summary +- CLI provides structure/metadata, Claude provides intelligence/understanding + +**ERROR HANDLING:** +- If session.md missing, show corrupted session warning +- If CLI fails, suggest rebuilding index +- Handle missing context.md or snapshots gracefully (show what's available) + +--- + +## CRITICAL: Check for Unconsolidated Logs (Inline Analysis) + +**YOU MUST CHECK THIS BEFORE DISPLAYING THE SESSION SUMMARY:** + +When resuming a session, check if the previous session left unconsolidated logs: + +1. Check if `.claude/sessions/{name}/conversation-log.jsonl` exists +2. If the file exists: + - Show brief message: "๐Ÿ“Š Analyzing previous session... (this may take 1-3 seconds)" + - Read the conversation log file + - Parse interactions from JSONL format + - **Parse self-contained conversation log (v3.6.2+):** + - Each entry has type: 'interaction' (user prompt) or 'assistant_response' (Claude's response) + - Extract full conversation from log entries: + - User prompts: `user_prompt` field in 'interaction' entries + - Claude responses: `response_text` field in 'assistant_response' entries + - Tools used: `tools_used` field in 'assistant_response' entries + - File modifications: `modified_files` field in 'interaction' entries + - Log is self-contained - NO need to read transcript file! + - **Backward compatibility**: If `transcript_path` exists but no `response_text`, fall back to reading transcript file (for v3.6.1 logs) + - **Capture git history (if available):** + - Run: `node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js capture-git "{name}"` + - This creates `.claude/sessions/{name}/git-history.json` (~2-3KB compressed) + - Contains: last 50 commits, uncommitted changes, branch status, hotspots + - Performance: ~60-90ms (acceptable at session boundary) + - If no git repo, command returns success: false (silent skip, no error) + - **Analyze the conversation with Claude inline:** + - Use the full conversation from log entries (user prompts + Claude responses) + - Extract conversation summary (2-3 paragraphs covering what happened) + - Identify key decisions made with rationale + - List completed todos/tasks + - Document files modified with context about what changed and why (from conversation, not just file paths) + - Assess current state, what's next, and any blockers + - Create consolidated snapshot via CLI: + ```bash + echo "# Consolidated Snapshot: {session_name} +**Timestamp**: {ISO timestamp} +**Method**: Claude Inline Analysis (Free) +**Status**: Consolidated from conversation log + +## Conversation Summary +{2-3 paragraph summary of what happened in session} + +## Key Decisions +- {Decision 1 with rationale} +- {Decision 2 with rationale} + +## Completed Tasks +- {Task 1} +- {Task 2} + +## Files Modified +- {file_path}: {what changed and why} + +## Current State +{Where things stand, what's next, blockers} + +## Notes +Consolidated via Claude inline analysis at session boundary. Zero cost, highest quality." | node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js write-snapshot "{name}" --stdin --type auto + ``` + - Delete conversation-log.jsonl after successful snapshot creation + - Update `.auto-capture-state` to reset counters and set last_snapshot_timestamp +3. If no log exists: + - **Still capture git history** for updated repository context: + - Run: `node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js capture-git "{name}"` + - This refreshes git context since last session + - Silent skip if no git repo (no error) + +**PERFORMANCE:** +- Log check: <5ms +- Claude analysis: 1-3s (acceptable at session boundaries - users expect loading) +- Snapshot write: <50ms +- Log deletion: <5ms +- **Total: ~1-3 seconds** (users expect loading at session resume) + +**NOTE:** This is the v3.5.1 architecture where: +- During session: Conversation logged incrementally (<2ms per interaction, zero blocking) +- At session boundaries: Claude inline analysis creates intelligent snapshots (FREE, highest quality) +- Result: User NEVER experiences blocking during work, only brief wait at session resume where loading is expected diff --git a/commands/delete.md b/commands/delete.md new file mode 100644 index 0000000..ebcd188 --- /dev/null +++ b/commands/delete.md @@ -0,0 +1,207 @@ +You are managing a session memory system. The user wants to delete a session permanently. + +## Task: Delete Session + +Delete a session and all its data. This action cannot be undone. + +**IMPORTANT:** This is a destructive operation. Always confirm with the user before deleting. + +--- + +## Step 1: Parse Arguments + +Check if user provided a session name: +- If user provided a session name (e.g., `/session:delete old-feature`) โ†’ Use that name +- If no name provided โ†’ Show error and list available sessions for reference + +If no session name provided: +``` +โŒ Session name required. + +Usage: /session:delete [session-name] + +Available sessions: /session:list +``` +Then STOP. + +--- + +## Step 2: Get Session Details + +Run the CLI command to get session information: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js get [session-name] +``` + +If the command fails (session not found), display: +``` +โŒ Session '[session-name]' not found. + +Available sessions: /session:list +``` +Then STOP. + +--- + +## Step 3: Check If Active Session + +Check if this is the currently active session by running: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js list --json +``` + +Parse the JSON and check if `activeSession === session-name`. + +--- + +## Step 4: Show Confirmation Prompt + +Use the AskUserQuestion tool to confirm deletion. + +### If NOT the active session: + +```json +{ + "questions": [ + { + "question": "โš ๏ธ Delete Session: [session-name]\n\n๐Ÿ“… Started: [started]\n๐Ÿ“ธ Snapshots: [count]\n๐Ÿ“ Files Involved: [count]\n\nThis will permanently delete all session data.\n\nAre you sure you want to delete this session?", + "header": "Confirm Delete", + "multiSelect": false, + "options": [ + { + "label": "Yes, Delete", + "description": "Permanently delete this session and all its data" + }, + { + "label": "No, Cancel", + "description": "Keep the session and go back" + } + ] + } + ] +} +``` + +### If IS the active session: + +```json +{ + "questions": [ + { + "question": "โš ๏ธ WARNING: Deleting ACTIVE Session!\n\n'[session-name]' is your currently active session.\n\n๐Ÿ“… Started: [started]\n๐Ÿ“ธ Snapshots: [count]\n๐Ÿ“ Files Involved: [count]\n\nDeleting this will:\n- End your current working session\n- Delete all snapshots and context\n- Clear the active session\n\nThis cannot be undone.\n\nAre you ABSOLUTELY SURE?", + "header": "Delete Active", + "multiSelect": false, + "options": [ + { + "label": "Yes, Delete Active Session", + "description": "I understand this will end my active session" + }, + { + "label": "No, Cancel", + "description": "Keep the session and go back" + } + ] + } + ] +} +``` + +--- + +## Step 5: Handle User Response + +### If user selected "No, Cancel": +``` +Session deletion cancelled. +``` +Then STOP. + +### If user selected "Yes" (or "Yes, Delete Active Session"): + +Proceed to Step 6. + +--- + +## Step 6: Execute Deletion + +Run the CLI delete command: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js delete [session-name] +``` + +The CLI will: +- Delete the session directory and all files +- Remove from index +- Clear active session if needed + +--- + +## Step 7: Display Result + +Parse the JSON response from the delete command. + +### If successful: + +**For regular session:** +``` +โœ… Session '[session-name]' has been deleted. + +๐Ÿ“Š Deleted: +- [count] snapshots +- [count] files tracked + +๐Ÿ’ก View remaining sessions: /session:list +``` + +**For active session:** +``` +โœ… Session '[session-name]' has been deleted. + +๐Ÿ“Š Deleted: +- [count] snapshots +- [count] files tracked + +โš ๏ธ No active session. Start a new one: + /session:start [name] + +๐Ÿ’ก View remaining sessions: /session:list +``` + +### If error occurred: + +``` +โŒ Error deleting session: [error message] + +Try rebuilding the index: + node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js update-index --full-rebuild +``` + +--- + +## Error Handling + +- **Session not found:** Show available sessions list +- **Permission error:** Show clear error message about file permissions +- **Active session:** Show extra warning and confirmation +- **CLI error:** Show error and suggest index rebuild + +--- + +## Performance + +- **Single confirmation:** < 300 tokens +- **CLI deletion:** < 50ms for small sessions, < 500ms for large sessions +- **Total time:** 1-2 seconds including user confirmation + +--- + +## Safety Features + +1. โœ… **Always requires confirmation** - No accidental deletions +2. โœ… **Shows what will be deleted** - User knows the impact +3. โœ… **Extra warning for active session** - Prevents losing current work +4. โœ… **Clear feedback** - User knows what happened +5. โœ… **Graceful error handling** - Helpful messages on failure diff --git a/commands/git-decompress.md b/commands/git-decompress.md new file mode 100644 index 0000000..f5e5ab9 --- /dev/null +++ b/commands/git-decompress.md @@ -0,0 +1,124 @@ +You are managing a session memory system. The user wants to decompress git history for human inspection. + +## Task: Decompress Git History + +Parse the session name from the command arguments. The command format is: `/session:git-decompress [name]` + +### Step 1: Validate and Read Compressed File + +1. Extract session name from arguments +2. Check if `.claude/sessions/{name}/git-history.json` exists +3. If not exists, show: + ``` + โŒ Error: No git history found for session '{name}' + ๐Ÿ’ก Git history is captured automatically at session start/continue + ๐Ÿ’ก Or run: /session:capture-git {name} + ``` + Then STOP. +4. Read `.claude/sessions/{name}/git-history.json` +5. Parse JSON into object + +### Step 2: Expand into Human-Readable Format + +Display the expanded markdown format: + +```markdown +# Git History: {s} +**Captured**: {t} +**Branch**: {b} +**HEAD**: {h} + +## Summary +- **Commits analyzed**: {sm.n} +- **Date range**: {sm.r} +- **Days span**: {sm.d} +- **Total files modified**: {sm.f} +- **Total changes**: {sm.ch} + +## Uncommitted Changes + +### Tracking Status +- **Ahead of upstream**: {uc.ah} commits +- **Behind upstream**: {uc.bh} commits + +### Staged for Commit ({uc.stg.length} files) +{for each file in uc.stg:} +- `{file[0]}`: {file[1]} + +### Modified (Unstaged) ({uc.mod.length} files) +{for each file in uc.mod:} +- `{file[0]}`: {file[1]} + +### New Files (Untracked) ({uc.new.length} files) +{for each file in uc.new:} +- `{file}` + +### Deleted Files ({uc.del.length} files) +{for each file in uc.del:} +- `{file}` + +### Conflicted Files ({uc.con.length} files) +{for each file in uc.con:} +- `{file}` + +**Total uncommitted changes**: {uc.tot} + +## Recent Commits + +{for each commit in c:} +### {commit[0]} - {commit[1]} +**Message**: {commit[2]} +**Changes**: {commit[3]} +**Files modified** ({commit[4]}): +{for each file in commit[5]:} +- `{file}` + +--- + +## Development Hotspots + +Shows directories with most commit activity: + +{for each hotspot in hot:} +- **{hotspot[0]}**: {hotspot[1]} commits + +--- + +**Note**: This is a decompressed view of the compressed JSON format used for token efficiency. The compressed format saves ~70-75% tokens compared to markdown while preserving all information. +``` + +### Step 3: Display Statistics + +After showing the decompressed data, display: + +``` +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” +๐Ÿ“Š Decompression Statistics + +Compressed size: {fileSize} bytes ({fileSizeKB} KB) +Estimated markdown size: ~{estimatedMarkdownSize} bytes (~{estimatedMarkdownKB} KB) +Compression efficiency: ~{compressionPercent}% smaller + +Token efficiency: Compressed JSON uses ~70-75% fewer tokens than markdown +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” +``` + +--- + +## Usage Notes + +- This command is primarily for debugging and human inspection +- Claude can read the compressed format directly (it's more efficient) +- Use this when you need to: + - Verify git history capture is working correctly + - Inspect what commits are included + - Debug git context issues + - Share git history in readable format + +--- + +## Error Handling + +- If git-history.json doesn't exist: Show helpful error with instructions +- If JSON is malformed: Show parsing error and suggest recapture +- If file is empty: Suggest running capture-git again diff --git a/commands/list.md b/commands/list.md new file mode 100644 index 0000000..cae9052 --- /dev/null +++ b/commands/list.md @@ -0,0 +1,231 @@ +You are managing a session memory system. The user wants to see all available sessions. + +## Task: List All Sessions (Enhanced with Interactive Selection) + +Display all sessions with enhanced metadata in a clean, organized format. Optionally enable interactive selection mode. + +**OPTIMIZATION:** This command uses the lightweight CLI tool for instant metadata retrieval (< 10ms, < 200 tokens). + +--- + +## Step 1: Detect Mode + +Check if user provided arguments: +- If user provided a **number** (e.g., `/session:list 2`) โ†’ Jump to **Step 5: Handle Selection** +- If user typed `/session:list` with no args โ†’ Continue to Step 2 (display mode) + +--- + +## Step 2: Get Session List from CLI + +Run the CLI command to get all session metadata: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js list +``` + +This returns JSON with all session data from the index (no file reading needed). + +--- + +## Step 3: Handle Empty Sessions + +If the JSON shows `totalSessions: 0`, display: +``` +No sessions found. + +๐Ÿ’ก Create your first session with: + /session:list [name] + +Example: + /session:start my-feature +``` +Then STOP. + +--- + +## Step 4: Format and Display Sessions (Enhanced) + +Parse the JSON response and format with **enhanced visual design**: + +### Calculate Stats: +- Count active vs closed sessions +- Calculate relative times (use helper function below) +- Determine activity status for badges + +### Display Format: + +``` +Available Sessions ({activeCount} active, {closedCount} closed): +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” + +{for each session in sessions array:} + +{number}. {name} {badges} + ๐Ÿ“… {relativeTime} (started {relativeStartTime}) ๐Ÿ“ธ {snapshotCount} snapshots ๐Ÿ“ {filesInvolvedCount} files + ๐ŸŽฏ {goal} + {if latestSnapshotSummary exists: show "๐Ÿ’ฌ Last: \"{latestSnapshotSummary}\""} + +{Add TWO blank lines between sessions for clear visual separation} + +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” +๐Ÿ’ก Select a session: /session:list [number] +๐Ÿ’ก Create new: /session:start [name] +``` + +### Badges Logic: +- If `session.name === activeSession`: Show `[ACTIVE] ๐Ÿ”ฅ` +- If `status === "closed"`: Show `โœ… CLOSED` +- If last update > 7 days and not closed: Show `๐ŸงŠ COLD` +- If last update < 1 hour: Show `๐Ÿ”ฅ HOT` + +### Relative Time Helper: + +Calculate relative time for display: +- < 1 minute: "just now" +- < 60 minutes: "{n}m ago" +- < 24 hours: "{n}h ago" +- < 7 days: "{n}d ago" +- < 30 days: "{n}w ago" +- >= 30 days: "{n} months ago" + +### Example Output: + +``` +Available Sessions (2 active, 1 closed): +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” + +1. feature-auth-system [ACTIVE] ๐Ÿ”ฅ HOT + ๐Ÿ“… 2h ago (started 3d ago) ๐Ÿ“ธ 5 snapshots ๐Ÿ“ 12 files + ๐ŸŽฏ Implement OAuth2 authentication system + ๐Ÿ’ฌ Last: "Completed login flow, testing redirect logic" + + +2. bugfix-login-issue โœ… CLOSED + ๐Ÿ“… 1d ago (started 2d ago) ๐Ÿ“ธ 3 snapshots ๐Ÿ“ 4 files + ๐ŸŽฏ Fix session timeout bug in login flow + + +3. refactor-api-layer ๐ŸงŠ COLD + ๐Ÿ“… 14d ago (started 15d ago) ๐Ÿ“ธ 8 snapshots ๐Ÿ“ 23 files + ๐ŸŽฏ Refactor REST API to GraphQL architecture + +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” +๐Ÿ’ก Select a session: /session:list [number] +๐Ÿ’ก Create new: /session:start [name] +``` + +After displaying, **STOP and wait for user input**. Do not prompt further. + +--- + +## Step 5: Handle Selection (Interactive Mode) + +If user provided a number (e.g., `/session:list 2`), this is interactive selection mode. + +### 5.1: Validate Selection + +1. Get session list again (same CLI command) +2. Check if number is valid (1 to totalSessions) +3. If invalid, show error and STOP: + ``` + โŒ Invalid selection. Please choose 1-{totalSessions}. + ``` + +### 5.2: Show Session Details + +Display the selected session with full details: + +``` +Selected Session: {name} +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” + +๐Ÿ“‹ Status: {status} {badges} +๐Ÿ“… Started: {started} +๐Ÿ“… Last Update: {lastUpdated} +๐Ÿ“ธ Snapshots: {snapshotCount} +๐Ÿ“ Files Involved: {filesInvolvedCount} + +๐ŸŽฏ Goal: +{goal} + +{if latestSnapshotSummary:} +๐Ÿ’ฌ Latest Snapshot: +{latestSnapshotSummary} + +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” +``` + +### 5.3: Use AskUserQuestion Tool + +Present action options using the AskUserQuestion tool: + +```json +{ + "questions": [ + { + "question": "What would you like to do with this session?", + "header": "Action", + "multiSelect": false, + "options": [ + { + "label": "Continue/Resume", + "description": "Load session context and continue working" + }, + { + "label": "View Status", + "description": "Show detailed session statistics and state" + }, + { + "label": "Save Snapshot", + "description": "Capture current conversation as a snapshot" + }, + { + "label": "Close Session", + "description": "Finalize and close this session" + }, + { + "label": "Delete Session", + "description": "Permanently delete this session and all its data" + }, + { + "label": "Back to List", + "description": "Return to session list" + } + ] + } + ] +} +``` + +### 5.4: Execute Selected Action + +Based on user's choice, execute the appropriate command: + +- **Continue/Resume** โ†’ Run: `/session:continue {sessionName}` +- **View Status** โ†’ Run: `/session:status` (after activating if needed) +- **Save Snapshot** โ†’ Run: `/session:save` +- **Close Session** โ†’ Run: `/session:close` +- **Delete Session** โ†’ Run: `/session:delete {sessionName}` +- **Back to List** โ†’ Run: `/session:list` (restart from Step 2) + +**Important:** Actually execute the command, don't just tell the user to run it. + +--- + +## Error Handling + +If CLI command fails, show: +``` +โŒ Error reading sessions. Try rebuilding the index: + node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js update-index --full-rebuild +``` + +--- + +## Performance Benefits + +- **Display Mode:** < 200 tokens, < 50ms +- **Selection Mode:** ~300-500 tokens total +- **No file reads** for list display (index only) +- **95-98% token reduction** vs old approach diff --git a/commands/plan-execute.md b/commands/plan-execute.md new file mode 100644 index 0000000..ce4f073 --- /dev/null +++ b/commands/plan-execute.md @@ -0,0 +1,195 @@ +You are executing the /session:plan-execute command to start executing a plan. + +**NOTE:** Plans are now global and independent of sessions. + +**CRITICAL - Command Format:** +All session plugin commands use the `/session:` prefix. DO NOT suggest commands without this prefix. +- โœ… Correct: `/session:plan-execute`, `/session:plan-status`, `/session:plan-finalize`, `/session:plan-list` +- โŒ Wrong: `/plan-execute`, `/plan-status`, `/plan-show`, `/plan-list` +Use ONLY the exact command formats specified in this template. + +## Arguments + +Parsed from user input: +- `plan_name`: {name} (required) + +ARGUMENTS: {name} + +## Workflow + +### Step 1: Validate Plan Exists + +Plans are stored globally in `.claude/plans/`. Check if the plan exists: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js plan-exists {plan_name} +``` + +If the plan doesn't exist, show error and STOP: +``` +โŒ Error: Plan '{plan_name}' not found + +Use /session:save-plan {name} to create a plan first. +Use /session:plan-list to see available plans. +``` + +### Step 2: Validate Plan Format + +Before executing, verify the plan is in implementation format (not conceptual): + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js get-plan-format {plan_name} +``` + +This returns JSON with `format: "conceptual"` or `format: "implementation"`. + +If the format is "conceptual", show this error and STOP: +``` +โŒ Error: Cannot execute conceptual plan + +Plan '{plan_name}' is still in conceptual format (requirements only). + +You must finalize the plan first to transform requirements into executable tasks: + + /session:plan-finalize {plan_name} + +This will use AI to break down requirements into concrete implementation tasks +organized by phases (Database, API, UI, Testing, etc.) + +After finalization, you can execute the plan. +``` + +If the format is "implementation", continue to next step. + +### Step 4: Load Plan Status + +Get the current plan status to show what will be executed: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js plan-status {session_name} {plan_name} +``` + +This returns JSON with plan metadata, progress, and current phase. + +### Step 5: Show Execution Overview + +Display a summary of what will be executed: + +``` +๐Ÿ“‹ Plan: {plan_name} +Goal: {goal} + +Progress: {completed_tasks}/{total_tasks} tasks ({percentage}%) +Status: {status} + +Phases: + 1. [โœ“] Phase 1: {name} (completed) + 2. [โ†’] Phase 2: {name} (in progress - will continue here) + 3. [ ] Phase 3: {name} (pending) + 4. [ ] Phase 4: {name} (pending) + +Current Phase: {current_phase_name} +Next Task: {next_task_description} + +Ready to execute this plan? +``` + +### Step 6: Execution Strategy + +**IMPORTANT**: Plan execution is currently **manual** with task tracking: + +1. Show the user the next task to work on +2. The user implements the task manually +3. After completing a task, update its status: + ```bash + node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js update-task-status {session_name} {plan_name} {task_id} completed + ``` +4. Show progress after each task completion +5. Repeat until all tasks are completed + +### Step 7: Display Current Task + +Show the next task that needs to be completed: + +``` +๐ŸŽฏ Next Task: {task_id} + +Phase: {phase_name} +Task: {task_description} + +Details: +{task_details} + +Technical Notes: +- {note_1} +- {note_2} + +Dependencies: {dependencies} (all completed โœ“) + +--- + +To mark this task as complete when done: +/update-task-status {task_id} completed + +To see overall progress: +/session:plan-status {plan_name} + +To continue to next task: +Just complete the current task and I'll show you the next one. +``` + +### Step 8: Task Completion Loop + +After the user completes work: + +1. Ask: "Have you completed task {task_id}?" +2. If yes, update task status: + ```bash + node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js update-task-status {session_name} {plan_name} {task_id} completed + ``` +3. Show updated progress +4. Load next task +5. If more tasks exist, show next task (Step 6) +6. If all tasks complete, show completion message (Step 8) + +### Step 9: Completion Message + +When all tasks are completed: + +``` +๐ŸŽ‰ Plan Complete: {plan_name} + +All tasks completed successfully! + +Summary: +- Total Tasks: {total_tasks} +- Completed: {total_tasks} (100%) +- Phases: {total_phases} +- Time Tracked: {duration} + +Next Steps: +1. Review all changes +2. Run tests if applicable +3. Create a pull request +4. Deploy to production + +Use /session:save to capture this milestone! +``` + +--- + +## Notes + +- The execution is **manual** - Claude doesn't automatically execute code +- Users implement tasks themselves, Claude tracks progress +- This provides visibility and structure without automation +- Future: Automated task execution with agent orchestration + +--- + +## Error Handling + +At each step, handle errors gracefully: +- Plan not found: Show clear message with available plans +- Invalid task ID: Show valid task IDs for current phase +- Session errors: Guide user to start/continue session diff --git a/commands/plan-finalize.md b/commands/plan-finalize.md new file mode 100644 index 0000000..66202d1 --- /dev/null +++ b/commands/plan-finalize.md @@ -0,0 +1,403 @@ +You are executing the /session:plan-finalize command to transform requirements into executable tasks. + +**NOTE:** Plans are now global and independent of sessions. + +**CRITICAL - Command Format:** +All session plugin commands use the `/session:` prefix. DO NOT suggest commands without this prefix. +- โœ… Correct: `/session:plan-execute`, `/session:plan-status`, `/session:plan-finalize` +- โŒ Wrong: `/plan-execute`, `/plan-status`, `/plan-show` +Use ONLY the exact command formats specified in this template. + +## Arguments + +Parsed from user input: +- `plan_name`: {name} (required) + +ARGUMENTS: {name} + +## Purpose + +This is the TRANSFORMATION step that bridges conceptual planning and execution: + +**Before (Conceptual - requirements.json):** +``` +Requirements (WHAT): +- "Restrict products based on user permissions" +- "Track who created each product" +``` + +**After (Implementation - orchestration.json + phases/):** +``` +Phase 1: Database Layer + โœ“ task-1-1: Add restriction_level column to public.new_product table + โœ“ task-1-2: Create migration script for ALTER TABLE + โœ“ task-1-3: Add created_by column with foreign key to users + +Phase 2: API Layer + โœ“ task-2-1: Add validation in POST /api/products endpoint + โœ“ task-2-2: Add validation in PUT /api/products/:id endpoint + โœ“ task-2-3: Return 403 error for restricted products + +Phase 3: UI Layer + โœ“ task-3-1: Add restriction checkbox in product form + โœ“ task-3-2: Show error message when restriction fails +``` + +**This step uses AI to break down requirements into concrete, actionable tasks.** + +## Workflow + +### Step 1: Load Plan and Validate Format + +Plans are global and stored in `.claude/plans/`. Check what format the plan is in: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js get-plan-format {plan_name} +``` + +This returns `format: "conceptual"` or `format: "implementation"`. + +**If format is "implementation":** +``` +โœ“ Plan '{plan_name}' is already finalized + +This plan has already been transformed into executable tasks. + +Use /session:plan-execute {plan_name} to start implementation. +``` +Then STOP. + +**If format is "conceptual":** Continue to next step. + +### Step 2: Load Requirements + +Load the requirements.json file from the global plans directory: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js load-requirements {plan_name} +``` + +This returns the requirements data: +```json +{ + "goal": "...", + "requirements": [ + { "id": "req-1", "description": "...", "priority": "high" }, + { "id": "req-2", "description": "...", "priority": "medium" } + ], + "metadata": { "work_type": "feature" } +} +``` + +### Step 4: Show Requirements Summary + +Display what will be transformed: + +``` +๐Ÿ“‹ Plan: {plan_name} + +Goal: {goal} +Format: Conceptual (requirements) + +Requirements to Transform: + 1. req-1: {description} [{priority}] + 2. req-2: {description} [{priority}] + ... ({total} requirements) + +Work Type: {work_type} + +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” + +๐Ÿ’ก Finalization Process: + +I will use AI to break down each requirement into concrete implementation tasks, +organized by phases (Database, API, UI, Testing, etc.) + +This transformation will: + โ€ข Convert high-level requirements into actionable tasks + โ€ข Organize tasks by implementation layer + โ€ข Add implementation details (SQL, API endpoints, UI components) + โ€ข Track which requirement led to which tasks + โ€ข Create execution-ready plan structure + +Ready to proceed? (yes/no) +``` + +### Step 5: Get User Confirmation + +Use the AskUserQuestion tool to confirm. + +If user says no/cancel, show: +``` +Plan finalization cancelled. The plan remains in conceptual format. +``` +Then STOP. + +If yes, continue. + +### Step 6: AI-Powered Task Breakdown + +Show progress indicator: +``` +๐Ÿค– AI Analysis in Progress... + +This will take 30-60 seconds. +``` + +Invoke the Task tool with: +- subagent_type: "general-purpose" +- model: "sonnet" (use sonnet for better quality breakdown) +- prompt: Read the file at `${CLAUDE_PLUGIN_ROOT}/prompts/breakdown-requirement.md`, replace `[REQUIREMENTS JSON INSERTED HERE]` with the actual requirements JSON, then execute those instructions + +The subagent will analyze requirements and return structured breakdown: +```json +{ + "implementation_goal": "...", + "phases": [ + { + "name": "Database Layer", + "description": "...", + "tasks": [ + { + "description": "Add restriction_level column to products", + "details": "ALTER TABLE products ADD COLUMN...", + "from_requirement": "req-1" + } + ] + } + ], + "traceability": { + "req-1": ["task-1-1", "task-2-1", "task-3-1"], + "req-2": ["task-1-2", "task-2-2"] + }, + "assumptions": [...], + "risks": [...] +} +``` + +### Step 7: Show Transformation Preview + +Display the AI-generated breakdown for user review: + +``` +โœ“ AI Analysis Complete + +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” +๐Ÿ“‹ Transformation Preview +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” + +Implementation Goal: +{implementation_goal} + +Phase 1: {phase_1_name} + โ€ข task-1-1: {description} + โ€ข task-1-2: {description} + โ€ข task-1-3: {description} + [{task_count} tasks] + +Phase 2: {phase_2_name} + โ€ข task-2-1: {description} + โ€ข task-2-2: {description} + [{task_count} tasks] + +Phase 3: {phase_3_name} + โ€ข task-3-1: {description} + [{task_count} tasks] + +[Show all phases] + +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” +Summary: +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” + +โ€ข Requirements: {requirement_count} +โ€ข Phases: {phase_count} +โ€ข Tasks: {task_count} +โ€ข Traceability: Complete (all tasks mapped to requirements) + +Assumptions: + - {assumption_1} + - {assumption_2} + +Risks: + - {risk_1} + - {risk_2} + +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” + +Does this breakdown look good? (yes/edit/cancel) +``` + +### Step 8: Handle User Response + +**If "yes":** Continue to Step 9 + +**If "edit":** +``` +What would you like to modify? + +You can: + a) Adjust task descriptions + b) Add/remove tasks + c) Change phase organization + d) Add more details to specific tasks + e) Re-run AI analysis with different focus + +Your choice: +``` + +Based on user input, make modifications and show preview again (repeat Step 7). + +**If "cancel":** +``` +Finalization cancelled. Plan remains in conceptual format. +``` +STOP. + +### Step 9: Transform and Save + +Show progress: +``` +๐Ÿ’พ Transforming plan... + +Creating implementation structure... +``` + +Call the transformation function: +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js transform-plan {plan_name} '{breakdown_json}' +``` + +This will: +1. Create orchestration.json with metadata and phase registry +2. Create phases/*.json files with tasks +3. Create execution-state.json for progress tracking +4. Keep requirements.json for traceability +5. Mark plan as "implementation" type + +### Step 10: Success Message + +``` +โœ“ Plan Finalized: {plan_name} + +Requirements successfully transformed into executable implementation plan! + +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” +Transformation Summary: +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” + +Input: + โ€ข Format: Conceptual (requirements) + โ€ข Requirements: {requirement_count} + +Output: + โ€ข Format: Implementation (orchestration + phases) + โ€ข Phases: {phase_count} + โ€ข Tasks: {task_count} + โ€ข Structure: Optimized for parallel execution + +Files Created: + โ€ข orchestration.json (coordinator) + โ€ข phases/phase-1-{name}.json + โ€ข phases/phase-2-{name}.json + โ€ข phases/phase-3-{name}.json + โ€ข execution-state.json (progress tracking) + +Preserved: + โ€ข requirements.json (for traceability) + +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” +Next Steps: +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” + +1. Review the finalized plan: + /session:plan-status {plan_name} + +2. Start execution: + /session:plan-execute {plan_name} + +3. Track progress as you implement each task + +๐ŸŽฏ Ready for implementation! +``` + +--- + +## Transformation Details + +### File Structure + +**Before (Conceptual):** +``` +plans/{plan_name}/ +โ”œโ”€โ”€ requirements.json (only file) +โ””โ”€โ”€ conversation-context.md (reference) +``` + +**After (Implementation):** +``` +plans/{plan_name}/ +โ”œโ”€โ”€ requirements.json (preserved for traceability) +โ”œโ”€โ”€ orchestration.json (coordinator + metadata) +โ”œโ”€โ”€ phases/ +โ”‚ โ”œโ”€โ”€ phase-1-database.json +โ”‚ โ”œโ”€โ”€ phase-2-api.json +โ”‚ โ””โ”€โ”€ phase-3-ui.json +โ”œโ”€โ”€ execution-state.json (runtime progress) +โ””โ”€โ”€ conversation-context.md (reference) +``` + +### Traceability + +Every task in the implementation plan has a `from_requirement` field: +```json +{ + "task_id": "task-1-1", + "description": "Add restriction_level column", + "from_requirement": "req-1" +} +``` + +This allows you to trace back from implementation tasks to original requirements. + +### Why AI-Powered? + +Breaking down requirements into tasks requires: +- Understanding of technical architecture (DB โ†’ API โ†’ UI) +- Knowledge of implementation patterns +- Ability to infer specific tasks from general requirements +- Context about dependencies and ordering + +AI excels at this transformation, turning: +- "Restrict products" โ†’ 10+ specific tasks across layers +- "Track creators" โ†’ Database schema, API logic, UI display + +### Quality Assurance + +The AI breakdown is trained to: +- Create concrete, actionable tasks (not vague) +- Provide implementation details (SQL, file paths, logic) +- Organize by architectural layers +- Specify dependencies correctly +- Estimate token usage realistically + +--- + +## Error Handling + +- **Plan not found**: Show available plans +- **Already finalized**: Show success, suggest execution +- **Invalid session**: Guide to start/continue +- **AI breakdown fails**: Offer retry or manual task creation +- **User cancels**: Keep conceptual format, can retry later + +--- + +## Notes + +- Finalization is REQUIRED to execute a plan +- AI breakdown takes 30-60 seconds (uses Sonnet for quality) +- User can review and modify before saving +- Original requirements.json is preserved for traceability +- Transformation is reversible (can re-finalize if needed) +- This is where requirements (WHAT) become tasks (HOW) diff --git a/commands/plan-list.md b/commands/plan-list.md new file mode 100644 index 0000000..0f844b4 --- /dev/null +++ b/commands/plan-list.md @@ -0,0 +1,148 @@ +You are executing the /session:plan-list command to list all global plans. + +**NOTE:** Plans are now global and stored in `.claude/plans/`. This command works without requiring an active session. + +**CRITICAL - Command Format:** +All session plugin commands use the `/session:` prefix. DO NOT suggest commands without this prefix. +- โœ… Correct: `/session:plan-execute`, `/session:plan-status`, `/session:plan-finalize`, `/session:plan-list` +- โŒ Wrong: `/plan-execute`, `/plan-status`, `/plan-show`, `/plan-list` +Use ONLY the exact command formats specified in this template. + +## Arguments + +No arguments required. + +ARGUMENTS: + +## Workflow + +### Step 1: List All Global Plans + +Get the list of all plans from the global plans directory: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js plan-list +``` + +This returns JSON: +```json +{ + "success": true, + "data": { + "plans": ["plan-1", "plan-2", "plan-3"], + "count": 3 + }, + "message": "Found 3 plan(s)" +} +``` + +### Step 2: Get Details for Each Plan + +For each plan in the list, get its format and basic metadata: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js get-plan-format {plan_name} +``` + +This tells you if it's "conceptual" (requirements only) or "implementation" (executable tasks). + +Optionally, for implementation plans, get status: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js plan-status {plan_name} +``` + +### Step 3: Display Plan List + +Show a formatted list of all plans: + +``` +๐Ÿ“‹ Global Plans ({count} total) + +Conceptual Plans (Requirements Only): + 1. api-redesign + โ”œโ”€ Goal: Redesign API for better performance + โ”œโ”€ Requirements: 12 + โ”œโ”€ Created: 3 days ago + โ””โ”€ Next: Use /session:plan-finalize api-redesign to create executable tasks + + 2. user-permissions + โ”œโ”€ Goal: Implement role-based permissions system + โ”œโ”€ Requirements: 8 + โ”œโ”€ Created: 1 week ago + โ””โ”€ Next: Use /session:plan-finalize user-permissions to create executable tasks + +Implementation Plans (Executable): + 3. oauth-implementation (feature) + โ”œโ”€ Progress: 15/22 tasks (68%) + โ”œโ”€ Status: in-progress + โ”œโ”€ Current: Phase 2 - OAuth Flow Implementation + โ””โ”€ Last Updated: 2 hours ago + + 4. database-migration (refactor) + โ”œโ”€ Progress: 8/8 tasks (100%) + โ”œโ”€ Status: completed + โ””โ”€ Completed: 1 day ago + +Helpful Commands: + /session:plan-status {name} - Show detailed plan status + /session:plan-execute {name} - Start/continue plan execution + /session:plan-finalize {name} - Transform conceptual plan to executable + /session:save-plan {name} - Create a new plan +``` + +### Step 4: Handle Empty Case + +If no plans exist, show: + +``` +๐Ÿ“‹ No plans found + +You haven't created any plans yet. + +Get started: + 1. Have a conversation about what you want to build + 2. Run /session:save-plan {name} to capture requirements + 3. Run /session:plan-finalize {name} to create executable tasks + 4. Run /session:plan-execute {name} to start implementation + +๐Ÿ’ก Plans are global and accessible from any session. +``` + +--- + +## Display Formatting + +### Plan Type Indicators +- ๐Ÿ“ Conceptual (requirements captured, not yet broken down into tasks) +- โš™๏ธ Implementation (executable tasks, ready to execute) + +### Status Icons +- โœ“ Completed +- โ†’ In Progress +- โ—‹ Pending +- โŠ˜ Blocked + +### Progress Bars +For implementation plans with progress: +``` +Progress: [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘] 68% (15/22 tasks) +``` + +--- + +## Error Handling + +- No plans directory: Show empty state message +- Corrupted plan files: Skip and show warning for specific plan +- CLI command failures: Show error message with suggestion to run /session:rebuild-index + +--- + +## Notes + +- This command does NOT require an active session +- Plans are stored globally in `.claude/plans/` +- Both conceptual and implementation plans are shown +- The list is sorted by last updated (most recent first) +- Use /session:plan-status {name} for detailed information about a specific plan diff --git a/commands/plan-save.md b/commands/plan-save.md new file mode 100644 index 0000000..ce77bfe --- /dev/null +++ b/commands/plan-save.md @@ -0,0 +1,285 @@ +You are executing the /session:save-plan command to create a conceptual plan from the current conversation. + +**CRITICAL - Command Format:** +All session plugin commands use the `/session:` prefix. DO NOT suggest commands without this prefix. +- โœ… Correct: `/session:plan-execute`, `/session:plan-status`, `/session:plan-finalize`, `/session:plan-list`, `/session:save-plan` +- โŒ Wrong: `/plan-execute`, `/plan-status`, `/plan-show`, `/plan-list`, `/save-plan` +Use ONLY the exact command formats specified in this template. + +## Arguments + +Parsed from user input: +- `plan_name`: {name} (required) + +ARGUMENTS: {name} + +## Workflow + +### Step 1: Check for Active Session (Optional) + +Plans are now global and don't require a session. However, if there's an active session, we can extract requirements from the conversation. + +Check for active session: + +```bash +[ -f .claude/sessions/.active-session ] && cat .claude/sessions/.active-session || echo "none" +``` + +- If result is "none": Skip Steps 2-3, create an empty plan with placeholder requirements (go to Step 4) +- If there's an active session: Continue to Step 2 to extract from conversation + +### Step 2: Read Conversation Log (If Session Active) + +**Only execute this step if there's an active session.** + +Load the conversation log for the active session. The conversation log file is at: +`.claude/sessions/{session_name}/conversation-log.jsonl` + +**Chunked Reading Strategy:** +1. Check if file exists +2. Count lines: `wc -l .claude/sessions/{session_name}/conversation-log.jsonl` +3. If <= 2000 lines: Read entire file +4. If > 2000 lines: Read in chunks of 2000 using Read tool's offset/limit parameters +5. Concatenate all chunks into full conversation log + +If the file doesn't exist or is empty: +- Show warning: "โš ๏ธ No conversation log found. Creating empty plan template." +- Continue to Step 4 with empty requirements + +### Step 3: Detect Work Type (Optional - If Session Active) + +Detect the work type from the conversation for metadata purposes: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js detect-work-type {session_name} +``` + +This returns a JSON object with: +```json +{ + "type": "feature|bug|spike|refactor|unknown", + "confidence": 87, + "scores": {...}, + "signals": {...} +} +``` + +Show the detection result: +``` +๐Ÿ” Analyzing conversation... +โœ“ Detected work type: {TYPE} ({confidence}% confidence) +``` + +This is for metadata only - conceptual plans don't use templates. + +### Step 4: Extract Requirements from Conversation + +Use a subagent to analyze the conversation and extract requirements (not tasks!). + +Invoke the Task tool with: +- subagent_type: "general-purpose" +- model: "haiku" +- prompt: Read the file at `${CLAUDE_PLUGIN_ROOT}/prompts/analyze-conversation.md`, replace placeholders with actual values, then execute those instructions + +The subagent will return extracted requirements: +```json +{ + "goal": "High-level objective", + "requirements": [ + { + "id": "req-1", + "description": "What the user wants (high-level)", + "notes": "Additional context", + "open_questions": ["Question 1", "Question 2"], + "priority": "high|medium|low", + "conversation_context": "Relevant conversation excerpts" + } + ], + "discussion_notes": "Free-form notes from planning discussion", + "conversation_summary": "Summary of conversation" +} +``` + +**IMPORTANT:** Extract REQUIREMENTS (what user wants), NOT tasks (how to implement). +- โœ“ Good requirement: "Restrict products based on user permissions" +- โœ— Bad (too detailed): "Add restriction_level column to public.new_product table" + +Requirements are exploratory and high-level during planning. + +### Step 4: Build Requirements Plan + +Create the requirements.json structure: + +```json +{ + "plan_name": "{plan_name}", + "plan_type": "conceptual", + "goal": "{extracted_goal_or_placeholder}", + "requirements": [...extracted_requirements_or_empty], + "discussion_notes": "{discussion_notes_or_empty}", + "conversation_summary": "{conversation_summary_or_empty}", + "created_at": "{ISO_8601_timestamp}", + "metadata": { + "work_type": "{detected_work_type_or_unknown}", + "estimated_complexity": "simple|moderate|complex", + "source_session": "{session_name_if_available_else_null}" + } +} +``` + +**Note:** The `session_name` field is no longer required. Plans are global and can be created with or without session context. + +### Step 6: Show Requirements Preview + +Display a preview of the requirements to the user: + +``` +๐Ÿ“‹ Requirements Preview: {plan_name} + +Goal: {goal} +Work Type: {type} ({confidence}% confidence) + +Requirements Captured: + 1. {req-1-description} + Notes: {req-1-notes} + Open Questions: {req-1-questions} + + 2. {req-2-description} + Notes: {req-2-notes} + + [Show first 3-4 requirements, summarize rest if more] + +๐Ÿ’ก This is a conceptual plan. Use /session:plan-finalize to transform requirements into executable tasks. + +Options: + 1. โœ“ Save this plan (recommended) + 2. Cancel +``` + +### Step 7: Get User Choice + +Use the AskUserQuestion tool to get the user's choice. + +Handle the response: +- **Option 1 (Save)**: Continue to Step 8 +- **Option 2 (Cancel)**: Show "Plan creation cancelled" and STOP + +### Step 8: Validate Requirements + +Validate the requirements against requirements-schema.json: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js validate-requirements '{requirements_json}' +``` + +If validation fails, show the errors and STOP: +``` +โŒ Validation errors found: + 1. {error_1} + 2. {error_2} + +Cannot save invalid plan. Please review. +``` + +If validation succeeds, continue. + +### Step 9: Save Requirements File + +Create the requirements.json file using the global plans directory: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js save-requirements {plan_name} '{requirements_json}' +``` + +This creates: +- `.claude/plans/{plan_name}/requirements.json` + +Also create a conversation context markdown file for reference (if conversation was analyzed): +- Path: `.claude/plans/{plan_name}/conversation-context.md` +- Content: Include conversation summary, key decisions, requirements discussion, etc. +- If no session context, skip this file or create with placeholder noting manual plan creation + +### Step 10: Display Success + +Show success message with next steps: + +``` +โœ“ Global plan saved: {plan_name} + +๐Ÿ“‹ Plan Details: + โ€ข Type: Conceptual (requirements captured) + โ€ข Work type: {type} (detected with {confidence}% confidence) + โ€ข Requirements: {requirement_count} + โ€ข Location: .claude/plans/{plan_name}/requirements.json + โ€ข Scope: Global (accessible from any session) + +๐Ÿ“ Next Steps: + + 1. Review requirements: + /session:plan-status {plan_name} + + 2. List all plans: + /session:plan-list + + 3. Transform into executable plan: + /session:plan-finalize {plan_name} + + This will use AI to break down requirements into concrete tasks + organized by implementation phases (Database, API, UI, etc.) + + 4. After finalization, execute: + /session:plan-execute {plan_name} + +๐Ÿ’ก Plans are now global and accessible from any session. No need to be in a specific session to work with plans. +``` + +--- + +## Error Handling + +At each step, handle errors gracefully: + +- **File not found**: Show clear message with suggestion on how to proceed +- **Validation failed**: Show specific validation errors +- **Detection low confidence**: Accept it (work type is just metadata) +- **Parse errors**: Show error details and abort +- **CLI command failures**: Check exit codes and show appropriate error messages + +Always provide actionable next steps when errors occur. + +--- + +## Key Principles + +**Planning Phase = Requirements Capture** + +- Users discuss WHAT they want (requirements), not HOW to implement (tasks) +- Keep it lightweight and exploratory +- Allow for open questions and uncertainty +- No forced structure - just capture what was discussed + +**Examples of Good Requirements:** +- "Restrict products based on user permissions" +- "Track who created each product" +- "Add audit logging for product changes" +- "Improve product search performance" + +**Examples of Bad (Too Detailed for Planning):** +- "Add restriction_level column to public.new_product table" โ† This is a task! +- "Create POST /api/products validation" โ† This is a task! +- "Add checkbox in product form component" โ† This is a task! + +The transformation from requirements โ†’ tasks happens in /session:plan-finalize. + +--- + +## Notes + +- The ${CLAUDE_PLUGIN_ROOT} environment variable should point to the session plugin source directory +- Plans are now global - stored in `.claude/plans/` regardless of active session +- The {session_name} variable is optional - used only if there's an active session for conversation context +- All CLI commands should use absolute paths +- Error messages should be user-friendly and actionable +- The workflow is designed to be interruptible - user can cancel at any point +- Conceptual plans use requirements.json format (not orchestration.json) +- Plans can be created with or without session context (conversation analysis is optional) diff --git a/commands/plan-status.md b/commands/plan-status.md new file mode 100644 index 0000000..6080eda --- /dev/null +++ b/commands/plan-status.md @@ -0,0 +1,174 @@ +You are executing the /session:plan-status command to show plan execution status. + +**NOTE:** Plans are now global and independent of sessions. + +**CRITICAL - Command Format:** +All session plugin commands use the `/session:` prefix. DO NOT suggest commands without this prefix. +- โœ… Correct: `/session:plan-execute`, `/session:plan-status`, `/session:plan-finalize`, `/session:plan-list` +- โŒ Wrong: `/plan-execute`, `/plan-status`, `/plan-show`, `/plan-list` +Use ONLY the exact command formats specified in this template. + +## Arguments + +Parsed from user input: +- `plan_name`: {name} (optional - if not provided, show status for all plans) + +ARGUMENTS: {name} + +## Workflow + +### Step 1: Get Plan Status + +Plans are stored globally in `.claude/plans/` and can be accessed without an active session. + +If plan_name is provided, get status for that specific plan: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js plan-status {plan_name} +``` + +If no plan_name, list all global plans first: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js plan-list +``` + +Then get status for each plan. + +### Step 2: Display Status + +**For a specific plan:** + +``` +๐Ÿ“‹ Plan Status: {plan_name} + +Goal: {goal} +Work Type: {work_type} +Scope: Global (accessible from any session) +Created: {created_date} +Last Updated: {updated_date} + +Overall Progress: {completed_tasks}/{total_tasks} tasks ({percentage}%) +โ”œโ”€ Completed: {completed} +โ”œโ”€ In progress: {in_progress} +โ”œโ”€ Pending: {pending} +โ””โ”€ Blocked: {blocked} + +Phase Progress: {completed_phases}/{total_phases} + +Phases: + 1. [โœ“] {phase_1_name} (completed) + โ”œโ”€ Tasks: 5/5 (100%) + โ””โ”€ Duration: {duration} + + 2. [โ†’] {phase_2_name} (in-progress) + โ”œโ”€ Tasks: 2/7 (29%) + โ”œโ”€ Current Task: {current_task_id} - {description} + โ””โ”€ Status: {task_status} + + 3. [ ] {phase_3_name} (pending) + โ”œโ”€ Tasks: 0/6 (0%) + โ””โ”€ Depends on: Phase 2 + + 4. [ ] {phase_4_name} (pending) + โ”œโ”€ Tasks: 0/4 (0%) + โ””โ”€ Depends on: Phase 2, Phase 3 + +Current Task: {current_task_id} + Description: {description} + Details: {details} + Status: {status} + Phase: {phase_name} + +Next Steps: + /session:plan-execute {plan_name} - Continue execution + /update-task-status {task_id} completed - Mark current task complete +``` + +**For all plans:** + +``` +๐Ÿ“‹ All Global Plans + +1. oauth-implementation (feature) + โ”œโ”€ Progress: 15/22 tasks (68%) + โ”œโ”€ Status: in-progress + โ”œโ”€ Current: Phase 2 - OAuth Flow Implementation + โ””โ”€ Last Updated: 2 hours ago + +2. database-migration (refactor) + โ”œโ”€ Progress: 8/8 tasks (100%) + โ”œโ”€ Status: completed + โ””โ”€ Completed: 1 day ago + +3. api-redesign (spike) + โ”œโ”€ Progress: 0/12 tasks (0%) + โ”œโ”€ Status: pending + โ””โ”€ Created: 3 days ago + +Use /session:plan-status {plan_name} for detailed status. +Use /session:plan-execute {plan_name} to start/continue execution. +Use /session:plan-list to see all available plans. +``` + +### Step 3: Show Recommendations + +Based on plan status, show context-aware recommendations: + +**If plan is in-progress:** +``` +๐Ÿ’ก Recommendations: +- Current task is {status} - {recommendation} +- {next_task_count} tasks remaining in current phase +- Estimated completion: {estimate} +``` + +**If plan is blocked:** +``` +โš ๏ธ Blocked: +- Task {task_id} is blocked +- Blocker: {blocker_reason} +- Action needed: {action} +``` + +**If plan is completed:** +``` +โœ… Plan Complete: +- All {total_tasks} tasks completed +- Duration: {total_duration} +- Consider: Code review, testing, deployment +``` + +--- + +## Display Formats + +### Progress Bar +``` +Progress: [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘] 68% (15/22 tasks) +``` + +### Status Icons +- [โœ“] Completed +- [โ†’] In Progress +- [ ] Pending +- [โœ—] Failed +- [โŠ˜] Blocked +- [~] Skipped + +### Phase Status +``` +Phase 2: OAuth Flow Implementation (in-progress) + โ”œโ”€ task-2-1: Create OAuth callback routes [โœ“] + โ”œโ”€ task-2-2: Implement JWT generation [โ†’] + โ”œโ”€ task-2-3: Add session middleware [ ] + โ””โ”€ task-2-4: Configure passport.js [ ] +``` + +--- + +## Error Handling + +- Plan not found: Show available plans using /session:plan-list +- Corrupted plan data: Show error with recovery steps +- No plans exist: Show message about creating first plan with /session:save-plan {name} diff --git a/commands/plan-update.md b/commands/plan-update.md new file mode 100644 index 0000000..58f3785 --- /dev/null +++ b/commands/plan-update.md @@ -0,0 +1,344 @@ +You are executing the /session:plan-update command to modify an existing plan. + +**NOTE:** Plans are now global and independent of sessions. + +**CRITICAL - Command Format:** +All session plugin commands use the `/session:` prefix. DO NOT suggest commands without this prefix. +- โœ… Correct: `/session:plan-execute`, `/session:plan-status`, `/session:plan-finalize`, `/session:plan-list`, `/session:plan-update` +- โŒ Wrong: `/plan-execute`, `/plan-status`, `/plan-show`, `/plan-list`, `/plan-update` +Use ONLY the exact command formats specified in this template. + +## Arguments + +Parsed from user input: +- `plan_name`: {name} (required - the plan to update) +- `update_request`: {request} (optional - natural language description of changes) + +ARGUMENTS: {name} {request} + +## Workflow + +### Step 1: Validate Plan Exists + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js plan-exists {plan_name} +``` + +If the plan doesn't exist, show error and STOP: +``` +โŒ Error: Plan '{plan_name}' not found + +Use /session:plan-list to see available plans. +Use /session:plan-save {name} to create a new plan. +``` + +### Step 2: Load Current Plan State + +Get the current plan state for preview generation: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js plan-status {plan_name} +``` + +This returns JSON with plan metadata, phases, tasks, and execution state. + +### Step 3: Parse Update Request + +If `update_request` is provided, parse it into structured operations. + +**Common Update Patterns:** + +| Natural Language | Operation | +|-----------------|-----------| +| "add a new task to phase X" | `{ type: 'add', target: 'task', data: {...} }` | +| "remove task-2-3" | `{ type: 'delete', target: 'task', data: { id: 'task-2-3' } }` | +| "rename phase 1 to 'Setup'" | `{ type: 'update', target: 'phase', data: { id: 'phase-1', name: 'Setup' } }` | +| "mark task-1-1 as completed" | `{ type: 'update', target: 'task', data: { id: 'task-1-1', status: 'completed' } }` | +| "add a new phase called Testing" | `{ type: 'add', target: 'phase', data: { name: 'Testing' } }` | + +If no `update_request` is provided, prompt the user: +``` +What changes would you like to make to plan '{plan_name}'? + +Examples: + - "add a new task 'Write unit tests' to phase 2" + - "remove the documentation phase" + - "rename task-3-1 to 'API integration'" + - "mark phase 1 as completed" + +Enter your update request: +``` + +### Step 4: Check Execution State + +Determine if the plan is being executed: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js get-execution-state {plan_name} +``` + +**If plan has started execution:** + +Show mode selection: +``` +โš ๏ธ Plan '{plan_name}' is currently being executed. + +Progress: {completed}/{total} tasks ({percentage}%) +Completed phases: {completed_phases} +Current phase: {current_phase} + +How would you like to proceed? + +1. [selective] Apply changes to pending tasks only (recommended) + - Completed work is preserved + - Only pending tasks/phases can be modified + - May need --force for some operations + +2. [rollback] Reset and replan (full update) + - All progress will be reset to pending + - Execution history is preserved in logs + - Start fresh with updated plan + +3. [cancel] Cancel update + +Choice [1/2/3]: +``` + +### Step 5: Generate Preview + +Show what changes will be made: + +``` +โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•— +โ•‘ Plan Update Preview โ•‘ +โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• + +Plan: {plan_name} +Mode: {selective|rollback} + +โ”€โ”€โ”€ Summary โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + Operations: {count} + + Additions: {add_count} + ~ Updates: {update_count} + - Deletions: {delete_count} + +โ”€โ”€โ”€ Operations โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + [1] ADD task: "Write unit tests" + Phase: phase-2-implementation + Description: Create comprehensive test suite + + ~ [2] UPDATE task: task-3-1 + description: "API endpoints" โ†’ "API integration" + + - [3] DELETE phase: phase-4-documentation + โš  Contains 3 tasks that will also be deleted + +โ”€โ”€โ”€ Warnings โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + โš  Deleting phase with completed tasks - use --force + โš  Some operations affect completed work + +โ”€โ”€โ”€ Safety Notices โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + โš  DESTRUCTIVE: This update includes 1 deletion(s) +``` + +### Step 6: Confirm with User + +``` +Apply these changes? [+1 ~1 -1] + [y] Yes, apply changes + [n] No, cancel + [e] Edit operations + [?] Show help + +Choice: +``` + +**If user chooses 'e' (edit):** +``` +--- Edit Mode --- +Operations: + [1] ADD task: "Write unit tests" + [2] UPDATE task: task-3-1 + [3] DELETE phase: phase-4-documentation + +Commands: + remove - Remove operation #n + done - Finish editing and confirm + cancel - Cancel all changes + +Edit> +``` + +### Step 7: Execute Update + +Based on mode selection: + +**For selective mode:** +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js plan-update-selective {plan_name} --operations '{operations_json}' +``` + +**For rollback mode:** +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js plan-update-rollback {plan_name} --operations '{operations_json}' +``` + +### Step 8: Report Results + +**Success:** +``` +โœ… Plan Updated Successfully + +Plan: {plan_name} +Mode: {mode} + +Changes Applied: + + Added 1 task + ~ Updated 1 task + - Deleted 1 phase (3 tasks removed) + +Updated Progress: {new_completed}/{new_total} tasks + +Next Steps: + /session:plan-status {plan_name} - View updated plan + /session:plan-execute {plan_name} - Continue execution +``` + +**Partial Success (selective mode):** +``` +โš ๏ธ Plan Partially Updated + +Applied: 2 operations +Skipped: 1 operation (affects completed work) + +Skipped Operations: + - DELETE phase: phase-1-setup (completed, requires --force) + +To apply skipped operations, use: + /session:plan-update {plan_name} --force +``` + +**Failure:** +``` +โŒ Update Failed + +Error: {error_message} + +Details: + - Operation 3 failed: {reason} + - Validation error: {details} + +Recovery: + - Backup created at: .claude/plans/{plan_name}/.backups/backup-{timestamp} + - To restore: /session:plan-restore {plan_name} {backup_name} +``` + +--- + +## Quick Update Examples + +### Add a Task +``` +/session:plan-update my-plan add a new task "Implement caching" to phase-2 +``` + +### Remove a Task +``` +/session:plan-update my-plan remove task-3-2 +``` + +### Rename a Phase +``` +/session:plan-update my-plan rename phase-1 to "Infrastructure Setup" +``` + +### Mark Task Complete +``` +/session:plan-update my-plan mark task-2-1 as completed +``` + +### Add a New Phase +``` +/session:plan-update my-plan add a new phase called "Performance Testing" after phase-3 +``` + +### Force Update (completed items) +``` +/session:plan-update my-plan remove task-1-1 --force +``` + +--- + +## Command Options + +| Option | Description | +|--------|-------------| +| `--force` | Allow modifications to completed items | +| `--yes` | Skip confirmation prompt | +| `--dry-run` | Preview changes without applying | +| `--mode selective` | Only update pending items (default for executing plans) | +| `--mode rollback` | Reset progress and apply all changes | +| `--json` | Output results as JSON | + +--- + +## Error Handling + +### Plan Not Found +``` +โŒ Error: Plan 'unknown-plan' not found + +Available plans: + - my-feature (in-progress, 45%) + - refactor-api (pending, 0%) + +Use /session:plan-list for full details. +``` + +### Invalid Operation +``` +โŒ Error: Could not parse update request + +Input: "do something to the plan" + +Could not determine: + - Operation type (add, remove, update?) + - Target (phase, task?) + +Try being more specific: + - "add a task called 'X' to phase Y" + - "remove task-1-2" + - "rename phase-1 to 'New Name'" +``` + +### Blocked by Execution State +``` +โŒ Error: Cannot modify in-progress task + +Task 'task-2-3' is currently in progress. +Wait for completion or use rollback mode. + +Options: + 1. Wait for task to complete + 2. Use /session:plan-update {plan} --mode rollback +``` + +### Validation Error +``` +โŒ Error: Invalid operation + +Cannot add task with duplicate ID 'task-1-1' +A task with this ID already exists in phase-1. + +Suggestion: Let the system generate a unique ID automatically. +``` + +--- + +## Related Commands + +- `/session:plan-status {name}` - View current plan status +- `/session:plan-execute {name}` - Execute plan tasks +- `/session:plan-list` - List all plans +- `/session:plan-save {name}` - Create new plan +- `/session:plan-finalize {name}` - Finalize conceptual plan diff --git a/commands/project-maps-generate.md b/commands/project-maps-generate.md new file mode 100644 index 0000000..f2fd46c --- /dev/null +++ b/commands/project-maps-generate.md @@ -0,0 +1,212 @@ +# Project Maps Generate Command + +Generate project context maps for the current project. + +## Usage + +``` +/project-maps-generate [--path ] +``` + +## Options + +- `--path `: Project path to scan (defaults to current directory) +- No options: Generate maps for current working directory + +## Implementation + +### Step 1: Determine Project Path + +Parse command arguments to determine project path: + +```javascript +const args = process.argv.slice(2); +const pathIndex = args.indexOf('--path'); +const projectPath = pathIndex >= 0 && args[pathIndex + 1] + ? args[pathIndex + 1] + : process.cwd(); +``` + +Default to current working directory if no path specified. + +### Step 2: Check if Maps Already Exist + +Check if maps have already been generated for this project: + +```bash +cd {working_directory} +node ${CLAUDE_PLUGIN_ROOT}/cli/lib/map-loader.js {project_path} --staleness-only 2>&1 +``` + +If maps exist (exit code 0), ask user if they want to regenerate: + +``` +โš ๏ธ Maps already exist for this project + +Existing maps: + Location: {maps_dir} + Last generated: {timestamp} + Staleness: {score}/100 + +Regenerate maps? This will overwrite existing maps. + โ€ข Yes, regenerate (will take ~10-30 seconds) + โ€ข No, use refresh instead (faster, preserves existing data) +``` + +If user chooses "No", suggest using refresh instead: +``` +Tip: Use /project-maps-refresh for faster updates +``` + +### Step 3: Initialize and Scan Project + +Show progress and start generation: + +``` +Generating project context maps... + +Project: {project_path} +Project hash: {hash} +``` + +Run the map generator: + +```bash +cd {working_directory} +node ${CLAUDE_PLUGIN_ROOT}/cli/lib/map-generator.js {project_path} +``` + +The map generator will: +1. Initialize configuration +2. Scan file system +3. Generate 11 map files (Phases 1-3) +4. Apply compression +5. Save to `~/.claude/project-maps/{project-hash}/` + +### Step 4: Show Progress + +The map generator outputs progress: + +``` +Scanning project... +Scanned 145 files in 127ms + +Generating maps... + โœ“ summary.json (2.1 KB โ†’ 907 B, 56% compression) + โœ“ tree.json (3.2 KB โ†’ 1.4 KB, 56% compression) + โœ“ metadata.json (12.5 KB โ†’ 5.2 KB, 58% compression) + โœ“ content-summaries.json (1.1 KB โ†’ 465 B, 58% compression) + โœ“ indices.json (11.8 KB โ†’ 5.0 KB, 58% compression) + โœ“ existence-proofs.json (4.0 KB โ†’ 1.7 KB, 58% compression) + โœ“ quick-queries.json (6.4 KB โ†’ 2.7 KB, 58% compression) + โœ“ dependencies-forward.json (1.1 KB โ†’ 477 B, 57% compression) + โœ“ dependencies-reverse.json (1.1 KB โ†’ 445 B, 60% compression) + โœ“ relationships.json (1.5 KB โ†’ 630 B, 58% compression) + โœ“ issues.json (1.3 KB โ†’ 557 B, 57% compression) +``` + +### Step 5: Display Summary + +After generation completes, show summary: + +``` +โœ“ Maps generated successfully! + +Summary: + Files scanned: {file_count} + Maps created: 11 + Storage location: {maps_dir} + + Total size: + โ€ข Original: {original_size} KB + โ€ข Compressed: {compressed_size} KB + โ€ข Compression: {compression_ratio}% + + Maps by tier: + โ€ข Tier 1 (Always loaded): summary.json, quick-queries.json + โ€ข Tier 2 (On demand): tree.json, existence-proofs.json + โ€ข Tier 3 (When needed): metadata.json, content-summaries.json, indices.json + โ€ข Tier 4 (Deep analysis): dependencies-*.json, relationships.json, issues.json + +Next steps: + โ€ข Load maps: /project-maps-load + โ€ข Quick queries: /project-maps-query + โ€ข Refresh maps: /project-maps-refresh +``` + +### Step 6: Verify Generation + +Verify all expected files were created: + +```bash +ls -lh ~/.claude/project-maps/{project_hash}/*.json | wc -l +``` + +Expected: 11 files + +If count != 11, show warning: +``` +โš ๏ธ Warning: Expected 11 map files but found {actual_count} +Some maps may have failed to generate. +``` + +## Error Handling + +**Project path doesn't exist:** +``` +โŒ Error: Project path not found + +Path: {project_path} +Please check the path and try again. +``` + +**Permission denied:** +``` +โŒ Error: Permission denied + +Cannot write to: ~/.claude/project-maps/ +Check directory permissions. +``` + +**Generation failed:** +``` +โŒ Map generation failed: {error_message} + +Possible causes: + 1. Insufficient disk space + 2. Invalid project structure + 3. File access permissions + +Try: + โ€ข Check disk space + โ€ข Verify project directory is accessible + โ€ข Run with --verbose for more details +``` + +**No files found:** +``` +โš ๏ธ No files found in project + +The project appears to be empty or all files are excluded. +Check your .gitignore or .projectmaprc configuration. +``` + +## Performance Notes + +- Small projects (<100 files): ~5-10 seconds +- Medium projects (100-1000 files): ~10-30 seconds +- Large projects (1000+ files): ~30-60 seconds +- Generation happens once, subsequent updates use incremental refresh (much faster) + +## Examples + +```bash +# Generate maps for current directory +/project-maps-generate + +# Generate maps for specific project +/project-maps-generate --path /path/to/project + +# Generate with verbose output +/project-maps-generate --verbose +``` diff --git a/commands/project-maps-list.md b/commands/project-maps-list.md new file mode 100644 index 0000000..5579fc9 --- /dev/null +++ b/commands/project-maps-list.md @@ -0,0 +1,120 @@ +# Project Maps List Command + +List all projects with generated context maps. + +## Usage + +``` +/project-maps-list +``` + +## Implementation + +### Step 1: Scan Maps Directory + +List all subdirectories in the maps storage: + +```bash +ls -d ~/.claude/project-maps/*/ 2>/dev/null +``` + +Each subdirectory represents a project hash. + +### Step 2: Load Summary for Each Project + +For each project hash, load the summary.json to get project details: + +```javascript +const fs = require('fs').promises; +const path = require('path'); +const MapLoader = require('./map-loader'); + +const mapsBaseDir = path.join(process.env.HOME, '.claude/project-maps'); +const projectDirs = await fs.readdir(mapsBaseDir); + +for (const hash of projectDirs) { + if (hash === 'maps' || hash === 'schemas' || hash === 'temp') continue; + + try { + const summaryPath = path.join(mapsBaseDir, hash, 'summary.json'); + const summary = await loadSummary(summaryPath); + // Display project info + } catch (error) { + // Skip invalid projects + } +} +``` + +### Step 3: Display Projects List + +Show all projects with their metadata: + +``` +Project Maps + +Found {count} projects with generated maps: + +1. {project_name} + Path: {project_path} + Hash: {project_hash} + Files: {file_count} + Generated: {timestamp} + Staleness: {score}/100 ({level}) + Size: {total_size} + +2. {project_name} + Path: {project_path} + Hash: {project_hash} + Files: {file_count} + Generated: {timestamp} + Staleness: {score}/100 ({level}) + Size: {total_size} + +Total storage: {total_storage_size} + +Commands: + โ€ข Load project: /project-maps-load + โ€ข Refresh: /project-maps-refresh + โ€ข Generate new: /project-maps-generate +``` + +### Step 4: Highlight Stale Projects + +Mark projects that need refresh: + +``` +โš ๏ธ The following projects may need refresh: + โ€ข {project_name} - Staleness: {score}/100 + โ€ข {project_name} - Staleness: {score}/100 + +Run: /project-maps-refresh to update +``` + +## Error Handling + +**No maps found:** +``` +No project maps found + +Storage location: ~/.claude/project-maps/ + +Generate maps for current project: + /project-maps-generate +``` + +**Corrupt project data:** +``` +โš ๏ธ Found {count} projects, but {error_count} have corrupt data: + โ€ข {hash} - Cannot read summary + โ€ข {hash} - Missing metadata + +Consider removing corrupt entries: + rm -rf ~/.claude/project-maps/{hash} +``` + +## Examples + +```bash +# List all projects with maps +/project-maps-list +``` diff --git a/commands/project-maps-load.md b/commands/project-maps-load.md new file mode 100644 index 0000000..5f38b20 --- /dev/null +++ b/commands/project-maps-load.md @@ -0,0 +1,301 @@ +# Project Maps Load Command + +Load and display project context maps with tiered loading. + +## Usage + +``` +/project-maps-load [--tier <1|2|3|4>] [--map ] +``` + +## Options + +- `--tier `: Load all maps from specific tier (1, 2, 3, or 4) +- `--map `: Load specific map by name +- No options: Load Tier 1 (summary + quick-queries) + +## Tier Levels + +**Tier 1** (Always loaded, ~3KB): +- `summary.json` - Project overview and statistics +- `quick-queries.json` - Pre-computed answers to common questions + +**Tier 2** (On demand, ~10KB): +- `tree.json` - Directory structure +- `existence-proofs.json` - File manifests and negative space + +**Tier 3** (When needed, ~60KB): +- `metadata.json` - Comprehensive file metadata +- `content-summaries.json` - Exports, imports, entities +- `indices.json` - Navigation indices by type/role/size/recency + +**Tier 4** (Deep analysis, ~10KB): +- `dependencies-forward.json` - Import graphs +- `dependencies-reverse.json` - Who imports what +- `relationships.json` - Dependency chains +- `issues.json` - Broken imports, circular deps, unused files + +## Implementation + +### Step 1: Check if Maps Exist + +First, verify maps exist for current project: + +```bash +cd {working_directory} +node ${CLAUDE_PLUGIN_ROOT}/cli/lib/map-loader.js . --staleness-only +``` + +If no maps exist (exit code 1), show error: +``` +โŒ No project maps found + +Generate maps first: + /project-maps-generate +``` + +### Step 2: Parse Arguments and Determine Load Mode + +Parse command arguments: + +```javascript +const args = process.argv.slice(2); +let loadMode = 'tier'; +let tierLevel = 1; +let mapName = null; + +if (args.includes('--tier')) { + const tierIndex = args.indexOf('--tier'); + tierLevel = parseInt(args[tierIndex + 1]) || 1; + loadMode = 'tier'; +} + +if (args.includes('--map')) { + const mapIndex = args.indexOf('--map'); + mapName = args[mapIndex + 1]; + loadMode = 'single'; +} +``` + +### Step 3: Load Maps + +**For Tier Loading:** + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/lib/map-loader.js . --tier {tier_level} +``` + +**For Single Map Loading:** + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/lib/map-loader.js . {map_name} +``` + +The loader will: +1. Decompress maps automatically +2. Check staleness and show warnings +3. Return the map data + +### Step 4: Display Results + +**Tier 1 Display (Summary):** + +``` +โœ“ Tier 1 maps loaded + +Project Overview: + Name: {project_name} + Path: {project_path} + Files: {total_files} + Size: {total_size} + Primary languages: {languages} + +Framework: {framework_name} ({framework_type}) + +Quick Answers: + โ€ข Entry points: {entry_points} + โ€ข Test location: {test_location} + โ€ข Largest files: {largest_files} + โ€ข Recently modified: {recent_files} + +Staleness: {staleness_score}/100 ({staleness_level}) + +Next steps: + โ€ข Load more detail: /project-maps-load --tier 2 + โ€ข Query specific info: /project-maps-query + โ€ข Refresh maps: /project-maps-refresh +``` + +**Tier 2 Display (Structure):** + +``` +โœ“ Tier 2 maps loaded + +Directory Structure: +{tree_visualization} + +Top-level directories: + โ€ข src/ ({file_count} files) + โ€ข tests/ ({file_count} files) + โ€ข config/ ({file_count} files) + +File Existence: + โœ“ package.json + โœ“ tsconfig.json + โœ“ .gitignore + โœ— jest.config.js (missing) + โœ— .env.example (missing) +``` + +**Tier 3 Display (Detailed Metadata):** + +``` +โœ“ Tier 3 maps loaded + +Detailed File Metadata: {total_files} files + +By Type: + โ€ข TypeScript: {ts_count} files ({ts_size}) + โ€ข JavaScript: {js_count} files ({js_size}) + โ€ข JSON: {json_count} files ({json_size}) + +By Role: + โ€ข Source: {source_count} files + โ€ข Tests: {test_count} files + โ€ข Config: {config_count} files + +Content Summaries: + Top exports: + โ€ข {file}: {exports} + โ€ข {file}: {exports} + +Indices loaded: + โ€ข By type: {type_count} types + โ€ข By role: {role_count} roles + โ€ข By size: {size_buckets} buckets + โ€ข By recency: Last {recent_days} days +``` + +**Tier 4 Display (Dependencies):** + +``` +โœ“ Tier 4 maps loaded + +Dependency Analysis: + +Forward Dependencies: + โ€ข {file} imports from {import_count} sources + โ€ข {file} imports from {import_count} sources + +Reverse Dependencies (Most imported): + 1. {file} - imported by {count} files + 2. {file} - imported by {count} files + 3. {file} - imported by {count} files + +Issues Detected: + โš ๏ธ Circular dependencies: {circular_count} + โš ๏ธ Broken imports: {broken_count} + โš ๏ธ Unused files: {unused_count} + +Relationship Metrics: + โ€ข Max dependency depth: {max_depth} + โ€ข Average dependencies per file: {avg_deps} + โ€ข Tightly coupled modules: {coupled_count} +``` + +**Single Map Display:** + +Show the specific map data in formatted JSON: + +``` +โœ“ Map loaded: {map_name} + +{formatted_json_output} + +Staleness: {score}/100 +Size: {compressed_size} compressed ({original_size} original, {ratio}% compression) +``` + +### Step 5: Staleness Warning + +If staleness score >= 30, show warning (automatically done by loader): + +``` +โš ๏ธ Maps may be outdated + Staleness: {score}/100 - {recommendation} + Consider running: /project-maps-refresh --incremental +``` + +## Error Handling + +**Maps not found:** +``` +โŒ No project maps found + +Generate maps first: + /project-maps-generate +``` + +**Invalid tier:** +``` +โŒ Invalid tier level: {tier} + +Valid tiers: 1, 2, 3, or 4 +``` + +**Map not found:** +``` +โŒ Map not found: {map_name} + +Available maps: + โ€ข summary + โ€ข tree + โ€ข metadata + โ€ข content-summaries + โ€ข indices + โ€ข existence-proofs + โ€ข quick-queries + โ€ข dependencies-forward + โ€ข dependencies-reverse + โ€ข relationships + โ€ข issues +``` + +**Load failed:** +``` +โŒ Failed to load maps: {error_message} + +Try: + 1. Regenerate maps: /project-maps-generate + 2. Check file permissions + 3. Verify maps directory exists +``` + +## Performance Notes + +- Tier 1: Instant load (~3KB) +- Tier 2: Very fast (~10KB) +- Tier 3: Fast (~60KB) +- Tier 4: Fast (~10KB) +- Single map: Depends on map size +- All decompression happens automatically + +## Examples + +```bash +# Load Tier 1 (default) +/project-maps-load + +# Load Tier 2 (directory structure) +/project-maps-load --tier 2 + +# Load Tier 3 (detailed metadata) +/project-maps-load --tier 3 + +# Load Tier 4 (dependencies) +/project-maps-load --tier 4 + +# Load specific map +/project-maps-load --map summary +/project-maps-load --map dependencies-forward +``` diff --git a/commands/project-maps-query.md b/commands/project-maps-query.md new file mode 100644 index 0000000..549020c --- /dev/null +++ b/commands/project-maps-query.md @@ -0,0 +1,297 @@ +# Project Maps Query Command + +Query pre-computed answers from project context maps. + +## Usage + +``` +/project-maps-query +``` + +## Query Types + +- `entry-points` - What are the entry points? +- `framework` - Which framework is used? +- `tests` - Where are the tests? +- `largest` - What are the largest files? +- `recent` - What changed recently? +- `structure` - What's the project structure? +- `languages` - What languages are used? +- `all` - Show all available queries + +## Implementation + +### Step 1: Check if Maps Exist + +Verify maps exist for current project: + +```bash +cd {working_directory} +node ${CLAUDE_PLUGIN_ROOT}/cli/lib/map-loader.js . --staleness-only +``` + +If no maps exist, show error and stop. + +### Step 2: Parse Query Type + +Extract query type from arguments: + +```javascript +const args = process.argv.slice(2); +const queryType = args[0] || 'all'; +``` + +### Step 3: Load Quick Queries Map + +Load the pre-computed quick-queries map: + +```javascript +const MapLoader = require('./map-loader'); +const loader = new MapLoader(process.cwd()); +const quickQueries = await loader.load('quick-queries'); +``` + +### Step 4: Execute Query and Display Results + +Based on query type, extract and display the relevant information: + +**Entry Points Query:** + +``` +Query: What are the entry points? + +Entry Points: + 1. src/index.ts - Main application entry + 2. src/server.ts - Server entry + 3. src/cli.ts - CLI entry + +Description: + These files serve as the main entry points to the application. + They are typically referenced in package.json or imported first. + +Related files: + โ€ข package.json: "main": "src/index.ts" + โ€ข package.json: "bin": "src/cli.ts" +``` + +**Framework Query:** + +``` +Query: Which framework is used? + +Framework: React +Type: Frontend (Single Page Application) +Version: Detected from package.json + +Key indicators: + โ€ข package.json dependencies: react, react-dom + โ€ข File patterns: *.jsx, *.tsx files in src/ + โ€ข Common React patterns detected + +Related: + โ€ข Build tool: Vite + โ€ข Testing: Jest + React Testing Library + โ€ข State management: Redux +``` + +**Tests Query:** + +``` +Query: Where are the tests? + +Test Files: {test_count} files + +Locations: + โ€ข tests/ - {count} files + โ€ข src/**/*.test.ts - {count} files + โ€ข src/**/*.spec.ts - {count} files + +Test Frameworks: + โ€ข Jest - Main test runner + โ€ข React Testing Library - Component tests + +Coverage: + โ€ข Source files: {source_count} + โ€ข Test files: {test_count} + โ€ข Coverage ratio: {ratio}% +``` + +**Largest Files Query:** + +``` +Query: What are the largest files? + +Largest Files (by size): + 1. dist/bundle.js - 2.4 MB (generated) + 2. src/components/Dashboard.tsx - 842 KB + 3. src/utils/helpers.ts - 567 KB + 4. node_modules/.bin/webpack - 234 KB (dependency) + 5. src/data/constants.json - 189 KB + +Recommendations: + โš ๏ธ Dashboard.tsx is unusually large (842 KB) + Consider splitting into smaller components + + โš ๏ธ helpers.ts contains many utilities (567 KB) + Consider organizing into separate modules +``` + +**Recent Changes Query:** + +``` +Query: What changed recently? + +Recently Modified Files (last 7 days): + 1. src/components/Login.tsx - 2 hours ago + 2. src/api/auth.ts - 5 hours ago + 3. tests/auth.test.ts - 5 hours ago + 4. src/types/user.ts - 1 day ago + 5. README.md - 3 days ago + +Activity Summary: + โ€ข Most active directory: src/components/ ({count} changes) + โ€ข Most active author: {author} ({count} commits) + โ€ข Files modified: {count} +``` + +**Structure Query:** + +``` +Query: What's the project structure? + +Project Structure: + +โ”œโ”€โ”€ src/ ({file_count} files) +โ”‚ โ”œโ”€โ”€ components/ ({file_count} files) +โ”‚ โ”œโ”€โ”€ utils/ ({file_count} files) +โ”‚ โ”œโ”€โ”€ api/ ({file_count} files) +โ”‚ โ””โ”€โ”€ types/ ({file_count} files) +โ”œโ”€โ”€ tests/ ({file_count} files) +โ”œโ”€โ”€ config/ ({file_count} files) +โ””โ”€โ”€ dist/ ({file_count} files) + +Conventions: + โ€ข Source code: src/ + โ€ข Tests: tests/ and *.test.ts + โ€ข Configuration: config/ + โ€ข Build output: dist/ +``` + +**Languages Query:** + +``` +Query: What languages are used? + +Primary Languages: + 1. TypeScript - {count} files ({percentage}%) + 2. JavaScript - {count} files ({percentage}%) + 3. JSON - {count} files ({percentage}%) + 4. Markdown - {count} files ({percentage}%) + +Language Distribution: + [โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–‘โ–‘โ–‘โ–‘] TypeScript (75%) + [โ–“โ–“โ–“โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘] JavaScript (15%) + [โ–“โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘] JSON (5%) + [โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘] Other (5%) +``` + +**All Queries:** + +``` +Available Queries: + +1. entry-points - What are the entry points? +2. framework - Which framework is used? +3. tests - Where are the tests? +4. largest - What are the largest files? +5. recent - What changed recently? +6. structure - What's the project structure? +7. languages - What languages are used? + +Usage: + /project-maps-query + +Example: + /project-maps-query entry-points + /project-maps-query framework +``` + +### Step 5: Show Staleness If Relevant + +If staleness score >= 30, append warning: + +``` +โš ๏ธ Note: Maps are {staleness_score}/100 stale + Query results may be outdated. Consider refreshing: + /project-maps-refresh +``` + +## Error Handling + +**Maps not found:** +``` +โŒ No project maps found + +Generate maps first: + /project-maps-generate +``` + +**Invalid query type:** +``` +โŒ Unknown query type: {query_type} + +Available query types: + โ€ข entry-points + โ€ข framework + โ€ข tests + โ€ข largest + โ€ข recent + โ€ข structure + โ€ข languages + โ€ข all + +Usage: + /project-maps-query +``` + +**No data available:** +``` +โš ๏ธ No data available for query: {query_type} + +This might happen if: + 1. The project doesn't have this information + 2. Maps need to be regenerated + 3. The data wasn't captured during generation + +Try: + /project-maps-refresh +``` + +## Performance Notes + +- Queries are instant (pre-computed during generation) +- No file system scanning required +- Answers come from quick-queries.json (~3KB) +- Perfect for getting quick insights without deep analysis + +## Examples + +```bash +# What are the entry points? +/project-maps-query entry-points + +# Which framework is used? +/project-maps-query framework + +# Where are the tests? +/project-maps-query tests + +# What are the largest files? +/project-maps-query largest + +# What changed recently? +/project-maps-query recent + +# Show all available queries +/project-maps-query all +``` diff --git a/commands/project-maps-refresh.md b/commands/project-maps-refresh.md new file mode 100644 index 0000000..9d7cdd9 --- /dev/null +++ b/commands/project-maps-refresh.md @@ -0,0 +1,176 @@ +# Project Maps Refresh Command + +Refresh project context maps (full or incremental). + +## Usage + +``` +/project-maps-refresh [--full|--incremental] +``` + +## Options + +- `--full`: Perform full rescan and regenerate all maps (slower, complete) +- `--incremental`: Only update changed files (faster, recommended for small changes) +- No option: Auto-detect based on changes (incremental if <30% files changed, otherwise full) + +## Implementation + +### Step 1: Check if Maps Exist + +First, check if maps have been generated for this project: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/lib/map-loader.js . --staleness-only +``` + +If no maps exist (exit code 1), show error and suggest running generation first: +``` +โŒ No project maps found + +Generate maps first: + /project-maps-generate + +Or manually: + node session/cli/lib/map-generator.js generate +``` + +### Step 2: Determine Refresh Mode + +Parse command arguments to determine refresh mode: +- If user specified `--full`: Use full refresh +- If user specified `--incremental`: Use incremental refresh +- If no option: Auto-detect + +For auto-detect: +1. Load summary map to get project hash and last refresh info +2. Count changed files using git diff +3. If changed files > 30% of total: Recommend full refresh +4. Otherwise: Use incremental refresh + +### Step 3: Perform Refresh + +**For Full Refresh:** + +Run the map generator to regenerate all maps: + +```bash +cd {working_directory} +node ${CLAUDE_PLUGIN_ROOT}/cli/lib/map-generator-cli.js refresh --full --project . +``` + +This will: +- Rescan entire project +- Regenerate all 11 maps +- Update staleness metadata +- Show completion statistics + +**For Incremental Refresh:** + +Run the incremental updater: + +```bash +cd {working_directory} +node ${CLAUDE_PLUGIN_ROOT}/cli/lib/incremental-updater-cli.js --project . --hash {project_hash} +``` + +This will: +- Use git diff to find changed files +- Rescan only changed files +- Update affected map entries +- Regenerate dependency chains +- Much faster than full refresh + +### Step 4: Show Results + +After refresh completes, display results: + +**Full Refresh:** +``` +โœ“ Full refresh completed + +Maps regenerated: + โ€ข summary.json (Level 1) + โ€ข tree.json (Level 2) + โ€ข metadata.json (Level 3) + โ€ข content-summaries.json (Level 3) + โ€ข indices.json (Level 3) + โ€ข existence-proofs.json (Level 2) + โ€ข quick-queries.json (Level 1) + โ€ข dependencies-forward.json (Level 4) + โ€ข dependencies-reverse.json (Level 4) + โ€ข relationships.json (Level 4) + โ€ข issues.json (Level 4) + +Statistics: + Files scanned: {total_files} + Time taken: {time_ms}ms + Maps location: {maps_dir} + +Staleness: 0/100 (fresh) +``` + +**Incremental Refresh:** +``` +โœ“ Incremental refresh completed + +Files updated: + โ€ข Modified: {modified_count} + โ€ข Added: {added_count} + โ€ข Deleted: {deleted_count} + +Maps updated: + โ€ข metadata.json + โ€ข content-summaries.json + โ€ข dependencies-forward.json + โ€ข dependencies-reverse.json + +Statistics: + Files scanned: {scanned_count} + Time taken: {time_ms}ms + Time saved: ~{time_saved_percent}% vs full rescan + +Staleness: 0/100 (fresh) +``` + +### Step 5: Verification + +After refresh, automatically verify staleness: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/lib/staleness-checker.js . {maps_dir}/summary.json +``` + +Expected result: Score should be 0/100 (fresh) + +## Error Handling + +**Git not available:** +``` +โš ๏ธ Warning: Git not available, falling back to full refresh +``` + +**Too many changes for incremental:** +``` +โš ๏ธ Too many files changed ({change_percent}%) + +Incremental refresh may miss dependencies. +Recommend: /project-maps-refresh --full +``` + +**Refresh failed:** +``` +โŒ Refresh failed: {error_message} + +Try: + 1. Check git status + 2. Ensure no file permission issues + 3. Run full refresh: /project-maps-refresh --full +``` + +## Notes + +- Incremental refresh is faster (target: <20% of full scan time) +- Full refresh guarantees consistency +- Refresh automatically updates staleness metadata +- Maps are compressed automatically during refresh diff --git a/commands/project-maps-stats.md b/commands/project-maps-stats.md new file mode 100644 index 0000000..376e9cf --- /dev/null +++ b/commands/project-maps-stats.md @@ -0,0 +1,139 @@ +# Project Maps Stats Command + +Show compression metrics and system statistics for project maps. + +## Usage + +``` +/project-maps-stats +``` + +## Implementation + +### Step 1: Scan All Project Maps + +Scan the maps directory and collect statistics: + +```bash +du -sh ~/.claude/project-maps/ +ls -lR ~/.claude/project-maps/ | wc -l +``` + +### Step 2: Calculate Compression Metrics + +For each project, read compression metadata: + +```javascript +const allStats = { + totalProjects: 0, + totalFiles: 0, + totalMaps: 0, + originalSize: 0, + compressedSize: 0, + totalStorage: 0 +}; + +// Aggregate from all summary.json files +for (const projectHash of projectHashes) { + const summary = await loadSummary(projectHash); + allStats.totalFiles += summary.statistics.totalFiles; + // ... aggregate other stats +} +``` + +### Step 3: Display Statistics + +Show comprehensive system stats: + +``` +Project Maps Statistics + +System Overview: + Projects mapped: {project_count} + Total files scanned: {total_files} + Total maps generated: {total_maps} + Storage location: ~/.claude/project-maps/ + +Storage Metrics: + Total storage used: {total_storage} MB + Original data size: {original_size} MB + Compressed size: {compressed_size} MB + Space saved: {space_saved} MB ({savings_percent}%) + +Compression Efficiency: + Average compression ratio: {avg_ratio}% + Best compression: {best_ratio}% ({project_name}) + Worst compression: {worst_ratio}% ({project_name}) + + Compression breakdown: + โ€ข Level 1 (minification): {level1_ratio}% + โ€ข Level 2 (key abbreviation): {level2_ratio}% + โ€ข Level 3 (deduplication): {level3_ratio}% + +Map Distribution: + โ€ข Per project: 11 maps (fixed) + โ€ข Total maps: {total_maps} + +Performance: + โ€ข Average generation time: {avg_gen_time}ms + โ€ข Average map size: {avg_map_size} KB + โ€ข Staleness distribution: + Fresh (0-30): {fresh_count} projects + Moderate (30-60): {moderate_count} projects + Critical (60+): {critical_count} projects + +Recommendations: + โš ๏ธ {stale_count} projects need refresh + โœ“ Storage efficiency: {efficiency}% + ๐Ÿ’ก Consider cleaning old maps: /project-maps-clean +``` + +### Step 4: Per-Project Breakdown + +Optionally show detailed per-project stats: + +``` +Per-Project Breakdown: + +1. {project_name} + Maps: 11 + Original: {original_size} KB + Compressed: {compressed_size} KB + Ratio: {ratio}% + Staleness: {score}/100 + +2. {project_name} + Maps: 11 + Original: {original_size} KB + Compressed: {compressed_size} KB + Ratio: {ratio}% + Staleness: {score}/100 +``` + +## Error Handling + +**No maps found:** +``` +No project maps found + +Generate maps first: + /project-maps-generate +``` + +**Cannot calculate stats:** +``` +โš ๏ธ Unable to calculate complete statistics + +Some map files may be corrupt or inaccessible. +Try regenerating maps for affected projects. +``` + +## Examples + +```bash +# Show system statistics +/project-maps-stats + +# Show detailed per-project stats +/project-maps-stats --detailed +``` diff --git a/commands/save.md b/commands/save.md new file mode 100644 index 0000000..4253501 --- /dev/null +++ b/commands/save.md @@ -0,0 +1,215 @@ +You are managing a session memory system. The user wants to manually save a snapshot of the current session state. + +**CRITICAL - Command Format:** +All session plugin commands use the `/session:` prefix. DO NOT suggest commands without this prefix. +- โœ… Correct: `/session:list`, `/session:start`, `/session:continue`, `/session:status` +- โŒ Wrong: `/session list`, `/session start`, `/session continue`, `/session status` +Use ONLY the exact command formats specified in this template. + +## Task: Save Session Snapshot + +Capture the current context and save it as a timestamped snapshot. + +**CRITICAL OPTIMIZATION:** This command now uses CLI for snapshot writes, enabling plan mode support. + +### Step 1: Validate Active Session + +1. Check if `.claude/sessions/.active-session` file exists +2. If NOT exists, show error: + ``` + โŒ Error: No active session + ๐Ÿ’ก Use /session:start [name] to create a new session + ๐Ÿ’ก Or use /session:continue [name] to resume an existing session + ``` + Then STOP. +3. Read the active session name from `.active-session` +4. Verify the session directory `.claude/sessions/{active_session}/` exists +5. If NOT exists, show error: + ``` + โŒ Error: Active session directory not found + The session may have been deleted. Please start a new session. + ``` + Then STOP. + +### Step 2: Capture Conversation Context + +Analyze the recent conversation (last 10-20 exchanges) and create a summary: +- What topics were discussed +- What problems were solved +- What decisions were made +- What tasks were attempted or completed + +Keep this summary concise but informative (3-5 sentences). + +### Step 3: Capture Completed Todos + +Look for any todos that were marked as completed in this conversation: +- Check for completed checkboxes in messages +- Check for explicit "completed" or "done" mentions +- List them in checkbox format: `- [x] Task description` + +If no todos were completed, write: `- No todos completed in this segment` + +### Step 4: Capture Files Modified + +Identify all files that were modified in this conversation: +- Files written with Write tool +- Files edited with Edit tool +- Files created or modified + +For each file, capture: +- File path +- Brief description of changes made (1-2 lines) + +Format: +```markdown +### path/to/file.ts +- Added authentication middleware +- Updated error handling +``` + +If no files were modified, write: `No files modified in this segment` + +### Step 5: Capture Current State + +Describe the current state of the work: +- What's working now +- What's in progress +- What's blocked +- What's next + +Format as bullet points (3-5 items). + +### Step 6: Capture Key Code Snippets (Optional) + +If any particularly important code was written or discussed, include a representative snippet: +- Limit to 20-30 lines maximum +- Include language identifier for syntax highlighting +- Add brief explanation + +Only include if genuinely important. Skip if no critical code. + +### Step 7: Generate Snapshot Content + +Create the snapshot content in this structure (but DON'T write it yet): + +```markdown +# Snapshot: {session_name} +**Timestamp**: {full_timestamp_YYYY-MM-DD_HH:MM:SS} +**Format Version**: 2.0 + +## Topics Discussed +1. **[Category]**: {topic_1_brief_description} +2. **[Category]**: {topic_2_brief_description} +{continue_for_all_topics} + +## Suggestions & Recommendations +1. **[Category]**: {suggestion} - {rationale} +{if_any_suggestions_given} + +## Decisions Made +1. **[Decision]**: {rationale} +{if_any_decisions_made} + +## Tasks Completed +1. {completed_task_1} +2. {completed_task_2} +{or_write_"No_tasks_completed"} + +## Files Modified +1. `{file_path}`: {what_changed_and_why} +{or_write_"No_files_modified"} + +## Current Status +- **Progress**: {where_things_stand} +- **Next Steps**: {what_should_be_done_next} +- **Blockers**: {issues_or_"None"} + +## Notes +{any_additional_important_observations} +``` + +### Step 8: Write Snapshot via CLI (CRITICAL - Plan Mode Support) + +**Instead of using the Write tool**, use the CLI with stdin to write the snapshot. +This enables snapshot saves even in plan mode where Write tool is blocked. + +Run this command, piping the snapshot content via stdin: + +```bash +echo "{snapshot_content}" | node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js write-snapshot {session_name} --stdin --type manual +``` + +**IMPORTANT:** Escape any special characters in the content appropriately for the shell. + +Alternative approach if echo has escaping issues: +```bash +cat <<'EOF' | node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js write-snapshot {session_name} --stdin --type manual +{snapshot_content} +EOF +``` + +The CLI will: +- Write the snapshot file with timestamp +- Update the index automatically +- Return success with filename + +### Step 9: Update context.md + +1. Read current `.claude/sessions/{active_session}/context.md` +2. If any key decisions were made in this conversation, add them to "Key Decisions" section: + ```markdown + ### {current_timestamp} + - Decision: {what_was_decided} + - Rationale: {why_this_approach} + - Impact: {what_this_affects} + ``` +3. If any important discoveries were made, add to "Important Discoveries" section +4. If any blockers were encountered or resolved, update "Blockers & Resolutions" section +5. Update the "Summary" section with a running summary including this snapshot +6. Write the updated context.md back (use Edit tool for this - it's allowed in plan mode for session files) + +### Step 10: Update session.md Timestamp + +1. Read `.claude/sessions/{active_session}/session.md` +2. Update the "Last Updated" field to current timestamp +3. If any new files were involved, add them to "Files Involved" section +4. Write back the updated session.md (use Edit tool) + +### Step 11: Display Success Message + +Show confirmation: + +``` +โœ“ Session snapshot saved +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” +๐Ÿ“ .claude/sessions/{session_name}/{timestamp}.md +๐Ÿ“ Captured: + - Conversation summary + - {X} completed todos + - {Y} file changes + - Current state and next steps + {if_decisions: "- {Z} key decisions"} + +๐Ÿ’พ Context updated in context.md +โฐ Session timestamp updated +``` + +--- + +**CRITICAL BENEFITS - PLAN MODE SUPPORT:** +- **Problem:** In plan mode, Write tool is blocked (prevents accidental code changes) +- **Impact:** Snapshots couldn't be saved, causing data loss on `/clear` +- **Solution:** CLI delegation via Bash bypasses Write tool restrictions +- **Result:** Zero data loss in plan mode, seamless user experience + +**PERFORMANCE BENEFITS:** +- **Before:** 15-25K tokens for snapshot analysis and writes +- **After:** 8-15K tokens, CLI handles write operations +- **Improvement:** ~40-50% token reduction, instant index update + +**IMPORTANT NOTES:** +- Use heredoc (cat <<'EOF') for reliable content piping, avoids escaping issues +- CLI write-snapshot automatically updates index, no separate step needed +- Edit tool can still be used for session.md and context.md (they're documentation, not code) +- This approach works in BOTH normal mode and plan mode diff --git a/commands/setup.md b/commands/setup.md new file mode 100644 index 0000000..28b8a7d --- /dev/null +++ b/commands/setup.md @@ -0,0 +1,369 @@ +You are helping the user configure session plugin hooks in their project's `.claude/settings.json` file. + +## Task: Setup Session Plugin Hooks + +This command manages the automatic configuration of session plugin hooks that enable auto-tracking of sessions, user interactions, and file modifications. + +**IMPORTANT:** This command uses the session CLI tool to perform hook management operations safely with atomic writes and backups. + +### Parse Command Arguments + +Extract the operation from the command arguments. Format: `/session:setup [options]` + +**Supported options:** +- No arguments: Install/configure hooks (default) +- `--permissions`: Install hooks + permission bypasses (eliminates ALL prompts) +- `--remove`: Remove hooks from settings.json +- `--status`: Show current hook and permission configuration +- `--force-cleanup`: Force cleanup of orphaned hooks +- `--dry-run`: Preview changes without applying them + +### Step 1: Determine Operation Mode + +1. Check arguments to determine which operation to perform: + - **Install mode** (default/no args): Add hooks to settings.json + - **Remove mode** (`--remove`): Remove hooks from settings.json + - **Status mode** (`--status`): Show current configuration + - **Cleanup mode** (`--force-cleanup`): Clean up orphaned hooks + - **Dry run** (`--dry-run`): Can be combined with other modes to preview + +### Step 2: Execute CLI Command + +Run the appropriate CLI command based on the operation mode: + +**For Install (hooks only):** +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js setup-hooks +``` + +**For Install (hooks + permissions):** +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js setup-hooks --permissions +``` + +**For Remove:** +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js setup-hooks --remove +``` + +**For Status:** +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js setup-hooks --status +``` + +**For Force Cleanup:** +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js setup-hooks --force-cleanup +``` + +**For Dry Run (example with install):** +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js setup-hooks --dry-run +``` + +The CLI will return JSON with the operation result. + +### Step 3: Display Results + +Parse the JSON response and display user-friendly output based on the action: + +#### Install Success (action: "installed") + +**If permissions were added (permissionsRequested: true, permissionsCount > 0):** +``` +โœ… Session plugin configured successfully! + +๐Ÿ“‹ Hooks added to .claude/settings.json: + โœ“ SessionStart - Auto-clears session on /clear + โœ“ SessionEnd - Cleanup on Claude Code exit + โœ“ UserPromptSubmit - Tracks user interactions + โœ“ PostToolUse (Write, Edit, NotebookEdit) - Tracks file changes + โœ“ Stop - Captures Claude's responses for self-contained logs + +๐Ÿ”“ Permissions added ({permissionsCount} entries): + โœ“ Read(.claude/sessions/**) + โœ“ Bash(git log --oneline:*) + โœ“ Bash(git status --porcelain:*) + โœ“ Bash(git diff --stat:*) + โœ“ Bash(git branch -vv:*) + โœ“ Bash(git rev-parse --abbrev-ref:*) + +โšก Result: ZERO permission prompts during: + โ€ข /session:continue (no Read prompts, no git prompts) + โ€ข /session:save (no Read prompts) + โ€ข /session:status (no Read prompts) + โ€ข All session operations run silently + +๐Ÿ’พ Backup saved: {backupPath} +๐Ÿ“ Settings: {settingsPath} + +โš ๏ธ IMPORTANT: Restart Claude Code for changes to take effect! + Hooks and permissions are loaded at startup. + +๐Ÿ’ก To disable temporarily: Set "disableAllHooks": true in settings.json +๐Ÿ’ก To remove these hooks: /session:setup --remove +``` + +**If permissions were NOT added (permissionsRequested: false):** +``` +โœ… Session plugin hooks configured successfully! + +๐Ÿ“‹ Hooks added to .claude/settings.json: + โœ“ SessionStart - Auto-clears session on /clear + โœ“ SessionEnd - Cleanup on Claude Code exit + โœ“ UserPromptSubmit - Tracks user interactions + โœ“ PostToolUse (Write, Edit, NotebookEdit) - Tracks file changes + โœ“ Stop - Captures Claude's responses for self-contained logs + +๐ŸŽฏ Sessions now automatically track: + โ€ข Session state changes + โ€ข User prompts and interactions + โ€ข Claude's full responses + โ€ข File modifications + +๐Ÿ’ก TIP: Eliminate ALL permission prompts during session operations! + Run: /session:setup --permissions + + This adds safe read-only permissions for: + โ€ข .claude/sessions/** files (Read access) + โ€ข git commands (log, status, diff, branch) + + Result: Zero prompts during /session:continue โšก + +๐Ÿ’พ Backup saved: {backupPath} +๐Ÿ“ Settings: {settingsPath} + +โš ๏ธ IMPORTANT: Restart Claude Code for hooks to take effect! + Hooks are loaded at startup and won't activate until you restart. + +๐Ÿ’ก To disable temporarily: Set "disableAllHooks": true in settings.json +๐Ÿ’ก To remove these hooks: /session:setup --remove +``` + +#### Already Configured (action: "already_configured") +``` +โ„น๏ธ Session plugin hooks are already configured! + +โœ“ All session plugin hooks are properly configured in settings.json + +Current hooks: + โœ“ SessionStart - Active + โœ“ UserPromptSubmit - Active + โœ“ PostToolUse - Active + โœ“ Stop - Active + +๐Ÿ’ก To reinstall: /session:setup --remove, then /session:setup +๐Ÿ’ก To view details: /session:setup --status +``` + +#### Remove Success (action: "removed") +``` +โœ… Session plugin hooks removed! + +๐Ÿ“‹ Removed from .claude/settings.json: + โœ“ SessionStart + โœ“ UserPromptSubmit + โœ“ PostToolUse + โœ“ Stop + +๐Ÿ’พ Backup saved: {backupPath} + +โš ๏ธ IMPORTANT: Restart Claude Code to stop hooks! + Active hooks will continue running until you restart. + +๐Ÿ’ก Sessions still work, but automatic tracking is disabled +๐Ÿ’ก To re-enable: /session:setup +``` + +#### Not Configured (action: "not_configured") +``` +โ„น๏ธ No session plugin hooks found + +Session plugin hooks are not currently configured in settings.json + +๐Ÿ’ก To install hooks: /session:setup +๐Ÿ’ก This will enable automatic session tracking +``` + +#### Status Display (action: "status") + +**When properly configured:** +``` +โœ… Session Plugin Status + +๐Ÿ“‹ Hooks configured in .claude/settings.json: + + โœ“ SessionStart + โ†’ node ${CLAUDE_PLUGIN_ROOT}/hooks/session-start.js + + โœ“ SessionEnd + โ†’ node ${CLAUDE_PLUGIN_ROOT}/hooks/session-end.js + + โœ“ UserPromptSubmit + โ†’ node ${CLAUDE_PLUGIN_ROOT}/hooks/user-prompt-submit.js + + โœ“ PostToolUse (3 matchers) + โ†’ Write: node ${CLAUDE_PLUGIN_ROOT}/hooks/post-tool-use.js + โ†’ Edit: node ${CLAUDE_PLUGIN_ROOT}/hooks/post-tool-use.js + โ†’ NotebookEdit: node ${CLAUDE_PLUGIN_ROOT}/hooks/post-tool-use.js + + โœ“ Stop + โ†’ node ${CLAUDE_PLUGIN_ROOT}/hooks/stop.js + +๐Ÿ“Š Hooks: {configuredHookTypes}/{totalHookTypes} hook types configured +โœ… All hooks pointing to valid scripts + +๐Ÿ”“ Permissions configured: {permissionsCount}/{totalPermissions} + +{if permissionsConfigured === true} + โœ… All session permissions configured + โ€ข Read(.claude/sessions/**) + โ€ข Bash(git log --oneline:*) + โ€ข Bash(git status --porcelain:*) + โ€ข Bash(git diff --stat:*) + โ€ข Bash(git branch -vv:*) + โ€ข Bash(git rev-parse --abbrev-ref:*) + + โšก Result: Zero prompts during session operations +{else if permissionsCount > 0 && permissionsCount < totalPermissions} + โš ๏ธ Partial permissions configured ({permissionsCount}/{totalPermissions}) + + ๐Ÿ’ก To add missing permissions: /session:setup --permissions +{else} + โš ๏ธ No session permissions configured + + ๐Ÿ’ก To eliminate permission prompts: /session:setup --permissions + This adds safe read-only permissions for session files and git commands +{end if} + +๐ŸŽฏ Plugin Status: Installed & Configured + +๐Ÿ’ก To remove: /session:setup --remove +``` + +**When orphaned (plugin uninstalled but hooks remain):** +``` +โš ๏ธ Session Plugin Hooks Status + +๐Ÿ“‹ Found in .claude/settings.json: + + โš ๏ธ SessionStart + โ†’ node ${CLAUDE_PLUGIN_ROOT}/hooks/session-start.js + โŒ Script not found (plugin may be uninstalled) + + โš ๏ธ UserPromptSubmit + โŒ Script not found + + โš ๏ธ PostToolUse (3 matchers) + โŒ All scripts not found + + โš ๏ธ Stop + โŒ Script not found + +๐Ÿ” Plugin Status: Not Found +โŒ Hooks are orphaned (pointing to missing files) + +Found {orphanedHooks.length} orphaned hook entries + +๐Ÿงน Cleanup Options: + 1. Auto-cleanup: /session:setup --force-cleanup + 2. Manual cleanup: Edit .claude/settings.json + 3. Reinstall plugin to restore functionality +``` + +#### Cleanup Success (action: "cleaned") +``` +โœ… Orphaned hooks cleaned up! + +๐Ÿงน Removed {removedCount} orphaned hook entries: +{List each orphaned hook that was removed} + +๐Ÿ’พ Backup saved: {backupPath} + +โš ๏ธ IMPORTANT: Restart Claude Code to apply cleanup! + Settings changes take effect on next restart. + +๐Ÿ’ก Settings.json has been cleaned +๐Ÿ’ก To reinstall hooks: /session:setup +``` + +#### No Orphans (action: "no_orphans") +``` +โœ… No orphaned hooks found + +All hooks in settings.json are valid + +๐Ÿ’ก Everything looks good! +``` + +#### Error Cases + +**On error (success: false):** +``` +โŒ Error: {error message} + +{Provide helpful context based on the error:} + +Common issues: +- **Malformed JSON**: settings.json has syntax errors + โ†’ Fix: Restore from backup or manually repair JSON + +- **Permission denied**: No write access to .claude/settings.json + โ†’ Fix: Check file permissions + +- **Plugin not found**: Session plugin may not be installed + โ†’ Fix: Reinstall the session plugin + +๐Ÿ’ก To restore from backup: cp .claude/settings.json.backup .claude/settings.json +๐Ÿ’ก Need help? Check the README or /session:setup --status +``` + +### Important Notes + +- **Atomic Operations**: All writes use atomic operations with backups +- **Idempotent**: Safe to run multiple times, won't create duplicates +- **Portable Paths**: Uses `${CLAUDE_PLUGIN_ROOT}` variable for cross-platform compatibility +- **Merge Strategy**: Preserves existing hooks when installing +- **Safety**: Creates `.backup` file before any modifications + +### Usage Examples + +```bash +# Install hooks only (basic setup) +/session:setup + +# Install hooks + permissions (RECOMMENDED - eliminates ALL prompts) +/session:setup --permissions + +# Check current status (shows hooks and permissions) +/session:setup --status + +# Preview what would be installed (dry run) +/session:setup --dry-run + +# Preview with permissions +/session:setup --permissions --dry-run + +# Remove hooks before uninstalling plugin +/session:setup --remove + +# Clean up orphaned hooks after plugin uninstall +/session:setup --force-cleanup +``` + +**Recommended:** Always use `--permissions` flag for best experience: +- Zero permission prompts during `/session:continue` +- Zero permission prompts during `/session:save` +- Zero permission prompts during `/session:status` +- Completely silent session operations + +--- + +**CRITICAL for Plugin Uninstallation:** + +Before uninstalling the session plugin, users should run: +```bash +/session:setup --remove +``` + +This ensures clean removal and prevents orphaned hook entries in settings.json. diff --git a/commands/start.md b/commands/start.md new file mode 100644 index 0000000..ad40675 --- /dev/null +++ b/commands/start.md @@ -0,0 +1,293 @@ +You are managing a session memory system. The user wants to start a new named session. + +**CRITICAL - Command Format:** +All session plugin commands use the `/session:` prefix. DO NOT suggest commands without this prefix. +- โœ… Correct: `/session:list`, `/session:start`, `/session:continue`, `/session:status` +- โŒ Wrong: `/session list`, `/session start`, `/session continue`, `/session status` +Use ONLY the exact command formats specified in this template. + +## Task: Start New Session + +Parse the session name from the command arguments. The command format is: `/session:start [name]` + +**OPTIMIZATION:** This command now updates the metadata index after creating the session. + +### Step 1: Validate Session Name + +1. Extract the session name from the arguments +2. Validate the name matches regex: `^[a-zA-Z0-9_-]+$` +3. If invalid, show error: + ``` + โŒ Error: Invalid session name '{name}' + Session names can only contain: + - Letters (a-z, A-Z) + - Numbers (0-9) + - Hyphens (-) + - Underscores (_) + + Example: my-session or my_session_123 + ``` + Then STOP. + +### Step 2: Check for Duplicate Sessions + +**CRITICAL:** Check both directory names AND session.md file contents to prevent duplicates. + +1. **Check directory collision:** + - Check if `.claude/sessions/{name}/` directory already exists + - If exists, show error: + ``` + โŒ Error: Session directory '{name}' already exists + ๐Ÿ’ก Use /session:continue {name} to resume + ๐Ÿ’ก Or use /session:list to see all sessions + ``` + Then STOP. + +2. **Check session name collision (NEW - prevents duplicate names):** + - Use the CLI to get all existing sessions: + ```bash + node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js list + ``` + - Parse the JSON response and check if any existing session has `name: "{name}"` + - If a session with this name exists (even if directory name is different), show error: + ``` + โŒ Error: A session named '{name}' already exists + ๐Ÿ’ก Use /session:list to see all sessions + ๐Ÿ’ก Choose a different name for this session + ``` + Then STOP. + +This dual-check prevents both directory collisions and duplicate session names. + +### Step 3: Check for Active Session and Transition (NEW - Session Cleanup) + +Before creating the new session, check if there's already an active session: + +1. Check if `.claude/sessions/.active-session` exists +2. If it exists: + - Read the current active session name + - Show: "๐Ÿ“‹ Closing previous session '{previous_session_name}'..." + - Close the previous session status: + ```bash + node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js update-status "{previous_session_name}" "closed" + ``` + - This marks the previous session as closed in `.auto-capture-state` +3. Continue to next step (the new session activation will overwrite `.active-session`) + +**Note:** The SessionEnd hook will handle final cleanup on Claude Code termination. + +### Step 4: Create Session Folder + +1. Create directory: `.claude/sessions/{name}/` +2. Verify creation was successful + +### Step 5: Initialize session.md + +**CRITICAL:** The session name in session.md MUST match the directory name to prevent duplicates. + +Create `.claude/sessions/{name}/session.md` with this content: + +```markdown +# Session: {name} + +**Started**: {current_timestamp_YYYY-MM-DD_HH:MM} +**Last Updated**: {current_timestamp_YYYY-MM-DD_HH:MM} + +## Goal +[Ask user to describe the goal for this session] + +## Overview +Working on: {name} + +## Key Milestones +- [ ] [To be defined during session] + +## Files Involved +- [Will be tracked as work progresses] + +## Configuration +- Auto-capture: enabled + +## Notes +Session started. Use /session:save to capture important milestones. +``` + +### Step 6: Initialize context.md + +Create `.claude/sessions/{name}/context.md` with this content: + +```markdown +# Session Context: {name} + +## Key Decisions +[Decisions will be captured during session] + +## Important Discoveries +[Discoveries will be documented as they occur] + +## Blockers & Resolutions +[Issues and resolutions will be tracked here] + +## Technical Context +[Architecture decisions and technical details] + +## Summary +Session started on {current_timestamp}. Ready to capture context. +``` + +### Step 7: Update Active Session Tracker + +1. Write the session name to `.claude/sessions/.active-session` (single line, just the name) +2. This marks it as the currently active session + +### Step 7.5: Initialize .auto-capture-state with Session Status + +Create `.claude/sessions/{name}/.auto-capture-state` with initial session status: + +```bash +echo '{ + "interaction_count": 0, + "modified_files": [], + "last_snapshot_timestamp": null, + "session_status": "active", + "session_started": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'", + "session_closed": null +}' > .claude/sessions/{name}/.auto-capture-state +``` + +This initializes the operational state tracking for the session, including the session status which is now tracked in JSON for fast, atomic updates. + +### Step 8: Update Index (NEW - CRITICAL) + +Run the CLI command to add the new session to the metadata index: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js update-index --session {name} +``` + +This ensures the new session appears immediately in `/session:list` without requiring a full rebuild. + +### Step 9: Display Success Message + +Show this confirmation to the user: + +``` +โœ“ Session '{name}' started +๐Ÿ“ Location: .claude/sessions/{name}/ +๐Ÿ’ก Use /session:save to capture important milestones +๐Ÿ“Š Check /session:status to monitor tokens + +Ready to work! What would you like to accomplish in this session? +``` + +### Step 10: Ask for Session Goal + +After showing the success message, ask the user: +"What is the main goal or purpose of this session? (This will be saved to session.md)" + +Wait for their response, then update the "Goal" section in session.md with their answer. + +--- + +**PERFORMANCE BENEFITS:** +- **Before:** No index integration, sessions invisible until manual list command scans +- **After:** Instant index update, session immediately visible in list +- **Improvement:** Better UX, no stale index issues + +**IMPORTANT:** +- Execute all steps in order +- Use the Read, Write, and Bash tools to perform file operations +- The CLI update-index command is fast (< 10ms) and ensures consistency +- Do not skip any steps + +--- + +## CRITICAL: Check for Unconsolidated Logs (Inline Analysis) + +**IMPORTANT:** New session start should NOT have unconsolidated logs, but check anyway for robustness. + +**MUST CHECK BEFORE DISPLAYING SUCCESS MESSAGE:** + +After starting the session, check if previous session left unconsolidated logs: + +1. Check if `.claude/sessions/{name}/conversation-log.jsonl` exists +2. If the file exists: + - Show brief message: "๐Ÿ“Š Analyzing previous session... (this may take 1-3 seconds)" + - Read the conversation log file + - Parse interactions from JSONL format + - **Capture git history (if available):** + - Run: `node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js capture-git "{name}"` + - This creates `.claude/sessions/{name}/git-history.json` (~2-3KB compressed) + - Contains: last 50 commits, uncommitted changes, branch status, hotspots + - Performance: ~60-90ms (acceptable at session boundary) + - If no git repo, command returns success: false (silent skip, no error) + - Analyze the conversation with Claude inline: + - Extract conversation summary (2-3 paragraphs covering what happened) + - Identify key decisions made with rationale + - List completed todos/tasks + - Document files modified with context about what changed and why + - Assess current state, what's next, and any blockers + - Create consolidated snapshot via CLI: + ```bash + echo "# Consolidated Snapshot: {session_name} +**Timestamp**: {ISO timestamp} +**Method**: Claude Inline Analysis (Free) +**Status**: Consolidated from conversation log +**Format Version**: 2.0 + +## Topics Discussed + +1. **[Category]**: [Brief description of what was discussed] +2. **[Category]**: [Brief description of what was discussed] +[Continue for ALL topics in chronological order] + +## Suggestions & Recommendations + +1. **[Category]**: [Specific suggestion] - [Rationale] +2. **[Category]**: [Specific suggestion] - [Rationale] +[Continue for ALL suggestions] + +## Decisions Made + +1. **[Decision]**: [Rationale and context] +2. **[Decision]**: [Rationale and context] +[Continue for ALL decisions] + +## Tasks Completed + +1. [Action completed in past tense] +2. [Action completed in past tense] +[Continue for ALL tasks] + +## Files Modified + +1. `[file_path]`: [What changed and why] +2. `[file_path]`: [What changed and why] +[Continue for ALL files] + +## Current Status + +- **Progress**: [Where things stand - what's been accomplished] +- **Next Steps**: [What should be done next] +- **Blockers**: [Issues or write \"None\"] + +## Notes +Consolidated via Claude inline analysis at session boundary. Zero cost, highest quality." | node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js write-snapshot "{name}" --stdin --type auto + ``` + - Delete conversation-log.jsonl after successful snapshot creation + - Update `.auto-capture-state` to reset counters and set last_snapshot_timestamp +3. If no log exists: + - **Still capture git history** for repository context: + - Run: `node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js capture-git "{name}"` + - This provides git context even for new sessions + - Silent skip if no git repo (no error) + - Initialize `.auto-capture-state` if needed + +**PERFORMANCE:** +- Log check: <5ms +- Claude analysis: 1-3s (acceptable at session boundaries - users expect loading) +- Snapshot write: <50ms +- Log deletion: <5ms +- **Total: ~1-3 seconds** (users expect loading at session start) + +**NOTE:** This is the v3.5.1 architecture where conversation logging is incremental (<2ms per interaction) and consolidation happens inline at session boundaries using FREE Claude analysis for highest quality. diff --git a/commands/status.md b/commands/status.md new file mode 100644 index 0000000..7676e3d --- /dev/null +++ b/commands/status.md @@ -0,0 +1,153 @@ +You are managing a session memory system. The user wants to check the current session status. + +## Task: Display Session Status (Ultra-Minimal) + +Show essential session information quickly and efficiently. + +**OPTIMIZATION:** Ultra-minimal output. Uses CLI for instant stats (<50ms, <50 tokens). + +### Step 1: Get Active Session from CLI + +Run the CLI command to get session list and find active session: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js list +``` + +Parse the JSON response to get `activeSession` field. + +If `activeSession` is null, show error: +``` +โŒ No active session + +๐Ÿ’ก /session:start [name] to create new session +๐Ÿ’ก /session:continue [name] to resume existing session +``` +Then STOP. + +### Step 2: Get Session Statistics + +Run the CLI stats command for the active session: + +```bash +node ${CLAUDE_PLUGIN_ROOT}/cli/session-cli.js stats {activeSession} +``` + +This returns JSON with: +- Session metadata (status, started, lastUpdated, goal) +- Snapshot counts (snapshotCount) +- File counts (filesInvolvedCount) + +### Step 3: Calculate Session Duration + +Parse the `started` timestamp from stats (format: "2025-11-13 14:30"). + +Calculate duration from start time to now: +1. Parse started date/time +2. Calculate difference in minutes +3. Format as: + - If < 60 min: "Xm" (e.g., "45m") + - If < 24 hours: "Xh Ym" (e.g., "2h 15m" or "5h 0m") + - If >= 24 hours: "Xd Yh" (e.g., "2d 3h") + +### Step 4: Calculate Time Since Last Activity + +Parse `lastUpdated` timestamp (ISO format: "2025-11-14T10:27:04.345Z"). + +Calculate time since last update: +1. Parse ISO timestamp +2. Calculate difference from now +3. Format as relative time: + - "just now" (< 1 min) + - "Xm ago" (< 60 min) + - "Xh ago" (< 24 hours) + - "Xd ago" (>= 24 hours) + +### Step 5: Display Ultra-Minimal Status + +Show clean, essential information only: + +``` +โœ“ Session: {sessionName} ({status}) + Working for: {duration} (started {started_short}) + Snapshots: {snapshotCount} total + Files: {filesInvolvedCount} tracked + Last activity: {time_since_last_update} + +๐Ÿ’ก /session:save to capture milestones +๐Ÿ’ก /session:close to finalize +``` + +**Format notes:** +- {status}: "active" or "closed" +- {started_short}: "Nov 14, 14:30" format +- All numbers: plain integers (no formatting) +- No emojis except status indicator (โœ“) +- No Unicode art, no progress bars +- 5 lines max + +### Example Output + +**Active session:** +``` +โœ“ Session: feature-auth (active) + Working for: 2h 15m (started Nov 14, 14:30) + Snapshots: 12 total + Files: 7 tracked + Last activity: 30m ago + +๐Ÿ’ก /session:save to capture milestones +๐Ÿ’ก /session:close to finalize +``` + +**Recently started:** +``` +โœ“ Session: bug-fix-login (active) + Working for: 15m (started Nov 14, 18:45) + Snapshots: 1 total + Files: 2 tracked + Last activity: just now + +๐Ÿ’ก /session:save to capture milestones +๐Ÿ’ก /session:close to finalize +``` + +**Closed session:** +``` +โœ“ Session: refactor-api (closed) + Worked for: 5h 30m (started Nov 13, 09:00) + Snapshots: 18 total + Files: 12 tracked + Last activity: 2d ago + +๐Ÿ’ก /session:continue {sessionName} to resume +``` + +--- + +**PERFORMANCE:** +- **Tokens:** ~50 tokens (vs 150 before) - **66% reduction** +- **Speed:** <50ms (CLI delegation) +- **Lines:** 5-7 lines (vs 15-20 before) - **70% reduction** + +**WHAT WAS REMOVED:** +- โŒ Token usage tracking (unreliable, verbose) +- โŒ Progress bars (unnecessary decoration) +- โŒ Warning messages (not reliable) +- โŒ Unicode art (bloat) +- โŒ Total size display (rarely useful) +- โŒ Auto vs manual snapshot breakdown (not essential) + +**WHAT WAS KEPT:** +- โœ… Session name and status +- โœ… Duration (how long working) +- โœ… Snapshot count (progress indicator) +- โœ… File count (scope indicator) +- โœ… Last activity (freshness indicator) +- โœ… Quick action tips + +**FOR TOKEN USAGE:** Users should run `/context` directly for accurate real-time token information. + +**ERROR HANDLING:** +- If CLI command fails, show error and suggest rebuilding index +- If timestamps can't be parsed, show raw values diff --git a/hooks/hooks.json b/hooks/hooks.json new file mode 100644 index 0000000..7c9e42b --- /dev/null +++ b/hooks/hooks.json @@ -0,0 +1,71 @@ +{ + "SessionStart": [ + { + "hooks": [ + { + "type": "command", + "command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/session-start.js" + } + ] + } + ], + "UserPromptSubmit": [ + { + "hooks": [ + { + "type": "command", + "command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/user-prompt-submit.js" + } + ] + } + ], + "PostToolUse": [ + { + "matcher": "Write", + "hooks": [ + { + "type": "command", + "command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/post-tool-use.js" + } + ] + }, + { + "matcher": "Edit", + "hooks": [ + { + "type": "command", + "command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/post-tool-use.js" + } + ] + }, + { + "matcher": "NotebookEdit", + "hooks": [ + { + "type": "command", + "command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/post-tool-use.js" + } + ] + } + ], + "Stop": [ + { + "hooks": [ + { + "type": "command", + "command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/stop.js" + } + ] + } + ], + "SessionEnd": [ + { + "hooks": [ + { + "type": "command", + "command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/session-end.js" + } + ] + } + ] +} diff --git a/hooks/post-tool-use.js b/hooks/post-tool-use.js new file mode 100755 index 0000000..3bc900f --- /dev/null +++ b/hooks/post-tool-use.js @@ -0,0 +1,188 @@ +#!/usr/bin/env node +// Intelligent Post-Tool-Use Hook - Tracks file modifications for smart analysis +// Works with async analysis system for intelligent snapshots +// +// SAFETY: Includes graceful failure handling to avoid blocking Claude Code +// if plugin is uninstalled or dependencies are missing. + +const fs = require('fs'); +const path = require('path'); + +// Graceful failure wrapper - protect against plugin uninstallation +try { + // Check if critical dependencies exist (indicates plugin is installed) + const cliLibPath = path.join(__dirname, '../cli/lib'); + if (!fs.existsSync(cliLibPath)) { + // Plugin likely uninstalled, exit silently + process.exit(0); + } + + const LockManager = require('../cli/lib/lock-manager'); + + // Read tool operation data from stdin (Claude Code provides this as JSON) + // NOTE: Do NOT use process.env.CLAUDE_TOOL_NAME - it's always "unknown" due to Claude Code bug + let toolName = 'unknown'; + let filePath = null; + + try { + const input = fs.readFileSync(0, 'utf8').trim(); + if (input) { + const eventData = JSON.parse(input); + + // Get tool name from stdin data (NOT environment variable) + toolName = eventData.tool_name || 'unknown'; + + // Extract file path from tool input + // Different tools use different field names for file paths + if (eventData.tool_input) { + if (eventData.tool_input.file_path) { + filePath = eventData.tool_input.file_path; + } else if (eventData.tool_input.notebook_path) { + // NotebookEdit uses notebook_path instead of file_path + filePath = eventData.tool_input.notebook_path; + } + } + } +} catch (err) { + // If we can't read stdin or parse it, exit early + process.exit(0); +} + +// Only track file modifications (Write, Edit, and NotebookEdit tools) +if (toolName !== 'Write' && toolName !== 'Edit' && toolName !== 'NotebookEdit') { + process.exit(0); +} + +// Configuration +const SESSIONS_DIR = '.claude/sessions'; +const ACTIVE_SESSION_FILE = path.join(SESSIONS_DIR, '.active-session'); +const lockManager = new LockManager(SESSIONS_DIR); + +// Exit early if no active session +if (!fs.existsSync(ACTIVE_SESSION_FILE)) { + process.exit(0); +} + +// Read active session name +let activeSession; +try { + activeSession = fs.readFileSync(ACTIVE_SESSION_FILE, 'utf8').trim(); +} catch (err) { + process.exit(0); +} + +if (!activeSession) { + process.exit(0); +} + +const sessionDir = path.join(SESSIONS_DIR, activeSession); +if (!fs.existsSync(sessionDir)) { + process.exit(0); +} + +// Check if auto-capture is enabled +const sessionMd = path.join(sessionDir, 'session.md'); +if (fs.existsSync(sessionMd)) { + try { + const content = fs.readFileSync(sessionMd, 'utf8'); + if (content.includes('Auto-capture: disabled')) { + process.exit(0); + } + } catch (err) { + // Continue if we can't read the file + } +} + +// State file +const stateFile = path.join(sessionDir, '.auto-capture-state'); + +// Use lock to prevent race conditions with user-prompt-submit.js hook +const lock = lockManager.acquireLock(`auto-capture-${activeSession}`, { + timeout: 1000, + wait: true +}); + +if (!lock.acquired) { + // Could not acquire lock - skip this update to avoid blocking + // The file will be captured on next tool use + process.exit(0); +} + +try { + // Initialize state if doesn't exist + let state = { + file_count: 0, + interaction_count: 0, + interactions_since_last_analysis: 0, + last_snapshot: '', + last_reason: '', + last_analysis_timestamp: '', + modified_files: [] // Track actual file paths + }; + + if (fs.existsSync(stateFile)) { + try { + state = JSON.parse(fs.readFileSync(stateFile, 'utf8')); + } catch (err) { + // Use default state if parse fails + } + } + + // Increment file count + state.file_count++; + + // Track the modified file path if we captured it + if (filePath) { + // Initialize modified_files array if it doesn't exist (backward compatibility) + if (!state.modified_files) { + state.modified_files = []; + } + + // Add file to list if not already tracked + const fileEntry = { + path: filePath, + operation: toolName.toLowerCase(), + timestamp: new Date().toISOString() + }; + + // Avoid duplicates - check if file already in list + const existingIndex = state.modified_files.findIndex(f => f.path === filePath); + if (existingIndex >= 0) { + // Update existing entry with latest operation + state.modified_files[existingIndex] = fileEntry; + } else { + // Add new file + state.modified_files.push(fileEntry); + } + } + + // Update state atomically + // Note: We no longer immediately create snapshot markers here + // Instead, the file_count contributes to analysis queue logic in user-prompt-submit.js + const tempPath = `${stateFile}.tmp.${Date.now()}`; + try { + fs.writeFileSync(tempPath, JSON.stringify(state, null, 2)); + fs.renameSync(tempPath, stateFile); + } catch (writeError) { + // Clean up temp file + if (fs.existsSync(tempPath)) { + try { + fs.unlinkSync(tempPath); + } catch (cleanupError) { + // Ignore + } + } + throw writeError; + } + } finally { + // Always release lock + lock.release(); + } + + process.exit(0); + +} catch (error) { + // Outer catch: Handle plugin missing/uninstalled + // Exit silently to avoid blocking Claude Code + process.exit(0); +} diff --git a/hooks/session-end.js b/hooks/session-end.js new file mode 100755 index 0000000..05ee15a --- /dev/null +++ b/hooks/session-end.js @@ -0,0 +1,111 @@ +#!/usr/bin/env node + +/** + * SessionEnd Hook + * + * Handles cleanup when Claude Code session terminates. + * Ensures .active-session file is removed and index is updated. + * + * Hook receives: + * - session_id: string + * - transcript_path: string + * - cwd: string + * - permission_mode: string + * - hook_event_name: "SessionEnd" + * - reason: "exit" | "clear" | "logout" | "prompt_input_exit" | "other" + * + * SAFETY: Includes graceful failure handling to avoid blocking Claude Code shutdown + * if plugin is uninstalled or dependencies are missing. + */ + +const fs = require('fs'); +const path = require('path'); + +// Graceful failure wrapper - protect against plugin uninstallation +try { + // Check if critical dependencies exist (indicates plugin is installed) + const cliLibPath = path.join(__dirname, '../cli/lib'); + if (!fs.existsSync(cliLibPath)) { + // Plugin likely uninstalled, exit silently + process.exit(0); + } + + const IndexManager = require('../cli/lib/index-manager'); + + // Constants + const SESSIONS_DIR = '.claude/sessions'; + const ACTIVE_SESSION_FILE = path.join(SESSIONS_DIR, '.active-session'); + const indexManager = new IndexManager(SESSIONS_DIR); + + try { + // Read input from stdin (provided by Claude Code) + const input = fs.readFileSync(0, 'utf8').trim(); + + // Parse the JSON input + let eventData; + try { + eventData = JSON.parse(input); + } catch (parseError) { + // If parsing fails, exit silently (no input provided) + process.exit(0); + } + + // Clean up active session marker + let sessionName = null; + + if (fs.existsSync(ACTIVE_SESSION_FILE)) { + try { + sessionName = fs.readFileSync(ACTIVE_SESSION_FILE, 'utf8').trim(); + } catch (readError) { + // Continue even if read fails + } + + // Delete the .active-session file + try { + fs.unlinkSync(ACTIVE_SESSION_FILE); + } catch (unlinkError) { + // File may already be deleted, continue + } + } + + // Mark session as closed in .auto-capture-state (fast, atomic) + if (sessionName) { + const sessionDir = path.join(SESSIONS_DIR, sessionName); + const statePath = path.join(sessionDir, '.auto-capture-state'); + + if (fs.existsSync(statePath)) { + try { + let state = JSON.parse(fs.readFileSync(statePath, 'utf8')); + state.session_status = 'closed'; + state.session_closed = new Date().toISOString(); + fs.writeFileSync(statePath, JSON.stringify(state, null, 2)); + } catch (stateError) { + // Silent fail - hook must be safe + // Session status update failed but continue with other cleanup + } + } + } + + // Update the index.json to clear activeSession using IndexManager + // This uses proper locking and atomic writes to prevent corruption + try { + const index = indexManager.read({ skipValidation: true }); + index.activeSession = null; + indexManager.write(index); + } catch (indexError) { + // Continue even if index update fails + // This prevents blocking the hook if index is temporarily locked + } + + // Exit successfully + process.exit(0); + + } catch (error) { + // Exit silently on any errors to avoid blocking Claude Code shutdown + process.exit(0); + } +} catch (error) { + // Outer catch: Handle plugin missing/uninstalled + // Exit silently to avoid blocking Claude Code + process.exit(0); +} diff --git a/hooks/session-start.js b/hooks/session-start.js new file mode 100755 index 0000000..0bc9e91 --- /dev/null +++ b/hooks/session-start.js @@ -0,0 +1,110 @@ +#!/usr/bin/env node + +/** + * SessionStart Hook + * + * Handles session state cleanup when /clear is executed. + * Clears active session markers to prevent confusion when context is lost. + * + * Hook receives: + * - source: "startup" | "resume" | "clear" | "compact" + * - session_id: string + * - cwd: string + * - permission_mode: string + * + * SAFETY: Includes graceful failure handling to avoid blocking Claude Code + * if plugin is uninstalled or dependencies are missing. + */ + +const fs = require('fs'); +const path = require('path'); + +// Graceful failure wrapper - protect against plugin uninstallation +try { + // Check if critical dependencies exist (indicates plugin is installed) + const cliLibPath = path.join(__dirname, '../cli/lib'); + if (!fs.existsSync(cliLibPath)) { + // Plugin likely uninstalled, exit silently + process.exit(0); + } + + // Import IndexManager for safe index updates + const IndexManager = require('../cli/lib/index-manager'); + + // Constants + const SESSIONS_DIR = '.claude/sessions'; + const ACTIVE_SESSION_FILE = path.join(SESSIONS_DIR, '.active-session'); + const indexManager = new IndexManager(SESSIONS_DIR); + + try { + // Read input from stdin (provided by Claude Code) + const input = fs.readFileSync(0, 'utf8').trim(); + + // Parse the JSON input + let eventData; + try { + eventData = JSON.parse(input); + } catch (parseError) { + // If parsing fails, exit silently (no input provided) + process.exit(0); + } + + const { source } = eventData; + + // Only process when source is "clear" + // Other sources ("startup", "resume", "compact") should allow normal auto-resume + if (source === 'clear') { + let sessionName = null; + + // Read the active session name before clearing (for the message) + if (fs.existsSync(ACTIVE_SESSION_FILE)) { + try { + sessionName = fs.readFileSync(ACTIVE_SESSION_FILE, 'utf8').trim(); + } catch (readError) { + // Continue even if read fails + } + + // Clear the .active-session file + try { + fs.unlinkSync(ACTIVE_SESSION_FILE); + } catch (unlinkError) { + // File may already be deleted, continue + } + } + + // Update the index.json to clear activeSession using IndexManager + // This uses proper locking and atomic writes to prevent corruption + try { + const index = indexManager.read({ skipValidation: true }); + index.activeSession = null; + indexManager.write(index); + } catch (indexError) { + // Continue even if index update fails + // This prevents blocking the hook if index is temporarily locked + } + + // Inject helpful context message to Claude + const output = { + hookSpecificOutput: { + additionalContext: sessionName + ? `๐Ÿ“‹ Session '${sessionName}' was auto-closed due to /clear command. The conversation context has been cleared.\n\nTo resume your work on this session, use: /session:continue ${sessionName}\nTo view all sessions, use: /session:list` + : 'Previous session was auto-closed due to /clear command. Use /session:list to view available sessions.' + } + }; + + // Output the context injection + console.log(JSON.stringify(output)); + } + + // Exit successfully + process.exit(0); + + } catch (error) { + // Exit silently on any errors to avoid blocking Claude Code startup + process.exit(0); + } +} catch (error) { + // Outer catch: Handle plugin missing/uninstalled + // Exit silently to avoid blocking Claude Code + process.exit(0); +} diff --git a/hooks/stop.js b/hooks/stop.js new file mode 100755 index 0000000..fe0f2c7 --- /dev/null +++ b/hooks/stop.js @@ -0,0 +1,210 @@ +#!/usr/bin/env node +// Stop Hook - Captures Claude's complete response for self-contained conversation logs +// This hook fires after Claude completes each response +// +// SAFETY: Includes graceful failure handling to avoid blocking Claude Code +// if plugin is uninstalled or dependencies are missing. + +const fs = require('fs'); +const path = require('path'); + +// Graceful failure wrapper - protect against plugin uninstallation +try { + // Check if critical dependencies exist (indicates plugin is installed) + const cliLibPath = path.join(__dirname, '../cli/lib'); + if (!fs.existsSync(cliLibPath)) { + // Plugin likely uninstalled, exit silently + process.exit(0); + } + + const LockManager = require('../cli/lib/lock-manager'); + +// Read stdin to get transcript path +let stdinData; +try { + const stdinInput = fs.readFileSync(0, 'utf8').trim(); + + if (!stdinInput) { + process.exit(0); + } + stdinData = JSON.parse(stdinInput); +} catch (stdinErr) { + // Cannot parse stdin, exit silently + process.exit(0); +} + +const transcriptPath = stdinData.transcript_path; + +if (!transcriptPath || !fs.existsSync(transcriptPath)) { + // No transcript path or file doesn't exist + process.exit(0); +} + +// Read transcript file to get Claude's last response (with exponential backoff retry) +// Uses smart retry strategy: fast success path (0-50ms), patient for edge cases (750ms max) +const MAX_RETRIES = 5; +const RETRY_DELAYS = [0, 50, 100, 200, 400]; // Exponential backoff in milliseconds + +function tryFindAssistantMessage() { + try { + const transcriptContent = fs.readFileSync(transcriptPath, 'utf8'); + const lines = transcriptContent.trim().split('\n'); + + // Find last assistant message (search backwards for efficiency) + for (let i = lines.length - 1; i >= 0; i--) { + try { + const entry = JSON.parse(lines[i]); + // Claude Code transcript format: {type: 'assistant', message: {role, content}} + if (entry.type === 'assistant' && entry.message) { + return entry.message; // Return the message object which has role and content + } + } catch (parseErr) { + // Skip malformed lines + continue; + } + } + return null; + } catch (readErr) { + return null; + } +} + +// Sleep function for retry delays +function sleep(ms) { + const start = Date.now(); + while (Date.now() - start < ms) { + // Busy wait (acceptable for short delays in hooks) + } +} + +// Try to find assistant message with exponential backoff retries +let lastAssistantMessage = null; + +for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) { + lastAssistantMessage = tryFindAssistantMessage(); + + if (lastAssistantMessage) { + break; + } + + // If not found and not last attempt, wait with exponential backoff + if (attempt < MAX_RETRIES) { + const nextDelay = RETRY_DELAYS[attempt]; // Next delay for next attempt + sleep(nextDelay); + } +} + +if (!lastAssistantMessage) { + // No assistant message found after all retries + process.exit(0); +} + +// Configuration +const SESSIONS_DIR = '.claude/sessions'; +const ACTIVE_SESSION_FILE = path.join(SESSIONS_DIR, '.active-session'); + +// Exit early if no active session +if (!fs.existsSync(ACTIVE_SESSION_FILE)) { + process.exit(0); +} + +// Read active session name +let activeSession; +try { + activeSession = fs.readFileSync(ACTIVE_SESSION_FILE, 'utf8').trim(); +} catch (err) { + process.exit(0); +} + +if (!activeSession) { + process.exit(0); +} + +const sessionDir = path.join(SESSIONS_DIR, activeSession); + +if (!fs.existsSync(sessionDir)) { + process.exit(0); +} + +// Check if auto-capture is enabled +const sessionMd = path.join(sessionDir, 'session.md'); + +if (fs.existsSync(sessionMd)) { + try { + const content = fs.readFileSync(sessionMd, 'utf8'); + if (content.includes('Auto-capture: disabled')) { + process.exit(0); + } + } catch (err) { + // Continue if we can't read the file + } +} + +// Use lock to prevent race conditions +const lockManager = new LockManager(SESSIONS_DIR); +const lock = lockManager.acquireLock(`auto-capture-${activeSession}`, { + timeout: 1000, + wait: true +}); + +if (!lock.acquired) { + // Could not acquire lock - skip this update to avoid blocking + process.exit(0); +} + +try { + // Extract tool uses from response + const toolUses = []; + if (lastAssistantMessage.content && Array.isArray(lastAssistantMessage.content)) { + lastAssistantMessage.content.forEach(block => { + if (block.type === 'tool_use') { + toolUses.push({ + tool: block.name, + input: block.input, + id: block.id || null + }); + } + }); + } + + // Helper to extract text from content blocks + function extractTextContent(content) { + if (typeof content === 'string') { + return content; + } + if (Array.isArray(content)) { + return content + .filter(block => block.type === 'text') + .map(block => block.text) + .join('\n'); + } + return ''; + } + + const responseText = extractTextContent(lastAssistantMessage.content); + + // Log Claude's response + const ConversationLogger = require('../cli/lib/conversation-logger'); + const logger = new ConversationLogger(sessionDir); + + logger.logAssistantResponse({ + timestamp: new Date().toISOString(), + response_text: responseText, + tools_used: toolUses, + message_id: lastAssistantMessage.id || null + }); + +} catch (error) { + // Silent failure - don't block hook execution +} finally { + // Always release lock + lock.release(); +} + +process.exit(0); + +} catch (error) { + // Outer catch: Handle plugin missing/uninstalled + // Exit silently to avoid blocking Claude Code + process.exit(0); +} diff --git a/hooks/user-prompt-submit.js b/hooks/user-prompt-submit.js new file mode 100755 index 0000000..5259d0f --- /dev/null +++ b/hooks/user-prompt-submit.js @@ -0,0 +1,226 @@ +#!/usr/bin/env node +// Truly Automatic Auto-Capture Hook - Creates snapshots automatically +// This hook creates snapshot files directly via CLI with NO manual intervention +// Snapshots are created every N interactions or when file thresholds are met +// +// SAFETY: Includes graceful failure handling to avoid blocking Claude Code +// if plugin is uninstalled or dependencies are missing. +// +// ORPHAN DETECTION: Periodically checks for orphaned hooks and auto-cleans them + +const fs = require('fs'); +const path = require('path'); + +// Graceful failure wrapper - protect against plugin uninstallation +try { + // Check if critical dependencies exist (indicates plugin is installed) + const cliLibPath = path.join(__dirname, '../cli/lib'); + if (!fs.existsSync(cliLibPath)) { + // Plugin likely uninstalled, exit silently + process.exit(0); + } + + const LockManager = require('../cli/lib/lock-manager'); + +// Configuration +const SESSIONS_DIR = '.claude/sessions'; +const ACTIVE_SESSION_FILE = path.join(SESSIONS_DIR, '.active-session'); +const lockManager = new LockManager(SESSIONS_DIR); + +// Living Context Configuration +const CONTEXT_UPDATE_THRESHOLD = 2; // Update context every 2 interactions (lightweight) +const SNAPSHOT_THRESHOLD = 5; // Full snapshot every 5 interactions (heavier) + +// Exit early if no active session +if (!fs.existsSync(ACTIVE_SESSION_FILE)) { + process.exit(0); +} + +// Read active session name +let activeSession; +try { + activeSession = fs.readFileSync(ACTIVE_SESSION_FILE, 'utf8').trim(); +} catch (err) { + process.exit(0); +} + +if (!activeSession) { + process.exit(0); +} + +const sessionDir = path.join(SESSIONS_DIR, activeSession); +if (!fs.existsSync(sessionDir)) { + process.exit(0); +} + +// Check if auto-capture is enabled +const sessionMd = path.join(sessionDir, 'session.md'); +if (fs.existsSync(sessionMd)) { + try { + const content = fs.readFileSync(sessionMd, 'utf8'); + if (content.includes('Auto-capture: disabled')) { + process.exit(0); + } + } catch (err) { + // Continue if we can't read the file + } +} + +// File paths +const stateFile = path.join(sessionDir, '.auto-capture-state'); + +// Use lock to prevent race conditions during state read-modify-write +const lock = lockManager.acquireLock(`auto-capture-${activeSession}`, { + timeout: 1000, + wait: true +}); + +if (!lock.acquired) { + // Could not acquire lock - skip this update to avoid blocking + // The next interaction will pick up the count + process.exit(0); +} + +try { + // Initialize state if doesn't exist + let state = { + file_count: 0, + interaction_count: 0, + interactions_since_context_update: 0, + interactions_since_snapshot: 0, + last_context_update: '', + last_snapshot_timestamp: '' + }; + + if (fs.existsSync(stateFile)) { + try { + state = JSON.parse(fs.readFileSync(stateFile, 'utf8')); + // Ensure Living Context fields exist + state.interactions_since_context_update = state.interactions_since_context_update || 0; + state.interactions_since_snapshot = state.interactions_since_snapshot || 0; + state.last_context_update = state.last_context_update || ''; + state.last_snapshot_timestamp = state.last_snapshot_timestamp || ''; + } catch (err) { + // Use default state if parse fails + } + } + + // Increment interaction count + state.interaction_count++; + state.interactions_since_context_update++; + state.interactions_since_snapshot++; + + // INCREMENTAL LOGGING SYSTEM: Log conversation for later consolidation + // This replaces the blocking snapshot system with fast (~1-2ms) logging + const timestamp = new Date().toISOString(); + + // Read stdin to get transcript path and user prompt + let transcriptPath = null; + let userPrompt = null; + try { + const stdinData = fs.readFileSync(0, 'utf8').trim(); + if (stdinData) { + const eventData = JSON.parse(stdinData); + transcriptPath = eventData.transcript_path || null; + userPrompt = eventData.prompt || null; + } + } catch (stdinErr) { + // If we can't read stdin, continue without transcript path + // This ensures hook doesn't fail if stdin format changes + } + + // Log interaction incrementally (non-blocking, ~1-2ms) + try { + const ConversationLogger = require('../cli/lib/conversation-logger'); + const logger = new ConversationLogger(sessionDir); + + logger.logInteraction({ + num: state.interaction_count, + timestamp: timestamp, + transcript_path: transcriptPath, + user_prompt: userPrompt, + state: state, + modified_files: state.modified_files || [] + }); + } catch (err) { + // Silent failure - don't block hook execution + // Consolidation will work with whatever data is available + } + + // Note: Snapshot consolidation now happens at session start/continue + // via consolidate-worker.js running in background + // This eliminates the 10-15 second blocking issue + + // Update state file atomically + const tempPath = `${stateFile}.tmp.${Date.now()}`; + try { + fs.writeFileSync(tempPath, JSON.stringify(state, null, 2)); + fs.renameSync(tempPath, stateFile); + } catch (writeError) { + // Clean up temp file + if (fs.existsSync(tempPath)) { + try { + fs.unlinkSync(tempPath); + } catch (cleanupError) { + // Ignore + } + } + throw writeError; + } + } finally { + // Always release lock + lock.release(); + } + + // ORPHAN DETECTION: Check for orphaned hooks every 20 prompts + // This auto-cleans up hooks if plugin was uninstalled without cleanup + try { + const orphanCheckFile = path.join(SESSIONS_DIR, '.orphan-check-counter'); + let checkCounter = 0; + + if (fs.existsSync(orphanCheckFile)) { + try { + checkCounter = parseInt(fs.readFileSync(orphanCheckFile, 'utf8').trim(), 10) || 0; + } catch (e) { + // Use default + } + } + + checkCounter++; + + // Check every 20 prompts + if (checkCounter >= 20) { + const HooksManager = require('../cli/lib/hooks-manager'); + const pluginRoot = path.dirname(__dirname); + const manager = new HooksManager(process.cwd()); + + // Detect orphaned hooks + const settings = manager.readSettings(); + const orphaned = manager.detectOrphanedHooks(settings, pluginRoot); + + if (orphaned.length > 0) { + // Auto-cleanup orphaned hooks + const cleaned = manager.removePluginHooks(settings, pluginRoot); + manager.createBackup(); + manager.writeSettings(cleaned); + + // NOTE: We cannot inject context here as this is UserPromptSubmit hook + // The cleanup happens silently in the background + } + + checkCounter = 0; // Reset counter + } + + // Write counter back + fs.writeFileSync(orphanCheckFile, checkCounter.toString()); + } catch (orphanError) { + // Silent failure - don't block hook execution + } + + process.exit(0); + +} catch (error) { + // Outer catch: Handle plugin missing/uninstalled + // Exit silently to avoid blocking Claude Code + process.exit(0); +} diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..b6e7795 --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,153 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:awudevelop/claude-plugins:session", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "6ec7a588b3153f448ed95229402b71570157359c", + "treeHash": "064dd651da7c4c8e8214c1c6289c9072110d35aa2e92a597f7db105870faca37", + "generatedAt": "2025-11-28T10:14:05.352142Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "session", + "description": "v3.17.4 - Advanced session management for Claude Code with intelligent context tracking, automatic snapshots, and git history capture. Features zero-blocking conversation logging, AI-powered analysis, and optimized parallel subagent architecture. Never lose context!", + "version": "3.17.4" + }, + "content": { + "files": [ + { + "path": "README.md", + "sha256": "3c319320ab963e04cd6c699198b7f6db1b3d89804a940d8f6cf1c12c11abf37c" + }, + { + "path": "hooks/stop.js", + "sha256": "37a676c6d29bff787dd6f3d18b86e4e14c92c0699c7ff32a352da3208c59d203" + }, + { + "path": "hooks/post-tool-use.js", + "sha256": "4917273a37d71ecda0dc832cd1c452a3e8b7335a9984600301f644d5d9d486da" + }, + { + "path": "hooks/session-start.js", + "sha256": "f62f244cb4129d1b67c819e5c6dff01b8b3e4b9b6afe5183132e70bc3f38d23b" + }, + { + "path": "hooks/session-end.js", + "sha256": "20a3105b844442ba037bec12db191530e8fc40fb2d0a26336f188e55434a0e7a" + }, + { + "path": "hooks/hooks.json", + "sha256": "0f1dbf53520fd253698253ff9486d5ae036d3ca51af5dc9c402e37084d8f50c2" + }, + { + "path": "hooks/user-prompt-submit.js", + "sha256": "b1fb6c52127d2f3d9953efef04578f762dd89982f9323ca2b50de63d026edac4" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "3af37a81dae483514f556399eaba1620a25a8f6a6b9c5a527977adffe6cda128" + }, + { + "path": "commands/plan-list.md", + "sha256": "693693eb8e5cd2006b9c4fa1f6b49ecf0633d9266bd2d08f665b293c66f99962" + }, + { + "path": "commands/project-maps-stats.md", + "sha256": "a374903c057cba5fecca3d7c74da3f350d69c59ef79c356f54516b9b5d437b95" + }, + { + "path": "commands/plan-status.md", + "sha256": "8d16bcb657e39a8511e4ae9aa8e20ddb3b4a33e208d1e19bf97370b3d4a365b7" + }, + { + "path": "commands/plan-finalize.md", + "sha256": "454a4840bb50554491864231774d6260f896a1e39955ceda2d1814e770327641" + }, + { + "path": "commands/project-maps-load.md", + "sha256": "d1f854feeda94633aa2a0846bb4a1c1cd4193765055f84fda564dd4a211c42b0" + }, + { + "path": "commands/plan-save.md", + "sha256": "f3e2eddab439fccbfac377a18834262b0548e3d9ebd95e809bab7089f6035849" + }, + { + "path": "commands/continue.md", + "sha256": "5980d87156eecdd37a4457d9e786047a1fe72e6d3fbe9454525897fc7a25d954" + }, + { + "path": "commands/setup.md", + "sha256": "2d98544ae5c7de808eb768cca498ef85ffb698a35440d965384687c28345f234" + }, + { + "path": "commands/status.md", + "sha256": "cdcfb2408bfced31d88cb0e630f51912a36ce74e90874bf76f06d2062d068381" + }, + { + "path": "commands/plan-execute.md", + "sha256": "fbb322c14fdbc6c6f6be144a311e0f85487ffc9ed42902c2ad114d5bd969541a" + }, + { + "path": "commands/continue.md.v3.6.4.backup", + "sha256": "2bf5ae7c4e32882a698f7551cad3551f59f6254fef465419ba9b25d1e3359857" + }, + { + "path": "commands/project-maps-refresh.md", + "sha256": "e1a33fed3e0663826ec6d7d3ee3d4d9df84d95f6b205a8cc6bc93b02ab850a17" + }, + { + "path": "commands/list.md", + "sha256": "1646d0b1670563cd520649efacdf09946a65f48c9d5d2ed49a9723b91d9d56f8" + }, + { + "path": "commands/close.md", + "sha256": "888bd9d87e8f2b0a4360ee36f1661a2cfbc0a0f5f8a40aa880ff4b266d7a4c9f" + }, + { + "path": "commands/project-maps-query.md", + "sha256": "6abcad95011a19f3f89de02efa5ca0d698abde6c7c7c2f4746c5bb2c16d448b1" + }, + { + "path": "commands/git-decompress.md", + "sha256": "eb3585f1fa09c96785d8d6b0ccfcbf0c6e7078b52969b0914a338233ab84b4bd" + }, + { + "path": "commands/delete.md", + "sha256": "10aa0161ee9a2dd3b29b02d6b7061f591d64ee9c6810c337ec7c4a7593137561" + }, + { + "path": "commands/save.md", + "sha256": "5fc88d41d7c9dd80cfee82cf01f886452bf461557533286841bd8f7bf5f54a10" + }, + { + "path": "commands/project-maps-generate.md", + "sha256": "7d1183f203b4fa3f51705c999d66ac4963af275b661129d1f4f61adc9bfe6b76" + }, + { + "path": "commands/start.md", + "sha256": "ef5fb5dde77fdaecd887c384c0926c1987822c42f885b40cbe5794a9893439ec" + }, + { + "path": "commands/project-maps-list.md", + "sha256": "d01bb7d92e97dae0e09742997dd15c42672ca45e735502f199d6beb899106313" + }, + { + "path": "commands/plan-update.md", + "sha256": "9c0bb605c3d31f36999a128cfee4a677c2ec7f2d61c9da178ac3c6cf9fe254a9" + } + ], + "dirSha256": "064dd651da7c4c8e8214c1c6289c9072110d35aa2e92a597f7db105870faca37" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file