repo-nexus 0.8.1 → 0.8.2

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
@@ -23,12 +23,12 @@ A **Virtual Meta-Repo** companion for multi-repo workspaces and shared AI contex
23
23
  >
24
24
  > Explore the comprehensive documentation, architecture guides, and interactive references on the **[Documentation Site](https://unoxen.github.io/repo-nexus/)**:
25
25
  >
26
- > - 🚀 **[Getting Started](https://unoxen.github.io/repo-nexus/guide/getting-started)** — Step-by-step onboarding walkthrough and workspace setup
27
- > - 📐 **[Architecture](https://unoxen.github.io/repo-nexus/guide/architecture)** & **[Why Repo Nexus?](https://unoxen.github.io/repo-nexus/guide/why-repo-nexus)** — Virtual Meta-Repo model, directory layout, and design rationale
28
- > - 💻 **[CLI Reference](https://unoxen.github.io/repo-nexus/cli/)** — Complete command syntax, global flags, batch execution (`rnex exec`), and Git hooks
29
- > - 🧩 **[Plugins Guide](https://unoxen.github.io/repo-nexus/plugins/)** — AI provider integrations (Claude, Codex, Copilot, Cursor, Gemini, Windsurf) and Karpathy LLM Wiki
30
- > - ⚙️ **[Configuration Schema](https://unoxen.github.io/repo-nexus/guide/configuration)** — Two-level `rnex.yaml` and `.local.rnex.yaml` specification
31
- > - ❓ **[Frequently Asked Questions (FAQ)](https://unoxen.github.io/repo-nexus/faq/)** — Common questions, Git submodule differences, and context strategies
26
+ > - 🚀 **[Getting Started](https://unoxen.github.io/repo-nexus/introduction/quick-start)** — Step-by-step onboarding walkthrough and workspace setup
27
+ > - 📐 **[Architecture](https://unoxen.github.io/repo-nexus/documentation/architecture)** & **[Why Repo Nexus?](https://unoxen.github.io/repo-nexus/introduction/why-rnex)** — Virtual Meta-Repo model, directory layout, and design rationale
28
+ > - 💻 **[CLI Reference](https://unoxen.github.io/repo-nexus/reference/cli)** — Complete command syntax, global flags, batch execution (`rnex exec`), and Git hooks
29
+ > - 🧩 **[Plugins Guide](https://unoxen.github.io/repo-nexus/documentation/plugin-ecosystem)** — AI provider integrations (Claude, Codex, Copilot, Cursor, Gemini, Windsurf) and Karpathy LLM Wiki
30
+ > - ⚙️ **[Configuration Schema](https://unoxen.github.io/repo-nexus/documentation/configuration)** — Two-level `rnex.yaml` and `.local.rnex.yaml` specification
31
+ > - ❓ **[Frequently Asked Questions (FAQ)](https://unoxen.github.io/repo-nexus/faq/general)** — Common questions, Git submodule differences, and context strategies
32
32
 
33
33
  ---
34
34
 
@@ -145,11 +145,11 @@ repo-nexus/
145
145
  │ ├── ai-instructions.sample.md # Base template for .rnex/ai-instructions.md
146
146
  │ └── rnex.example.yaml # Full config reference with examples
147
147
  ├── docs/
148
- │ ├── guide/ # Architecture, workflows, and getting started
149
- │ ├── cli/ # Comprehensive CLI reference manual
148
+ │ ├── introduction/ # Welcome, Why rnex?, Quick Start, and Pure Examples
149
+ │ ├── documentation/ # Architecture, Configuration, Workflows, Lifecycle, Plugins
150
+ │ ├── reference/ # CLI Reference, RNEX Hooks, Git Hooks, and Environment
150
151
  │ ├── plugins/ # Scoped plugin guides and specifications
151
- │ ├── examples/ # Multi-repo patterns and case studies
152
- │ └── faq/ # Frequently Asked Questions
152
+ │ └── faq/ # Frequently Asked Questions & Troubleshooting
153
153
  ├── .github/
154
154
  │ └── workflows/ci.yml # GitHub Actions CI workflow
155
155
  ├── scripts/
@@ -170,6 +170,13 @@ git:
170
170
  hooks:
171
171
  $_hooks_block
172
172
 
173
+ # RNEX Lifecycle Hooks
174
+ rnex_hooks:
175
+ before_sync: []
176
+ after_sync: []
177
+ before_clone: []
178
+ after_clone: []
179
+
173
180
  # Workspace plugins
174
181
  plugins:
175
182
  $(printf '%b' "$_init_plugins")
@@ -28,6 +28,19 @@ cmd_plugin_list() {
28
28
  printf ' %b[available]%b %b%-15s%b %b(v%s)%b - %s\n' \
29
29
  "$_DIM" "$_NC" "$_BOLD" "$_name" "$_NC" "$_DIM" "${_version:-0.1.0}" "$_NC" "$_desc"
30
30
  fi
31
+
32
+ _pcmds="$(plugin_list_commands "$_name" 2>/dev/null || true)"
33
+ if [ -n "$_pcmds" ]; then
34
+ echo "$_pcmds" | while read -r _c; do
35
+ [ -n "$_c" ] || continue
36
+ _cdesc="$(plugin_get_command_desc "$_name" "$_c" 2>/dev/null || true)"
37
+ if [ -n "$_cdesc" ]; then
38
+ printf ' %b↳ rnex plugin %s %-10s%b %s\n' "$_DIM" "$_name" "$_c" "$_NC" "$_cdesc"
39
+ else
40
+ printf ' %b↳ rnex plugin %s %s%b\n' "$_DIM" "$_name" "$_c" "$_NC"
41
+ fi
42
+ done
43
+ fi
31
44
  done
32
45
  printf '\n'
33
46
  log_dim "To enable a plugin: rnex plugin enable <name>"
@@ -284,13 +297,31 @@ cmd_plugin() {
284
297
  ;;
285
298
  enable|install)
286
299
  shift
300
+ _h_pname=""
301
+ for _arg in "$@"; do
302
+ case "$_arg" in --*) ;; *) _h_pname="$_arg" ;; esac
303
+ done
304
+ RNEX_PLUGIN_NAME="$_h_pname"
305
+ export RNEX_PLUGIN_NAME
306
+ run_hook "before_plugin_enable" "$@"
287
307
  cmd_plugin_enable "$@"
288
- return $?
308
+ _rc=$?
309
+ [ "$_rc" -eq 0 ] && run_hook "after_plugin_enable" "$@"
310
+ return "$_rc"
289
311
  ;;
290
312
  disable|uninstall|remove)
291
313
  shift
314
+ _h_pname=""
315
+ for _arg in "$@"; do
316
+ case "$_arg" in --*) ;; *) _h_pname="$_arg" ;; esac
317
+ done
318
+ RNEX_PLUGIN_NAME="$_h_pname"
319
+ export RNEX_PLUGIN_NAME
320
+ run_hook "before_plugin_disable" "$@"
292
321
  cmd_plugin_disable "$@"
293
- return $?
322
+ _rc=$?
323
+ [ "$_rc" -eq 0 ] && run_hook "after_plugin_disable" "$@"
324
+ return "$_rc"
294
325
  ;;
295
326
  update|upgrade)
296
327
  shift
@@ -10,12 +10,57 @@ cmd_repo() {
10
10
  _subcmd="$1"
11
11
  shift
12
12
  case "$_subcmd" in
13
- add) cmd_repo_add "$@" ;;
14
- remove|rm) cmd_repo_remove "$@" ;;
15
- set) cmd_repo_set "$@" ;;
16
- clone) cmd_repo_clone "$@" ;;
17
- status) cmd_repo_status "$@" ;;
18
- exec) cmd_repo_exec "$@" ;;
13
+ add)
14
+ run_hook "before_repo_add" "$@"
15
+ cmd_repo_add "$@"
16
+ _rc=$?
17
+ [ "$_rc" -eq 0 ] && run_hook "after_repo_add" "$@"
18
+ return "$_rc"
19
+ ;;
20
+ remove|rm)
21
+ for _arg in "$@"; do
22
+ case "$_arg" in
23
+ -*) ;;
24
+ *) export RNEX_REPO_NAME="$_arg"; break ;;
25
+ esac
26
+ done
27
+ run_hook "before_repo_remove" "$@"
28
+ cmd_repo_remove "$@"
29
+ _rc=$?
30
+ [ "$_rc" -eq 0 ] && run_hook "after_repo_remove" "$@"
31
+ return "$_rc"
32
+ ;;
33
+ set)
34
+ for _arg in "$@"; do
35
+ case "$_arg" in
36
+ -*) ;;
37
+ *) export RNEX_REPO_NAME="$_arg"; break ;;
38
+ esac
39
+ done
40
+ run_hook "before_repo_set" "$@"
41
+ cmd_repo_set "$@"
42
+ _rc=$?
43
+ [ "$_rc" -eq 0 ] && run_hook "after_repo_set" "$@"
44
+ return "$_rc"
45
+ ;;
46
+ clone)
47
+ [ $# -gt 0 ] && export RNEX_REPO_NAME="$1"
48
+ run_hook "before_clone" "$@"
49
+ cmd_repo_clone "$@"
50
+ _rc=$?
51
+ [ "$_rc" -eq 0 ] && run_hook "after_clone" "$@"
52
+ return "$_rc"
53
+ ;;
54
+ status)
55
+ cmd_repo_status "$@"
56
+ ;;
57
+ exec)
58
+ run_hook "before_exec" "$@"
59
+ cmd_repo_exec "$@"
60
+ _rc=$?
61
+ run_hook "after_exec" "$@"
62
+ return "$_rc"
63
+ ;;
19
64
  list|ls) cmd_list "$@" ;;
20
65
  help|-h|--help) cmd_repo_help ;;
21
66
  *) die "Unknown repo subcommand: $_subcmd (try 'rnex repo help')" ;;
@@ -115,6 +160,7 @@ cmd_repo_add() {
115
160
 
116
161
  [ -n "$_name" ] || die "Could not determine repository name from '$_url'"
117
162
  [ -n "$_url" ] || die "Usage: rnex repo add <url> [--name <name>] [--branch <branch>] [--local] [--disabled] [--readonly]"
163
+ export RNEX_REPO_NAME="$_name"
118
164
 
119
165
  ensure_repos_dir
120
166
  _target_dir="$(resolve_repo_path "$_name")"
@@ -392,10 +438,17 @@ cmd_repo_exec() {
392
438
  _repo_dir="$(resolve_repo_path "$_name")"
393
439
  [ -d "$_repo_dir" ] || die "Repo '$_name' is not cloned yet at $_repo_dir"
394
440
 
441
+ _b="$(git -C "$_repo_dir" symbolic-ref --short HEAD 2>/dev/null || git -C "$_repo_dir" rev-parse --short HEAD 2>/dev/null || true)"
395
442
  _cmd="$*"
396
443
  printf '%b[%s]%b %s\n' "$_B" "$_name" "$_NC" "$_cmd"
397
444
  printf '%s\n' "----------------------------------------"
398
- (cd "$_repo_dir" && eval "$_cmd")
445
+ (
446
+ RNEX_REPO_NAME="$_name"
447
+ RNEX_REPO_PATH="$_repo_dir"
448
+ RNEX_REPO_BRANCH="$_b"
449
+ export RNEX_REPO_NAME RNEX_REPO_PATH RNEX_REPO_BRANCH
450
+ cd "$_repo_dir" && eval "$_cmd"
451
+ )
399
452
  }
400
453
 
401
454
  # Clone all enabled repositories declared in configuration that are not yet cloned.
@@ -481,7 +534,14 @@ cmd_exec() {
481
534
 
482
535
  printf '\n%b[%s]%b %s\n' "$_B" "$_name" "$_NC" "$_cmd"
483
536
  printf '%s\n' "----------------------------------------"
484
- if (cd "$_repo_dir" && eval "$_cmd"); then
537
+ _b="$(git -C "$_repo_dir" symbolic-ref --short HEAD 2>/dev/null || git -C "$_repo_dir" rev-parse --short HEAD 2>/dev/null || true)"
538
+ if (
539
+ RNEX_REPO_NAME="$_name"
540
+ RNEX_REPO_PATH="$_repo_dir"
541
+ RNEX_REPO_BRANCH="$_b"
542
+ export RNEX_REPO_NAME RNEX_REPO_PATH RNEX_REPO_BRANCH
543
+ cd "$_repo_dir" && eval "$_cmd"
544
+ ); then
485
545
  printf '%b[✓] %s succeeded%b\n' "$_G" "$_name" "$_NC"
486
546
  else
487
547
  _rc=$?
@@ -83,7 +83,11 @@ cmd_sync() {
83
83
  reconcile_gitignore "$NEXUS_DIR"
84
84
 
85
85
  # 1.2. Reconcile universal workspace instructions in AGENTS.md (permanent main context file)
86
+ # and all existing permanent provider instructions files
86
87
  merge_rnex_instructions "$NEXUS_DIR/AGENTS.md"
88
+ for _if in CLAUDE.md GEMINI.md CODEX.md .cursorrules .windsurfrules .github/copilot-instructions.md; do
89
+ [ -f "$NEXUS_DIR/$_if" ] && merge_rnex_instructions "$NEXUS_DIR/$_if"
90
+ done
87
91
 
88
92
  # 1.3. Generate auto-sync script (hardcoded harness)
89
93
  _write_auto_sync_script "$NEXUS_DIR"
@@ -105,6 +105,7 @@ cmd_help() {
105
105
  plugin install [--local] <name> Alias for plugin enable
106
106
  plugin update [name] Update enabled plugin(s) from source
107
107
  plugin disable [--local] <name> Disable plugin from workspace
108
+ plugin <name> <cmd> [options] Execute a command exposed by an enabled plugin
108
109
 
109
110
  EXAMPLES
110
111
  rnex init # Initialize workspace in current folder
@@ -121,6 +122,8 @@ cmd_help() {
121
122
  rnex list # List all member repos and active branches
122
123
  rnex status # Inspect workspace configuration and health
123
124
  rnex sync # Reconcile all repos, plugins, skills, and .rnex directories
125
+ rnex plugin karpathy-llm ingest # Ingest sources into the Karpathy LLM Wiki
126
+ rnex plugin karpathy-llm lint --strict # Validate Karpathy LLM Wiki links and limits
124
127
  rnex completion zsh # Generate Zsh completion script
125
128
 
126
129
  EOF
package/lib/hooks.sh CHANGED
@@ -117,6 +117,70 @@ _run_hook_internal() {
117
117
  ) || true
118
118
  fi
119
119
  done
120
+
121
+ # 2. Execute configured commands from rnex_hooks.<event_name>
122
+ if [ -z "$_hook_target_plugin" ]; then
123
+ _hook_norm="$(printf '%s' "$_hook_phase_cmd" | tr '-' '_')"
124
+ case ":${RNEX_HOOK_ACTIVE:-}:" in
125
+ *":${_hook_norm}:"*)
126
+ # Re-entrant loop guard: skip re-entrant execution of this hook event
127
+ ;;
128
+ *)
129
+ _rnex_cmds="$(yaml_get_rnex_hook_commands "$_hook_norm" 2>/dev/null || true)"
130
+ if [ -n "$_rnex_cmds" ]; then
131
+ _prev_active="${RNEX_HOOK_ACTIVE:-}"
132
+ export RNEX_HOOK_ACTIVE="${RNEX_HOOK_ACTIVE:+${RNEX_HOOK_ACTIVE}:}${_hook_norm}"
133
+ _is_blocking=0
134
+ case "$_hook_norm" in
135
+ before_*) _is_blocking=1 ;;
136
+ esac
137
+ _old_ifs="$IFS"
138
+ IFS='
139
+ '
140
+ for _rcmd in $_rnex_cmds; do
141
+ IFS="$_old_ifs"
142
+ [ -n "$_rcmd" ] || continue
143
+ if [ "$_is_blocking" -eq 1 ]; then
144
+ (
145
+ RNEX_ROOT="$_hook_root"
146
+ RNEX_CONFIG_MERGED="$_hook_config_merged"
147
+ RNEX_CMD="$_hook_cmd"
148
+ RNEX_ARGS="$_hook_args"
149
+ RNEX_HOOK_EVENT="$_hook_phase_cmd"
150
+ RNEX_HOOK_ARGS="$_hook_args"
151
+ RNEX_QUIET="$_hook_quiet"
152
+ RNEX_PROVIDER_SKILL_DIRS="$_skill_dirs"
153
+ export RNEX_ROOT RNEX_CONFIG_MERGED RNEX_CMD RNEX_ARGS RNEX_HOOK_EVENT RNEX_HOOK_ARGS RNEX_QUIET RNEX_PROVIDER_SKILL_DIRS RNEX_LIB_DIR NEXUS_DIR WORKSPACE_YAML WORKSPACE_LOCAL_YAML
154
+ cd "$_hook_root" && eval "$_rcmd"
155
+ ) || {
156
+ _cmd_rc=$?
157
+ export RNEX_HOOK_ACTIVE="$_prev_active"
158
+ WORKSPACE_LOCAL_YAML="$_old_local_yaml"
159
+ WORKSPACE_YAML="$_old_yaml"
160
+ NEXUS_DIR="$_old_nexus"
161
+ return "$_cmd_rc"
162
+ }
163
+ else
164
+ (
165
+ RNEX_ROOT="$_hook_root"
166
+ RNEX_CONFIG_MERGED="$_hook_config_merged"
167
+ RNEX_CMD="$_hook_cmd"
168
+ RNEX_ARGS="$_hook_args"
169
+ RNEX_HOOK_EVENT="$_hook_phase_cmd"
170
+ RNEX_HOOK_ARGS="$_hook_args"
171
+ RNEX_QUIET="$_hook_quiet"
172
+ RNEX_PROVIDER_SKILL_DIRS="$_skill_dirs"
173
+ export RNEX_ROOT RNEX_CONFIG_MERGED RNEX_CMD RNEX_ARGS RNEX_HOOK_EVENT RNEX_HOOK_ARGS RNEX_QUIET RNEX_PROVIDER_SKILL_DIRS RNEX_LIB_DIR NEXUS_DIR WORKSPACE_YAML WORKSPACE_LOCAL_YAML
174
+ cd "$_hook_root" && eval "$_rcmd"
175
+ ) || true
176
+ fi
177
+ done
178
+ IFS="$_old_ifs"
179
+ export RNEX_HOOK_ACTIVE="$_prev_active"
180
+ fi
181
+ ;;
182
+ esac
183
+ fi
120
184
  WORKSPACE_LOCAL_YAML="$_old_local_yaml"
121
185
  WORKSPACE_YAML="$_old_yaml"
122
186
  NEXUS_DIR="$_old_nexus"
package/lib/plugins.sh CHANGED
@@ -751,7 +751,16 @@ run_plugin_command() {
751
751
  _rpc_yaml="${WORKSPACE_YAML:-$_rpc_root/${RNEX_CONFIG_FILE:-rnex.yaml}}"
752
752
  _rpc_local_yaml="${WORKSPACE_LOCAL_YAML:-${LOCAL_WORKSPACE_YAML:-$_rpc_root/${RNEX_LOCAL_CONFIG_FILE:-.local.rnex.yaml}}}"
753
753
  _rpc_lib_dir="${RNEX_LIB_DIR:-$_rpc_root/lib}"
754
+ _rpc_args="$*"
754
755
 
756
+ RNEX_PLUGIN_NAME="$_rpc_plugin"
757
+ RNEX_PLUGIN_COMMAND="$_rpc_cmd"
758
+ RNEX_PLUGIN_ARGS="$_rpc_args"
759
+ export RNEX_PLUGIN_NAME RNEX_PLUGIN_COMMAND RNEX_PLUGIN_ARGS
760
+
761
+ if command -v run_hook >/dev/null 2>&1; then
762
+ run_hook "before_plugin_command" "$_rpc_plugin" "$_rpc_cmd" "$@"
763
+ fi
755
764
  (
756
765
  RNEX_ROOT="$_rpc_root"
757
766
  NEXUS_DIR="$_rpc_root"
@@ -760,12 +769,19 @@ run_plugin_command() {
760
769
  LOCAL_WORKSPACE_YAML="$_rpc_local_yaml"
761
770
  RNEX_LIB_DIR="$_rpc_lib_dir"
762
771
  RNEX_PLUGIN_NAME="$_rpc_plugin"
772
+ RNEX_PLUGIN_COMMAND="$_rpc_cmd"
773
+ RNEX_PLUGIN_ARGS="$_rpc_args"
763
774
  RNEX_PLUGIN_DIR="$_rpc_root/.rnex/plugins/$_rpc_plugin"
764
- export RNEX_ROOT NEXUS_DIR WORKSPACE_YAML WORKSPACE_LOCAL_YAML LOCAL_WORKSPACE_YAML RNEX_LIB_DIR RNEX_PLUGIN_NAME RNEX_PLUGIN_DIR
775
+ export RNEX_ROOT NEXUS_DIR WORKSPACE_YAML WORKSPACE_LOCAL_YAML LOCAL_WORKSPACE_YAML RNEX_LIB_DIR RNEX_PLUGIN_NAME RNEX_PLUGIN_COMMAND RNEX_PLUGIN_ARGS RNEX_PLUGIN_DIR
765
776
  if [ -x "$_rpc_script" ]; then
766
777
  "$_rpc_script" "$@"
767
778
  else
768
779
  sh "$_rpc_script" "$@"
769
780
  fi
770
781
  )
782
+ _rc=$?
783
+ if [ "$_rc" -eq 0 ] && command -v run_hook >/dev/null 2>&1; then
784
+ run_hook "after_plugin_command" "$_rpc_plugin" "$_rpc_cmd" "$@"
785
+ fi
786
+ return "$_rc"
771
787
  }
package/lib/sdk.sh CHANGED
@@ -272,6 +272,13 @@ rnex_block_merge() {
272
272
  clean_rnex_instructions() {
273
273
  _dst="$1"
274
274
  [ -f "$_dst" ] || return 0
275
+
276
+ # Permanent main context files must NEVER be stripped or deleted
277
+ case "$(basename "$_dst")" in
278
+ AGENTS.md|CLAUDE.md|GEMINI.md|CODEX.md|.cursorrules|.windsurfrules|copilot-instructions.md)
279
+ return 0
280
+ ;;
281
+ esac
275
282
  if grep -qF "$AI_MARKER_START" "$_dst" 2>/dev/null; then
276
283
  _non_rnex="$(awk -v s="$AI_MARKER_START" -v e="$AI_MARKER_END" '
277
284
  $0 == s { skip=1; next }
package/lib/workspace.sh CHANGED
@@ -339,12 +339,12 @@ upgrade_workspace_config() {
339
339
  ' "$_f" > "$_tmp" && mv "$_tmp" "$_f"
340
340
  fi
341
341
 
342
- # 4. Remove legacy git_hooks: setting and add structured git: section if missing
343
- if grep -qE '^[ ]*(git_hooks|hooks):' "$_f" 2>/dev/null; then
342
+ # 4. Remove legacy top-level git_hooks: or hooks: setting and add structured git: section if missing
343
+ if grep -qE '^(git_hooks|hooks):' "$_f" 2>/dev/null; then
344
344
  _tmp="$(mktemp)"
345
345
  awk '
346
346
  /^[ ]*#.*[aA]utomated workspace Git hooks/ { next }
347
- /^[ ]*(git_hooks|hooks):/ { next }
347
+ /^(git_hooks|hooks):/ { next }
348
348
  { print }
349
349
  ' "$_f" > "$_tmp" && mv "$_tmp" "$_f"
350
350
  fi
@@ -368,6 +368,13 @@ upgrade_workspace_config() {
368
368
  print " pre-commit: []"
369
369
  print " pre-push: []"
370
370
  print ""
371
+ print "# RNEX Lifecycle Hooks"
372
+ print "rnex_hooks:"
373
+ print " before_sync: []"
374
+ print " after_sync: []"
375
+ print " before_clone: []"
376
+ print " after_clone: []"
377
+ print ""
371
378
  inserted=1
372
379
  }
373
380
  { print }
@@ -387,6 +394,13 @@ upgrade_workspace_config() {
387
394
  print " - \"rnex sync --quiet\""
388
395
  print " pre-commit: []"
389
396
  print " pre-push: []"
397
+ print ""
398
+ print "# RNEX Lifecycle Hooks"
399
+ print "rnex_hooks:"
400
+ print " before_sync: []"
401
+ print " after_sync: []"
402
+ print " before_clone: []"
403
+ print " after_clone: []"
390
404
  }
391
405
  }
392
406
  ' "$_f" > "$_tmp" && mv "$_tmp" "$_f"
package/lib/yaml.sh CHANGED
@@ -267,9 +267,11 @@ _yaml_git_ignore_from_file() {
267
267
  function unquote(v) {
268
268
  sub(/^[ \t]+/, "", v)
269
269
  if (v ~ /^"/) {
270
- v = substr(v, 2); sub(/".*$/, "", v)
270
+ sub(/^"/, "", v)
271
+ sub(/"[ \t]*(#.*)?$/, "", v)
271
272
  } else if (v ~ /^\047/) {
272
- v = substr(v, 2); sub(/\047.*$/, "", v)
273
+ sub(/^\047/, "", v)
274
+ sub(/\047[ \t]*(#.*)?$/, "", v)
273
275
  } else {
274
276
  sub(/[ \t]+#.*$/, "", v)
275
277
  sub(/[ \t]+$/, "", v)
@@ -391,9 +393,11 @@ _yaml_git_hook_commands_from_file() {
391
393
  function unquote(v) {
392
394
  sub(/^[ \t]+/, "", v)
393
395
  if (v ~ /^"/) {
394
- v = substr(v, 2); sub(/".*$/, "", v)
396
+ sub(/^"/, "", v)
397
+ sub(/"[ \t]*(#.*)?$/, "", v)
395
398
  } else if (v ~ /^\047/) {
396
- v = substr(v, 2); sub(/\047.*$/, "", v)
399
+ sub(/^\047/, "", v)
400
+ sub(/\047[ \t]*(#.*)?$/, "", v)
397
401
  } else {
398
402
  sub(/[ \t]+#.*$/, "", v)
399
403
  sub(/[ \t]+$/, "", v)
@@ -476,6 +480,157 @@ yaml_get_git_hook_commands() {
476
480
  fi
477
481
  }
478
482
 
483
+ # ---- RNEX Lifecycle Hooks Configuration Operations (rnex_hooks) -------------
484
+
485
+ # Extract list of hook/event names defined under rnex_hooks from a YAML file.
486
+ _yaml_rnex_hooks_list_from_file() {
487
+ _yrhl_f="$1"
488
+ [ -f "$_yrhl_f" ] || return 0
489
+ awk '
490
+ /^[ \t]*(rnex_hooks|rnex-hooks):[ \t]*(#.*)?$/ {
491
+ in_hooks = 1
492
+ match($0, /^[ \t]*/)
493
+ hooks_indent = RLENGTH
494
+ hook_item_indent = -1
495
+ next
496
+ }
497
+ in_hooks && /^[^ \t#]/ { exit }
498
+ !in_hooks { next }
499
+ {
500
+ match($0, /^[ \t]*/)
501
+ indent = RLENGTH
502
+ trimmed = substr($0, indent + 1)
503
+ }
504
+ trimmed ~ /^([#]|$)/ { next }
505
+
506
+ in_hooks && (indent <= hooks_indent) { exit }
507
+
508
+ in_hooks {
509
+ if (hook_item_indent == -1) {
510
+ hook_item_indent = indent
511
+ }
512
+ if (indent == hook_item_indent) {
513
+ k = trimmed
514
+ sub(/:.*/, "", k)
515
+ gsub(/^["\047]|["\047]$/, "", k)
516
+ gsub(/[[:space:]]/, "", k)
517
+ gsub(/-/, "_", k)
518
+ if (length(k) > 0) print k
519
+ }
520
+ }
521
+ ' "$_yrhl_f"
522
+ }
523
+
524
+ # Enumerate configured hook names under rnex_hooks merged from rnex.yaml and .local.rnex.yaml.
525
+ yaml_list_rnex_hooks() {
526
+ _yaml_resolve_files
527
+ {
528
+ _yaml_rnex_hooks_list_from_file "$_wy"
529
+ _yaml_rnex_hooks_list_from_file "$_wly"
530
+ } | awk '!seen[$0]++'
531
+ }
532
+
533
+ # Extract command list for a specific hook under rnex_hooks.<event_name> from a YAML file.
534
+ # Supports both underscore and hyphenated keys (e.g. after_sync or after-sync).
535
+ _yaml_rnex_hook_commands_from_file() {
536
+ _yrhc_f="$1"; _yrhc_hook="$2"
537
+ [ -f "$_yrhc_f" ] || return 0
538
+ awk -v target_hook="$_yrhc_hook" '
539
+ function unquote(v) {
540
+ sub(/^[ \t]+/, "", v)
541
+ if (v ~ /^"/) {
542
+ sub(/^"/, "", v)
543
+ sub(/"[ \t]*(#.*)?$/, "", v)
544
+ } else if (v ~ /^\047/) {
545
+ sub(/^\047/, "", v)
546
+ sub(/\047[ \t]*(#.*)?$/, "", v)
547
+ } else {
548
+ sub(/[ \t]+#.*$/, "", v)
549
+ sub(/[ \t]+$/, "", v)
550
+ }
551
+ return v
552
+ }
553
+ BEGIN {
554
+ target_norm = target_hook
555
+ gsub(/-/, "_", target_norm)
556
+ }
557
+ /^[ \t]*(rnex_hooks|rnex-hooks):[ \t]*(#.*)?$/ {
558
+ in_hooks = 1
559
+ match($0, /^[ \t]*/)
560
+ hooks_indent = RLENGTH
561
+ next
562
+ }
563
+ in_hooks && /^[^ \t#]/ { exit }
564
+ !in_hooks { next }
565
+ {
566
+ match($0, /^[ \t]*/)
567
+ indent = RLENGTH
568
+ trimmed = substr($0, indent + 1)
569
+ }
570
+ trimmed ~ /^([#]|$)/ { next }
571
+
572
+ in_hook_cmds {
573
+ if (indent > target_indent || (indent == target_indent && trimmed ~ /^-([ \t]|$)/)) {
574
+ if (trimmed ~ /^-([ \t]|$)/) {
575
+ item = unquote(substr(trimmed, 2))
576
+ if (length(item) > 0) print item
577
+ }
578
+ next
579
+ }
580
+ exit
581
+ }
582
+
583
+ in_hooks && (indent <= hooks_indent) { exit }
584
+
585
+ in_hooks {
586
+ k = trimmed
587
+ sub(/:.*/, "", k)
588
+ gsub(/^["\047]|["\047]$/, "", k)
589
+ gsub(/[[:space:]]/, "", k)
590
+ k_norm = k
591
+ gsub(/-/, "_", k_norm)
592
+ if (k_norm == target_norm && trimmed ~ /:[ \t]*/) {
593
+ target_indent = indent
594
+ val = trimmed
595
+ sub(/^[^:]*:[ \t]*/, "", val)
596
+ if (val ~ /^(#.*)?$/) {
597
+ in_hook_cmds = 1
598
+ next
599
+ }
600
+ if (val ~ /^\[/) {
601
+ sub(/^\[/, "", val)
602
+ sub(/\][ \t]*(#.*)?$/, "", val)
603
+ n = split(val, parts, ",")
604
+ for (i = 1; i <= n; i++) {
605
+ item = unquote(parts[i])
606
+ if (length(item) > 0) print item
607
+ }
608
+ exit
609
+ }
610
+ item = unquote(val)
611
+ if (length(item) > 0) print item
612
+ exit
613
+ }
614
+ }
615
+ ' "$_yrhc_f"
616
+ }
617
+
618
+ # Read command list for a specific hook under rnex_hooks.<event_name>
619
+ # supporting both underscore and hyphenated event keys (e.g. after_sync and after-sync),
620
+ # with .local.rnex.yaml override priority.
621
+ yaml_get_rnex_hook_commands() {
622
+ _event_name="$1"
623
+ _event_norm="$(printf '%s' "$_event_name" | tr '-' '_')"
624
+ _yaml_resolve_files
625
+ if [ -f "$_wly" ] && _yaml_rnex_hooks_list_from_file "$_wly" | grep -qx "$_event_norm"; then
626
+ _yaml_rnex_hook_commands_from_file "$_wly" "$_event_norm"
627
+ return 0
628
+ fi
629
+ if [ -f "$_wy" ]; then
630
+ _yaml_rnex_hook_commands_from_file "$_wy" "$_event_norm"
631
+ fi
632
+ }
633
+
479
634
  # ---- Plugin Configuration Operations ---------------------------------------
480
635
 
481
636
  _yaml_list_plugins_from_file() {
@@ -516,9 +671,11 @@ _yaml_plugin_list_from_file() {
516
671
  function unquote(v) {
517
672
  sub(/^[ \t]+/, "", v)
518
673
  if (v ~ /^"/) {
519
- v = substr(v, 2); sub(/".*$/, "", v)
674
+ sub(/^"/, "", v)
675
+ sub(/"[ \t]*(#.*)?$/, "", v)
520
676
  } else if (v ~ /^\047/) {
521
- v = substr(v, 2); sub(/\047.*$/, "", v)
677
+ sub(/^\047/, "", v)
678
+ sub(/\047[ \t]*(#.*)?$/, "", v)
522
679
  } else {
523
680
  sub(/[ \t]+#.*$/, "", v)
524
681
  sub(/[ \t]+$/, "", v)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "repo-nexus",
3
- "version": "0.8.1",
3
+ "version": "0.8.2",
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",
@@ -50,7 +50,9 @@
50
50
  "linux"
51
51
  ],
52
52
  "devDependencies": {
53
- "vitepress": "^1.6.4"
53
+ "mermaid": "^11.17.2",
54
+ "vitepress": "^1.6.4",
55
+ "vitepress-plugin-mermaid": "^2.0.17"
54
56
  },
55
57
  "overrides": {
56
58
  "esbuild": "^0.25.0",
@@ -1,188 +1,109 @@
1
1
  # ==============================================================================
2
- # rnex.yaml — Repo Nexus Workspace Configuration (Full Example)
2
+ # rnex.yaml — Repo Nexus Workspace Configuration (Exhaustive Schema Showcase)
3
3
  # ==============================================================================
4
- # This file is the central team manifest for a Repo Nexus workspace (committed to Git).
4
+ # Central team manifest for a Repo Nexus workspace (committed to Git).
5
5
  #
6
6
  # TWO-LEVEL CONFIGURATION:
7
- # 1. Repo Config (rnex.yaml): Shared across team, tracks member repos, URLs, plugins.
8
- # 2. Local Config (.local.rnex.yaml): Machine-specific (gitignored, highest priority),
9
- # overrides enable/disable states, URLs, or local developer settings.
10
- #
11
- # Place it in your workspace root directory and run `rnex sync` to apply.
12
- #
13
- # For more information: https://github.com/unoxen/repo-nexus
14
-
15
- # ------------------------------------------------------------------------------
16
- # version — Workspace configuration schema version
17
- # ------------------------------------------------------------------------------
18
- # Used by `rnex sync` to safely detect and reconcile configuration
19
- # and routing instructions across CLI releases.
20
- #
21
- version: 0.8.0
22
-
23
- # ------------------------------------------------------------------------------
24
- # repos_dir — Directory for member repository clones
25
- # ------------------------------------------------------------------------------
26
- # Default: ./repos (ignored by Git in the workspace .gitignore)
27
- #
28
- # Examples:
29
- # repos_dir: ./repos # relative (recommended)
30
- # repos_dir: ./custom-repos # custom relative path
7
+ # 1. Team Manifest (rnex.yaml): Shared across team, tracks member repos, URLs, plugins.
8
+ # 2. Local Overrides (.local.rnex.yaml): Machine-specific (gitignored, highest priority),
9
+ # overrides enable/disable states, URLs, read-only flags, or developer settings.
31
10
 
32
- repos_dir: ./repos
11
+ # Workspace Metadata
12
+ version: "1"
13
+ name: "acme-platform"
14
+ description: "Multi-repo platform workspace and shared AI context"
15
+ repos_dir: "./repos"
16
+ code_workspace: "acme.code-workspace"
33
17
 
34
- # ------------------------------------------------------------------------------
35
- # code_workspace — VS Code / Cursor multi-root workspace file
36
- # ------------------------------------------------------------------------------
37
- # Automatically generates and maintains a multi-root .code-workspace file mapping
38
- # the workspace root and all active member repository clones.
39
- #
40
- # Default: false
41
- #
42
- # Examples:
43
- # code_workspace: false # disabled (default)
44
- # code_workspace: true # generates <workspace-name>.code-workspace
45
- # code_workspace: workspace.code-workspace # custom filename
46
- #
47
- code_workspace: false
48
-
49
- # ------------------------------------------------------------------------------
50
- # git — Git Integration (Ignore rules & Git hooks)
51
- # ------------------------------------------------------------------------------
52
- # git.ignore: list of patterns added to .gitignore (directories starting with
53
- # .rnex or rnex are recursively ignored by default with trailing slashes).
54
- # git.hooks: mapping of hook names (post-merge, post-checkout, pre-commit, pre-push)
55
- # to command lists executed by the native Git hooks.
56
- #
18
+ # Git Integration (Ignore rules & Git hooks)
57
19
  git:
58
20
  ignore:
59
21
  - "repos/"
60
22
  - "**/.rnex*/"
61
23
  - "**/rnex*/"
24
+ - "*.log"
25
+ - ".env.local"
62
26
  hooks:
63
27
  post-merge:
64
28
  - "rnex sync --quiet"
65
29
  post-checkout:
66
30
  - "rnex sync --quiet"
67
- pre-commit: []
68
- pre-push: []
69
-
70
- # ------------------------------------------------------------------------------
71
- # plugins — Workspace plugins, tool integrations, and AI instruction packs
72
- # ------------------------------------------------------------------------------
73
- # Plugins extend your workspace with curated AI guidelines, context rules,
74
- # tool provider integrations (e.g. GitHub Copilot), and templates.
75
- #
76
- # Manage plugins with:
77
- # rnex plugin list # View available and active plugins
78
- # rnex plugin enable [--local] <name> # Enable plugin (global or local override)
79
- # rnex plugin disable [--local] <name> # Disable plugin from workspace
80
- # rnex plugin info <name> # View plugin details & configurable options
81
- # rnex plugin <name> <cmd> [options] # Run plugin CLI subcommand (e.g. karpathy-llm lint)
82
- #
83
- # Built-in plugins:
84
- # claude — Anthropic Claude Code integration: manages CLAUDE.md; generates user skills in .claude/skills/
85
- # codex — OpenAI Codex integration: manages CODEX.md; generates user skills in .codex/skills/
86
- # copilot — GitHub Copilot integration: manages .github/copilot-instructions.md; generates user skills in .github/skills/
87
- # cursor — Cursor IDE integration: manages .cursorrules & .cursor/rules/; generates user skills in .cursor/rules/
88
- # gemini — Google Gemini / Antigravity integration: manages GEMINI.md; generates user skills in .agents/skills/
89
- # windsurf — Windsurf IDE integration: manages .windsurfrules; generates user skills in .windsurf/rules/
90
- # karpathy-llm — Andrej Karpathy's agent behavioral principles,
91
- # context engineering guidelines, and LLM Wiki architecture
92
- #
93
- # Note on AI Architecture:
94
- # AGENTS.md at workspace root is the universal cross-tool standard. Assistants that read AGENTS.md
95
- # all the time need no separate top-level instructions file. Assistants with native
96
- # formats (Claude with CLAUDE.md, Codex with CODEX.md, Gemini with GEMINI.md, Cursor with .cursorrules, Windsurf with .windsurfrules)
97
- # have their instruction files maintained automatically when their plugin is enabled.
98
- # Agentic skills live self-contained inside .rnex/skills/ (core) and .rnex/plugins/<plugin>/skills/ (plugins).
99
- # Provider plugins generate zero-logic User Skills (prefixed with rnex-) into IDE-specific skill directories
100
- # linking directly to the agentic skill protocols inside .rnex/.
101
-
102
- plugins:
103
- # claude:
104
- # skills: true # generate user skills in .claude/skills/ (default: true)
105
- # instructions: true # maintain routing instructions in CLAUDE.md (default: true)
106
- # auto_sync_on: SessionStart # trigger auto-sync on lifecycle event (default: SessionStart, or false)
107
- #
108
- # codex:
109
- # skills: true # generate user skills in .codex/skills/ (default: true)
110
- # instructions: true # maintain routing instructions in CODEX.md (default: true)
111
- #
112
- # copilot:
113
- # skills: true # generate user skills in .github/skills/ (default: true)
114
- # instructions: true # maintain routing instructions in .github/copilot-instructions.md (default: true)
115
- #
116
- # cursor:
117
- # skills: true # generate user skills in .cursor/rules/ (default: true)
118
- # instructions: true # maintain routing instructions in .cursorrules (default: true)
119
- #
120
- # gemini:
121
- # skills: true # generate user skills in .agents/skills/ (default: true)
122
- # instructions: true # maintain routing instructions in GEMINI.md (default: true)
123
- # auto_sync_on: SessionStart # trigger auto-sync on lifecycle event (default: SessionStart, or false)
124
- #
125
- # windsurf:
126
- # skills: true # generate user skills in .windsurf/rules/ (default: true)
127
- # instructions: true # maintain routing instructions in .windsurfrules (default: true)
128
- #
129
- # karpathy-llm:
130
- # wiki_dir: "wiki" # Directory for curated atomic markdown pages (default: wiki)
131
- # sources: # Intake documents: directories and/or glob patterns (default below)
132
- # - docs # directory: all files (hidden dirs and node_modules pruned)
133
- # - "repos/**/README.md" # recursive glob (quote it); disabled repos are excluded
134
- # # A sources list in .local.rnex.yaml replaces this list entirely.
135
-
31
+ pre-commit:
32
+ - "rnex plugin karpathy-llm lint"
33
+ pre-push:
34
+ - "rnex plugin karpathy-llm lint --strict"
136
35
 
137
- # ------------------------------------------------------------------------------
138
- # repos — Member repositories managed by Repo Nexus
139
- # ------------------------------------------------------------------------------
140
- # Each repo has:
141
- # url: Git repository URL (SSH or HTTPS).
142
- # branch: Branch to checkout and track (optional).
143
- # enabled: true (default) keeps the repo active in workspace.
144
- # false disables the repo (skipped by rnex clone, rnex exec, etc.).
145
- # Can be overridden locally in .local.rnex.yaml.
146
- # readonly: false (default) allows normal active development and modifications.
147
- # true designates the repository as read-only (used only for information).
148
- # AI coding assistants and tools use this repository strictly for reference,
149
- # context, and type definitions without modifying or committing code.
150
- #
151
- # Examples:
152
- # backend:
153
- # url: git@github.com:myorg/backend-api.git
154
- # branch: main
155
- # enabled: true # default
156
- # readonly: false # default
157
- #
158
- # frontend:
159
- # url: https://github.com/myorg/web-app.git
160
- # branch: develop
161
- # enabled: true
162
- #
163
- # docs-reference:
164
- # url: git@github.com:myorg/docs-reference.git
165
- # readonly: true # information-only repository
166
- # enabled: true
167
- #
168
- # analytics:
169
- # url: git@github.com:myorg/analytics.git
170
- # enabled: false # disabled: skipped by clone & exec
36
+ # RNEX Lifecycle Hooks (Map of RNEX events to command lists)
37
+ rnex_hooks:
38
+ before_init: []
39
+ after_init:
40
+ - "echo 'Workspace initialized'"
41
+ before_sync: []
42
+ after_sync:
43
+ - "rnex plugin karpathy-llm ingest --quiet"
44
+ before_clone: []
45
+ after_clone:
46
+ - "rnex exec npm install"
47
+ before_repo_add: []
48
+ after_repo_add: []
49
+ before_repo_remove: []
50
+ after_repo_remove: []
51
+ before_repo_set: []
52
+ after_repo_set: []
53
+ before_plugin_enable: []
54
+ after_plugin_enable: []
55
+ before_plugin_disable: []
56
+ after_plugin_disable: []
57
+ before_plugin_command: []
58
+ after_plugin_command: []
59
+ before_exec: []
60
+ after_exec: []
171
61
 
62
+ # Member Repositories
172
63
  repos:
173
- # backend:
174
- # url: git@github.com:myorg/backend-api.git
175
- # branch: main
176
- # readonly: false
177
- #
178
- # frontend:
179
- # url: https://github.com/myorg/web-app.git
180
- # branch: develop
181
- #
182
- # docs-reference:
183
- # url: git@github.com:myorg/docs-reference.git
184
- # readonly: true
185
- #
186
- # analytics:
187
- # url: git@github.com:myorg/analytics.git
188
- # enabled: false
64
+ backend:
65
+ url: "git@github.com:acme/backend-api.git"
66
+ branch: "main"
67
+ enabled: true
68
+ readonly: false
69
+ description: "Core Go/PostgreSQL API service"
70
+ frontend:
71
+ url: "https://github.com/acme/web-client.git"
72
+ branch: "develop"
73
+ enabled: true
74
+ readonly: false
75
+ description: "React/TypeScript web application"
76
+ shared-contracts:
77
+ url: "git@github.com:acme/contracts.git"
78
+ branch: "v2"
79
+ enabled: true
80
+ readonly: true
81
+ description: "Read-only OpenAPI & Protobuf schemas"
82
+
83
+ # Scoped Plugins & AI Providers
84
+ plugins:
85
+ claude:
86
+ enabled: true
87
+ skills: true
88
+ cursor:
89
+ enabled: true
90
+ skills: true
91
+ codex:
92
+ enabled: true
93
+ skills: true
94
+ gemini:
95
+ enabled: false
96
+ skills: true
97
+ windsurf:
98
+ enabled: false
99
+ skills: true
100
+ copilot:
101
+ enabled: false
102
+ skills: true
103
+ karpathy-llm:
104
+ enabled: true
105
+ wiki_dir: "wiki"
106
+ sources:
107
+ - "docs"
108
+ - "adr"
109
+ - "repos/**/README.md"
@@ -34,8 +34,8 @@ When working in a workspace with an active Karpathy LLM Wiki:
34
34
  - **Bounded Hot Cache**: `<wiki_dir>/hot.md` enforces a strict ~500-word ceiling with 3 structured sections: 1. Architecture & Repo Map, 2. Current Focus & Recent Ingests, 3. Key Contracts. Ingest and lint workflows must condense older context to prevent bloat.
35
35
  - **Behavioral Principles**: Strictly adhere to the coding agent principles defined at `.rnex/plugins/karpathy-llm/rules/behavioral.md`.
36
36
  - **Annotated Indexing**: `<wiki_dir>/index.md` entries must maintain a single 1-line summary next to each atomic page link (e.g. `- [Auth Flow](auth.md): JWT validation and token rotation`) so agents pinpoint target pages in a single read without trial-and-error scanning.
37
- - **Ingestion**: When files appear in configured `sources` or member repositories are added, execute the `wiki-ingest` agentic skill protocol (`.rnex/plugins/karpathy-llm/skills/wiki-ingest.md`). One source document produces 5–25 atomic pages — never collapse a source into a single file.
38
- - **Maintenance**: Execute the `wiki-lint` agentic skill protocol (`.rnex/plugins/karpathy-llm/skills/wiki-lint.md`) to validate paths, update `mentioned_in`, and preserve graph integrity.
37
+ - **Ingestion**: When files appear in configured `sources` or member repositories are added, execute `rnex plugin karpathy-llm ingest` or the `wiki-ingest` agentic skill protocol (`.rnex/plugins/karpathy-llm/skills/wiki-ingest.md`). One source document produces 5–25 atomic pages — never collapse a source into a single file.
38
+ - **Maintenance**: Execute `rnex plugin karpathy-llm lint` or the `wiki-lint` agentic skill protocol (`.rnex/plugins/karpathy-llm/skills/wiki-lint.md`) to validate paths, update `mentioned_in`, and preserve graph integrity.
39
39
 
40
40
  ---
41
41
 
@@ -8,6 +8,14 @@ Universal agentic skill protocol for decomposing and ingesting raw source materi
8
8
 
9
9
  Use this skill when ingesting new reference materials, architecture documentation, transcripts, articles, or member repository READMEs into the workspace curated wiki knowledge graph.
10
10
 
11
+ ## CLI Helper
12
+
13
+ You can also invoke the built-in deterministic ingest helper directly from the terminal:
14
+
15
+ ```sh
16
+ rnex plugin karpathy-llm ingest [--source <path>] [--repo <name>] [--quiet]
17
+ ```
18
+
11
19
  ## Ingestion Protocol
12
20
 
13
21
  1. **Resolve Configuration & Direct Source Paths:**
@@ -8,6 +8,14 @@ Universal agentic skill protocol for maintaining Karpathy LLM Wiki graph integri
8
8
 
9
9
  Use this skill to perform health checks and maintenance on the curated wiki knowledge graph, resolve broken links, recompute bidirectional relations, and preserve the ~500-word hot cache boundary.
10
10
 
11
+ ## CLI Helper
12
+
13
+ You can also invoke the built-in deterministic lint helper directly from the terminal:
14
+
15
+ ```sh
16
+ rnex plugin karpathy-llm lint [--strict] [--quiet]
17
+ ```
18
+
11
19
  ## Maintenance Protocol
12
20
 
13
21
  1. **Resolve Configuration & Verify Paths:**