repo-nexus 0.4.5 → 0.4.7

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.
@@ -23,6 +23,34 @@
23
23
 
24
24
  repos_dir: ./repos
25
25
 
26
+ # ------------------------------------------------------------------------------
27
+ # ai_instructions — Main AI instructions routing file
28
+ # ------------------------------------------------------------------------------
29
+ # Main instructions file created and managed by Repo Nexus.
30
+ # Default: AGENTS.md (recognized by modern AI coding assistants)
31
+ #
32
+ # Examples:
33
+ # ai_instructions: AGENTS.md # default standard
34
+ # ai_instructions: CLAUDE.md # for Anthropic Claude Code CLI
35
+ # ai_instructions: GEMINI.md # for Google Gemini / Antigravity CLI
36
+ #
37
+ ai_instructions: AGENTS.md
38
+
39
+ # ------------------------------------------------------------------------------
40
+ # code_workspace — VS Code / Cursor multi-root workspace file
41
+ # ------------------------------------------------------------------------------
42
+ # Automatically generates and maintains a multi-root .code-workspace file mapping
43
+ # the workspace root and all active member repository clones.
44
+ #
45
+ # Default: false
46
+ #
47
+ # Examples:
48
+ # code_workspace: false # disabled (default)
49
+ # code_workspace: true # generates <workspace-name>.code-workspace
50
+ # code_workspace: workspace.code-workspace # custom filename
51
+ #
52
+ code_workspace: false
53
+
26
54
  # ------------------------------------------------------------------------------
27
55
  # plugins — Workspace plugins and AI instruction packs
28
56
  # ------------------------------------------------------------------------------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "repo-nexus",
3
- "version": "0.4.5",
3
+ "version": "0.4.7",
4
4
  "description": "Lightweight, zero-dependency Virtual Meta-Repo companion for multi-repo workspaces and shared AI context (no git submodules)",
5
5
  "bin": {
6
6
  "repo-nexus": "rnex",
package/rnex CHANGED
@@ -118,6 +118,8 @@ require_workspace() {
118
118
  WORKSPACE_YAML="$_cfg_path"
119
119
  _init_local_yaml
120
120
  _load_repos_dir
121
+ _load_ai_instructions_file
122
+ _load_code_workspace
121
123
  log_info "Using workspace at ${_BOLD}$NEXUS_DIR${_NC} ${_DIM}(via config: $WORKSPACE_YAML)${_NC}"
122
124
  return 0
123
125
  fi
@@ -144,6 +146,8 @@ require_workspace() {
144
146
  fi
145
147
  _init_local_yaml
146
148
  _load_repos_dir
149
+ _load_ai_instructions_file
150
+ _load_code_workspace
147
151
 
148
152
  log_info "Using workspace at ${_BOLD}$NEXUS_DIR${_NC} ${_DIM}($(basename "$WORKSPACE_YAML") found)${_NC}"
149
153
  }
@@ -161,10 +165,10 @@ _init_local_yaml() {
161
165
  _load_repos_dir() {
162
166
  _rd=""
163
167
  if [ -f "$WORKSPACE_LOCAL_YAML" ]; then
164
- _rd="$(awk '/^repos_dir:/ { sub(/^repos_dir:[ ]*/, ""); sub(/[ ]*#.*/, ""); print }' "$WORKSPACE_LOCAL_YAML")"
168
+ _rd="$(awk '/^repos_dir:/ { sub(/^repos_dir:[ ]*/, ""); sub(/[ ]*#.*/, ""); val=$0 } END { if (val) print val }' "$WORKSPACE_LOCAL_YAML")"
165
169
  fi
166
170
  if [ -z "$_rd" ] && [ -f "$WORKSPACE_YAML" ]; then
167
- _rd="$(awk '/^repos_dir:/ { sub(/^repos_dir:[ ]*/, ""); sub(/[ ]*#.*/, ""); print }' "$WORKSPACE_YAML")"
171
+ _rd="$(awk '/^repos_dir:/ { sub(/^repos_dir:[ ]*/, ""); sub(/[ ]*#.*/, ""); val=$0 } END { if (val) print val }' "$WORKSPACE_YAML")"
168
172
  fi
169
173
  _rd="${_rd:-./repos}"
170
174
  case "$_rd" in
@@ -173,6 +177,44 @@ _load_repos_dir() {
173
177
  esac
174
178
  }
175
179
 
180
+ _load_ai_instructions_file() {
181
+ _aif=""
182
+ if [ -f "$WORKSPACE_LOCAL_YAML" ]; then
183
+ _aif="$(awk '/^(ai_instructions|ai_instructions_file):/ { sub(/^[a-zA-Z0-9_]+:[ ]*/, ""); sub(/[ ]*#.*/, ""); val=$0 } END { if (val) print val }' "$WORKSPACE_LOCAL_YAML")"
184
+ fi
185
+ if [ -z "$_aif" ] && [ -f "$WORKSPACE_YAML" ]; then
186
+ _aif="$(awk '/^(ai_instructions|ai_instructions_file):/ { sub(/^[a-zA-Z0-9_]+:[ ]*/, ""); sub(/[ ]*#.*/, ""); val=$0 } END { if (val) print val }' "$WORKSPACE_YAML")"
187
+ fi
188
+ _aif="$(echo "$_aif" | tr -d " \t\r\n'\"")"
189
+ AI_INSTRUCTIONS_FILE="${_aif:-AGENTS.md}"
190
+ }
191
+
192
+ _load_code_workspace() {
193
+ _cw=""
194
+ if [ -f "$WORKSPACE_LOCAL_YAML" ]; then
195
+ _cw="$(awk '/^(code_workspace|vscode_workspace):/ { sub(/^[a-zA-Z0-9_]+:[ ]*/, ""); sub(/[ ]*#.*/, ""); val=$0 } END { if (val) print val }' "$WORKSPACE_LOCAL_YAML")"
196
+ fi
197
+ if [ -z "$_cw" ] && [ -f "$WORKSPACE_YAML" ]; then
198
+ _cw="$(awk '/^(code_workspace|vscode_workspace):/ { sub(/^[a-zA-Z0-9_]+:[ ]*/, ""); sub(/[ ]*#.*/, ""); val=$0 } END { if (val) print val }' "$WORKSPACE_YAML")"
199
+ fi
200
+ _cw="$(echo "$_cw" | tr -d " \t\r\n'\"")"
201
+ case "$_cw" in
202
+ true|yes|1)
203
+ _ws_basename="$(basename "$NEXUS_DIR")"
204
+ CODE_WORKSPACE_FILE="$_ws_basename.code-workspace"
205
+ ;;
206
+ false|no|0|none|"")
207
+ CODE_WORKSPACE_FILE=""
208
+ ;;
209
+ *)
210
+ case "$_cw" in
211
+ *.code-workspace) CODE_WORKSPACE_FILE="$_cw" ;;
212
+ *) CODE_WORKSPACE_FILE="$_cw.code-workspace" ;;
213
+ esac
214
+ ;;
215
+ esac
216
+ }
217
+
176
218
  # ---- YAML Parser / Manipulator (for rnex.yaml & .local.rnex.yaml) ----------
177
219
 
178
220
  _yaml_list_plugins_from_file() {
@@ -902,6 +944,74 @@ merge_rnex_instructions() {
902
944
  log_ok "Merged Repo Nexus routing instructions with existing $(basename "$_dst")"
903
945
  }
904
946
 
947
+ sync_code_workspace() {
948
+ [ -n "$CODE_WORKSPACE_FILE" ] || return 0
949
+ _ws_path="$NEXUS_DIR/$CODE_WORKSPACE_FILE"
950
+ _root_name="$(basename "$NEXUS_DIR")"
951
+
952
+ _f_tmp="$(mktemp)"
953
+
954
+ printf ' {\n "name": "%s (Workspace Root)",\n "path": "."\n }' "$_root_name" > "$_f_tmp"
955
+
956
+ _repos_rel="${REPOS_DIR#"$NEXUS_DIR"/}"
957
+ _repos_rel="${_repos_rel#./}"
958
+ [ -n "$_repos_rel" ] || _repos_rel="repos"
959
+
960
+ yaml_list_repos | while read -r _rname; do
961
+ [ -n "$_rname" ] || continue
962
+ if yaml_repo_enabled "$_rname"; then
963
+ _rdir="$(resolve_repo_path "$_rname")"
964
+ if [ -d "$_rdir" ]; then
965
+ printf ',\n {\n "name": "%s",\n "path": "%s/%s"\n }' "$_rname" "$_repos_rel" "$_rname" >> "$_f_tmp"
966
+ fi
967
+ fi
968
+ done
969
+
970
+ if [ ! -f "$_ws_path" ]; then
971
+ {
972
+ printf '{\n "folders": [\n'
973
+ cat "$_f_tmp"
974
+ printf '\n ],\n "settings": {\n "search.exclude": {\n "**/node_modules": true,\n "**/.git": true\n }\n }\n}\n'
975
+ } > "$_ws_path"
976
+ rm -f "$_f_tmp"
977
+ log_ok "Created $CODE_WORKSPACE_FILE (VS Code / Cursor multi-root workspace)"
978
+ return 0
979
+ fi
980
+
981
+ if grep -q '"folders"[ ]*:' "$_ws_path" 2>/dev/null; then
982
+ _tmp_out="$(mktemp)"
983
+ awk -v f_src="$_f_tmp" '
984
+ BEGIN { in_f = 0 }
985
+ /"folders"[ ]*:[ ]*\[/ {
986
+ in_f = 1
987
+ print " \"folders\": ["
988
+ while ((getline line < f_src) > 0) print line
989
+ close(f_src)
990
+ next
991
+ }
992
+ in_f {
993
+ if (/\]/) {
994
+ in_f = 0
995
+ has_comma = ($0 ~ /,[ ]*$/) ? "," : ""
996
+ print " ]" has_comma
997
+ }
998
+ next
999
+ }
1000
+ { print }
1001
+ ' "$_ws_path" > "$_tmp_out" && mv "$_tmp_out" "$_ws_path"
1002
+ rm -f "$_f_tmp"
1003
+ log_ok "Updated folders in $CODE_WORKSPACE_FILE"
1004
+ else
1005
+ {
1006
+ printf '{\n "folders": [\n'
1007
+ cat "$_f_tmp"
1008
+ printf '\n ],\n "settings": {\n "search.exclude": {\n "**/node_modules": true,\n "**/.git": true\n }\n }\n}\n'
1009
+ } > "$_ws_path"
1010
+ rm -f "$_f_tmp"
1011
+ log_ok "Updated $CODE_WORKSPACE_FILE"
1012
+ fi
1013
+ }
1014
+
905
1015
  # ============================================================================
906
1016
  # Commands
907
1017
  # ============================================================================
@@ -909,10 +1019,32 @@ merge_rnex_instructions() {
909
1019
  cmd_init() {
910
1020
  _non_interactive=0
911
1021
  _target_dir=""
1022
+ _cli_ai_instructions=""
1023
+ _cli_code_workspace=""
912
1024
 
913
1025
  while [ $# -gt 0 ]; do
914
1026
  case "$1" in
915
1027
  -y|--yes) _non_interactive=1 ;;
1028
+ --ai|--instructions|--ai-instructions)
1029
+ shift
1030
+ _cli_ai_instructions="$1"
1031
+ ;;
1032
+ --code-workspace|--vscode)
1033
+ _cli_code_workspace="true"
1034
+ if [ $# -ge 2 ]; then
1035
+ case "$2" in
1036
+ -*) ;;
1037
+ *)
1038
+ case "$2" in
1039
+ true|false|*.code-workspace)
1040
+ shift
1041
+ _cli_code_workspace="$1"
1042
+ ;;
1043
+ esac
1044
+ ;;
1045
+ esac
1046
+ fi
1047
+ ;;
916
1048
  *)
917
1049
  if [ -z "$_target_dir" ]; then
918
1050
  _target_dir="$1"
@@ -946,6 +1078,12 @@ cmd_init() {
946
1078
  # Directory for member repository clones
947
1079
  repos_dir: ./repos
948
1080
 
1081
+ # Main AI instructions routing file (default: AGENTS.md; e.g. CLAUDE.md, GEMINI.md)
1082
+ ai_instructions: ${_cli_ai_instructions:-AGENTS.md}
1083
+
1084
+ # VS Code / Cursor multi-root workspace file (default: false; e.g. true or workspace.code-workspace)
1085
+ code_workspace: ${_cli_code_workspace:-false}
1086
+
949
1087
  # Workspace plugins
950
1088
  plugins:
951
1089
 
@@ -956,11 +1094,22 @@ YAML_EOF
956
1094
  log_ok "Created $RNEX_CONFIG_FILE"
957
1095
  fi
958
1096
 
959
- # ---- 2. Merge routing instructions into AGENTS.md -------------------------
960
- _target_agents="$_target_dir/AGENTS.md"
1097
+ # ---- 2. Merge routing instructions into main AI instructions file ---------
1098
+ _target_aif="$_cli_ai_instructions"
1099
+ if [ -z "$_target_aif" ] && [ -f "$_target_dir/$RNEX_LOCAL_CONFIG_FILE" ]; then
1100
+ _target_aif="$(awk '/^(ai_instructions|ai_instructions_file):/ { sub(/^[a-zA-Z0-9_]+:[ ]*/, ""); sub(/[ ]*#.*/, ""); val=$0 } END { if (val) print val }' "$_target_dir/$RNEX_LOCAL_CONFIG_FILE")"
1101
+ fi
1102
+ if [ -z "$_target_aif" ] && [ -f "$_target_yaml" ]; then
1103
+ _target_aif="$(awk '/^(ai_instructions|ai_instructions_file):/ { sub(/^[a-zA-Z0-9_]+:[ ]*/, ""); sub(/[ ]*#.*/, ""); val=$0 } END { if (val) print val }' "$_target_yaml")"
1104
+ fi
1105
+ _target_aif="$(echo "$_target_aif" | tr -d " \t\r\n'\"")"
1106
+ _target_aif="${_target_aif:-AGENTS.md}"
1107
+
1108
+ _target_agents="$_target_dir/$_target_aif"
961
1109
  merge_rnex_instructions "$_target_agents"
962
- [ -f "$_target_dir/CLAUDE.md" ] && merge_rnex_instructions "$_target_dir/CLAUDE.md"
963
- [ -f "$_target_dir/.cursorrules" ] && merge_rnex_instructions "$_target_dir/.cursorrules"
1110
+ [ -f "$_target_dir/AGENTS.md" ] && [ "$_target_aif" != "AGENTS.md" ] && merge_rnex_instructions "$_target_dir/AGENTS.md"
1111
+ [ -f "$_target_dir/CLAUDE.md" ] && [ "$_target_aif" != "CLAUDE.md" ] && merge_rnex_instructions "$_target_dir/CLAUDE.md"
1112
+ [ -f "$_target_dir/.cursorrules" ] && [ "$_target_aif" != ".cursorrules" ] && merge_rnex_instructions "$_target_dir/.cursorrules"
964
1113
 
965
1114
  # ---- 3. Create repos directory with .gitkeep -----------------------------
966
1115
  _repos_dir="$_target_dir/repos"
@@ -974,10 +1123,50 @@ YAML_EOF
974
1123
  # ---- 5. Ensure repos/, .rnex/, and local configs are gitignored ---------
975
1124
  reconcile_gitignore "$_target_dir"
976
1125
 
1126
+ # ---- 6. Generate VS Code / Cursor workspace if configured ----------------
1127
+ _target_cw="$_cli_code_workspace"
1128
+ if [ -z "$_target_cw" ] && [ -f "$_target_dir/$RNEX_LOCAL_CONFIG_FILE" ]; then
1129
+ _target_cw="$(awk '/^(code_workspace|vscode_workspace):/ { sub(/^[a-zA-Z0-9_]+:[ ]*/, ""); sub(/[ ]*#.*/, ""); val=$0 } END { if (val) print val }' "$_target_dir/$RNEX_LOCAL_CONFIG_FILE")"
1130
+ fi
1131
+ if [ -z "$_target_cw" ] && [ -f "$_target_yaml" ]; then
1132
+ _target_cw="$(awk '/^(code_workspace|vscode_workspace):/ { sub(/^[a-zA-Z0-9_]+:[ ]*/, ""); sub(/[ ]*#.*/, ""); val=$0 } END { if (val) print val }' "$_target_yaml")"
1133
+ fi
1134
+ _target_cw="$(echo "$_target_cw" | tr -d " \t\r\n'\"")"
1135
+ case "$_target_cw" in
1136
+ true|yes|1)
1137
+ _cw_name="$(basename "$_target_dir").code-workspace"
1138
+ ;;
1139
+ false|no|0|none|"")
1140
+ _cw_name=""
1141
+ ;;
1142
+ *)
1143
+ case "$_target_cw" in
1144
+ *.code-workspace) _cw_name="$_target_cw" ;;
1145
+ *) _cw_name="$_target_cw.code-workspace" ;;
1146
+ esac
1147
+ ;;
1148
+ esac
1149
+
1150
+ if [ -n "$_cw_name" ]; then
1151
+ _orig_nexus="$NEXUS_DIR"
1152
+ _orig_repos="$REPOS_DIR"
1153
+ _orig_cw="$CODE_WORKSPACE_FILE"
1154
+ CODE_WORKSPACE_FILE="$_cw_name"
1155
+ NEXUS_DIR="$_target_dir"
1156
+ _repos_rel="repos"
1157
+ REPOS_DIR="$_target_dir/$_repos_rel"
1158
+ sync_code_workspace
1159
+ NEXUS_DIR="$_orig_nexus"
1160
+ REPOS_DIR="$_orig_repos"
1161
+ CODE_WORKSPACE_FILE="$_orig_cw"
1162
+ fi
1163
+
977
1164
  if [ "$_config_created" -eq 1 ]; then
978
1165
  printf '\n'
979
1166
  log_ok "Initialized Repo Nexus workspace at ${_BOLD}$_target_dir${_NC}"
980
- log_dim "Created $RNEX_CONFIG_FILE, AGENTS.md, .rnex/, and repos/"
1167
+ _created_items="$RNEX_CONFIG_FILE, $_target_aif, .rnex/, and repos/"
1168
+ [ -n "$_cw_name" ] && _created_items="$_created_items (and $_cw_name)"
1169
+ log_dim "Created $_created_items"
981
1170
  printf '\n'
982
1171
  log_info "Next steps:"
983
1172
  log_dim "1. Add repositories with: rnex add <name> <git-url>"
@@ -1035,6 +1224,7 @@ cmd_add() {
1035
1224
  [ "$_rnex_dir" = "false" ] && yaml_set_local "$_name" "rnex_dir" "false"
1036
1225
  [ "$_enabled" = "false" ] && yaml_set_local "$_name" "enabled" "false"
1037
1226
  sync_repo_rnex "$_name"
1227
+ sync_code_workspace
1038
1228
  printf '\n'
1039
1229
  log_ok "Registered repo '${_name}' in $(basename "$WORKSPACE_LOCAL_YAML")"
1040
1230
  return 0
@@ -1050,6 +1240,7 @@ cmd_add() {
1050
1240
  [ "$_rnex_dir" = "false" ] && yaml_set "$_name" "rnex_dir" "false"
1051
1241
  [ "$_enabled" = "false" ] && yaml_set "$_name" "enabled" "false"
1052
1242
  sync_repo_rnex "$_name"
1243
+ sync_code_workspace
1053
1244
  printf '\n'
1054
1245
  log_ok "Updated repo '${_name}' in $(basename "$WORKSPACE_YAML")"
1055
1246
  return 0
@@ -1058,6 +1249,7 @@ cmd_add() {
1058
1249
 
1059
1250
  yaml_add_repo "$_name" "$_url" "$_rnex_dir" "$_enabled"
1060
1251
  sync_repo_rnex "$_name"
1252
+ sync_code_workspace
1061
1253
  printf '\n'
1062
1254
  log_ok "Registered and added repo '${_name}'"
1063
1255
  }
@@ -1101,6 +1293,7 @@ cmd_clone() {
1101
1293
  fi
1102
1294
  fi
1103
1295
  done
1296
+ sync_code_workspace
1104
1297
  printf '\n'
1105
1298
  }
1106
1299
 
@@ -1158,6 +1351,7 @@ cmd_enable() {
1158
1351
  log_ok "Enabled repo '$_name' in $(basename "$WORKSPACE_YAML")"
1159
1352
  fi
1160
1353
  sync_repo_rnex "$_name"
1354
+ sync_code_workspace
1161
1355
  }
1162
1356
 
1163
1357
  cmd_disable() {
@@ -1181,6 +1375,7 @@ cmd_disable() {
1181
1375
  yaml_set "$_name" "enabled" "false"
1182
1376
  log_ok "Disabled repo '$_name' in $(basename "$WORKSPACE_YAML")"
1183
1377
  fi
1378
+ sync_code_workspace
1184
1379
  }
1185
1380
 
1186
1381
  cmd_show() {
@@ -1205,6 +1400,7 @@ cmd_remove() {
1205
1400
  else
1206
1401
  log_ok "Unregistered repo '$_name'"
1207
1402
  fi
1403
+ sync_code_workspace
1208
1404
  }
1209
1405
 
1210
1406
  cmd_list() {
@@ -1262,6 +1458,10 @@ cmd_status() {
1262
1458
  printf ' %b○%b Local Config: %s %b(not found — using repo defaults)%b\n' "$_DIM" "$_NC" "$WORKSPACE_LOCAL_YAML" "$_DIM" "$_NC"
1263
1459
  fi
1264
1460
  printf ' %b●%b Repos Dir: %s\n' "$_DIM" "$_NC" "$REPOS_DIR"
1461
+ printf ' %b●%b AI File: %s\n' "$_DIM" "$_NC" "$AI_INSTRUCTIONS_FILE"
1462
+ if [ -n "$CODE_WORKSPACE_FILE" ]; then
1463
+ printf ' %b●%b Workspace: %s\n' "$_DIM" "$_NC" "$CODE_WORKSPACE_FILE"
1464
+ fi
1265
1465
 
1266
1466
  _gi="$NEXUS_DIR/.gitignore"
1267
1467
  _gi_repos=0; _gi_rnex=0; _gi_local=0; _gi_has_counter=0
@@ -1280,17 +1480,29 @@ cmd_status() {
1280
1480
  printf '\n'
1281
1481
 
1282
1482
  printf '%bWorkspace AI Context (Routing):%b\n' "$_BOLD" "$_NC"
1283
- if [ -e "$NEXUS_DIR/AGENTS.md" ]; then
1284
- printf ' %b✓%b %s\n' "$_G" "$_NC" "AGENTS.md"
1483
+ _main_ai="${AI_INSTRUCTIONS_FILE:-AGENTS.md}"
1484
+ if [ -e "$NEXUS_DIR/$_main_ai" ]; then
1485
+ printf ' %b✓%b %s %b(main instructions)%b\n' "$_G" "$_NC" "$_main_ai" "$_DIM" "$_NC"
1285
1486
  else
1286
- printf ' %b✗%b %s (missing from workspace root — run "rnex fix")\n' "$_R" "$_NC" "AGENTS.md"
1287
- fi
1288
- if [ -f "$NEXUS_DIR/CLAUDE.md" ]; then
1289
- printf ' %b✓%b %s\n' "$_G" "$_NC" "CLAUDE.md"
1487
+ printf ' %b✗%b %s %b(main instructions — MISSING; run "rnex fix" to create)%b\n' "$_R" "$_NC" "$_main_ai" "$_R" "$_NC"
1290
1488
  fi
1291
- if [ -f "$NEXUS_DIR/.cursorrules" ]; then
1292
- printf ' %b✓%b %s\n' "$_G" "$_NC" ".cursorrules"
1489
+ for _aux_ai in "AGENTS.md" "CLAUDE.md" "GEMINI.md" ".cursorrules"; do
1490
+ if [ "$_aux_ai" != "$_main_ai" ] && [ -f "$NEXUS_DIR/$_aux_ai" ]; then
1491
+ printf ' %b✓%b %s\n' "$_G" "$_NC" "$_aux_ai"
1492
+ fi
1493
+ done
1494
+ if [ -n "$CODE_WORKSPACE_FILE" ]; then
1495
+ if [ -f "$NEXUS_DIR/$CODE_WORKSPACE_FILE" ]; then
1496
+ printf ' %b✓%b %s %b(VS Code / Cursor workspace)%b\n' "$_G" "$_NC" "$CODE_WORKSPACE_FILE" "$_DIM" "$_NC"
1497
+ else
1498
+ printf ' %b✗%b %s %b(VS Code / Cursor workspace — MISSING; run "rnex fix" to create)%b\n' "$_R" "$_NC" "$CODE_WORKSPACE_FILE" "$_R" "$_NC"
1499
+ fi
1293
1500
  fi
1501
+ for _found_cw in "$NEXUS_DIR"/*.code-workspace; do
1502
+ if [ -f "$_found_cw" ] && [ "$(basename "$_found_cw")" != "$CODE_WORKSPACE_FILE" ]; then
1503
+ printf ' %b✓%b %s %b(VS Code / Cursor workspace)%b\n' "$_G" "$_NC" "$(basename "$_found_cw")" "$_DIM" "$_NC"
1504
+ fi
1505
+ done
1294
1506
  if [ -d "$NEXUS_DIR/.rnex" ]; then
1295
1507
  printf ' %b✓%b %s\n' "$_G" "$_NC" ".rnex/"
1296
1508
  fi
@@ -1360,10 +1572,11 @@ cmd_fix() {
1360
1572
  # 1. Ensure .gitignore ignores repos/, .rnex/, and local configs, and strips legacy counters
1361
1573
  reconcile_gitignore "$NEXUS_DIR"
1362
1574
 
1363
- # 2. Reconcile instructions in AGENTS.md (and optional AI assistant files if present)
1364
- merge_rnex_instructions "$NEXUS_DIR/AGENTS.md"
1365
- [ -f "$NEXUS_DIR/CLAUDE.md" ] && merge_rnex_instructions "$NEXUS_DIR/CLAUDE.md"
1366
- [ -f "$NEXUS_DIR/.cursorrules" ] && merge_rnex_instructions "$NEXUS_DIR/.cursorrules"
1575
+ # 2. Reconcile instructions in main AI instructions file (and optional AI assistant files if present)
1576
+ merge_rnex_instructions "$NEXUS_DIR/$AI_INSTRUCTIONS_FILE"
1577
+ [ -f "$NEXUS_DIR/AGENTS.md" ] && [ "$AI_INSTRUCTIONS_FILE" != "AGENTS.md" ] && merge_rnex_instructions "$NEXUS_DIR/AGENTS.md"
1578
+ [ -f "$NEXUS_DIR/CLAUDE.md" ] && [ "$AI_INSTRUCTIONS_FILE" != "CLAUDE.md" ] && merge_rnex_instructions "$NEXUS_DIR/CLAUDE.md"
1579
+ [ -f "$NEXUS_DIR/.cursorrules" ] && [ "$AI_INSTRUCTIONS_FILE" != ".cursorrules" ] && merge_rnex_instructions "$NEXUS_DIR/.cursorrules"
1367
1580
 
1368
1581
  # 3. Reconcile plugins
1369
1582
  sync_plugins
@@ -1381,6 +1594,9 @@ cmd_fix() {
1381
1594
  fi
1382
1595
  done
1383
1596
 
1597
+ # 5. Reconcile VS Code / Cursor multi-root workspace if configured
1598
+ sync_code_workspace
1599
+
1384
1600
  log_ok "Fix complete — workspace, plugins, and member .rnex directories reconciled"
1385
1601
  }
1386
1602
 
@@ -1716,7 +1932,8 @@ cmd_help() {
1716
1932
  -v, --version Show version
1717
1933
 
1718
1934
  WORKSPACE & SYSTEM SETUP
1719
- init [-y] [dir] Initialize a new Repo Nexus workspace in current (or specified) dir
1935
+ init [-y] [--ai <file>] [--code-workspace [file]] [dir]
1936
+ Initialize a new Repo Nexus workspace (default AI file: AGENTS.md)
1720
1937
  install [dir] Install rnex & repo-nexus globally into ~/.local/bin (or custom dir)
1721
1938
  fix Reconcile workspace, plugins & member .rnex/ directories (alias: sync)
1722
1939
  completion <shell> Generate shell completion script (bash, zsh, fish)