feat: Optimize context hook file listings to save tokens

Improvements to SessionStart context hook file display:

1. **Remove redundant files**: Files in "Modified" list are now excluded from "Read" list
   - Prevents duplication when a file was both read and modified
   - Reduces token usage by eliminating redundant information

2. **Use relative paths**: Convert absolute paths to project-relative paths
   - Example: /Users/alexnewman/Scripts/claude-mem/src/hooks/context.ts → src/hooks/context.ts
   - Significantly reduces token consumption in context injection
   - Makes file references more readable and portable

Implementation:
- Added toRelativePath() helper function to convert paths
- Added filesModifiedSet.forEach(file => filesReadSet.delete(file)) to remove duplicates
- Applied to both files_read and files_modified when building Sets

Impact: Reduces token usage in Tier 1 summaries (most recent session) where file lists are displayed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Alex Newman
2025-10-22 17:23:44 -04:00
parent 6441d9103c
commit f556546994
2 changed files with 26 additions and 10 deletions
+18 -2
View File
@@ -181,12 +181,25 @@ export function contextHook(input?: SessionStartInput, useColors: boolean = fals
const filesReadSet = new Set<string>();
const filesModifiedSet = new Set<string>();
// Helper function to convert absolute paths to relative paths
const toRelativePath = (filePath: string): string => {
try {
// Only convert if it's an absolute path
if (path.isAbsolute(filePath)) {
return path.relative(cwd, filePath);
}
return filePath;
} catch {
return filePath;
}
};
for (const obs of observations) {
if (obs.files_read) {
try {
const files = JSON.parse(obs.files_read);
if (Array.isArray(files)) {
files.forEach(f => filesReadSet.add(f));
files.forEach(f => filesReadSet.add(toRelativePath(f)));
}
} catch {
// Skip invalid JSON
@@ -197,7 +210,7 @@ export function contextHook(input?: SessionStartInput, useColors: boolean = fals
try {
const files = JSON.parse(obs.files_modified);
if (Array.isArray(files)) {
files.forEach(f => filesModifiedSet.add(f));
files.forEach(f => filesModifiedSet.add(toRelativePath(f)));
}
} catch {
// Skip invalid JSON
@@ -205,6 +218,9 @@ export function contextHook(input?: SessionStartInput, useColors: boolean = fals
}
}
// Remove files from filesReadSet if they're already in filesModifiedSet (avoid redundancy)
filesModifiedSet.forEach(file => filesReadSet.delete(file));
if (filesReadSet.size > 0) {
if (useColors) {
output.push(`${colors.dim}Files Read: ${Array.from(filesReadSet).join(', ')}${colors.reset}`);