coder-config 0.42.30 → 0.42.31

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 CHANGED
@@ -396,6 +396,9 @@ Context is automatically restored within 24 hours of being saved.
396
396
 
397
397
  ### Setup
398
398
 
399
+ **From the UI:** Go to **System > Sessions** and click "Install All"
400
+
401
+ **From the CLI:**
399
402
  ```bash
400
403
  coder-config session install
401
404
  ```
@@ -1,36 +1,15 @@
1
1
  #!/bin/bash
2
- # Session End Hook - Save session info for potential resume
3
- # Install: Add to ~/.claude/settings.json hooks.SessionEnd
2
+ # Session End Hook - Log session info
3
+ # Context is saved by /flush to .claude/session-context.md (project-local)
4
4
 
5
5
  # Read hook input
6
6
  INPUT=$(cat)
7
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
8
 
12
9
  # Skip if no session ID
13
10
  [ -z "$SESSION_ID" ] && exit 0
14
11
 
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
12
+ # Log session end (optional, for debugging)
13
+ # echo "Session $SESSION_ID ended" >> /tmp/claude-sessions.log
35
14
 
36
15
  exit 0
@@ -1,35 +1,13 @@
1
1
  #!/bin/bash
2
2
  # Session Start Hook - Restore context from previous session
3
- # Install: Add to ~/.claude/settings.json hooks.SessionStart
3
+ # Context is stored in .claude/session-context.md (project-local)
4
4
 
5
- # Session state directory
6
- STATE_DIR="$HOME/.coder-config/sessions"
5
+ PROJECT_CONTEXT=".claude/session-context.md"
7
6
 
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
7
+ if [ -f "$PROJECT_CONTEXT" ]; then
8
+ echo "<session-context source=\"project\">"
9
+ cat "$PROJECT_CONTEXT"
10
+ echo "</session-context>"
33
11
  fi
34
12
 
35
13
  exit 0
package/lib/constants.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * Constants and tool path configurations
3
3
  */
4
4
 
5
- const VERSION = '0.42.30';
5
+ const VERSION = '0.42.31';
6
6
 
7
7
  // Tool-specific path configurations
8
8
  const TOOL_PATHS = {
package/lib/sessions.js CHANGED
@@ -1,56 +1,28 @@
1
1
  /**
2
2
  * Session persistence management
3
- * Saves and restores Claude Code session context
3
+ * Context is stored in project-local .claude/session-context.md
4
4
  */
5
5
 
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
8
  const os = require('os');
9
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
10
  /**
16
- * Ensure session directory exists
11
+ * Get session status for a project
17
12
  */
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();
13
+ function getSessionStatus(projectDir = process.cwd()) {
14
+ const contextFile = path.join(projectDir, '.claude', 'session-context.md');
29
15
 
30
16
  const status = {
31
17
  hasSavedContext: false,
32
- lastSession: null,
18
+ contextPath: contextFile,
33
19
  contextAge: null,
34
20
  };
35
21
 
36
- // Check for flushed context
37
- if (fs.existsSync(LAST_FLUSHED_FILE)) {
22
+ if (fs.existsSync(contextFile)) {
38
23
  status.hasSavedContext = true;
39
- const stat = fs.statSync(LAST_FLUSHED_FILE);
24
+ const stat = fs.statSync(contextFile);
40
25
  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
26
  }
55
27
 
56
28
  return status;
@@ -66,74 +38,41 @@ function showSessionStatus() {
66
38
 
67
39
  if (status.hasSavedContext) {
68
40
  console.log(` Saved context: Yes`);
41
+ console.log(` Location: ${status.contextPath}`);
69
42
  if (status.contextAge !== null) {
70
43
  if (status.contextAge < 60) {
71
- console.log(` Context age: ${status.contextAge} minutes`);
44
+ console.log(` Age: ${status.contextAge} minutes`);
72
45
  } else if (status.contextAge < 1440) {
73
- console.log(` Context age: ${Math.floor(status.contextAge / 60)} hours`);
46
+ console.log(` Age: ${Math.floor(status.contextAge / 60)} hours`);
74
47
  } else {
75
- console.log(` Context age: ${Math.floor(status.contextAge / 1440)} days`);
48
+ console.log(` Age: ${Math.floor(status.contextAge / 1440)} days`);
76
49
  }
77
50
  }
78
51
  } else {
79
52
  console.log(' Saved context: None');
53
+ console.log(` Expected at: ${status.contextPath}`);
80
54
  }
81
55
 
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
- }
56
+ console.log('\nTo save context, use /flush in Claude Code.');
96
57
  }
97
58
 
98
59
  /**
99
- * Print instructions for manual flush
100
- * (Actual flush happens in Claude Code via /flush command)
60
+ * Print instructions for flush
101
61
  */
102
62
  function flushContext() {
103
63
  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');
64
+ console.log('Use /flush in Claude Code to save session context.');
65
+ console.log('Context is saved to: .claude/session-context.md');
111
66
  }
112
67
 
113
68
  /**
114
69
  * Clear saved session context
115
70
  */
116
- function clearContext() {
117
- ensureSessionDir();
118
-
119
- let cleared = false;
71
+ function clearContext(projectDir = process.cwd()) {
72
+ const contextFile = path.join(projectDir, '.claude', 'session-context.md');
120
73
 
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) {
74
+ if (fs.existsSync(contextFile)) {
75
+ fs.unlinkSync(contextFile);
137
76
  console.log('Session context cleared.');
138
77
  } else {
139
78
  console.log('No session context to clear.');
@@ -147,12 +86,10 @@ function installHooks() {
147
86
  const claudeDir = path.join(os.homedir(), '.claude');
148
87
  const settingsFile = path.join(claudeDir, 'settings.json');
149
88
 
150
- // Ensure .claude directory exists
151
89
  if (!fs.existsSync(claudeDir)) {
152
90
  fs.mkdirSync(claudeDir, { recursive: true });
153
91
  }
154
92
 
155
- // Load existing settings
156
93
  let settings = {};
157
94
  if (fs.existsSync(settingsFile)) {
158
95
  try {
@@ -163,31 +100,22 @@ function installHooks() {
163
100
  }
164
101
  }
165
102
 
166
- // Initialize hooks if needed
167
103
  if (!settings.hooks) {
168
104
  settings.hooks = {};
169
105
  }
170
106
 
171
- // Find coder-config hooks directory
172
107
  const hooksSrcDir = path.join(__dirname, '..', 'hooks');
173
108
  const sessionStartHook = path.join(hooksSrcDir, 'session-start.sh');
174
- const sessionEndHook = path.join(hooksSrcDir, 'session-end.sh');
175
109
 
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}`);
110
+ if (!fs.existsSync(sessionStartHook)) {
111
+ console.error('Session hook not found:', sessionStartHook);
182
112
  return;
183
113
  }
184
114
 
185
- // Make hooks executable
186
115
  try {
187
116
  fs.chmodSync(sessionStartHook, '755');
188
- fs.chmodSync(sessionEndHook, '755');
189
117
  } catch (e) {
190
- console.warn('Could not set executable permission on hooks:', e.message);
118
+ // Continue even if chmod fails
191
119
  }
192
120
 
193
121
  // Add SessionStart hook
@@ -198,54 +126,30 @@ function installHooks() {
198
126
  settings.hooks.SessionStart = [settings.hooks.SessionStart];
199
127
  }
200
128
 
201
- // Check if our hook is already installed
202
- const startHookEntry = { type: 'command', command: sessionStartHook };
203
129
  const hasStartHook = settings.hooks.SessionStart.some(h =>
204
130
  typeof h === 'object' && h.command === sessionStartHook
205
131
  );
206
132
  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];
133
+ settings.hooks.SessionStart.push({ type: 'command', command: sessionStartHook });
216
134
  }
217
135
 
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
136
  try {
228
137
  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.');
138
+ console.log('Session hook installed.\n');
139
+ console.log('SessionStart hook restores context from .claude/session-context.md');
140
+ console.log('Use /flush in Claude Code to save context.');
235
141
  } catch (e) {
236
142
  console.error('Error writing settings.json:', e.message);
237
143
  }
238
144
  }
239
145
 
240
146
  /**
241
- * Get flushed context content (for hooks)
147
+ * Get flushed context content
242
148
  */
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');
149
+ function getFlushedContext(projectDir = process.cwd()) {
150
+ const contextFile = path.join(projectDir, '.claude', 'session-context.md');
151
+ if (fs.existsSync(contextFile)) {
152
+ return fs.readFileSync(contextFile, 'utf8');
249
153
  }
250
154
  return null;
251
155
  }
@@ -258,21 +162,17 @@ function installFlushCommand() {
258
162
  const commandsDir = path.join(claudeDir, 'commands');
259
163
  const destFile = path.join(commandsDir, 'flush.md');
260
164
 
261
- // Find the template
262
165
  const templateFile = path.join(__dirname, '..', 'templates', 'commands', 'flush.md');
263
166
 
264
167
  if (!fs.existsSync(templateFile)) {
265
168
  console.error('Flush command template not found.');
266
- console.log(`Expected: ${templateFile}`);
267
169
  return false;
268
170
  }
269
171
 
270
- // Ensure commands directory exists
271
172
  if (!fs.existsSync(commandsDir)) {
272
173
  fs.mkdirSync(commandsDir, { recursive: true });
273
174
  }
274
175
 
275
- // Check if command already exists
276
176
  if (fs.existsSync(destFile)) {
277
177
  const existing = fs.readFileSync(destFile, 'utf8');
278
178
  const template = fs.readFileSync(templateFile, 'utf8');
@@ -280,15 +180,10 @@ function installFlushCommand() {
280
180
  console.log('/flush command already installed.');
281
181
  return true;
282
182
  }
283
- // Backup existing
284
- const backupFile = path.join(commandsDir, 'flush.md.bak');
285
- fs.copyFileSync(destFile, backupFile);
286
- console.log(`Backed up existing /flush to ${backupFile}`);
287
183
  }
288
184
 
289
- // Copy template
290
185
  fs.copyFileSync(templateFile, destFile);
291
- console.log('/flush command installed to ~/.claude/commands/flush.md');
186
+ console.log('/flush command installed.');
292
187
  return true;
293
188
  }
294
189
 
@@ -297,17 +192,10 @@ function installFlushCommand() {
297
192
  */
298
193
  function installAll() {
299
194
  console.log('Installing session persistence...\n');
300
-
301
- // Install hooks
302
195
  installHooks();
303
-
304
196
  console.log('');
305
-
306
- // Install command
307
197
  installFlushCommand();
308
-
309
- console.log('\nSession persistence setup complete!');
310
- console.log('Use /flush in Claude Code to save context before exiting.');
198
+ console.log('\nUse /flush in Claude Code to save context before exiting.');
311
199
  }
312
200
 
313
201
  module.exports = {
@@ -319,6 +207,4 @@ module.exports = {
319
207
  getFlushedContext,
320
208
  installFlushCommand,
321
209
  installAll,
322
- SESSION_DIR,
323
- FLUSHED_CONTEXT_FILE,
324
210
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coder-config",
3
- "version": "0.42.30",
3
+ "version": "0.42.31",
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",
@@ -1,6 +1,6 @@
1
1
  # Flush Context to Resumable Doc
2
2
 
3
- Save all current session context to a resumable document that will be automatically restored on the next session start.
3
+ Save all current session context to a resumable document in the current project's `.claude/` directory.
4
4
 
5
5
  ## Instructions
6
6
 
@@ -12,9 +12,11 @@ Save all current session context to a resumable document that will be automatica
12
12
  - **Pending Work**: What still needs to be done
13
13
  - **Important Context**: Any critical information needed to continue
14
14
 
15
- 2. Write this summary to: `~/.coder-config/sessions/flushed-context.md`
15
+ 2. Determine the project root (where `.git/` or `.claude/` exists) and write this summary to: `<project-root>/.claude/session-context.md`
16
+ - If `.claude/` directory doesn't exist, create it
17
+ - This keeps the context local to this specific project
16
18
 
17
- 3. Confirm to the user that context has been saved and will be restored on next session.
19
+ 3. Confirm to the user that context has been saved to the project directory and will be available on the next session in this project.
18
20
 
19
21
  ## Output Format
20
22