coder-config 0.42.23 → 0.42.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -2
- package/config-loader.js +11 -0
- package/hooks/session-end.sh +36 -0
- package/hooks/session-start.sh +35 -0
- package/lib/cli.js +19 -0
- package/lib/constants.js +1 -1
- package/lib/sessions.js +262 -0
- package/package.json +1 -1
- package/templates/commands/flush.md +47 -0
- package/ui/dist/assets/{index-BBAJoPTR.js → index-BYU08qhX.js} +139 -127
- package/ui/dist/index.html +1 -1
package/README.md
CHANGED
|
@@ -211,7 +211,9 @@ coder-config workstream auto-activate "My Work" off # Never auto-activate
|
|
|
211
211
|
coder-config workstream auto-activate "My Work" default # Use global setting
|
|
212
212
|
```
|
|
213
213
|
|
|
214
|
-
### Loop Commands (Ralph Loop)
|
|
214
|
+
### Loop Commands (Ralph Loop) - Experimental
|
|
215
|
+
|
|
216
|
+
> **Note:** Ralph Loops is an experimental feature, disabled by default. Enable it in the Web UI under **Preferences > Experimental Features**.
|
|
215
217
|
|
|
216
218
|
Ralph Loops enable autonomous development - Claude Code runs continuously until a task is completed.
|
|
217
219
|
|
|
@@ -268,7 +270,7 @@ coder-config update --check # Check for updates without installing
|
|
|
268
270
|
coder-config update /path/src # Update from local development source
|
|
269
271
|
```
|
|
270
272
|
|
|
271
|
-
The UI
|
|
273
|
+
The UI checks for updates automatically and auto-updates when enabled in Preferences. After server updates, the UI auto-refreshes to load the new version.
|
|
272
274
|
|
|
273
275
|
### Web UI
|
|
274
276
|
|
|
@@ -380,6 +382,44 @@ Persistent memory for Claude Code sessions.
|
|
|
380
382
|
|
|
381
383
|
Manage via Web UI or edit files directly.
|
|
382
384
|
|
|
385
|
+
## Session Persistence
|
|
386
|
+
|
|
387
|
+
Save context from a Claude Code session and restore it on the next session start.
|
|
388
|
+
|
|
389
|
+
### How It Works
|
|
390
|
+
|
|
391
|
+
1. **Save context** - Use `/flush` in Claude Code to write a context summary
|
|
392
|
+
2. **Auto-preserve** - The `session-end` hook preserves your flushed context when the session ends
|
|
393
|
+
3. **Auto-restore** - The `session-start` hook injects saved context into your next session
|
|
394
|
+
|
|
395
|
+
Context is automatically restored within 24 hours of being saved.
|
|
396
|
+
|
|
397
|
+
### Setup
|
|
398
|
+
|
|
399
|
+
```bash
|
|
400
|
+
# Install the Claude Code hooks
|
|
401
|
+
coder-config session install-hooks
|
|
402
|
+
|
|
403
|
+
# Copy the /flush command to your Claude Code commands
|
|
404
|
+
cp /path/to/coder-config/templates/commands/flush.md ~/.claude/commands/
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### CLI Commands
|
|
408
|
+
|
|
409
|
+
```bash
|
|
410
|
+
coder-config session # Show session status
|
|
411
|
+
coder-config session flush # Instructions for saving context
|
|
412
|
+
coder-config session clear # Clear saved context
|
|
413
|
+
coder-config session install-hooks # Install Claude Code hooks
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Storage Location
|
|
417
|
+
|
|
418
|
+
Session data is stored in `~/.coder-config/sessions/`:
|
|
419
|
+
- `flushed-context.md` - Context saved by /flush command
|
|
420
|
+
- `last-flushed-context.md` - Preserved context from last session end
|
|
421
|
+
- `last-session.json` - Metadata about the last session
|
|
422
|
+
|
|
383
423
|
## Workstreams
|
|
384
424
|
|
|
385
425
|
Workstreams are **context sets** for multi-project workflows. They group related projects and inject context rules into every Claude session.
|
package/config-loader.js
CHANGED
|
@@ -31,6 +31,7 @@ const { getProjectsRegistryPath, loadProjectsRegistry, saveProjectsRegistry, pro
|
|
|
31
31
|
const { getWorkstreamsPath, loadWorkstreams, saveWorkstreams, workstreamList, workstreamCreate, workstreamUpdate, workstreamDelete, workstreamUse, workstreamActive, workstreamAddProject, workstreamRemoveProject, workstreamInject, workstreamDetect, workstreamGet, getActiveWorkstream, countWorkstreamsForProject, workstreamInstallHook, workstreamInstallHookGemini, workstreamInstallHookCodex, workstreamDeactivate, workstreamCheckPath, getSettingsPath, loadSettings, saveSettings, workstreamAddTrigger, workstreamRemoveTrigger, workstreamSetAutoActivate, setGlobalAutoActivate, shouldAutoActivate, workstreamCheckFolder, workstreamInstallCdHook, workstreamUninstallCdHook, workstreamCdHookStatus } = require('./lib/workstreams');
|
|
32
32
|
const { getActivityPath, getDefaultActivity, loadActivity, saveActivity, detectProjectRoot, activityLog, activitySummary, generateWorkstreamName, activitySuggestWorkstreams, activityClear } = require('./lib/activity');
|
|
33
33
|
const { getLoopsPath, loadLoops, saveLoops, loadLoopState, saveLoopState, loadHistory, saveHistory, loopList, loopCreate, loopGet, loopUpdate, loopDelete, loopStart, loopPause, loopResume, loopCancel, loopApprove, loopComplete, loopStatus, loopHistory, loopConfig, getActiveLoop, recordIteration, saveClarifications, savePlan, loadClarifications, loadPlan, loopInject, archiveLoop } = require('./lib/loops');
|
|
34
|
+
const { getSessionStatus, showSessionStatus, flushContext, clearContext, installHooks: sessionInstallHooks, getFlushedContext, SESSION_DIR, FLUSHED_CONTEXT_FILE } = require('./lib/sessions');
|
|
34
35
|
const { runCli } = require('./lib/cli');
|
|
35
36
|
|
|
36
37
|
class ClaudeConfigManager {
|
|
@@ -205,6 +206,16 @@ class ClaudeConfigManager {
|
|
|
205
206
|
activitySuggestWorkstreams() { return activitySuggestWorkstreams(this.installDir); }
|
|
206
207
|
activityClear(olderThanDays) { return activityClear(this.installDir, olderThanDays); }
|
|
207
208
|
|
|
209
|
+
// Sessions
|
|
210
|
+
getSessionStatus() { return getSessionStatus(); }
|
|
211
|
+
sessionStatus() { return showSessionStatus(); }
|
|
212
|
+
sessionFlush() { return flushContext(); }
|
|
213
|
+
sessionClear() { return clearContext(); }
|
|
214
|
+
sessionInstallHooks() { return sessionInstallHooks(); }
|
|
215
|
+
getFlushedContext() { return getFlushedContext(); }
|
|
216
|
+
getSessionDir() { return SESSION_DIR; }
|
|
217
|
+
getFlushedContextPath() { return FLUSHED_CONTEXT_FILE; }
|
|
218
|
+
|
|
208
219
|
// Update - check npm for updates or update from local source
|
|
209
220
|
async update(args = []) {
|
|
210
221
|
const https = require('https');
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Session End Hook - Save session info for potential resume
|
|
3
|
+
# Install: Add to ~/.claude/settings.json hooks.SessionEnd
|
|
4
|
+
|
|
5
|
+
# Read hook input
|
|
6
|
+
INPUT=$(cat)
|
|
7
|
+
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // empty')
|
|
8
|
+
TRANSCRIPT_PATH=$(echo "$INPUT" | jq -r '.transcript_path // empty')
|
|
9
|
+
CWD=$(echo "$INPUT" | jq -r '.cwd // empty')
|
|
10
|
+
REASON=$(echo "$INPUT" | jq -r '.reason // empty')
|
|
11
|
+
|
|
12
|
+
# Skip if no session ID
|
|
13
|
+
[ -z "$SESSION_ID" ] && exit 0
|
|
14
|
+
|
|
15
|
+
# Session state directory
|
|
16
|
+
STATE_DIR="$HOME/.coder-config/sessions"
|
|
17
|
+
mkdir -p "$STATE_DIR"
|
|
18
|
+
|
|
19
|
+
# Save session metadata
|
|
20
|
+
cat > "$STATE_DIR/last-session.json" << EOF
|
|
21
|
+
{
|
|
22
|
+
"session_id": "$SESSION_ID",
|
|
23
|
+
"transcript_path": "$TRANSCRIPT_PATH",
|
|
24
|
+
"cwd": "$CWD",
|
|
25
|
+
"reason": "$REASON",
|
|
26
|
+
"timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
|
27
|
+
}
|
|
28
|
+
EOF
|
|
29
|
+
|
|
30
|
+
# If there's a flushed context file, preserve it
|
|
31
|
+
FLUSH_FILE="$STATE_DIR/flushed-context.md"
|
|
32
|
+
if [ -f "$FLUSH_FILE" ]; then
|
|
33
|
+
cp "$FLUSH_FILE" "$STATE_DIR/last-flushed-context.md"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
exit 0
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Session Start Hook - Restore context from previous session
|
|
3
|
+
# Install: Add to ~/.claude/settings.json hooks.SessionStart
|
|
4
|
+
|
|
5
|
+
# Session state directory
|
|
6
|
+
STATE_DIR="$HOME/.coder-config/sessions"
|
|
7
|
+
|
|
8
|
+
# Check for saved context to inject
|
|
9
|
+
LAST_CONTEXT="$STATE_DIR/last-flushed-context.md"
|
|
10
|
+
LAST_SESSION="$STATE_DIR/last-session.json"
|
|
11
|
+
|
|
12
|
+
# Only inject if we have flushed context
|
|
13
|
+
if [ -f "$LAST_CONTEXT" ]; then
|
|
14
|
+
# Check if context is recent (within 24 hours)
|
|
15
|
+
if [ "$(uname)" = "Darwin" ]; then
|
|
16
|
+
# macOS
|
|
17
|
+
FILE_AGE=$(( $(date +%s) - $(stat -f %m "$LAST_CONTEXT") ))
|
|
18
|
+
else
|
|
19
|
+
# Linux
|
|
20
|
+
FILE_AGE=$(( $(date +%s) - $(stat -c %Y "$LAST_CONTEXT") ))
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
# 24 hours = 86400 seconds
|
|
24
|
+
if [ "$FILE_AGE" -lt 86400 ]; then
|
|
25
|
+
# Output context - Claude will see this in the session
|
|
26
|
+
echo "<session-context source=\"previous-session\">"
|
|
27
|
+
echo "The following context was saved from a previous session:"
|
|
28
|
+
echo ""
|
|
29
|
+
cat "$LAST_CONTEXT"
|
|
30
|
+
echo ""
|
|
31
|
+
echo "</session-context>"
|
|
32
|
+
fi
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
exit 0
|
package/lib/cli.js
CHANGED
|
@@ -272,6 +272,19 @@ function runCli(manager) {
|
|
|
272
272
|
}
|
|
273
273
|
break;
|
|
274
274
|
|
|
275
|
+
// Session management
|
|
276
|
+
case 'session':
|
|
277
|
+
if (args[1] === 'flush') {
|
|
278
|
+
manager.sessionFlush();
|
|
279
|
+
} else if (args[1] === 'clear') {
|
|
280
|
+
manager.sessionClear();
|
|
281
|
+
} else if (args[1] === 'install-hooks') {
|
|
282
|
+
manager.sessionInstallHooks();
|
|
283
|
+
} else {
|
|
284
|
+
manager.sessionStatus();
|
|
285
|
+
}
|
|
286
|
+
break;
|
|
287
|
+
|
|
275
288
|
// Maintenance
|
|
276
289
|
case 'update':
|
|
277
290
|
manager.update(args.slice(1)).catch(err => {
|
|
@@ -392,6 +405,12 @@ Workstream Commands:
|
|
|
392
405
|
Per-session activation (enables parallel work):
|
|
393
406
|
export CODER_WORKSTREAM=<name-or-id>
|
|
394
407
|
${loopHelp}
|
|
408
|
+
Session Persistence:
|
|
409
|
+
session Show session status (saved context)
|
|
410
|
+
session flush Manually save current context
|
|
411
|
+
session clear Clear saved session context
|
|
412
|
+
session install-hooks Install Claude Code hooks for session persistence
|
|
413
|
+
|
|
395
414
|
Registry Commands:
|
|
396
415
|
registry List MCPs in global registry
|
|
397
416
|
registry add <name> '<json>' Add MCP to global registry
|
package/lib/constants.js
CHANGED
package/lib/sessions.js
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session persistence management
|
|
3
|
+
* Saves and restores Claude Code session context
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const os = require('os');
|
|
9
|
+
|
|
10
|
+
const SESSION_DIR = path.join(os.homedir(), '.coder-config', 'sessions');
|
|
11
|
+
const LAST_SESSION_FILE = path.join(SESSION_DIR, 'last-session.json');
|
|
12
|
+
const FLUSHED_CONTEXT_FILE = path.join(SESSION_DIR, 'flushed-context.md');
|
|
13
|
+
const LAST_FLUSHED_FILE = path.join(SESSION_DIR, 'last-flushed-context.md');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Ensure session directory exists
|
|
17
|
+
*/
|
|
18
|
+
function ensureSessionDir() {
|
|
19
|
+
if (!fs.existsSync(SESSION_DIR)) {
|
|
20
|
+
fs.mkdirSync(SESSION_DIR, { recursive: true });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get session status
|
|
26
|
+
*/
|
|
27
|
+
function getSessionStatus() {
|
|
28
|
+
ensureSessionDir();
|
|
29
|
+
|
|
30
|
+
const status = {
|
|
31
|
+
hasSavedContext: false,
|
|
32
|
+
lastSession: null,
|
|
33
|
+
contextAge: null,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Check for flushed context
|
|
37
|
+
if (fs.existsSync(LAST_FLUSHED_FILE)) {
|
|
38
|
+
status.hasSavedContext = true;
|
|
39
|
+
const stat = fs.statSync(LAST_FLUSHED_FILE);
|
|
40
|
+
status.contextAge = Math.floor((Date.now() - stat.mtimeMs) / 1000 / 60); // minutes
|
|
41
|
+
} else if (fs.existsSync(FLUSHED_CONTEXT_FILE)) {
|
|
42
|
+
status.hasSavedContext = true;
|
|
43
|
+
const stat = fs.statSync(FLUSHED_CONTEXT_FILE);
|
|
44
|
+
status.contextAge = Math.floor((Date.now() - stat.mtimeMs) / 1000 / 60);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Check for last session metadata
|
|
48
|
+
if (fs.existsSync(LAST_SESSION_FILE)) {
|
|
49
|
+
try {
|
|
50
|
+
status.lastSession = JSON.parse(fs.readFileSync(LAST_SESSION_FILE, 'utf8'));
|
|
51
|
+
} catch (e) {
|
|
52
|
+
// Ignore parse errors
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return status;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Show session status
|
|
61
|
+
*/
|
|
62
|
+
function showSessionStatus() {
|
|
63
|
+
const status = getSessionStatus();
|
|
64
|
+
|
|
65
|
+
console.log('Session Persistence Status\n');
|
|
66
|
+
|
|
67
|
+
if (status.hasSavedContext) {
|
|
68
|
+
console.log(` Saved context: Yes`);
|
|
69
|
+
if (status.contextAge !== null) {
|
|
70
|
+
if (status.contextAge < 60) {
|
|
71
|
+
console.log(` Context age: ${status.contextAge} minutes`);
|
|
72
|
+
} else if (status.contextAge < 1440) {
|
|
73
|
+
console.log(` Context age: ${Math.floor(status.contextAge / 60)} hours`);
|
|
74
|
+
} else {
|
|
75
|
+
console.log(` Context age: ${Math.floor(status.contextAge / 1440)} days`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
console.log(' Saved context: None');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (status.lastSession) {
|
|
83
|
+
console.log(`\n Last session:`);
|
|
84
|
+
console.log(` ID: ${status.lastSession.session_id || 'unknown'}`);
|
|
85
|
+
console.log(` CWD: ${status.lastSession.cwd || 'unknown'}`);
|
|
86
|
+
console.log(` Ended: ${status.lastSession.timestamp || 'unknown'}`);
|
|
87
|
+
console.log(` Reason: ${status.lastSession.reason || 'unknown'}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
console.log(`\n Storage: ${SESSION_DIR}`);
|
|
91
|
+
|
|
92
|
+
if (!status.hasSavedContext) {
|
|
93
|
+
console.log('\nTo save context, use /flush in Claude Code or:');
|
|
94
|
+
console.log(' coder-config session flush');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Print instructions for manual flush
|
|
100
|
+
* (Actual flush happens in Claude Code via /flush command)
|
|
101
|
+
*/
|
|
102
|
+
function flushContext() {
|
|
103
|
+
console.log('Session context flush\n');
|
|
104
|
+
console.log('To save session context, use the /flush command in Claude Code.');
|
|
105
|
+
console.log('This tells Claude to write a summary to:');
|
|
106
|
+
console.log(` ${FLUSHED_CONTEXT_FILE}\n`);
|
|
107
|
+
console.log('The context will be automatically restored on the next session start');
|
|
108
|
+
console.log('(if session hooks are installed).\n');
|
|
109
|
+
console.log('Install hooks with:');
|
|
110
|
+
console.log(' coder-config session install-hooks');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Clear saved session context
|
|
115
|
+
*/
|
|
116
|
+
function clearContext() {
|
|
117
|
+
ensureSessionDir();
|
|
118
|
+
|
|
119
|
+
let cleared = false;
|
|
120
|
+
|
|
121
|
+
if (fs.existsSync(FLUSHED_CONTEXT_FILE)) {
|
|
122
|
+
fs.unlinkSync(FLUSHED_CONTEXT_FILE);
|
|
123
|
+
cleared = true;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (fs.existsSync(LAST_FLUSHED_FILE)) {
|
|
127
|
+
fs.unlinkSync(LAST_FLUSHED_FILE);
|
|
128
|
+
cleared = true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (fs.existsSync(LAST_SESSION_FILE)) {
|
|
132
|
+
fs.unlinkSync(LAST_SESSION_FILE);
|
|
133
|
+
cleared = true;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (cleared) {
|
|
137
|
+
console.log('Session context cleared.');
|
|
138
|
+
} else {
|
|
139
|
+
console.log('No session context to clear.');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Install Claude Code hooks for session persistence
|
|
145
|
+
*/
|
|
146
|
+
function installHooks() {
|
|
147
|
+
const claudeDir = path.join(os.homedir(), '.claude');
|
|
148
|
+
const settingsFile = path.join(claudeDir, 'settings.json');
|
|
149
|
+
|
|
150
|
+
// Ensure .claude directory exists
|
|
151
|
+
if (!fs.existsSync(claudeDir)) {
|
|
152
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Load existing settings
|
|
156
|
+
let settings = {};
|
|
157
|
+
if (fs.existsSync(settingsFile)) {
|
|
158
|
+
try {
|
|
159
|
+
settings = JSON.parse(fs.readFileSync(settingsFile, 'utf8'));
|
|
160
|
+
} catch (e) {
|
|
161
|
+
console.error('Error reading settings.json:', e.message);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Initialize hooks if needed
|
|
167
|
+
if (!settings.hooks) {
|
|
168
|
+
settings.hooks = {};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Find coder-config hooks directory
|
|
172
|
+
const hooksSrcDir = path.join(__dirname, '..', 'hooks');
|
|
173
|
+
const sessionStartHook = path.join(hooksSrcDir, 'session-start.sh');
|
|
174
|
+
const sessionEndHook = path.join(hooksSrcDir, 'session-end.sh');
|
|
175
|
+
|
|
176
|
+
// Verify hooks exist
|
|
177
|
+
if (!fs.existsSync(sessionStartHook) || !fs.existsSync(sessionEndHook)) {
|
|
178
|
+
console.error('Session hooks not found in coder-config package.');
|
|
179
|
+
console.log('Expected locations:');
|
|
180
|
+
console.log(` ${sessionStartHook}`);
|
|
181
|
+
console.log(` ${sessionEndHook}`);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Make hooks executable
|
|
186
|
+
try {
|
|
187
|
+
fs.chmodSync(sessionStartHook, '755');
|
|
188
|
+
fs.chmodSync(sessionEndHook, '755');
|
|
189
|
+
} catch (e) {
|
|
190
|
+
console.warn('Could not set executable permission on hooks:', e.message);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Add SessionStart hook
|
|
194
|
+
if (!settings.hooks.SessionStart) {
|
|
195
|
+
settings.hooks.SessionStart = [];
|
|
196
|
+
}
|
|
197
|
+
if (!Array.isArray(settings.hooks.SessionStart)) {
|
|
198
|
+
settings.hooks.SessionStart = [settings.hooks.SessionStart];
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Check if our hook is already installed
|
|
202
|
+
const startHookEntry = { type: 'command', command: sessionStartHook };
|
|
203
|
+
const hasStartHook = settings.hooks.SessionStart.some(h =>
|
|
204
|
+
typeof h === 'object' && h.command === sessionStartHook
|
|
205
|
+
);
|
|
206
|
+
if (!hasStartHook) {
|
|
207
|
+
settings.hooks.SessionStart.push(startHookEntry);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Add SessionEnd hook
|
|
211
|
+
if (!settings.hooks.SessionEnd) {
|
|
212
|
+
settings.hooks.SessionEnd = [];
|
|
213
|
+
}
|
|
214
|
+
if (!Array.isArray(settings.hooks.SessionEnd)) {
|
|
215
|
+
settings.hooks.SessionEnd = [settings.hooks.SessionEnd];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const endHookEntry = { type: 'command', command: sessionEndHook };
|
|
219
|
+
const hasEndHook = settings.hooks.SessionEnd.some(h =>
|
|
220
|
+
typeof h === 'object' && h.command === sessionEndHook
|
|
221
|
+
);
|
|
222
|
+
if (!hasEndHook) {
|
|
223
|
+
settings.hooks.SessionEnd.push(endHookEntry);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Save settings
|
|
227
|
+
try {
|
|
228
|
+
fs.writeFileSync(settingsFile, JSON.stringify(settings, null, 2));
|
|
229
|
+
console.log('Session hooks installed.\n');
|
|
230
|
+
console.log('Hooks added:');
|
|
231
|
+
console.log(' - SessionStart: Restores saved context');
|
|
232
|
+
console.log(' - SessionEnd: Preserves flushed context\n');
|
|
233
|
+
console.log('To save context before exiting, use /flush in Claude Code.');
|
|
234
|
+
console.log('The saved context will be restored on the next session start.');
|
|
235
|
+
} catch (e) {
|
|
236
|
+
console.error('Error writing settings.json:', e.message);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Get flushed context content (for hooks)
|
|
242
|
+
*/
|
|
243
|
+
function getFlushedContext() {
|
|
244
|
+
if (fs.existsSync(LAST_FLUSHED_FILE)) {
|
|
245
|
+
return fs.readFileSync(LAST_FLUSHED_FILE, 'utf8');
|
|
246
|
+
}
|
|
247
|
+
if (fs.existsSync(FLUSHED_CONTEXT_FILE)) {
|
|
248
|
+
return fs.readFileSync(FLUSHED_CONTEXT_FILE, 'utf8');
|
|
249
|
+
}
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
module.exports = {
|
|
254
|
+
getSessionStatus,
|
|
255
|
+
showSessionStatus,
|
|
256
|
+
flushContext,
|
|
257
|
+
clearContext,
|
|
258
|
+
installHooks,
|
|
259
|
+
getFlushedContext,
|
|
260
|
+
SESSION_DIR,
|
|
261
|
+
FLUSHED_CONTEXT_FILE,
|
|
262
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coder-config",
|
|
3
|
-
"version": "0.42.
|
|
3
|
+
"version": "0.42.26",
|
|
4
4
|
"description": "Configuration manager for AI coding tools - Claude Code, Gemini CLI, Codex CLI, Antigravity. Manage MCPs, rules, permissions, memory, and workstreams.",
|
|
5
5
|
"author": "regression.io",
|
|
6
6
|
"main": "config-loader.js",
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Flush Context to Resumable Doc
|
|
2
|
+
|
|
3
|
+
Save all current session context to a resumable document that will be automatically restored on the next session start.
|
|
4
|
+
|
|
5
|
+
## Instructions
|
|
6
|
+
|
|
7
|
+
1. Create a comprehensive summary of the current session including:
|
|
8
|
+
- **Task Summary**: What the user asked for and the overall goal
|
|
9
|
+
- **Current State**: Where we are in the task (completed, in-progress, blocked)
|
|
10
|
+
- **Key Decisions Made**: Important choices and their rationale
|
|
11
|
+
- **Files Modified**: List of files created or changed
|
|
12
|
+
- **Pending Work**: What still needs to be done
|
|
13
|
+
- **Important Context**: Any critical information needed to continue
|
|
14
|
+
|
|
15
|
+
2. Write this summary to: `~/.coder-config/sessions/flushed-context.md`
|
|
16
|
+
|
|
17
|
+
3. Confirm to the user that context has been saved and will be restored on next session.
|
|
18
|
+
|
|
19
|
+
## Output Format
|
|
20
|
+
|
|
21
|
+
Write the file in this format:
|
|
22
|
+
|
|
23
|
+
```markdown
|
|
24
|
+
# Session Context - [Date]
|
|
25
|
+
|
|
26
|
+
## Task Summary
|
|
27
|
+
[What the user wanted to accomplish]
|
|
28
|
+
|
|
29
|
+
## Current State
|
|
30
|
+
[in-progress | completed | blocked]
|
|
31
|
+
[Brief status description]
|
|
32
|
+
|
|
33
|
+
## Key Decisions
|
|
34
|
+
- [Decision 1]: [Rationale]
|
|
35
|
+
- [Decision 2]: [Rationale]
|
|
36
|
+
|
|
37
|
+
## Files Modified
|
|
38
|
+
- `path/to/file1` - [what was changed]
|
|
39
|
+
- `path/to/file2` - [what was changed]
|
|
40
|
+
|
|
41
|
+
## Pending Work
|
|
42
|
+
- [ ] [Task 1]
|
|
43
|
+
- [ ] [Task 2]
|
|
44
|
+
|
|
45
|
+
## Important Context
|
|
46
|
+
[Any critical information needed to continue this work]
|
|
47
|
+
```
|