coder-config 0.43.14 → 0.43.18

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/lib/constants.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * Constants and tool path configurations
3
3
  */
4
4
 
5
- const VERSION = '0.43.14';
5
+ const VERSION = '0.43.18';
6
6
 
7
7
  // Tool-specific path configurations
8
8
  const TOOL_PATHS = {
@@ -186,15 +186,28 @@ function workstreamUse(installDir, idOrName, evalMode = false) {
186
186
 
187
187
  // Output for eval mode: eval "$(coder-config workstream use name --eval)"
188
188
  if (evalMode) {
189
+ // Output export command and a user-friendly message to stderr
189
190
  console.log(`export CODER_WORKSTREAM="${ws.name}"`);
191
+ console.log(`echo "📂 Workstream: ${ws.name}"`);
190
192
  return ws;
191
193
  }
192
194
 
193
- // Normal mode: show instructions
194
- console.log(`To activate workstream "${ws.name}", run:`);
195
- console.log(` eval "$(coder-config workstream use ${ws.name} --eval)"`);
196
- console.log(`\nOr manually:`);
197
- console.log(` export CODER_WORKSTREAM="${ws.name}"`);
195
+ // Normal mode: check if cws function exists and give appropriate instructions
196
+ const cwsInstalled = workstreamCdHookStatus().installed;
197
+ if (cwsInstalled) {
198
+ console.log(`Use the cws function to activate workstreams:`);
199
+ console.log(` cws ${ws.name}`);
200
+ console.log('');
201
+ console.log(`Or if calling directly:`);
202
+ console.log(` eval "$(coder-config workstream use ${ws.name} --eval)"`);
203
+ } else {
204
+ console.log(`To activate workstream "${ws.name}", install the cd hook first:`);
205
+ console.log(` coder-config workstream install-cd-hook`);
206
+ console.log('');
207
+ console.log(`Then use: cws ${ws.name}`);
208
+ console.log('');
209
+ console.log(`Or manually: export CODER_WORKSTREAM="${ws.name}"`);
210
+ }
198
211
  return ws;
199
212
  }
200
213
 
@@ -1111,37 +1124,42 @@ function workstreamInstallCdHook() {
1111
1124
  ? path.join(process.env.HOME || '', '.zshrc')
1112
1125
  : path.join(process.env.HOME || '', '.bashrc');
1113
1126
 
1114
- const hookMarker = '# coder-config workstream cd hook';
1127
+ const hookMarker = '# coder-config workstream hooks';
1128
+ const oldHookMarker = '# coder-config workstream cd hook';
1129
+ const endMarker = '# end coder-config workstream hooks';
1130
+ const oldEndMarker = '# end coder-config workstream cd hook';
1131
+
1115
1132
  const hookCode = `
1116
1133
  ${hookMarker}
1117
- coder_workstream_cd() {
1118
- # Run cd directly (not in subshell) - if it fails, it prints its own error
1119
- builtin cd "$@" || return $?
1120
-
1121
- # Check for matching workstreams
1122
- local result
1123
- result=$(coder-config workstream check-folder "$PWD" --json 2>/dev/null)
1134
+ # Wrap coder-config to handle 'workstream use' specially (sets env in current shell)
1135
+ coder-config() {
1136
+ if [ "$1" = "workstream" ] && [ "$2" = "use" ] && [ -n "$3" ]; then
1137
+ # workstream use <name> - activate in current shell
1138
+ shift 2 # remove 'workstream use'
1139
+ eval "$(command coder-config workstream use "$@" --eval)"
1140
+ else
1141
+ # All other commands - pass through
1142
+ command coder-config "$@"
1143
+ fi
1144
+ }
1124
1145
 
1146
+ # Auto-activate workstream on cd
1147
+ _coder_workstream_cd() {
1148
+ builtin cd "$@" || return $?
1149
+ local result count current
1150
+ result=$(command coder-config workstream check-folder "$PWD" --json 2>/dev/null)
1125
1151
  [ -z "$result" ] && return 0
1126
-
1127
- local count current
1128
1152
  count=$(echo "$result" | grep -o '"count":[0-9]*' | cut -d: -f2)
1129
1153
  current=$(echo "$result" | grep -o '"current":true' || echo "")
1130
-
1131
- # Already on matching workstream
1132
1154
  [ -n "$current" ] && return 0
1133
-
1134
1155
  [ "$count" = "0" ] && return 0
1135
-
1136
1156
  if [ "$count" = "1" ]; then
1137
- # Single match - auto-activate
1138
1157
  local name id
1139
1158
  name=$(echo "$result" | grep -o '"name":"[^"]*"' | head -1 | cut -d'"' -f4)
1140
1159
  id=$(echo "$result" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4)
1141
1160
  export CODER_WORKSTREAM="$id"
1142
1161
  echo "📂 Workstream: $name"
1143
1162
  elif [ "$count" -gt 1 ]; then
1144
- # Multiple matches - prompt
1145
1163
  echo "Multiple workstreams match this folder:"
1146
1164
  local i=1
1147
1165
  echo "$result" | grep -o '"name":"[^"]*"' | cut -d'"' -f4 | while read -r name; do
@@ -1154,34 +1172,45 @@ coder_workstream_cd() {
1154
1172
  local id name
1155
1173
  id=$(echo "$result" | grep -o '"id":"[^"]*"' | sed -n "\${choice}p" | cut -d'"' -f4)
1156
1174
  name=$(echo "$result" | grep -o '"name":"[^"]*"' | sed -n "\${choice}p" | cut -d'"' -f4)
1157
- if [ -n "$id" ]; then
1158
- export CODER_WORKSTREAM="$id"
1159
- echo "📂 Workstream: $name"
1160
- fi
1175
+ [ -n "$id" ] && export CODER_WORKSTREAM="$id" && echo "📂 Workstream: $name"
1161
1176
  fi
1162
1177
  fi
1163
1178
  }
1164
- alias cd='coder_workstream_cd'
1165
- # end coder-config workstream cd hook
1179
+ alias cd='_coder_workstream_cd'
1180
+ ${endMarker}
1166
1181
  `;
1167
1182
 
1168
- // Check if hook already installed
1183
+ let content = '';
1169
1184
  if (fs.existsSync(rcFile)) {
1170
- const content = fs.readFileSync(rcFile, 'utf8');
1171
- if (content.includes(hookMarker)) {
1172
- console.log('✓ Workstream cd hook already installed');
1173
- console.log(` Location: ${rcFile}`);
1174
- return true;
1185
+ content = fs.readFileSync(rcFile, 'utf8');
1186
+ }
1187
+
1188
+ // Remove old hook block if present (either old or new marker)
1189
+ if (content.includes(oldHookMarker) || content.includes(hookMarker)) {
1190
+ const startMarker = content.includes(hookMarker) ? hookMarker : oldHookMarker;
1191
+ const endMark = content.includes(endMarker) ? endMarker : oldEndMarker;
1192
+ const startIdx = content.indexOf(startMarker);
1193
+ const endIdx = content.indexOf(endMark);
1194
+ if (startIdx !== -1 && endIdx !== -1) {
1195
+ // Remove the block including any leading newline
1196
+ let removeStart = startIdx;
1197
+ if (startIdx > 0 && content[startIdx - 1] === '\n') {
1198
+ removeStart = startIdx - 1;
1199
+ }
1200
+ content = content.slice(0, removeStart) + content.slice(endIdx + endMark.length);
1175
1201
  }
1176
1202
  }
1177
1203
 
1178
- // Append hook to rc file
1179
- fs.appendFileSync(rcFile, hookCode);
1180
- console.log(`✓ Installed workstream cd hook`);
1204
+ // Append new hook
1205
+ fs.writeFileSync(rcFile, content + hookCode);
1206
+ console.log(`✓ Installed workstream hooks`);
1181
1207
  console.log(` Location: ${rcFile}`);
1182
1208
  console.log('');
1183
1209
  console.log('Restart your shell or run:');
1184
1210
  console.log(` source ${rcFile}`);
1211
+ console.log('');
1212
+ console.log('Now you can use:');
1213
+ console.log(' coder-config workstream use <name> # activates in current shell');
1185
1214
 
1186
1215
  return true;
1187
1216
  }
@@ -1201,34 +1230,38 @@ function workstreamUninstallCdHook() {
1201
1230
  return false;
1202
1231
  }
1203
1232
 
1204
- const content = fs.readFileSync(rcFile, 'utf8');
1205
- const hookMarker = '# coder-config workstream cd hook';
1206
- const endMarker = '# end coder-config workstream cd hook';
1207
-
1208
- if (!content.includes(hookMarker)) {
1209
- console.log('Workstream cd hook not installed');
1210
- return false;
1233
+ let content = fs.readFileSync(rcFile, 'utf8');
1234
+
1235
+ // Support both old and new marker names
1236
+ const markers = [
1237
+ { start: '# coder-config workstream hooks', end: '# end coder-config workstream hooks' },
1238
+ { start: '# coder-config workstream cd hook', end: '# end coder-config workstream cd hook' },
1239
+ ];
1240
+
1241
+ let found = false;
1242
+ for (const { start, end } of markers) {
1243
+ if (content.includes(start)) {
1244
+ const startIdx = content.indexOf(start);
1245
+ const endIdx = content.indexOf(end);
1246
+ if (startIdx !== -1 && endIdx !== -1) {
1247
+ let removeStart = startIdx;
1248
+ if (startIdx > 0 && content[startIdx - 1] === '\n') {
1249
+ removeStart = startIdx - 1;
1250
+ }
1251
+ content = content.slice(0, removeStart) + content.slice(endIdx + end.length);
1252
+ found = true;
1253
+ }
1254
+ }
1211
1255
  }
1212
1256
 
1213
- // Remove the hook block
1214
- const startIdx = content.indexOf(hookMarker);
1215
- const endIdx = content.indexOf(endMarker);
1216
-
1217
- if (startIdx === -1 || endIdx === -1) {
1218
- console.error('Could not find hook boundaries');
1257
+ if (!found) {
1258
+ console.log('Workstream hooks not installed');
1219
1259
  return false;
1220
1260
  }
1221
1261
 
1222
- // Find the newline before the marker (to remove leading blank line)
1223
- let removeStart = startIdx;
1224
- if (startIdx > 0 && content[startIdx - 1] === '\n') {
1225
- removeStart = startIdx - 1;
1226
- }
1227
-
1228
- const newContent = content.slice(0, removeStart) + content.slice(endIdx + endMarker.length);
1229
- fs.writeFileSync(rcFile, newContent);
1262
+ fs.writeFileSync(rcFile, content);
1230
1263
 
1231
- console.log(`✓ Uninstalled workstream cd hook from ${rcFile}`);
1264
+ console.log(`✓ Uninstalled workstream hooks from ${rcFile}`);
1232
1265
  console.log('');
1233
1266
  console.log('Restart your shell or run:');
1234
1267
  console.log(` source ${rcFile}`);
@@ -1251,7 +1284,9 @@ function workstreamCdHookStatus() {
1251
1284
  }
1252
1285
 
1253
1286
  const content = fs.readFileSync(rcFile, 'utf8');
1254
- const installed = content.includes('# coder-config workstream cd hook');
1287
+ // Check for both old and new markers
1288
+ const installed = content.includes('# coder-config workstream hooks') ||
1289
+ content.includes('# coder-config workstream cd hook');
1255
1290
 
1256
1291
  return { installed, shell: isZsh ? 'zsh' : 'bash', rcFile };
1257
1292
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coder-config",
3
- "version": "0.43.14",
3
+ "version": "0.43.18",
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",