* Refactor CLAUDE.md and related files for December 2025 updates - Updated CLAUDE.md in src/services/worker with new entries for December 2025, including changes to Search.ts, GeminiAgent.ts, SDKAgent.ts, and SessionManager.ts. - Revised CLAUDE.md in src/shared to reflect updates and new entries for December 2025, including paths.ts and worker-utils.ts. - Modified hook-constants.ts to clarify exit codes and their behaviors. - Added comprehensive hooks reference documentation for Claude Code, detailing usage, events, and examples. - Created initial CLAUDE.md files in various directories to track recent activity. * fix: Merge user-message-hook output into context-hook hookSpecificOutput - Add footer message to additionalContext in context-hook.ts - Remove user-message-hook from SessionStart hooks array - Fixes issue where stderr+exit(1) approach was silently discarded Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Update logs and documentation for recent plugin and worker service changes - Added detailed logs for worker service activities from Dec 10, 2025 to Jan 7, 2026, including initialization patterns, cleanup confirmations, and diagnostic logging. - Updated plugin documentation with recent activities, including plugin synchronization and configuration changes from Dec 3, 2025 to Jan 7, 2026. - Enhanced the context hook and worker service logs to reflect improvements and fixes in the plugin architecture. - Documented the migration and verification processes for the Claude memory system and its integration with the marketplace. * Refactor hooks architecture and remove deprecated user-message-hook - Updated hook configurations in CLAUDE.md and hooks.json to reflect changes in session start behavior. - Removed user-message-hook functionality as it is no longer utilized in Claude Code 2.1.0; context is now injected silently. - Enhanced context-hook to handle session context injection without user-visible messages. - Cleaned up documentation across multiple files to align with the new hook structure and removed references to obsolete hooks. - Adjusted timing and command execution for hooks to improve performance and reliability. * fix: Address PR #610 review issues - Replace USER_MESSAGE_ONLY test with BLOCKING_ERROR test in hook-constants.test.ts - Standardize Claude Code 2.1.0 note wording across all three documentation files - Exclude deprecated user-message-hook.ts from logger-usage-standards test Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: Remove hardcoded fake token counts from context injection Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Address PR #610 review issues by fixing test files, standardizing documentation notes, and verifying code quality improvements. * fix: Add path validation to CLAUDE.md distribution to prevent invalid directory creation - Add isValidPathForClaudeMd() function to reject invalid paths: - Tilde paths (~) that Node.js doesn't expand - URLs (http://, https://) - Paths with spaces (likely command text or PR references) - Paths with # (GitHub issue/PR references) - Relative paths that escape project boundary - Integrate validation in updateFolderClaudeMdFiles loop - Add 6 unit tests for path validation - Update .gitignore to prevent accidental commit of malformed directories - Clean up existing invalid directories (~/, PR #610..., git diff..., https:) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * fix: Implement path validation in CLAUDE.md generation to prevent invalid directory creation - Added `isValidPathForClaudeMd()` function to validate file paths in `src/utils/claude-md-utils.ts`. - Integrated path validation in `updateFolderClaudeMdFiles` to skip invalid paths. - Added 6 new unit tests in `tests/utils/claude-md-utils.test.ts` to cover various rejection cases. - Updated `.gitignore` to prevent tracking of invalid directories. - Cleaned up existing invalid directories in the repository. * feat: Promote critical WARN logs to ERROR level across codebase Comprehensive log-level audit promoting 38+ WARN messages to ERROR for improved debugging and incident response: - Parser: observation type errors, data contamination - SDK/Agents: empty init responses (Gemini, OpenRouter) - Worker/Queue: session recovery, auto-recovery failures - Chroma: sync failures, search failures (now treated as critical) - SQLite: search failures (primary data store) - Session/Generator: failures, missing context - Infrastructure: shutdown, process management failures - File Operations: CLAUDE.md updates, config reads - Branch Management: recovery checkout failures Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * fix: Address PR #614 review issues - Remove incorrectly tracked tilde-prefixed files from git - Fix absolute path validation to check projectRoot boundaries - Add test coverage for absolute path validation edge cases Closes review issues: - Issue 1: ~/ prefixed files removed from tracking - Issue 3: Absolute paths now validated against projectRoot - Issue 4: Added 3 new test cases for absolute path scenarios Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * build assets and context --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
10 KiB
Technical Report: Issue #599 - Windows Drive Root 400 Error
Issue: #599 Title: user-message-hook.js fails with 400 error when running from Windows drive root (C:) Author: PakAbhishek Created: 2026-01-07 Severity: Low Priority: Medium Component: Hooks / Session Initialization
1. Executive Summary
When running Claude Code from a Windows drive root directory (e.g., C:\), the user-message-hook.js script fails with a 400 HTTP error during session startup. The root cause is that path.basename('C:\') returns an empty string on Windows, which causes the API call to /api/context/inject?project= to fail with the error "Project(s) parameter is required".
Key Findings:
- The bug is cosmetic only - all core memory functionality continues to work correctly
- A robust fix already exists in
src/utils/project-name.ts(getProjectName()function) but is not used byuser-message-hook.ts - The fix requires updating
user-message-hook.tsto use the existinggetProjectName()utility instead of rawpath.basename() - The
context-hook.tsis already immune to this bug because it usesgetProjectContext()which wrapsgetProjectName()
Affected Files:
src/hooks/user-message-hook.ts(needs fix)plugin/scripts/user-message-hook.js(built artifact, auto-fixed by rebuild)
2. Problem Analysis
2.1 User-Reported Symptoms
-
Error message on Claude Code startup when cwd is
C:\:error: Failed to fetch context: 400 at C:\Users\achau\.claude\plugins\cache\thedotmack\claude-mem\9.0.0\scripts\user-message-hook.js:19:1339 -
The error appears during the SessionStart hook phase
-
Despite the error, all other functionality works correctly:
- Worker health check: passing
- MCP tools: connected and functional
- Memory search: working
- Session observations: saved correctly
2.2 Reproduction Steps
- Open terminal on Windows
- Navigate to drive root:
cd C:\ - Start Claude Code:
claude - Observe the startup error
2.3 Environment
- OS: Windows 11
- claude-mem version: 9.0.0
- Bun version: 1.3.5
- Claude Code: Latest
3. Technical Details
3.1 Code Flow Analysis
The user-message-hook.ts extracts the project name using:
// File: src/hooks/user-message-hook.ts (lines 18-23)
const project = basename(process.cwd());
const response = await fetch(
`http://127.0.0.1:${port}/api/context/inject?project=${encodeURIComponent(project)}&colors=true`,
{ method: 'GET' }
);
When process.cwd() returns C:\, the path.basename() function returns an empty string:
> require('path').basename('C:\\')
''
This results in an API call to:
/api/context/inject?project=&colors=true
3.2 Server-Side Validation
The /api/context/inject endpoint in SearchRoutes.ts performs strict validation:
// File: src/services/worker/http/routes/SearchRoutes.ts (lines 207-223)
private handleContextInject = this.wrapHandler(async (req: Request, res: Response): Promise<void> => {
const projectsParam = (req.query.projects as string) || (req.query.project as string);
const useColors = req.query.colors === 'true';
if (!projectsParam) {
this.badRequest(res, 'Project(s) parameter is required');
return;
}
const projects = projectsParam.split(',').map(p => p.trim()).filter(Boolean);
if (projects.length === 0) {
this.badRequest(res, 'At least one project is required');
return;
}
// ...
});
The validation correctly rejects empty project names, returning HTTP 400.
3.3 Existing Solution
A robust solution already exists in src/utils/project-name.ts:
// File: src/utils/project-name.ts (lines 12-40)
export function getProjectName(cwd: string | null | undefined): string {
if (!cwd || cwd.trim() === '') {
logger.warn('PROJECT_NAME', 'Empty cwd provided, using fallback', { cwd });
return 'unknown-project';
}
const basename = path.basename(cwd);
// Edge case: Drive roots on Windows (C:\, J:\) or Unix root (/)
// path.basename('C:\') returns '' (empty string)
if (basename === '') {
const isWindows = process.platform === 'win32';
if (isWindows) {
const driveMatch = cwd.match(/^([A-Z]):\\/i);
if (driveMatch) {
const driveLetter = driveMatch[1].toUpperCase();
const projectName = `drive-${driveLetter}`;
logger.info('PROJECT_NAME', 'Drive root detected', { cwd, projectName });
return projectName;
}
}
logger.warn('PROJECT_NAME', 'Root directory detected, using fallback', { cwd });
return 'unknown-project';
}
return basename;
}
This function:
- Handles null/undefined cwd
- Handles empty basename (drive roots)
- Returns meaningful names like
drive-C,drive-Dfor Windows drive roots - Returns
unknown-projectfor Unix root or other edge cases
3.4 Comparison: Fixed vs. Unfixed Hooks
| Hook | Implementation | Status |
|---|---|---|
context-hook.ts |
Uses getProjectContext() which calls getProjectName() |
Immune to bug |
user-message-hook.ts |
Uses raw basename(process.cwd()) |
Vulnerable |
new-hook.ts |
Receives cwd from stdin, uses getProjectName() |
Immune to bug |
save-hook.ts |
Uses basename but receives cwd from API context | Context-dependent |
4. Impact Assessment
4.1 Severity: Low
- Functional Impact: Cosmetic only - the error message is displayed but does not affect core functionality
- Data Integrity: No data loss or corruption
- Workaround Available: Yes - run Claude from a project directory instead of drive root
4.2 Affected Users
- Users running Claude Code from Windows drive roots (C:, D:, etc.)
- Estimated as a small percentage of users based on typical usage patterns
- More likely to affect users doing quick tests or troubleshooting
4.3 User Experience Impact
- Confusing error message on startup
- Users may incorrectly believe the plugin is broken
- Error appears in stderr alongside legitimate context information
5. Root Cause Analysis
5.1 Primary Cause
The user-message-hook.ts was implemented using a direct path.basename() call instead of the standardized getProjectName() utility function that handles edge cases.
5.2 Contributing Factors
- Inconsistent Pattern Usage: Different hooks use different approaches to extract project names
- Missing Validation: No client-side validation of project name before making API call
- Edge Case Not Tested: Windows drive root is an unusual but valid working directory
5.3 Historical Context
The getProjectName() utility was added to handle this exact edge case (see src/utils/project-name.ts), but not all hooks were updated to use it. The context-hook.ts uses the newer getProjectContext() function, while user-message-hook.ts still uses the older pattern.
6. Recommended Solutions
6.1 Primary Fix (Recommended)
Update user-message-hook.ts to use the existing getProjectName() utility:
// Current (vulnerable):
import { basename } from "path";
const project = basename(process.cwd());
// Fixed:
import { getProjectName } from "../utils/project-name.js";
const project = getProjectName(process.cwd());
Benefits:
- Uses battle-tested utility
- Consistent with other hooks
- Handles all edge cases (drive roots, Unix root, empty cwd)
- Provides meaningful project names (
drive-C) instead of fallbacks
6.2 Alternative: Inline Fix (User-Suggested)
The user suggested an inline fix in the issue:
let projectName = basename(process.cwd());
if (!projectName || projectName === '') {
const cwd = process.cwd();
projectName = cwd.match(/^([A-Za-z]:)[\\/]?$/)
? `drive-${cwd[0].toUpperCase()}`
: 'unknown-project';
}
Evaluation:
- Functionally correct
- Duplicates existing logic in
getProjectName() - Does not address the pattern inconsistency
- Acceptable if import constraints prevent using the utility
6.3 Additional Improvements (Optional)
-
Add Client-Side Validation:
if (!project || project.trim() === '') { throw new Error('Unable to determine project name from working directory'); } -
Standardize All Hooks: Audit other hooks using
basename(process.cwd())and update to usegetProjectName() -
Add Unit Tests: Create tests for
user-message-hook.tscovering:- Normal project directories
- Windows drive roots (C:, D:)
- Unix root (/)
- Trailing slashes
7. Priority and Severity Assessment
7.1 Classification
| Metric | Value | Justification |
|---|---|---|
| Severity | Low | Cosmetic error only, no functional impact |
| Priority | Medium | User-facing error, easy fix, affects Windows users |
| Effort | Trivial | Single line change + rebuild |
| Risk | Very Low | Using existing, tested utility function |
7.2 Recommendation
Recommended Action: Fix in next patch release (9.0.1)
Rationale:
- Simple fix with minimal risk
- Improves Windows user experience
- Demonstrates responsiveness to community feedback
- Pattern already exists in codebase
7.3 Testing Requirements
- Verify fix on Windows with
C:\as cwd - Verify existing behavior unchanged for normal project directories
- Verify worktree detection still works correctly
- Run full hook test suite
8. Appendix
8.1 Related Files
| File | Purpose | Fix Required |
|---|---|---|
/Users/alexnewman/conductor/workspaces/claude-mem/budapest/src/hooks/user-message-hook.ts |
Source hook (needs fix) | Yes |
/Users/alexnewman/conductor/workspaces/claude-mem/budapest/plugin/scripts/user-message-hook.js |
Built hook | Auto-rebuilds |
/Users/alexnewman/conductor/workspaces/claude-mem/budapest/src/utils/project-name.ts |
Utility (has fix) | No |
/Users/alexnewman/conductor/workspaces/claude-mem/budapest/src/hooks/context-hook.ts |
Reference implementation | No |
/Users/alexnewman/conductor/workspaces/claude-mem/budapest/src/services/worker/http/routes/SearchRoutes.ts |
API validation | No |
8.2 Related Issues
- Windows compatibility has been a focus area, with 56+ memory entries documenting Windows-specific fixes
- This issue follows the pattern of other Windows edge case bugs