repo-nexus 0.5.4 → 0.5.6

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/CHANGELOG.md CHANGED
@@ -16,6 +16,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16
16
  - Interactive `rnex init` determines and records `git_hooks` preference upfront in new workspaces.
17
17
  - Workspace schema migration in `rnex update` and `rnex fix -y` non-destructively inserts `git_hooks` into older configurations.
18
18
  - `rnex status` and `rnex hooks status` display configuration state alongside runtime Git hooks status.
19
+ - **Modular GitHub Copilot Plugin & Extensible Provider Sync (`plugins: copilot: ...`)**:
20
+ - Encapsulated GitHub Copilot integration as a built-in Repo Nexus plugin (`copilot`) located in `toolkit/plugins/copilot/`.
21
+ - Extensible configuration options per provider under `plugins:` in `rnex.yaml` and `.local.rnex.yaml`:
22
+ - `prompts: true|false`: Syncs operational prompts into `.github/prompts/*.prompt.md` with YAML frontmatter for VS Code Copilot Chat prompt picker & slash commands.
23
+ - `skills: true|false`: Syncs agent skills into `.github/skills/<name>/SKILL.md` for Copilot Agent mode & `gh skill`.
24
+ - `instructions: true|false`: Synthesizes workspace routing and active plugin guidelines into `.github/copilot-instructions.md`, preserving manual user instructions outside `<!-- REPO-NEXUS -->` markers.
25
+ - `agents: true|false`: Syncs active plugin custom agents into `.github/agents/*.agent.md` and Copilot skills.
26
+ - `enabled: false`: Allows local machine overrides in `.local.rnex.yaml` without altering team configuration.
27
+ - Decoupled cross-plugin asset discovery: `copilot` provider inspects all active plugins (e.g. `karpathy-llm`) and mirrors their prompts, workflows, skills, agents, and guidelines without introducing plugin dependencies.
28
+ - CLI management via `rnex plugin enable [--local] copilot`, `rnex plugin disable [--local] copilot`, and `rnex plugin info copilot`.
29
+ - Added `--copilot` initialization flag to `rnex init` enabling the plugin in newly generated workspaces.
30
+ - Clean reconciliation in `rnex fix`: safely removes `.github/prompts/`, `.github/skills/`, `.github/agents/`, and `.github/copilot-instructions.md` when disabled or when specific target options are toggled off.
31
+ - Diagnostics and configurable options reporting integrated into `rnex status`.
19
32
 
20
33
  ### Fixed
21
34
  - **Git Hooks Self-Rewrite & Wrapper Preservation**:
@@ -24,6 +37,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
24
37
  - Preserved custom / repository-owned wrappers in `.rnex/hooks/` that are not auto-managed by `rnex`.
25
38
  - Added `cmp -s` check before writing hook files to eliminate unnecessary file churn and in-place overwrites.
26
39
  - Automatically chain to existing repository-owned `.githooks/` scripts if present.
40
+ - **Track Workspace `.rnex/` in Version Control**:
41
+ - Removed `.rnex/` from `.gitignore` templates and generation.
42
+ - `reconcile_gitignore` and `rnex fix` actively strip legacy `.rnex/` ignore rules from `.gitignore` so that team prompts (`.rnex/prompts/`), plugins (`.rnex/plugins/`), and hooks (`.rnex/hooks/`) are tracked in git.
43
+ - Updated `rnex status` to expect `.rnex/` to remain tracked by git.
27
44
 
28
45
  ## [0.5.1] - 2026-10-08
29
46
 
package/README.md CHANGED
@@ -215,7 +215,25 @@ rnex plugin enable karpathy-llm
215
215
  rnex plugin disable karpathy-llm
216
216
  ```
217
217
 
218
- ### Built-in Plugin: `karpathy-llm`
218
+ ### Built-in Plugins
219
+
220
+ #### 1. `copilot`
221
+ The `copilot` plugin provides GitHub Copilot integration, automatically mirroring workspace and active plugin assets:
222
+ * **Prompts (`.github/prompts/*.prompt.md`)**: Formatted with YAML frontmatter (`name`, `description`) for the VS Code Copilot Chat prompt picker and slash commands.
223
+ * **Agent Skills (`.github/skills/<name>/SKILL.md`)**: Configured for GitHub Copilot Agent mode and `gh skill`.
224
+ * **Custom Agents (`.github/agents/*.agent.md`)**: Active plugins' agent definitions mirrored for Copilot workspace custom agents.
225
+ * **Instructions (`.github/copilot-instructions.md`)**: Synthesized workspace routing and active plugin guidelines, preserving manual user instructions.
226
+ * **Configurable Options**:
227
+ ```yaml
228
+ plugins:
229
+ copilot:
230
+ prompts: true # mirror prompts to .github/prompts/*.prompt.md (default: true)
231
+ skills: true # mirror skills to .github/skills/<name>/SKILL.md (default: true)
232
+ instructions: true # mirror guidelines to .github/copilot-instructions.md (default: true)
233
+ agents: true # mirror custom agents to .github/agents/*.agent.md (default: true)
234
+ ```
235
+
236
+ #### 2. `karpathy-llm`
219
237
  The `karpathy-llm` plugin packages Andrej Karpathy's verified LLM agent design patterns, context engineering principles, and the autonomous **Karpathy LLM Wiki** architecture:
220
238
  * **The 4 Cardinal Agent Rules** (`.rnex/plugins/karpathy-llm/rules/behavioral.md`):
221
239
  1. *Think Before Coding:* Formulate explicit assumptions, boundary checks, and trade-offs before writing code.
@@ -248,8 +266,13 @@ repos_dir: ./repos
248
266
  # Automated workspace Git hooks (default: true)
249
267
  git_hooks: true
250
268
 
251
- # Workspace plugins
269
+ # Workspace plugins and tool integrations
252
270
  plugins:
271
+ copilot:
272
+ prompts: true
273
+ skills: true
274
+ instructions: true
275
+ agents: true
253
276
  karpathy-llm: {}
254
277
 
255
278
  # Member repositories (enabled by default)
package/docs/CLI.md CHANGED
@@ -72,15 +72,18 @@ rnex init [options] [directory]
72
72
  - `--code-workspace [filename]`: Enable VS Code / Cursor multi-root workspace file generation. Defaults to `<directory-name>.code-workspace` if omitted.
73
73
  - `--hooks`: Force-enable automated Git hooks setup during initialization.
74
74
  - `--no-hooks`: Skip Git hooks configuration during initialization.
75
+ - `--copilot`: Enable GitHub Copilot integration plugin (mirrors prompts, skills, agents, and instructions to `.github/`).
76
+ - `--no-copilot`: Skip GitHub Copilot plugin (default).
75
77
 
76
78
  #### What it does:
77
79
  1. Creates `rnex.yaml` with schema versioning (`version: <version>`), `repos_dir: ./repos`, and configured defaults.
78
80
  2. Merges Repo Nexus routing instructions (`<!-- REPO-NEXUS:START -->` ... `<!-- REPO-NEXUS:END -->`) into the target AI instructions file.
79
81
  3. Creates `./repos/` directory with a tracked `.gitkeep`.
80
82
  4. Creates `.rnex/`, `.rnex/plugins/`, and copies standardized prompts to `.rnex/prompts/`.
81
- 5. Reconciles `.gitignore` to ensure `repos/`, `.rnex/`, and `.local.rnex.yaml` are never tracked by the meta-repo.
83
+ 5. Reconciles `.gitignore` to ensure `repos/` and `.local.rnex.yaml` are never tracked by the meta-repo (while keeping `.rnex/` tracked).
82
84
  6. Generates a multi-root `.code-workspace` file if configured.
83
85
  7. Prompts to configure automated workspace Git hooks (`core.hooksPath = .rnex/hooks`) if inside a Git repository.
86
+ 8. Configures enabled plugins (including `copilot` if requested).
84
87
 
85
88
  #### Examples:
86
89
  ```sh
@@ -110,7 +113,7 @@ rnex status
110
113
  #### What it reports:
111
114
  - **Configuration & Versions**: Path, version tag, and load status of `rnex.yaml` and `.local.rnex.yaml`.
112
115
  - **Paths**: Clones directory (`repos_dir`) and primary AI instructions file.
113
- - **Git Integration**: Validation that `.gitignore` ignores `repos/`, `.rnex/`, and local files, and whether `core.hooksPath` points to `.rnex/hooks`.
116
+ - **Git Integration**: Validation that `.gitignore` ignores `repos/` and local files (while keeping `.rnex/` tracked), and whether `core.hooksPath` points to `.rnex/hooks`.
114
117
  - **AI Routing Context**: Existence and routing block markers in `AGENTS.md`, `CLAUDE.md`, `.code-workspace`, and prompts catalog (`.rnex/prompts/index.md`).
115
118
  - **Active Plugins**: List of enabled plugins, scoped versions, and asset directories.
116
119
  - **Member Repositories**: Every registered repository, enabled/disabled state, clone health, and active Git branch.
@@ -353,14 +356,14 @@ Unsets `core.hooksPath` in Git configuration, removes `.rnex/hooks/`, and record
353
356
  Repo Nexus features a modular plugin architecture where plugin rules, instructions, and templates are scoped strictly under `.rnex/plugins/<plugin-name>/`.
354
357
 
355
358
  ```sh
356
- rnex plugin <list|info|enable|disable> [name]
359
+ rnex plugin <list|info|enable|disable> [options] [name]
357
360
  ```
358
361
 
359
362
  ### Subcommands
360
363
  - **`rnex plugin list`**: Displays all available plugins distributed with `rnex` and highlights enabled plugins.
361
- - **`rnex plugin info <name>`**: Shows description, version, scoped directory, and external template paths for a plugin.
362
- - **`rnex plugin enable <name>`**: Enables a plugin in `rnex.yaml`, copies assets to `.rnex/plugins/<name>/`, and reconciles workspace files.
363
- - **`rnex plugin disable <name>`**: Removes plugin assets from `.rnex/plugins/<name>/` and disables the plugin in `rnex.yaml`.
364
+ - **`rnex plugin info <name>`**: Shows description, version, configurable options, scoped directory, and external template paths for a plugin.
365
+ - **`rnex plugin enable [--local] <name>`**: Enables a plugin in `rnex.yaml` (or `.local.rnex.yaml` with `--local`), copies assets to `.rnex/plugins/<name>/`, and reconciles workspace files.
366
+ - **`rnex plugin disable [--local] <name>`**: Removes plugin assets from `.rnex/plugins/<name>/` and disables the plugin in `rnex.yaml` (or overrides with `enabled: false` in `.local.rnex.yaml` with `--local`).
364
367
 
365
368
  ---
366
369
 
@@ -74,21 +74,29 @@ code_workspace: false
74
74
  git_hooks: true
75
75
 
76
76
  # ------------------------------------------------------------------------------
77
- # plugins — Workspace plugins and AI instruction packs
77
+ # plugins — Workspace plugins, tool integrations, and AI instruction packs
78
78
  # ------------------------------------------------------------------------------
79
79
  # Plugins extend your workspace with curated AI guidelines, context rules,
80
- # and scaffolding templates scoped within `.rnex/plugins/<plugin-name>/`.
80
+ # tool provider integrations (e.g. GitHub Copilot), and templates.
81
81
  #
82
82
  # Manage plugins with:
83
- # rnex plugin list # View available and active plugins
84
- # rnex plugin enable <name> # Enable plugin in workspace
85
- # rnex plugin disable <name> # Disable plugin from workspace
83
+ # rnex plugin list # View available and active plugins
84
+ # rnex plugin enable [--local] <name> # Enable plugin (global or local override)
85
+ # rnex plugin disable [--local] <name> # Disable plugin from workspace
86
+ # rnex plugin info <name> # View plugin details & configurable options
86
87
  #
87
88
  # Built-in plugins:
89
+ # copilot — GitHub Copilot integration: mirrors operational prompts, skills,
90
+ # agents, and synthesized instructions into .github/
88
91
  # karpathy-llm — Andrej Karpathy's agent behavioral principles,
89
92
  # context engineering guidelines, and LLM Wiki architecture
90
93
 
91
94
  plugins:
95
+ # copilot:
96
+ # prompts: true # mirror prompts to .github/prompts/*.prompt.md (default: true)
97
+ # skills: true # mirror skills to .github/skills/<name>/SKILL.md (default: true)
98
+ # instructions: true # mirror instructions to .github/copilot-instructions.md (default: true)
99
+ # agents: true # mirror custom agents to .github/agents/*.agent.md (default: true)
92
100
  # karpathy-llm: {}
93
101
 
94
102
  # ------------------------------------------------------------------------------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "repo-nexus",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
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
@@ -147,6 +147,7 @@ require_workspace() {
147
147
  _load_ai_instructions_file
148
148
  _load_code_workspace
149
149
  _load_git_hooks
150
+ _load_copilot
150
151
  log_info "Using workspace at ${_BOLD}$NEXUS_DIR${_NC} ${_DIM}(via config: $WORKSPACE_YAML)${_NC}"
151
152
  return 0
152
153
  fi
@@ -177,6 +178,7 @@ require_workspace() {
177
178
  _load_ai_instructions_file
178
179
  _load_code_workspace
179
180
  _load_git_hooks
181
+ _load_copilot
180
182
 
181
183
  log_info "Using workspace at ${_BOLD}$NEXUS_DIR${_NC} ${_DIM}($(basename "$WORKSPACE_YAML") found)${_NC}"
182
184
  }
@@ -268,6 +270,18 @@ _load_git_hooks() {
268
270
  GIT_HOOKS_CONFIG="$_gh"
269
271
  }
270
272
 
273
+ _load_copilot() {
274
+ _cp=""
275
+ if [ -f "$WORKSPACE_LOCAL_YAML" ]; then
276
+ _cp="$(awk '/^(copilot|copilot_sync):/ { sub(/^[a-zA-Z0-9_]+:[ ]*/, ""); sub(/[ ]*#.*/, ""); val=$0 } END { if (val) print val }' "$WORKSPACE_LOCAL_YAML")"
277
+ fi
278
+ if [ -z "$_cp" ] && [ -f "$WORKSPACE_YAML" ]; then
279
+ _cp="$(awk '/^(copilot|copilot_sync):/ { sub(/^[a-zA-Z0-9_]+:[ ]*/, ""); sub(/[ ]*#.*/, ""); val=$0 } END { if (val) print val }' "$WORKSPACE_YAML")"
280
+ fi
281
+ _cp="$(echo "$_cp" | tr -d " \t\r\n'\"")"
282
+ COPILOT_CONFIG="$_cp"
283
+ }
284
+
271
285
  # ---- YAML Parser / Manipulator (for rnex.yaml & .local.rnex.yaml) ----------
272
286
 
273
287
  _yaml_list_plugins_from_file() {
@@ -352,22 +366,211 @@ yaml_has_plugin() {
352
366
  yaml_list_plugins | grep -qx "$1" 2>/dev/null
353
367
  }
354
368
 
355
- yaml_enable_plugin() {
356
- _name="$1"
357
- if ! grep -q '^plugins:' "$WORKSPACE_YAML" 2>/dev/null; then
358
- printf '\nplugins:\n' >> "$WORKSPACE_YAML"
369
+ yaml_plugin_enabled() {
370
+ _plugin="$1"
371
+ yaml_has_plugin "$_plugin" || return 1
372
+ _val="$(yaml_plugin_get "$_plugin" "enabled")"
373
+ _val="$(printf '%s' "$_val" | tr '[:upper:]' '[:lower:]')"
374
+ case "$_val" in
375
+ false|no|0|disabled|off) return 1 ;;
376
+ *) return 0 ;;
377
+ esac
378
+ }
379
+
380
+ copilot_plugin_enabled() {
381
+ if yaml_plugin_enabled "copilot"; then
382
+ return 0
383
+ fi
384
+ case "$COPILOT_CONFIG" in
385
+ true|yes|1) return 0 ;;
386
+ *) return 1 ;;
387
+ esac
388
+ }
389
+
390
+ copilot_prompts_enabled() {
391
+ copilot_plugin_enabled || return 1
392
+ _val="$(yaml_plugin_get "copilot" "prompts")"
393
+ _val="$(printf '%s' "$_val" | tr '[:upper:]' '[:lower:]')"
394
+ case "$_val" in
395
+ false|no|0|disabled|off) return 1 ;;
396
+ *) return 0 ;;
397
+ esac
398
+ }
399
+
400
+ copilot_skills_enabled() {
401
+ copilot_plugin_enabled || return 1
402
+ _val="$(yaml_plugin_get "copilot" "skills")"
403
+ _val="$(printf '%s' "$_val" | tr '[:upper:]' '[:lower:]')"
404
+ case "$_val" in
405
+ false|no|0|disabled|off) return 1 ;;
406
+ *) return 0 ;;
407
+ esac
408
+ }
409
+
410
+ copilot_instructions_enabled() {
411
+ copilot_plugin_enabled || return 1
412
+ _val="$(yaml_plugin_get "copilot" "instructions")"
413
+ _val="$(printf '%s' "$_val" | tr '[:upper:]' '[:lower:]')"
414
+ case "$_val" in
415
+ false|no|0|disabled|off) return 1 ;;
416
+ *) return 0 ;;
417
+ esac
418
+ }
419
+
420
+ copilot_agents_enabled() {
421
+ copilot_plugin_enabled || return 1
422
+ _val="$(yaml_plugin_get "copilot" "agents")"
423
+ _val="$(printf '%s' "$_val" | tr '[:upper:]' '[:lower:]')"
424
+ case "$_val" in
425
+ false|no|0|disabled|off) return 1 ;;
426
+ *) return 0 ;;
427
+ esac
428
+ }
429
+
430
+ _yaml_plugin_set_in_file() {
431
+ _file="$1"; _plugin="$2"; _field="$3"; _value="$4"
432
+ if [ ! -f "$_file" ]; then
433
+ mkdir -p "$(dirname "$_file")"
434
+ printf 'plugins:\n' > "$_file"
435
+ elif ! grep -q '^plugins:' "$_file" 2>/dev/null; then
436
+ printf '\nplugins:\n' >> "$_file"
359
437
  fi
360
- if ! yaml_has_plugin "$_name"; then
438
+
439
+ if ! awk -v plugin="$_plugin" '
440
+ /^plugins:[ ]*$/ || /^plugins:[ ]*#/ { in_p=1; next }
441
+ in_p && /^[^ #]/ { in_p=0 }
442
+ in_p && match($0, "^ " plugin ":[ ]*(#.*)?$") { found=1; exit }
443
+ END { exit !found }
444
+ ' "$_file" 2>/dev/null; then
445
+ if grep -qE "^ $_plugin:[ ]*(\{\}|\[\])?$" "$_file" 2>/dev/null; then
446
+ _tmp="$(mktemp)"
447
+ awk -v plugin="$_plugin" -v field="$_field" -v value="$_value" '
448
+ match($0, "^ " plugin ":[ ]*(\\{\\}|\\[\\])?$") {
449
+ printf " %s:\n %s: %s\n", plugin, field, value
450
+ next
451
+ }
452
+ { print }
453
+ ' "$_file" > "$_tmp" && mv "$_tmp" "$_file"
454
+ return 0
455
+ fi
361
456
  _tmp="$(mktemp)"
362
- awk -v name="$_name" '
363
- /^plugins:/ {
457
+ awk -v plugin="$_plugin" -v field="$_field" -v value="$_value" '
458
+ /^plugins:[ ]*$/ || /^plugins:[ ]*#/ {
364
459
  print
365
- printf " %s: {}\n", name
460
+ printf " %s:\n %s: %s\n", plugin, field, value
366
461
  added=1
367
462
  next
368
463
  }
369
464
  { print }
370
- ' "$WORKSPACE_YAML" > "$_tmp" && mv "$_tmp" "$WORKSPACE_YAML"
465
+ END {
466
+ if (!added) {
467
+ printf "plugins:\n %s:\n %s: %s\n", plugin, field, value
468
+ }
469
+ }
470
+ ' "$_file" > "$_tmp" && mv "$_tmp" "$_file"
471
+ return 0
472
+ fi
473
+
474
+ _tmp="$(mktemp)"
475
+ awk -v plugin="$_plugin" -v field="$_field" -v value="$_value" '
476
+ /^plugins:/ { in_plugins=1; print; next }
477
+ in_plugins && /^[^ #]/ {
478
+ if (in_target && !field_set) {
479
+ printf " %s: %s\n", field, value
480
+ field_set=1
481
+ }
482
+ in_plugins=0; in_target=0
483
+ }
484
+ in_plugins && match($0, "^ " plugin ":[ ]*(#.*)?$") {
485
+ in_target=1; print; next
486
+ }
487
+ in_target && /^ [^ #]/ {
488
+ if (!field_set) {
489
+ printf " %s: %s\n", field, value
490
+ field_set=1
491
+ }
492
+ in_target=0
493
+ }
494
+ in_target && match($0, "^ " field ":") {
495
+ printf " %s: %s\n", field, value
496
+ field_set=1
497
+ next
498
+ }
499
+ { print }
500
+ END {
501
+ if (in_target && !field_set) {
502
+ printf " %s: %s\n", field, value
503
+ }
504
+ }
505
+ ' "$_file" > "$_tmp" && mv "$_tmp" "$_file"
506
+ }
507
+
508
+ yaml_plugin_set() {
509
+ _plugin="$1"; _field="$2"; _value="$3"
510
+ _yaml_plugin_set_in_file "$WORKSPACE_YAML" "$_plugin" "$_field" "$_value"
511
+ }
512
+
513
+ yaml_plugin_set_local() {
514
+ _plugin="$1"; _field="$2"; _value="$3"
515
+ if [ ! -f "$WORKSPACE_LOCAL_YAML" ]; then
516
+ cat <<'EOF' > "$WORKSPACE_LOCAL_YAML"
517
+ # ==============================================================================
518
+ # .local.rnex.yaml — Repo Nexus Local Configuration (Machine-Specific)
519
+ # ==============================================================================
520
+ # This file is gitignored. Use it to specify local repository paths, overrides,
521
+ # and enable/disable states for this workstation.
522
+
523
+ plugins:
524
+ EOF
525
+ fi
526
+ _yaml_plugin_set_in_file "$WORKSPACE_LOCAL_YAML" "$_plugin" "$_field" "$_value"
527
+ }
528
+
529
+ yaml_enable_plugin() {
530
+ _name="$1"
531
+ _target_file="${2:-$WORKSPACE_YAML}"
532
+ if [ ! -f "$_target_file" ]; then
533
+ printf 'plugins:\n' > "$_target_file"
534
+ elif ! grep -q '^plugins:' "$_target_file" 2>/dev/null; then
535
+ printf '\nplugins:\n' >> "$_target_file"
536
+ fi
537
+ if ! _yaml_list_plugins_from_file "$_target_file" | grep -qx "$_name" 2>/dev/null; then
538
+ _tmp="$(mktemp)"
539
+ if [ "$_name" = "copilot" ]; then
540
+ awk -v name="$_name" '
541
+ /^plugins:[ ]*$/ || /^plugins:[ ]*#/ {
542
+ print
543
+ printf " %s:\n prompts: true\n skills: true\n instructions: true\n agents: true\n", name
544
+ added=1
545
+ next
546
+ }
547
+ { print }
548
+ END {
549
+ if (!added) {
550
+ printf "plugins:\n %s:\n prompts: true\n skills: true\n instructions: true\n agents: true\n", name
551
+ }
552
+ }
553
+ ' "$_target_file" > "$_tmp" && mv "$_tmp" "$_target_file"
554
+ else
555
+ awk -v name="$_name" '
556
+ /^plugins:[ ]*$/ || /^plugins:[ ]*#/ {
557
+ print
558
+ printf " %s: {}\n", name
559
+ added=1
560
+ next
561
+ }
562
+ { print }
563
+ END {
564
+ if (!added) {
565
+ printf "plugins:\n %s: {}\n", name
566
+ }
567
+ }
568
+ ' "$_target_file" > "$_tmp" && mv "$_tmp" "$_target_file"
569
+ fi
570
+ else
571
+ if [ -f "$WORKSPACE_LOCAL_YAML" ] && [ "$_target_file" = "$WORKSPACE_LOCAL_YAML" ]; then
572
+ _yaml_plugin_set_in_file "$_target_file" "$_name" "enabled" "true"
573
+ fi
371
574
  fi
372
575
  }
373
576
 
@@ -734,8 +937,8 @@ EOF
734
937
  _dest_pdir="$_r_rnex/plugins/$_pname"
735
938
  mkdir -p "$_dest_pdir"
736
939
 
737
- # Copy rules/workflows/instructions into member plugin dir
738
- for _sub in rules workflows instructions; do
940
+ # Copy rules/workflows/instructions/prompts/skills/agents into member plugin dir
941
+ for _sub in rules workflows instructions prompts skills agents; do
739
942
  if [ -d "$_pdir/$_sub" ]; then
740
943
  mkdir -p "$_dest_pdir/$_sub"
741
944
  cp -r "$_pdir/$_sub"/* "$_dest_pdir/$_sub"/ 2>/dev/null || true
@@ -846,8 +1049,8 @@ sync_plugins() {
846
1049
  if [ "$_pdir" != "$_scoped_dest" ]; then
847
1050
  mkdir -p "$_scoped_dest"
848
1051
 
849
- # Copy rules, workflows, instructions into scoped plugin directory
850
- for _sub in rules workflows instructions; do
1052
+ # Copy rules, workflows, instructions, prompts, skills, agents into scoped plugin directory
1053
+ for _sub in rules workflows instructions prompts skills agents; do
851
1054
  if [ -d "$_pdir/$_sub" ]; then
852
1055
  mkdir -p "$_scoped_dest/$_sub"
853
1056
  cp -r "$_pdir/$_sub"/* "$_scoped_dest/$_sub"/ 2>/dev/null || true
@@ -890,14 +1093,11 @@ reconcile_gitignore() {
890
1093
  repos/*
891
1094
  !repos/.gitkeep
892
1095
 
893
- # Repo Nexus internal state & cache
894
- .rnex/
895
-
896
1096
  # Local machine-specific configuration
897
1097
  $RNEX_LOCAL_CONFIG_FILE
898
1098
  .rnex.local.yaml
899
1099
  GI_EOF
900
- log_ok "Created .gitignore (ignoring repos/, .rnex/, and $RNEX_LOCAL_CONFIG_FILE)"
1100
+ log_ok "Created .gitignore (ignoring repos/ and $RNEX_LOCAL_CONFIG_FILE)"
901
1101
  return 0
902
1102
  fi
903
1103
 
@@ -908,18 +1108,19 @@ GI_EOF
908
1108
  log_ok "Removed legacy lint trigger counter entries from .gitignore"
909
1109
  fi
910
1110
 
911
- # 2. Ensure repos/* is ignored
1111
+ # 2. Strip legacy .rnex/ entries if present (.rnex/ contains tracked prompts, plugins, and hooks)
1112
+ if grep -qE '^[ ]*#?[ ]*Repo Nexus internal state' "$_gi" 2>/dev/null || grep -qE '^\.rnex/?$' "$_gi" 2>/dev/null; then
1113
+ _tmp="$(mktemp)"
1114
+ grep -vE '(^[ ]*#?[ ]*Repo Nexus internal state|^\.rnex/?$)' "$_gi" > "$_tmp" && mv "$_tmp" "$_gi"
1115
+ log_ok "Removed .rnex/ from .gitignore (.rnex should be tracked in git)"
1116
+ fi
1117
+
1118
+ # 3. Ensure repos/* is ignored
912
1119
  if ! grep -q "^repos" "$_gi" 2>/dev/null; then
913
1120
  printf '\n# Member repos (managed by rnex)\nrepos/*\n!repos/.gitkeep\n' >> "$_gi"
914
1121
  log_dim "Added repos/* to .gitignore"
915
1122
  fi
916
1123
 
917
- # 3. Ensure .rnex/ is ignored
918
- if ! grep -q '^\.rnex/' "$_gi" 2>/dev/null && ! grep -q '^\.rnex$' "$_gi" 2>/dev/null; then
919
- printf '\n# Repo Nexus internal state & cache\n.rnex/\n' >> "$_gi"
920
- log_dim "Added .rnex/ to .gitignore"
921
- fi
922
-
923
1124
  # 4. Ensure local config files are ignored
924
1125
  if ! grep -qF "$RNEX_LOCAL_CONFIG_FILE" "$_gi" 2>/dev/null; then
925
1126
  printf '\n# Local machine-specific configuration\n%s\n' "$RNEX_LOCAL_CONFIG_FILE" >> "$_gi"
@@ -1132,6 +1333,115 @@ sync_code_workspace() {
1132
1333
  fi
1133
1334
  }
1134
1335
 
1336
+ sync_copilot_instructions() {
1337
+ _dst_ci="$NEXUS_DIR/.github/copilot-instructions.md"
1338
+ if ! copilot_instructions_enabled; then
1339
+ if [ -f "$_dst_ci" ]; then
1340
+ if grep -q "$AI_MARKER_START" "$_dst_ci" 2>/dev/null; then
1341
+ _non_rnex="$(awk -v s="$AI_MARKER_START" -v e="$AI_MARKER_END" '
1342
+ $0 ~ s { skip=1; next }
1343
+ $0 ~ e { skip=0; next }
1344
+ !skip { print }
1345
+ ' "$_dst_ci" | tr -d " \t\r\n")"
1346
+ if [ -z "$_non_rnex" ]; then
1347
+ rm -f "$_dst_ci"
1348
+ else
1349
+ _tmp="$(mktemp)"
1350
+ awk -v s="$AI_MARKER_START" -v e="$AI_MARKER_END" '
1351
+ $0 ~ s { skip=1; next }
1352
+ $0 ~ e { skip=0; next }
1353
+ !skip { print }
1354
+ ' "$_dst_ci" > "$_tmp" && mv "$_tmp" "$_dst_ci"
1355
+ fi
1356
+ fi
1357
+ fi
1358
+ return 0
1359
+ fi
1360
+
1361
+ mkdir -p "$NEXUS_DIR/.github"
1362
+ _body_tmp="$(mktemp)"
1363
+
1364
+ {
1365
+ cat <<'EOF'
1366
+ # GitHub Copilot Instructions (Repo Nexus Virtual Meta-Repo)
1367
+
1368
+ This workspace operates as a **Repo Nexus Virtual Meta-Repo** uniting independent repositories.
1369
+
1370
+ ## Routing & Operating Protocol
1371
+ 1. Inspect `.local.rnex.yaml` when present, then `rnex.yaml`.
1372
+ 2. Master operational prompts are indexed at `.rnex/prompts/index.md` (and mirrored in `.github/prompts/`).
1373
+ 3. Member repositories reside in `repos/<name>/`. Inspect `repos/<name>/.rnex/` for repository-specific context.
1374
+ 4. Perform Git commits directly inside member repository roots (`repos/<name>/`).
1375
+ EOF
1376
+
1377
+ # Append active plugins instructions & rules
1378
+ _active_p="$(yaml_list_plugins)"
1379
+ if [ -n "$_active_p" ]; then
1380
+ printf '\n## Active Plugins & Guidelines\n'
1381
+ echo "$_active_p" | while read -r _pname; do
1382
+ [ -n "$_pname" ] || continue
1383
+ yaml_plugin_enabled "$_pname" || continue
1384
+ [ "$_pname" != "copilot" ] || continue
1385
+ _pdir="$(find_plugin_dir "$_pname" 2>/dev/null || true)"
1386
+ [ -n "$_pdir" ] || continue
1387
+ _pdesc="$(plugin_get_field "$_pdir" "description")"
1388
+ printf '\n### Plugin: %s\n' "$_pname"
1389
+ [ -n "$_pdesc" ] && printf '%s\n\n' "$_pdesc"
1390
+
1391
+ for _rfile in "$_pdir"/rules/*.md "$NEXUS_DIR/.rnex/plugins/$_pname"/rules/*.md; do
1392
+ if [ -f "$_rfile" ]; then
1393
+ printf '#### Rules (%s)\n' "$(basename "$_rfile")"
1394
+ cat "$_rfile"
1395
+ printf '\n'
1396
+ break
1397
+ fi
1398
+ done
1399
+
1400
+ for _ifile in "$_pdir"/instructions/*.md "$NEXUS_DIR/.rnex/plugins/$_pname"/instructions/*.md; do
1401
+ if [ -f "$_ifile" ]; then
1402
+ printf '#### Instructions (%s)\n' "$(basename "$_ifile")"
1403
+ cat "$_ifile"
1404
+ printf '\n'
1405
+ break
1406
+ fi
1407
+ done
1408
+ done
1409
+ fi
1410
+ } > "$_body_tmp"
1411
+
1412
+ if [ ! -f "$_dst_ci" ]; then
1413
+ {
1414
+ printf '%s\n' "$AI_MARKER_START"
1415
+ cat "$_body_tmp"
1416
+ printf '\n%s\n' "$AI_MARKER_END"
1417
+ } > "$_dst_ci"
1418
+ elif grep -q "$AI_MARKER_START" "$_dst_ci" 2>/dev/null; then
1419
+ _tmp="$(mktemp)"
1420
+ awk -v s="$AI_MARKER_START" -v e="$AI_MARKER_END" -v src="$_body_tmp" '
1421
+ $0 ~ s {
1422
+ print s
1423
+ while ((getline line < src) > 0) print line
1424
+ close(src)
1425
+ print e
1426
+ skip=1
1427
+ next
1428
+ }
1429
+ $0 ~ e { skip=0; next }
1430
+ !skip { print }
1431
+ ' "$_dst_ci" > "$_tmp" && mv "$_tmp" "$_dst_ci"
1432
+ else
1433
+ _tmp="$(mktemp)"
1434
+ cat "$_dst_ci" > "$_tmp"
1435
+ {
1436
+ printf '\n\n%s\n' "$AI_MARKER_START"
1437
+ cat "$_body_tmp"
1438
+ printf '\n%s\n' "$AI_MARKER_END"
1439
+ } >> "$_tmp"
1440
+ mv "$_tmp" "$_dst_ci"
1441
+ fi
1442
+ rm -f "$_body_tmp"
1443
+ }
1444
+
1135
1445
  sync_prompts() {
1136
1446
  _src_prompts=""
1137
1447
  if [ -d "$SCRIPT_LOCATION/toolkit/prompts" ]; then
@@ -1152,6 +1462,208 @@ sync_prompts() {
1152
1462
  _b="$(basename "$_pfile")"
1153
1463
  cp -f "$_pfile" "$_dst_prompts/$_b"
1154
1464
  done
1465
+
1466
+ # Copilot prompts sync (.github/prompts/*.prompt.md)
1467
+ if copilot_prompts_enabled; then
1468
+ _copilot_prompts="$NEXUS_DIR/.github/prompts"
1469
+ mkdir -p "$_copilot_prompts"
1470
+
1471
+ # Base toolkit prompts
1472
+ for _pfile in "$_src_prompts"/rnex-*.md; do
1473
+ [ -f "$_pfile" ] || continue
1474
+ _pname="$(basename "$_pfile" .md)"
1475
+ _desc="$(awk '
1476
+ /^#/ { in_title=1; next }
1477
+ in_title && /^[A-Za-z]/ { print; exit }
1478
+ ' "$_pfile" 2>/dev/null)"
1479
+ [ -n "$_desc" ] || _desc="Repo Nexus prompt for $_pname"
1480
+
1481
+ _dst_cp="$_copilot_prompts/$_pname.prompt.md"
1482
+ {
1483
+ printf -- '---\nname: %s\ndescription: %s\n---\n\n' "$_pname" "$_desc"
1484
+ cat "$_pfile"
1485
+ } > "$_dst_cp"
1486
+ done
1487
+
1488
+ # Active plugins prompts & workflows
1489
+ yaml_list_plugins | while read -r _pname; do
1490
+ [ -n "$_pname" ] || continue
1491
+ yaml_plugin_enabled "$_pname" || continue
1492
+ [ "$_pname" != "copilot" ] || continue
1493
+ _pdir="$(find_plugin_dir "$_pname" 2>/dev/null || true)"
1494
+ [ -n "$_pdir" ] || continue
1495
+
1496
+ for _sub in prompts workflows; do
1497
+ for _s_dir in "$_pdir/$_sub" "$NEXUS_DIR/.rnex/plugins/$_pname/$_sub"; do
1498
+ [ -d "$_s_dir" ] || continue
1499
+ for _pfile in "$_s_dir"/*.md; do
1500
+ [ -f "$_pfile" ] || continue
1501
+ _base="$(basename "$_pfile" .md)"
1502
+ case "$_base" in
1503
+ index|README) continue ;;
1504
+ esac
1505
+ _desc="$(awk '
1506
+ /^#/ { in_title=1; next }
1507
+ in_title && /^[A-Za-z]/ { print; exit }
1508
+ ' "$_pfile" 2>/dev/null)"
1509
+ [ -n "$_desc" ] || _desc="Prompt $_base from plugin $_pname"
1510
+
1511
+ _dst_cp="$_copilot_prompts/$_base.prompt.md"
1512
+ {
1513
+ printf -- '---\nname: %s\ndescription: %s\n---\n\n' "$_base" "$_desc"
1514
+ cat "$_pfile"
1515
+ } > "$_dst_cp"
1516
+ done
1517
+ done
1518
+ done
1519
+ done
1520
+ else
1521
+ if [ -d "$NEXUS_DIR/.github/prompts" ]; then
1522
+ rm -f "$NEXUS_DIR/.github/prompts"/*.prompt.md 2>/dev/null || true
1523
+ rmdir "$NEXUS_DIR/.github/prompts" 2>/dev/null || true
1524
+ fi
1525
+ fi
1526
+
1527
+ # Copilot skills sync (.github/skills/<name>/SKILL.md)
1528
+ if copilot_skills_enabled; then
1529
+ _copilot_skills="$NEXUS_DIR/.github/skills"
1530
+ mkdir -p "$_copilot_skills"
1531
+
1532
+ # Base toolkit skills
1533
+ for _pfile in "$_src_prompts"/rnex-*.md; do
1534
+ [ -f "$_pfile" ] || continue
1535
+ _pname="$(basename "$_pfile" .md)"
1536
+ _desc="$(awk '
1537
+ /^#/ { in_title=1; next }
1538
+ in_title && /^[A-Za-z]/ { print; exit }
1539
+ ' "$_pfile" 2>/dev/null)"
1540
+ [ -n "$_desc" ] || _desc="Repo Nexus prompt for $_pname"
1541
+
1542
+ _dst_sk_dir="$_copilot_skills/$_pname"
1543
+ mkdir -p "$_dst_sk_dir"
1544
+ _dst_sk="$_dst_sk_dir/SKILL.md"
1545
+ {
1546
+ printf -- '---\nname: %s\ndescription: %s\n---\n\n' "$_pname" "$_desc"
1547
+ cat "$_pfile"
1548
+ } > "$_dst_sk"
1549
+ done
1550
+
1551
+ # Active plugins skills, prompts, & workflows
1552
+ yaml_list_plugins | while read -r _pname; do
1553
+ [ -n "$_pname" ] || continue
1554
+ yaml_plugin_enabled "$_pname" || continue
1555
+ [ "$_pname" != "copilot" ] || continue
1556
+ _pdir="$(find_plugin_dir "$_pname" 2>/dev/null || true)"
1557
+ [ -n "$_pdir" ] || continue
1558
+
1559
+ # A. Dedicated skills in plugin
1560
+ for _s_dir in "$_pdir/skills" "$NEXUS_DIR/.rnex/plugins/$_pname/skills"; do
1561
+ [ -d "$_s_dir" ] || continue
1562
+ for _s_entry in "$_s_dir"/*; do
1563
+ if [ -d "$_s_entry" ] && [ -f "$_s_entry/SKILL.md" ]; then
1564
+ _sname="$(basename "$_s_entry")"
1565
+ mkdir -p "$_copilot_skills/$_sname"
1566
+ cp -f "$_s_entry/SKILL.md" "$_copilot_skills/$_sname/SKILL.md"
1567
+ elif [ -f "$_s_entry" ]; then
1568
+ _sname="$(basename "$_s_entry" .md)"
1569
+ mkdir -p "$_copilot_skills/$_sname"
1570
+ if grep -q '^---' "$_s_entry" 2>/dev/null; then
1571
+ cp -f "$_s_entry" "$_copilot_skills/$_sname/SKILL.md"
1572
+ else
1573
+ _desc="$(awk '
1574
+ /^#/ { in_title=1; next }
1575
+ in_title && /^[A-Za-z]/ { print; exit }
1576
+ ' "$_s_entry" 2>/dev/null)"
1577
+ [ -n "$_desc" ] || _desc="Skill $_sname from plugin $_pname"
1578
+ {
1579
+ printf -- '---\nname: %s\ndescription: %s\n---\n\n' "$_sname" "$_desc"
1580
+ cat "$_s_entry"
1581
+ } > "$_copilot_skills/$_sname/SKILL.md"
1582
+ fi
1583
+ fi
1584
+ done
1585
+ done
1586
+
1587
+ # B. Plugin prompts & workflows as skills if not already provided
1588
+ for _sub in prompts workflows; do
1589
+ for _s_dir in "$_pdir/$_sub" "$NEXUS_DIR/.rnex/plugins/$_pname/$_sub"; do
1590
+ [ -d "$_s_dir" ] || continue
1591
+ for _pfile in "$_s_dir"/*.md; do
1592
+ [ -f "$_pfile" ] || continue
1593
+ _base="$(basename "$_pfile" .md)"
1594
+ case "$_base" in
1595
+ index|README) continue ;;
1596
+ esac
1597
+ _dst_sk_dir="$_copilot_skills/$_base"
1598
+ if [ ! -f "$_dst_sk_dir/SKILL.md" ]; then
1599
+ mkdir -p "$_dst_sk_dir"
1600
+ _desc="$(awk '
1601
+ /^#/ { in_title=1; next }
1602
+ in_title && /^[A-Za-z]/ { print; exit }
1603
+ ' "$_pfile" 2>/dev/null)"
1604
+ [ -n "$_desc" ] || _desc="Skill $_base from plugin $_pname"
1605
+ {
1606
+ printf -- '---\nname: %s\ndescription: %s\n---\n\n' "$_base" "$_desc"
1607
+ cat "$_pfile"
1608
+ } > "$_dst_sk_dir/SKILL.md"
1609
+ fi
1610
+ done
1611
+ done
1612
+ done
1613
+ done
1614
+ else
1615
+ if [ -d "$NEXUS_DIR/.github/skills" ]; then
1616
+ rm -rf "$NEXUS_DIR/.github/skills" 2>/dev/null || true
1617
+ fi
1618
+ fi
1619
+
1620
+ # Copilot agents sync (.github/agents/*.agent.md)
1621
+ if copilot_agents_enabled; then
1622
+ _copilot_agents="$NEXUS_DIR/.github/agents"
1623
+
1624
+ yaml_list_plugins | while read -r _pname; do
1625
+ [ -n "$_pname" ] || continue
1626
+ yaml_plugin_enabled "$_pname" || continue
1627
+ [ "$_pname" != "copilot" ] || continue
1628
+ _pdir="$(find_plugin_dir "$_pname" 2>/dev/null || true)"
1629
+ [ -n "$_pdir" ] || continue
1630
+
1631
+ for _s_dir in "$_pdir/agents" "$NEXUS_DIR/.rnex/plugins/$_pname/agents"; do
1632
+ [ -d "$_s_dir" ] || continue
1633
+ for _afile in "$_s_dir"/*.md; do
1634
+ [ -f "$_afile" ] || continue
1635
+ _aname="$(basename "$_afile" .agent.md)"
1636
+ _aname="$(basename "$_aname" .md)"
1637
+ mkdir -p "$_copilot_agents"
1638
+ if grep -q '^---' "$_afile" 2>/dev/null; then
1639
+ cp -f "$_afile" "$_copilot_agents/$_aname.agent.md"
1640
+ else
1641
+ _desc="$(awk '
1642
+ /^#/ { in_title=1; next }
1643
+ in_title && /^[A-Za-z]/ { print; exit }
1644
+ ' "$_afile" 2>/dev/null)"
1645
+ [ -n "$_desc" ] || _desc="Agent $_aname from plugin $_pname"
1646
+ {
1647
+ printf -- '---\nname: %s\ndescription: %s\n---\n\n' "$_aname" "$_desc"
1648
+ cat "$_afile"
1649
+ } > "$_copilot_agents/$_aname.agent.md"
1650
+ fi
1651
+ # Also mirror to skills if skills enabled
1652
+ if copilot_skills_enabled; then
1653
+ mkdir -p "$_copilot_skills/$_aname"
1654
+ cp -f "$_copilot_agents/$_aname.agent.md" "$_copilot_skills/$_aname/SKILL.md"
1655
+ fi
1656
+ done
1657
+ done
1658
+ done
1659
+ else
1660
+ if [ -d "$NEXUS_DIR/.github/agents" ]; then
1661
+ rm -rf "$NEXUS_DIR/.github/agents" 2>/dev/null || true
1662
+ fi
1663
+ fi
1664
+
1665
+ # Copilot instructions sync (.github/copilot-instructions.md)
1666
+ sync_copilot_instructions
1155
1667
  }
1156
1668
 
1157
1669
  upgrade_workspace_config() {
@@ -1486,12 +1998,15 @@ cmd_init() {
1486
1998
  _cli_code_workspace=""
1487
1999
  _cli_hooks=""
1488
2000
  _cli_no_hooks=0
2001
+ _cli_copilot=""
1489
2002
 
1490
2003
  while [ $# -gt 0 ]; do
1491
2004
  case "$1" in
1492
2005
  -y|--yes) _non_interactive=1 ;;
1493
2006
  --hooks) _cli_hooks="true" ;;
1494
2007
  --no-hooks) _cli_no_hooks=1; _cli_hooks="false" ;;
2008
+ --copilot) _cli_copilot="true" ;;
2009
+ --no-copilot) _cli_copilot="false" ;;
1495
2010
  --ai|--instructions|--ai-instructions)
1496
2011
  shift
1497
2012
  _cli_ai_instructions="$1"
@@ -1561,11 +2076,15 @@ cmd_init() {
1561
2076
  log_dim "To reconcile repos and plugins, run:"
1562
2077
  log_dim " rnex fix"
1563
2078
  else
2079
+ _init_plugins=""
2080
+ if [ "$_cli_copilot" = "true" ]; then
2081
+ _init_plugins=" copilot:\n prompts: true\n skills: true\n instructions: true\n agents: true\n"
2082
+ fi
2083
+
1564
2084
  cat > "$_target_yaml" <<YAML_EOF
1565
- # Repo Nexus workspace configuration (Virtual Meta-Repo)
2085
+ # Repo Nexus workspace configuration
1566
2086
  # See docs/rnex.example.yaml for a comprehensive example with all options.
1567
2087
 
1568
- # Workspace configuration version
1569
2088
  version: $RNEX_VERSION
1570
2089
 
1571
2090
  # Directory for member repository clones
@@ -1582,7 +2101,7 @@ git_hooks: $_init_git_hooks
1582
2101
 
1583
2102
  # Workspace plugins
1584
2103
  plugins:
1585
-
2104
+ $(printf '%b' "$_init_plugins")
1586
2105
  # Member repositories managed by Repo Nexus
1587
2106
  repos:
1588
2107
  YAML_EOF
@@ -1617,11 +2136,18 @@ YAML_EOF
1617
2136
  mkdir -p "$_target_dir/.rnex/plugins"
1618
2137
  mkdir -p "$_target_dir/.rnex/prompts"
1619
2138
  _orig_nexus="$NEXUS_DIR"
2139
+ _orig_yaml="$WORKSPACE_YAML"
2140
+ _orig_local_yaml="$WORKSPACE_LOCAL_YAML"
1620
2141
  NEXUS_DIR="$_target_dir"
2142
+ WORKSPACE_YAML="$_target_yaml"
2143
+ WORKSPACE_LOCAL_YAML="$_target_dir/$RNEX_LOCAL_CONFIG_FILE"
2144
+ sync_plugins
1621
2145
  sync_prompts
2146
+ WORKSPACE_LOCAL_YAML="$_orig_local_yaml"
2147
+ WORKSPACE_YAML="$_orig_yaml"
1622
2148
  NEXUS_DIR="$_orig_nexus"
1623
2149
 
1624
- # ---- 5. Ensure repos/, .rnex/, and local configs are gitignored ---------
2150
+ # ---- 5. Ensure repos/ and local configs are gitignored ---------
1625
2151
  reconcile_gitignore "$_target_dir"
1626
2152
 
1627
2153
  # ---- 6. Generate VS Code / Cursor workspace if configured ----------------
@@ -1978,18 +2504,18 @@ cmd_status() {
1978
2504
  fi
1979
2505
 
1980
2506
  _gi="$NEXUS_DIR/.gitignore"
1981
- _gi_repos=0; _gi_rnex=0; _gi_local=0; _gi_has_counter=0
2507
+ _gi_repos=0; _gi_local=0; _gi_has_counter=0; _gi_has_rnex=0
1982
2508
  if [ -f "$_gi" ]; then
1983
2509
  grep -q '^repos' "$_gi" 2>/dev/null && _gi_repos=1
1984
- (grep -q '^\.rnex/' "$_gi" 2>/dev/null || grep -q '^\.rnex$' "$_gi" 2>/dev/null) && _gi_rnex=1
1985
2510
  grep -qF "$RNEX_LOCAL_CONFIG_FILE" "$_gi" 2>/dev/null && _gi_local=1
1986
2511
  grep -q "lint_trigger_counter" "$_gi" 2>/dev/null && _gi_has_counter=1
2512
+ (grep -q '^\.rnex/' "$_gi" 2>/dev/null || grep -q '^\.rnex$' "$_gi" 2>/dev/null) && _gi_has_rnex=1
1987
2513
  fi
1988
2514
 
1989
- if [ "$_gi_repos" -eq 1 ] && [ "$_gi_rnex" -eq 1 ] && [ "$_gi_local" -eq 1 ] && [ "$_gi_has_counter" -eq 0 ]; then
1990
- printf ' %b✓%b Git Ignore: repos/, .rnex/, and %s ignored in .gitignore\n' "$_G" "$_NC" "$RNEX_LOCAL_CONFIG_FILE"
2515
+ if [ "$_gi_repos" -eq 1 ] && [ "$_gi_local" -eq 1 ] && [ "$_gi_has_counter" -eq 0 ] && [ "$_gi_has_rnex" -eq 0 ]; then
2516
+ printf ' %b✓%b Git Ignore: repos/ and %s ignored in .gitignore\n' "$_G" "$_NC" "$RNEX_LOCAL_CONFIG_FILE"
1991
2517
  else
1992
- printf ' %b!%b Git Ignore: recommend running "rnex fix" to update .gitignore (repos/, .rnex/, local configs)\n' "$_Y" "$_NC"
2518
+ printf ' %b!%b Git Ignore: recommend running "rnex fix" to update .gitignore (repos/, local configs)\n' "$_Y" "$_NC"
1993
2519
  fi
1994
2520
 
1995
2521
  _hooks_path="$(git -C "$NEXUS_DIR" config --get core.hooksPath 2>/dev/null || true)"
@@ -2037,6 +2563,7 @@ cmd_status() {
2037
2563
  fi
2038
2564
  ;;
2039
2565
  esac
2566
+
2040
2567
  printf '\n'
2041
2568
 
2042
2569
  printf '%bWorkspace AI Context (Routing):%b\n' "$_BOLD" "$_NC"
@@ -2069,6 +2596,18 @@ cmd_status() {
2069
2596
  if [ -f "$NEXUS_DIR/.rnex/prompts/index.md" ]; then
2070
2597
  printf ' %b✓%b %s %b(prompts catalog)%b\n' "$_G" "$_NC" ".rnex/prompts/index.md" "$_DIM" "$_NC"
2071
2598
  fi
2599
+ if [ -d "$NEXUS_DIR/.github/prompts" ]; then
2600
+ printf ' %b✓%b %s %b(Copilot prompts)%b\n' "$_G" "$_NC" ".github/prompts/" "$_DIM" "$_NC"
2601
+ fi
2602
+ if [ -d "$NEXUS_DIR/.github/skills" ]; then
2603
+ printf ' %b✓%b %s %b(Copilot skills)%b\n' "$_G" "$_NC" ".github/skills/" "$_DIM" "$_NC"
2604
+ fi
2605
+ if [ -d "$NEXUS_DIR/.github/agents" ]; then
2606
+ printf ' %b✓%b %s %b(Copilot agents)%b\n' "$_G" "$_NC" ".github/agents/" "$_DIM" "$_NC"
2607
+ fi
2608
+ if [ -f "$NEXUS_DIR/.github/copilot-instructions.md" ]; then
2609
+ printf ' %b✓%b %s %b(Copilot instructions)%b\n' "$_G" "$_NC" ".github/copilot-instructions.md" "$_DIM" "$_NC"
2610
+ fi
2072
2611
  printf '\n'
2073
2612
 
2074
2613
  printf '%bActive Plugins:%b\n' "$_BOLD" "$_NC"
@@ -2082,8 +2621,19 @@ cmd_status() {
2082
2621
  if [ -n "$_pdir" ]; then
2083
2622
  _ver="$(plugin_get_field "$_pdir" "version")"
2084
2623
  _desc="$(plugin_get_field "$_pdir" "description")"
2085
- printf ' %b●%b %-18s %b(v%s)%b %s\n' "$_G" "$_NC" "$_pname" "$_DIM" "${_ver:-0.1.0}" "$_NC" "${_desc:+- $_desc}"
2086
- printf ' %bScoped directory: .rnex/plugins/%s%b\n' "$_DIM" "$_pname" "$_NC"
2624
+ if ! yaml_plugin_enabled "$_pname"; then
2625
+ printf ' %b○%b %-18s %b[disabled locally]%b\n' "$_DIM" "$_NC" "$_pname" "$_DIM" "$_NC"
2626
+ else
2627
+ printf ' %b●%b %-18s %b(v%s)%b %s\n' "$_G" "$_NC" "$_pname" "$_DIM" "${_ver:-0.1.0}" "$_NC" "${_desc:+- $_desc}"
2628
+ printf ' %bScoped directory: .rnex/plugins/%s%b\n' "$_DIM" "$_pname" "$_NC"
2629
+ if [ "$_pname" = "copilot" ]; then
2630
+ printf ' %b↳ Options: prompts=%s, skills=%s, instructions=%s, agents=%s%b\n' "$_DIM" \
2631
+ "$(copilot_prompts_enabled && echo "true" || echo "false")" \
2632
+ "$(copilot_skills_enabled && echo "true" || echo "false")" \
2633
+ "$(copilot_instructions_enabled && echo "true" || echo "false")" \
2634
+ "$(copilot_agents_enabled && echo "true" || echo "false")" "$_NC"
2635
+ fi
2636
+ fi
2087
2637
  else
2088
2638
  printf ' %b✗%b %-18s %bMISSING%b\n' "$_R" "$_NC" "$_pname" "$_R" "$_NC"
2089
2639
  printf ' %b↳ [!] Issue: plugin declared in config but directory not found on disk%b\n' "$_R" "$_NC"
@@ -2174,6 +2724,7 @@ cmd_fix() {
2174
2724
  _load_ai_instructions_file
2175
2725
  _load_code_workspace
2176
2726
  _load_git_hooks
2727
+ _load_copilot
2177
2728
  [ "$_fix_quiet" -eq 0 ] && log_ok "Upgraded workspace configuration and routing instructions to v$RNEX_VERSION"
2178
2729
  fi
2179
2730
  fi
@@ -2330,8 +2881,10 @@ cmd_plugin_info() {
2330
2881
  _author="$(plugin_get_field "$_pdir" "author")"
2331
2882
  _home="$(plugin_get_field "$_pdir" "homepage")"
2332
2883
 
2333
- if yaml_has_plugin "$_name"; then
2884
+ if yaml_plugin_enabled "$_name"; then
2334
2885
  _status="${_G}enabled${_NC}"
2886
+ elif yaml_has_plugin "$_name"; then
2887
+ _status="${_DIM}disabled locally (${WORKSPACE_LOCAL_YAML})${_NC}"
2335
2888
  else
2336
2889
  _status="${_DIM}available (not enabled)${_NC}"
2337
2890
  fi
@@ -2344,6 +2897,14 @@ cmd_plugin_info() {
2344
2897
  [ -n "$_home" ] && printf '%bHomepage:%b %s\n' "$_BOLD" "$_NC" "$_home"
2345
2898
  printf '%bLocation:%b %s\n' "$_BOLD" "$_NC" "$_pdir"
2346
2899
 
2900
+ if [ "$_name" = "copilot" ]; then
2901
+ printf '\n%bConfigurable Options (in rnex.yaml or .local.rnex.yaml):%b\n' "$_BOLD" "$_NC"
2902
+ printf ' - prompts: true|false (mirror prompts to .github/prompts/*.prompt.md; current: %s)\n' "$(copilot_prompts_enabled && echo "true" || echo "false")"
2903
+ printf ' - skills: true|false (mirror skills to .github/skills/<name>/SKILL.md; current: %s)\n' "$(copilot_skills_enabled && echo "true" || echo "false")"
2904
+ printf ' - instructions: true|false (mirror instructions to .github/copilot-instructions.md; current: %s)\n' "$(copilot_instructions_enabled && echo "true" || echo "false")"
2905
+ printf ' - agents: true|false (mirror agents to .github/agents/*.agent.md; current: %s)\n' "$(copilot_agents_enabled && echo "true" || echo "false")"
2906
+ fi
2907
+
2347
2908
  printf '\n%bScoped Directory:%b .rnex/plugins/%s\n' "$_BOLD" "$_NC" "$_name"
2348
2909
 
2349
2910
  _tmpl="$(plugin_list_templates "$_pdir")"
@@ -2363,8 +2924,16 @@ cmd_plugin_info() {
2363
2924
 
2364
2925
  cmd_plugin_enable() {
2365
2926
  require_workspace
2366
- _pname="$1"
2367
- [ -n "$_pname" ] || die "Usage: rnex plugin enable <name>"
2927
+ _is_local=0
2928
+ _pname=""
2929
+ while [ $# -gt 0 ]; do
2930
+ case "$1" in
2931
+ --local) _is_local=1 ;;
2932
+ *) _pname="$1" ;;
2933
+ esac
2934
+ shift
2935
+ done
2936
+ [ -n "$_pname" ] || die "Usage: rnex plugin enable [--local] <name>"
2368
2937
 
2369
2938
  _pdir="$(find_plugin_dir "$_pname" 2>/dev/null || true)"
2370
2939
  [ -n "$_pdir" ] || die "Plugin '$_pname' not found."
@@ -2372,8 +2941,13 @@ cmd_plugin_enable() {
2372
2941
  _name="$(plugin_get_field "$_pdir" "name")"
2373
2942
  [ -n "$_name" ] || _name="$_pname"
2374
2943
 
2375
- yaml_enable_plugin "$_name"
2376
- log_ok "Plugin '$_name' enabled in $(basename "$WORKSPACE_YAML")"
2944
+ if [ "$_is_local" -eq 1 ]; then
2945
+ yaml_enable_plugin "$_name" "$WORKSPACE_LOCAL_YAML"
2946
+ log_ok "Plugin '$_name' enabled locally in $(basename "$WORKSPACE_LOCAL_YAML")"
2947
+ else
2948
+ yaml_enable_plugin "$_name" "$WORKSPACE_YAML"
2949
+ log_ok "Plugin '$_name' enabled in $(basename "$WORKSPACE_YAML")"
2950
+ fi
2377
2951
 
2378
2952
  sync_plugins
2379
2953
  cmd_fix
@@ -2382,8 +2956,16 @@ cmd_plugin_enable() {
2382
2956
 
2383
2957
  cmd_plugin_disable() {
2384
2958
  require_workspace
2385
- _pname="$1"
2386
- [ -n "$_pname" ] || die "Usage: rnex plugin disable <name>"
2959
+ _is_local=0
2960
+ _pname=""
2961
+ while [ $# -gt 0 ]; do
2962
+ case "$1" in
2963
+ --local) _is_local=1 ;;
2964
+ *) _pname="$1" ;;
2965
+ esac
2966
+ shift
2967
+ done
2968
+ [ -n "$_pname" ] || die "Usage: rnex plugin disable [--local] <name>"
2387
2969
 
2388
2970
  _pdir="$(find_plugin_dir "$_pname" 2>/dev/null || true)"
2389
2971
  _name="$_pname"
@@ -2392,22 +2974,34 @@ cmd_plugin_disable() {
2392
2974
  [ -n "$_n" ] && _name="$_n"
2393
2975
  fi
2394
2976
 
2395
- yaml_disable_plugin "$_name"
2396
-
2397
- # Remove scoped plugin from workspace .rnex/plugins/
2398
- if [ -d "$NEXUS_DIR/.rnex/plugins/$_name" ]; then
2399
- rm -rf "$NEXUS_DIR/.rnex/plugins/$_name"
2400
- log_ok "Removed workspace plugin scope: .rnex/plugins/$_name"
2977
+ if [ "$_is_local" -eq 1 ]; then
2978
+ if _yaml_list_plugins_from_file "$WORKSPACE_YAML" | grep -qx "$_name" 2>/dev/null; then
2979
+ yaml_plugin_set_local "$_name" "enabled" "false"
2980
+ log_ok "Plugin '$_name' disabled locally in $(basename "$WORKSPACE_LOCAL_YAML")"
2981
+ else
2982
+ _yaml_disable_plugin_in_file "$WORKSPACE_LOCAL_YAML" "$_name"
2983
+ log_ok "Plugin '$_name' removed from $(basename "$WORKSPACE_LOCAL_YAML")"
2984
+ fi
2985
+ else
2986
+ yaml_disable_plugin "$_name"
2987
+ log_ok "Plugin '$_name' disabled from workspace"
2401
2988
  fi
2402
2989
 
2403
- # Remove scoped plugin from member repos .rnex/plugins/
2404
- yaml_list_repos | while read -r _rname; do
2405
- _rpath="$(resolve_repo_path "$_rname")"
2406
- if [ -d "$_rpath/.rnex/plugins/$_name" ]; then
2407
- rm -rf "$_rpath/.rnex/plugins/$_name"
2990
+ if ! yaml_plugin_enabled "$_name"; then
2991
+ if [ -d "$NEXUS_DIR/.rnex/plugins/$_name" ]; then
2992
+ rm -rf "$NEXUS_DIR/.rnex/plugins/$_name"
2993
+ log_ok "Removed workspace plugin scope: .rnex/plugins/$_name"
2408
2994
  fi
2409
- done
2410
2995
 
2996
+ yaml_list_repos | while read -r _rname; do
2997
+ _rpath="$(resolve_repo_path "$_rname")"
2998
+ if [ -d "$_rpath/.rnex/plugins/$_name" ]; then
2999
+ rm -rf "$_rpath/.rnex/plugins/$_name"
3000
+ fi
3001
+ done
3002
+ fi
3003
+
3004
+ sync_prompts
2411
3005
  log_ok "Plugin '$_name' disabled from workspace"
2412
3006
  }
2413
3007
 
@@ -2630,7 +3224,7 @@ cmd_help() {
2630
3224
  -v, --version Show version
2631
3225
 
2632
3226
  WORKSPACE & SYSTEM SETUP
2633
- init [-y] [--ai <file>] [--code-workspace [file]] [--hooks|--no-hooks] [dir]
3227
+ init [-y] [--ai <file>] [--code-workspace [file]] [--hooks|--no-hooks] [--copilot|--no-copilot] [dir]
2634
3228
  Initialize a new Repo Nexus workspace (default AI file: AGENTS.md)
2635
3229
  install [dir] Install rnex & repo-nexus globally into ~/.local/bin (or custom dir)
2636
3230
  fix [-y] [--quiet] Reconcile workspace, plugins, prompts & member .rnex/ (alias: sync)
@@ -2654,8 +3248,8 @@ cmd_help() {
2654
3248
  PLUGIN MANAGEMENT
2655
3249
  plugin [list] List available and enabled plugins
2656
3250
  plugin info <name> Show details of a plugin
2657
- plugin enable <name> Enable plugin in workspace (scoped to .rnex/plugins/<name>/)
2658
- plugin disable <name> Disable plugin from workspace
3251
+ plugin enable [--local] <name> Enable plugin in workspace (scoped to .rnex/plugins/<name>/)
3252
+ plugin disable [--local] <name> Disable plugin from workspace
2659
3253
 
2660
3254
  EXAMPLES
2661
3255
  rnex init # Initialize workspace in current folder
@@ -0,0 +1,37 @@
1
+ # GitHub Copilot Plugin for Repo Nexus
2
+
3
+ A built-in Repo Nexus plugin providing bidirectional alignment and operational prompt/skill mirroring for GitHub Copilot.
4
+
5
+ ## Capabilities
6
+
7
+ 1. **Prompts Mirroring**: Standardized Repo Nexus prompts (`rnex-feature`, `rnex-audit`, etc.) and active plugins' prompts/workflows are synchronized into `.github/prompts/*.prompt.md` with YAML frontmatter.
8
+ 2. **Agent Skills**: Prompts, active plugin skills, and agent bundles are mirrored into `.github/skills/<name>/SKILL.md` for GitHub Copilot Agent mode.
9
+ 3. **Custom Agents**: Active plugins' agents are mirrored into `.github/agents/*.agent.md`.
10
+ 4. **Instructions Integration**: Active plugins' rules/instructions and Repo Nexus routing instructions are synthesized into `.github/copilot-instructions.md`.
11
+
12
+ ## Usage
13
+
14
+ Enable the plugin across the workspace:
15
+ ```bash
16
+ rnex plugin enable copilot
17
+ ```
18
+
19
+ Or configure options in `rnex.yaml` or `.local.rnex.yaml`:
20
+ ```yaml
21
+ plugins:
22
+ copilot:
23
+ prompts: true
24
+ skills: true
25
+ instructions: true
26
+ agents: true
27
+ ```
28
+
29
+ ## Options
30
+
31
+ | Option | Type | Default | Description |
32
+ |--------|------|---------|-------------|
33
+ | `prompts` | boolean | `true` | Mirror prompts to `.github/prompts/*.prompt.md` |
34
+ | `skills` | boolean | `true` | Mirror skills to `.github/skills/<name>/SKILL.md` |
35
+ | `instructions` | boolean | `true` | Mirror guidelines to `.github/copilot-instructions.md` |
36
+ | `agents` | boolean | `true` | Mirror custom agents to `.github/agents/*.agent.md` |
37
+ | `enabled` | boolean | `true` | Set to `false` in `.local.rnex.yaml` to override team config |
@@ -0,0 +1,29 @@
1
+ # GitHub Copilot Integration for Repo Nexus
2
+
3
+ This workspace has the Repo Nexus `copilot` plugin enabled.
4
+
5
+ ## Operating Principles
6
+ - **Prompts (`.github/prompts/*.prompt.md`)**: Operational Repo Nexus prompts and active plugins' prompts/workflows are mirrored here with YAML frontmatter (`name`, `description`) for use in the VS Code Copilot Chat prompt picker and slash commands.
7
+ - **Agent Skills (`.github/skills/<name>/SKILL.md`)**: Standard prompts, active plugin skills, and agent bundles are mirrored as individual skill bundles with frontmatter for GitHub Copilot Agent mode and `gh skill`.
8
+ - **Custom Agents (`.github/agents/*.agent.md`)**: Active plugins' agent definitions (such as `wiki-curator`) are mirrored here for Copilot workspace custom agents.
9
+ - **Copilot Instructions (`.github/copilot-instructions.md`)**: Synthesizes workspace routing and active plugin guidelines between `<!-- REPO-NEXUS:START -->` and `<!-- REPO-NEXUS:END -->`, preserving any manual user instructions outside those markers.
10
+ - **Decoupled Cross-Plugin Discovery**: Plugins remain independent and decoupled; the `copilot` provider discovers and mirrors assets from whatever plugins are currently active.
11
+
12
+ ## Configuration
13
+ Configure plugin options in `rnex.yaml` or override them per developer in `.local.rnex.yaml`:
14
+
15
+ ```yaml
16
+ plugins:
17
+ copilot:
18
+ prompts: true # Mirror prompts to .github/prompts/ (default: true)
19
+ skills: true # Mirror skills to .github/skills/ (default: true)
20
+ instructions: true # Mirror routing & plugin guidelines to .github/copilot-instructions.md (default: true)
21
+ agents: true # Mirror custom agents to .github/agents/ (default: true)
22
+ ```
23
+
24
+ To disable locally without altering team configuration, add to `.local.rnex.yaml`:
25
+ ```yaml
26
+ plugins:
27
+ copilot:
28
+ enabled: false
29
+ ```
@@ -0,0 +1,7 @@
1
+ name: copilot
2
+ version: 0.5.1
3
+ description: GitHub Copilot integration (mirrors workspace prompts to .github/prompts and skills to .github/skills)
4
+ author: nu-nenoi
5
+ homepage: https://github.com/nu-nenoi/repo-nexus
6
+ instructions:
7
+ - instructions/copilot-integration.md: .rnex/plugins/copilot/instructions/copilot-integration.md
@@ -0,0 +1,8 @@
1
+ ---
2
+ name: wiki-curator
3
+ description: Autonomous knowledge librarian for the Karpathy LLM Wiki architecture.
4
+ ---
5
+
6
+ # Wiki Curator Agent
7
+
8
+ Autonomous knowledge librarian specialized in synthesizing unstructured source documents into the atomic Karpathy LLM Wiki graph.
@@ -0,0 +1,10 @@
1
+ # Karpathy LLM Wiki Ingestion Workflow (`wiki-ingest`)
2
+
3
+ Autonomous workflow for decomposing and ingesting raw source documents from `raw/` into atomic Karpathy LLM Wiki pages.
4
+
5
+ ## Protocol
6
+ 1. Scan `raw/` for uningested documents not yet recorded in `wiki/_log.md`.
7
+ 2. Read source materials completely; preserve original files in `raw/` unmodified.
8
+ 3. Decompose each source document into atomic wiki pages in `wiki/` (5–25 pages per source).
9
+ 4. For every page, write required YAML frontmatter with typed relations (`sources`, `related`, `extends`, `contradicts`, `mentioned_in`).
10
+ 5. Update `wiki/index.md` and append an entry to `wiki/_log.md`.
@@ -0,0 +1,10 @@
1
+ # Karpathy LLM Wiki Lint & Graph Maintenance (`wiki-lint`)
2
+
3
+ Periodic maintenance workflow to preserve wiki graph integrity, validate typed relations, and recompute bidirectional links.
4
+
5
+ ## Protocol
6
+ 1. Verify all frontmatter relation paths (`sources`, `related`, `extends`, `contradicts`) resolve to existing files.
7
+ 2. Recompute `mentioned_in` backlinks for every page across the entire wiki graph.
8
+ 3. Find orphaned pages not reachable from `wiki/index.md` or any `mentioned_in` link, and index them.
9
+ 4. Detect duplicate/overlapping pages and check for factual contradictions.
10
+ 5. Identify knowledge gaps and append audit results to `wiki/_log.md`.
@@ -0,0 +1,14 @@
1
+ ---
2
+ name: wiki-ingest
3
+ description: Autonomous ingestion and atomic decomposition of raw sources into Karpathy LLM Wiki pages.
4
+ ---
5
+
6
+ # Karpathy LLM Wiki Ingestion Skill
7
+
8
+ Use this skill when decomposing raw documents, research notes, meeting logs, or external articles from `raw/` into atomic wiki pages under `wiki/`.
9
+
10
+ ## Key Rules
11
+ - Source documents stay untouched in `raw/`.
12
+ - Produce 5–25 atomic pages per document (never lump into one large file).
13
+ - Include YAML frontmatter with typed relations (`sources`, `related`, `extends`, `contradicts`, `mentioned_in`).
14
+ - Record completed ingestion in `wiki/_log.md`.
@@ -0,0 +1,14 @@
1
+ ---
2
+ name: wiki-lint
3
+ description: Autonomous link validation, backlink recalculation, and graph repair for Karpathy LLM Wiki.
4
+ ---
5
+
6
+ # Karpathy LLM Wiki Lint Skill
7
+
8
+ Use this skill when auditing and maintaining knowledge graph integrity across `/wiki/`.
9
+
10
+ ## Key Steps
11
+ - Validate all relation filepaths exist.
12
+ - Recalculate and update `mentioned_in` backlinks.
13
+ - Check for orphan pages and update `wiki/index.md`.
14
+ - Flag contradictions and record maintenance in `wiki/_log.md`.