nerftools 0.3.2__tar.gz → 1.1.0__tar.gz

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.
Files changed (298) hide show
  1. {nerftools-0.3.2 → nerftools-1.1.0}/.cspell.json +10 -14
  2. {nerftools-0.3.2 → nerftools-1.1.0}/.github/workflows/ci.yml +1 -1
  3. {nerftools-0.3.2 → nerftools-1.1.0}/.github/workflows/release-please.yml +8 -9
  4. {nerftools-0.3.2 → nerftools-1.1.0}/.gitignore +3 -0
  5. nerftools-1.1.0/.release-please-manifest.json +3 -0
  6. nerftools-1.1.0/CHANGELOG.md +136 -0
  7. {nerftools-0.3.2 → nerftools-1.1.0}/CONTRIBUTING.md +3 -3
  8. {nerftools-0.3.2 → nerftools-1.1.0}/PKG-INFO +1 -1
  9. {nerftools-0.3.2 → nerftools-1.1.0}/README.md +16 -6
  10. {nerftools-0.3.2 → nerftools-1.1.0}/docs/nerf-manifest.md +167 -3
  11. nerftools-1.1.0/docs/sdd/2026-04-04-nerf-refactor/frd.md +401 -0
  12. nerftools-1.1.0/docs/sdd/2026-04-04-nerf-refactor/hla.md +530 -0
  13. nerftools-1.1.0/docs/sdd/2026-04-04-nerf-refactor/locked.md +9 -0
  14. nerftools-1.1.0/docs/sdd/2026-04-04-nerf-refactor/manifest-spec.md +1032 -0
  15. nerftools-1.1.0/docs/sdd/2026-04-04-nerf-refactor/plan.md +227 -0
  16. nerftools-1.1.0/nerf.yaml +22 -0
  17. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/__init__.py +0 -1
  18. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/builder.py +228 -23
  19. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/cli.py +49 -18
  20. nerftools-1.1.0/nerftools/config.py +391 -0
  21. nerftools-1.1.0/nerftools/default_manifests/az-account.yaml +48 -0
  22. nerftools-1.1.0/nerftools/default_manifests/az-aks.yaml +293 -0
  23. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/default_manifests/az-boards.yaml +146 -18
  24. nerftools-1.1.0/nerftools/default_manifests/az-cosmosdb.yaml +133 -0
  25. nerftools-1.1.0/nerftools/default_manifests/az-devops.yaml +33 -0
  26. nerftools-1.1.0/nerftools/default_manifests/az-keyvault.yaml +171 -0
  27. nerftools-1.1.0/nerftools/default_manifests/az-monitor.yaml +152 -0
  28. nerftools-1.1.0/nerftools/default_manifests/az-network.yaml +602 -0
  29. nerftools-1.1.0/nerftools/default_manifests/az-pipelines.yaml +114 -0
  30. nerftools-1.1.0/nerftools/default_manifests/az-postgres.yaml +103 -0
  31. nerftools-1.1.0/nerftools/default_manifests/az-repos.yaml +248 -0
  32. nerftools-1.1.0/nerftools/default_manifests/az-resource.yaml +110 -0
  33. nerftools-1.1.0/nerftools/default_manifests/az-role.yaml +119 -0
  34. nerftools-1.1.0/nerftools/default_manifests/az-storage.yaml +102 -0
  35. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/default_manifests/gh.yaml +118 -13
  36. nerftools-1.1.0/nerftools/default_manifests/git.yaml +541 -0
  37. nerftools-1.1.0/nerftools/default_manifests/kubectl.yaml +449 -0
  38. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/default_manifests/nx.yaml +6 -6
  39. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/default_manifests/pkgrun.yaml +3 -3
  40. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/default_manifests/tg.yaml +10 -10
  41. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/default_manifests/uv.yaml +4 -4
  42. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/formats.py +2 -2
  43. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/manifest.py +177 -0
  44. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/rendering.py +49 -5
  45. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/skill.py +1 -1
  46. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/.claude-plugin/plugin.json +1 -1
  47. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-account/SKILL.md +57 -0
  48. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-account/scripts/nerf-az-account-list +39 -0
  49. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-account/scripts/nerf-az-account-set +69 -0
  50. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-account/scripts/nerf-az-account-show +39 -0
  51. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-aks/SKILL.md +165 -0
  52. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-aks/scripts/nerf-az-aks-command-invoke +100 -0
  53. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-aks/scripts/nerf-az-aks-get-credentials +94 -0
  54. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-aks/scripts/nerf-az-aks-get-credentials-admin +94 -0
  55. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-aks/scripts/nerf-az-aks-get-versions +77 -0
  56. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-aks/scripts/nerf-az-aks-list +52 -0
  57. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-aks/scripts/nerf-az-aks-nodepool-list +88 -0
  58. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-aks/scripts/nerf-az-aks-nodepool-show +99 -0
  59. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-aks/scripts/nerf-az-aks-show +88 -0
  60. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-az-boards/SKILL.md +69 -28
  61. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-boards/scripts/nerf-az-boards-area-list +47 -0
  62. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-az-boards/scripts/nerf-az-boards-mywi-comment +41 -13
  63. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-az-boards/scripts/nerf-az-boards-mywi-show +31 -9
  64. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-az-boards/scripts/nerf-az-boards-wi-add-parent +41 -13
  65. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-az-boards/scripts/nerf-az-boards-wi-comment +41 -13
  66. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-boards/scripts/nerf-az-boards-wi-create +129 -0
  67. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-boards/scripts/nerf-az-boards-wi-list +77 -0
  68. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-boards/scripts/nerf-az-boards-wi-show +87 -0
  69. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-boards/scripts/nerf-az-boards-wi-update +122 -0
  70. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-cosmosdb/SKILL.md +84 -0
  71. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-cosmosdb/scripts/nerf-az-cosmosdb-database-list +88 -0
  72. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-cosmosdb/scripts/nerf-az-cosmosdb-list +52 -0
  73. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-cosmosdb/scripts/nerf-az-cosmosdb-network-rule-list +88 -0
  74. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-cosmosdb/scripts/nerf-az-cosmosdb-show +88 -0
  75. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-devops/SKILL.md +27 -0
  76. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-devops/scripts/nerf-az-devops-set-default-project +69 -0
  77. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-keyvault/SKILL.md +101 -0
  78. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-keyvault/scripts/nerf-az-keyvault-list +52 -0
  79. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-keyvault/scripts/nerf-az-keyvault-network-rule-list +82 -0
  80. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-keyvault/scripts/nerf-az-keyvault-secret-list +77 -0
  81. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-keyvault/scripts/nerf-az-keyvault-secret-stats +118 -0
  82. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-keyvault/scripts/nerf-az-keyvault-show +82 -0
  83. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-monitor/SKILL.md +71 -0
  84. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-monitor/scripts/nerf-az-monitor-activity-log +113 -0
  85. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-monitor/scripts/nerf-az-monitor-diagnostic-settings-list +77 -0
  86. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-monitor/scripts/nerf-az-monitor-metrics-list +126 -0
  87. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/SKILL.md +339 -0
  88. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-nic-show +88 -0
  89. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-nsg-list +52 -0
  90. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-nsg-show +88 -0
  91. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-private-dns-link-list +88 -0
  92. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-private-dns-link-show +99 -0
  93. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-private-dns-record-list +88 -0
  94. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-private-dns-zone-list +52 -0
  95. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-private-dns-zone-show +88 -0
  96. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-private-endpoint-list +52 -0
  97. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-private-endpoint-show +88 -0
  98. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-private-link-resource-list +77 -0
  99. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-public-ip-list +52 -0
  100. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-public-ip-show +88 -0
  101. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-route-table-show +88 -0
  102. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-subnet-show +99 -0
  103. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-vnet-list +52 -0
  104. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-vnet-peering-list +88 -0
  105. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-vnet-peering-show +99 -0
  106. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-network/scripts/nerf-az-network-vnet-show +88 -0
  107. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-pipelines/SKILL.md +76 -0
  108. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-az-pipelines/scripts/nerf-az-pipelines-check +31 -9
  109. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-pipelines/scripts/nerf-az-pipelines-list +47 -0
  110. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-pipelines/scripts/nerf-az-pipelines-run-show +87 -0
  111. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-pipelines/scripts/nerf-az-pipelines-runs +47 -0
  112. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-postgres/SKILL.md +66 -0
  113. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-postgres/scripts/nerf-az-postgres-flexible-server-firewall-rule-list +88 -0
  114. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-postgres/scripts/nerf-az-postgres-flexible-server-list +52 -0
  115. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-postgres/scripts/nerf-az-postgres-flexible-server-show +88 -0
  116. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-repos/SKILL.md +126 -0
  117. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-az-repos/scripts/nerf-az-repos-pr-comments +30 -9
  118. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-az-repos/scripts/nerf-az-repos-pr-create +39 -12
  119. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-repos/scripts/nerf-az-repos-pr-list +86 -0
  120. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-repos/scripts/nerf-az-repos-pr-set-status +118 -0
  121. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-az-repos/scripts/nerf-az-repos-pr-show +31 -9
  122. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-repos/scripts/nerf-az-repos-pr-vote +118 -0
  123. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-resource/SKILL.md +78 -0
  124. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-resource/scripts/nerf-az-group-list +47 -0
  125. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-resource/scripts/nerf-az-group-show +77 -0
  126. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-resource/scripts/nerf-az-resource-list +62 -0
  127. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-resource/scripts/nerf-az-resource-show +77 -0
  128. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-role/SKILL.md +72 -0
  129. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-role/scripts/nerf-az-role-assignment-by-id +77 -0
  130. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-role/scripts/nerf-az-role-assignment-list +73 -0
  131. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-role/scripts/nerf-az-role-definition-list +63 -0
  132. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-storage/SKILL.md +65 -0
  133. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-storage/scripts/nerf-az-storage-account-list +52 -0
  134. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-storage/scripts/nerf-az-storage-account-network-rule-list +88 -0
  135. nerftools-1.1.0/out/claude-plugin/skills/nerf-az-storage/scripts/nerf-az-storage-account-show +88 -0
  136. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-gh/SKILL.md +68 -7
  137. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-issue-comment +28 -8
  138. nerftools-1.1.0/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-issue-create +87 -0
  139. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-issue-list +16 -9
  140. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-issue-view +19 -5
  141. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-pr-create +26 -9
  142. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-pr-diff +19 -5
  143. nerftools-1.1.0/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-pr-inline-comments +79 -0
  144. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-pr-list +16 -9
  145. nerftools-1.1.0/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-pr-review-comments +111 -0
  146. nerftools-1.1.0/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-pr-reviews +99 -0
  147. nerftools-1.1.0/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-pr-thread-comment +91 -0
  148. nerftools-1.1.0/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-pr-thread-comments +79 -0
  149. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-pr-view +19 -5
  150. nerftools-1.1.0/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-run-list +81 -0
  151. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-run-view +20 -6
  152. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/SKILL.md +372 -0
  153. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-add +148 -0
  154. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-branch-checkout-remote +200 -0
  155. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-branch-delete-merged +189 -0
  156. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-branch-list-local +128 -0
  157. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-branch-list-remote +128 -0
  158. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-commit +171 -0
  159. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-commit-amend +188 -0
  160. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-create-branch +168 -0
  161. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-diff +128 -0
  162. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-diff-staged +128 -0
  163. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-fetch +168 -0
  164. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-log +128 -0
  165. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-pull +168 -0
  166. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-push-branch +188 -0
  167. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-push-main +168 -0
  168. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-rebase-unpushed +194 -0
  169. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-reset-hard-last +148 -0
  170. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-reset-unpushed +200 -0
  171. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-revert +158 -0
  172. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-status +128 -0
  173. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-switch +168 -0
  174. nerftools-1.1.0/out/claude-plugin/skills/nerf-git/scripts/nerf-git-tag +170 -0
  175. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/SKILL.md +290 -0
  176. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-api-resources +57 -0
  177. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-api-versions +39 -0
  178. nerftools-0.3.2/out/claude-plugin/skills/nerf-az-pipelines/scripts/nerf-az-pipelines-list → nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-cluster-info +10 -7
  179. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-config-current-context +39 -0
  180. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-config-get-contexts +39 -0
  181. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-config-use-context +79 -0
  182. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-describe +131 -0
  183. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-exec +124 -0
  184. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-explain +86 -0
  185. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-get +145 -0
  186. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-get-secrets +107 -0
  187. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-logs +133 -0
  188. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-port-forward +152 -0
  189. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-rollout-restart +97 -0
  190. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-top-nodes +47 -0
  191. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-top-pods +68 -0
  192. nerftools-1.1.0/out/claude-plugin/skills/nerf-kubectl/scripts/nerf-kubectl-version +39 -0
  193. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-nx/scripts/nerf-nx-affected +5 -2
  194. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-nx/scripts/nerf-nx-graph +5 -2
  195. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-nx/scripts/nerf-nx-reset +5 -2
  196. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-nx/scripts/nerf-nx-run +20 -6
  197. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-nx/scripts/nerf-nx-show-project +20 -6
  198. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-nx/scripts/nerf-nx-show-projects +5 -2
  199. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-pkgrun/scripts/nerf-pkgrun-cspell +13 -2
  200. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-pkgrun/scripts/nerf-pkgrun-markdownlint +13 -2
  201. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-pkgrun/scripts/nerf-pkgrun-prettier +13 -2
  202. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-stdutils/SKILL.md +4 -4
  203. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-stdutils/scripts/nerf-find +1 -1
  204. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-stdutils/scripts/nerf-find-cwd +1 -1
  205. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-stdutils/scripts/nerf-grep +14 -5
  206. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-stdutils/scripts/nerf-grep-recursive-cwd +19 -5
  207. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-tg/scripts/nerf-tg-fmt +5 -2
  208. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-tg/scripts/nerf-tg-fmt-all +5 -2
  209. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-tg/scripts/nerf-tg-init +5 -2
  210. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-tg/scripts/nerf-tg-init-all +5 -2
  211. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-tg/scripts/nerf-tg-output +5 -2
  212. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-tg/scripts/nerf-tg-output-all +5 -2
  213. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-tg/scripts/nerf-tg-plan +5 -2
  214. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-tg/scripts/nerf-tg-plan-all +5 -2
  215. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-tg/scripts/nerf-tg-validate +5 -2
  216. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-tg/scripts/nerf-tg-validate-all +5 -2
  217. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-uv/scripts/nerf-uv-mypy +13 -2
  218. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-uv/scripts/nerf-uv-pytest +13 -2
  219. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-uv/scripts/nerf-uv-ruff-check +13 -2
  220. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-uv/scripts/nerf-uv-ruff-fix +13 -2
  221. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerftools/SKILL.md +12 -0
  222. {nerftools-0.3.2 → nerftools-1.1.0}/pyproject.toml +1 -1
  223. {nerftools-0.3.2 → nerftools-1.1.0}/release-please-config.json +1 -1
  224. nerftools-1.1.0/tests/test_builder.py +1202 -0
  225. nerftools-1.1.0/tests/test_config.py +297 -0
  226. {nerftools-0.3.2 → nerftools-1.1.0}/tests/test_formats.py +14 -3
  227. {nerftools-0.3.2 → nerftools-1.1.0}/tests/test_manifest.py +371 -37
  228. {nerftools-0.3.2 → nerftools-1.1.0}/tests/test_nerfctl.py +1 -15
  229. nerftools-1.1.0/tests/test_rendering.py +59 -0
  230. {nerftools-0.3.2 → nerftools-1.1.0}/tests/test_skill.py +42 -2
  231. {nerftools-0.3.2 → nerftools-1.1.0}/uv.lock +1 -1
  232. nerftools-0.3.2/.release-please-manifest.json +0 -3
  233. nerftools-0.3.2/CHANGELOG.md +0 -66
  234. nerftools-0.3.2/nerf-plugin.yaml +0 -21
  235. nerftools-0.3.2/nerftools/default_manifests/az-pipelines.yaml +0 -42
  236. nerftools-0.3.2/nerftools/default_manifests/az-repos.yaml +0 -137
  237. nerftools-0.3.2/nerftools/default_manifests/git.yaml +0 -202
  238. nerftools-0.3.2/nerftools/nerfctl/claude/install-plugin.sh +0 -57
  239. nerftools-0.3.2/nerftools/plugin_meta.py +0 -200
  240. nerftools-0.3.2/out/claude-plugin/scripts/nerfctl-install-plugin +0 -57
  241. nerftools-0.3.2/out/claude-plugin/skills/nerf-az-boards/scripts/nerf-az-boards-wi-create +0 -98
  242. nerftools-0.3.2/out/claude-plugin/skills/nerf-az-boards/scripts/nerf-az-boards-wi-list +0 -55
  243. nerftools-0.3.2/out/claude-plugin/skills/nerf-az-boards/scripts/nerf-az-boards-wi-show +0 -65
  244. nerftools-0.3.2/out/claude-plugin/skills/nerf-az-boards/scripts/nerf-az-boards-wi-update +0 -96
  245. nerftools-0.3.2/out/claude-plugin/skills/nerf-az-pipelines/SKILL.md +0 -50
  246. nerftools-0.3.2/out/claude-plugin/skills/nerf-az-pipelines/scripts/nerf-az-pipelines-runs +0 -36
  247. nerftools-0.3.2/out/claude-plugin/skills/nerf-az-repos/SKILL.md +0 -73
  248. nerftools-0.3.2/out/claude-plugin/skills/nerf-az-repos/scripts/nerf-az-repos-pr-list +0 -74
  249. nerftools-0.3.2/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-issue-create +0 -70
  250. nerftools-0.3.2/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-pr-comment +0 -71
  251. nerftools-0.3.2/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-pr-review-comments +0 -65
  252. nerftools-0.3.2/out/claude-plugin/skills/nerf-gh/scripts/nerf-gh-run-list +0 -74
  253. nerftools-0.3.2/out/claude-plugin/skills/nerf-git/SKILL.md +0 -153
  254. nerftools-0.3.2/out/claude-plugin/skills/nerf-git/scripts/nerf-git-add +0 -56
  255. nerftools-0.3.2/out/claude-plugin/skills/nerf-git/scripts/nerf-git-commit +0 -68
  256. nerftools-0.3.2/out/claude-plugin/skills/nerf-git/scripts/nerf-git-commit-amend +0 -85
  257. nerftools-0.3.2/out/claude-plugin/skills/nerf-git/scripts/nerf-git-fetch +0 -65
  258. nerftools-0.3.2/out/claude-plugin/skills/nerf-git/scripts/nerf-git-log +0 -36
  259. nerftools-0.3.2/out/claude-plugin/skills/nerf-git/scripts/nerf-git-pull +0 -65
  260. nerftools-0.3.2/out/claude-plugin/skills/nerf-git/scripts/nerf-git-push-branch +0 -84
  261. nerftools-0.3.2/out/claude-plugin/skills/nerf-git/scripts/nerf-git-push-main +0 -65
  262. nerftools-0.3.2/out/claude-plugin/skills/nerf-git/scripts/nerf-git-reset-hard-last +0 -56
  263. nerftools-0.3.2/out/claude-plugin/skills/nerf-git/scripts/nerf-git-revert +0 -55
  264. nerftools-0.3.2/out/claude-plugin/skills/nerf-git/scripts/nerf-git-tag +0 -67
  265. nerftools-0.3.2/tests/test_builder.py +0 -646
  266. nerftools-0.3.2/tests/test_plugin_meta.py +0 -187
  267. {nerftools-0.3.2 → nerftools-1.1.0}/.claude-plugin/marketplace.json +0 -0
  268. {nerftools-0.3.2 → nerftools-1.1.0}/.editorconfig +0 -0
  269. {nerftools-0.3.2 → nerftools-1.1.0}/.github/workflows/release.yml +0 -0
  270. {nerftools-0.3.2 → nerftools-1.1.0}/.markdownlint-cli2.jsonc +0 -0
  271. {nerftools-0.3.2 → nerftools-1.1.0}/.prettierrc +0 -0
  272. {nerftools-0.3.2 → nerftools-1.1.0}/.python-version +0 -0
  273. {nerftools-0.3.2 → nerftools-1.1.0}/LICENSE +0 -0
  274. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/default_manifests/README.md +0 -0
  275. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/default_manifests/__init__.py +0 -0
  276. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/default_manifests/stdutils.yaml +0 -0
  277. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/nerfctl/__init__.py +0 -0
  278. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/nerfctl/claude/grant-allow.sh +0 -0
  279. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/nerfctl/claude/grant-by-threat.sh +0 -0
  280. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/nerfctl/claude/grant-deny.sh +0 -0
  281. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/nerfctl/claude/grant-list.sh +0 -0
  282. {nerftools-0.3.2 → nerftools-1.1.0}/nerftools/nerfctl/claude/grant-reset.sh +0 -0
  283. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/scripts/nerfctl-grant-allow +0 -0
  284. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/scripts/nerfctl-grant-by-threat +0 -0
  285. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/scripts/nerfctl-grant-deny +0 -0
  286. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/scripts/nerfctl-grant-list +0 -0
  287. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/scripts/nerfctl-grant-reset +0 -0
  288. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-nx/SKILL.md +0 -0
  289. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-pkgrun/SKILL.md +0 -0
  290. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-tg/SKILL.md +0 -0
  291. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerf-uv/SKILL.md +0 -0
  292. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerfctl-grant-allow/SKILL.md +0 -0
  293. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerfctl-grant-by-threat/SKILL.md +0 -0
  294. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerfctl-grant-deny/SKILL.md +0 -0
  295. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerfctl-grant-list/SKILL.md +0 -0
  296. {nerftools-0.3.2 → nerftools-1.1.0}/out/claude-plugin/skills/nerfctl-grant-reset/SKILL.md +0 -0
  297. {nerftools-0.3.2 → nerftools-1.1.0}/pypi-dist/.gitignore +0 -0
  298. {nerftools-0.3.2 → nerftools-1.1.0}/tests/__init__.py +0 -0
@@ -5,26 +5,22 @@
5
5
  "agentic",
6
6
  "Agentworks",
7
7
  "bunx",
8
+ "codegen",
9
+ "coreutils",
8
10
  "dataclass",
9
11
  "dataclasses",
10
- "defanged",
11
- "elif",
12
+ "errexit",
12
13
  "esac",
14
+ "footguns",
13
15
  "execdir",
14
16
  "exitcode",
15
- "frontmatter",
16
- "gwat",
17
- "invokable",
18
17
  "metacharacter",
19
18
  "metacharacters",
20
19
  "myapp",
21
20
  "mypy",
22
21
  "mywi",
23
22
  "nerfctl",
24
- "nerfed",
25
23
  "nerftools",
26
- "noprofile",
27
- "norc",
28
24
  "okdir",
29
25
  "oneline",
30
26
  "permissioning",
@@ -33,16 +29,13 @@
33
29
  "pnpx",
34
30
  "pyproject",
35
31
  "pytest",
36
- "pytestmark",
37
32
  "rulesync",
38
33
  "Rulesync",
39
34
  "stdutils",
40
35
  "subshell",
41
- "tmpl",
42
- "upgen",
36
+ "TOCTOU",
37
+ "typer",
43
38
  "uppercased",
44
- "usecases",
45
- "variadics",
46
39
  "wiql",
47
40
  "WIQL"
48
41
  ],
@@ -52,6 +45,9 @@
52
45
  "ignorePaths": [
53
46
  "node_modules",
54
47
  "out/",
55
- "CHANGELOG.md"
48
+ "CHANGELOG.md",
49
+ "**/*.yaml",
50
+ "**/*.yml",
51
+ "**/*.py"
56
52
  ]
57
53
  }
@@ -60,4 +60,4 @@ jobs:
60
60
  - name: cspell
61
61
  uses: streetsidesoftware/cspell-action@v8
62
62
  with:
63
- files: "**/*.{md,py,yaml}"
63
+ files: "**/*.md"
@@ -13,12 +13,11 @@ jobs:
13
13
  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
14
14
  outputs:
15
15
  pr_branch: ${{ steps.extract.outputs.pr_branch }}
16
- app_token: ${{ steps.app-token.outputs.token }}
17
16
  steps:
18
17
  # Use a GitHub App token so the release PR (and any subsequent pushes
19
18
  # to its branch) trigger CI workflows. The default GITHUB_TOKEN creates
20
19
  # events as github-actions[bot], which GitHub won't run workflows for.
21
- - uses: actions/create-github-app-token@v2
20
+ - uses: actions/create-github-app-token@v3
22
21
  id: app-token
23
22
  with:
24
23
  app-id: ${{ vars.RELEASE_APP_ID }}
@@ -43,7 +42,7 @@ jobs:
43
42
  if: needs.release-please.outputs.pr_branch
44
43
  runs-on: ubuntu-latest
45
44
  steps:
46
- - uses: actions/create-github-app-token@v2
45
+ - uses: actions/create-github-app-token@v3
47
46
  id: app-token
48
47
  with:
49
48
  app-id: ${{ vars.RELEASE_APP_ID }}
@@ -59,19 +58,19 @@ jobs:
59
58
  with:
60
59
  enable-cache: true
61
60
 
62
- - name: Install dependencies
63
- run: uv sync --frozen
61
+ - name: Sync lockfile and install dependencies
62
+ run: uv sync
64
63
 
65
64
  - name: Regenerate Claude Code plugin
66
- run: uv run nerf generate --target claude-plugin --plugin-config nerf-plugin.yaml --outdir ./out/claude-plugin
65
+ run: uv run nerf generate --target claude-plugin -c nerf.yaml --outdir ./out/claude-plugin
67
66
 
68
- - name: Commit updated plugin
67
+ - name: Commit updated plugin and lockfile
69
68
  run: |
70
69
  git config user.name "nerftools-release[bot]"
71
70
  git config user.email "nerftools-release[bot]@users.noreply.github.com"
72
- git add out/claude-plugin/
71
+ git add out/claude-plugin/ uv.lock
73
72
  if git diff --cached --quiet; then
74
- echo "No changes to plugin output"
73
+ echo "No changes to plugin output or lockfile"
75
74
  else
76
75
  git commit -m "build: regenerate Claude Code plugin for release"
77
76
  git push
@@ -40,3 +40,6 @@ Thumbs.db
40
40
  .pytest_cache/
41
41
  htmlcov/
42
42
  .coverage
43
+
44
+ # tmuxinator config is personal
45
+ .tmuxinator.yml
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "1.1.0"
3
+ }
@@ -0,0 +1,136 @@
1
+ # Changelog
2
+
3
+ ## [1.1.0](https://github.com/WayfarerLabs/nerftools/compare/v1.0.0...v1.1.0) (2026-05-04)
4
+
5
+
6
+ ### Features
7
+
8
+ * **az-devops:** new package with az-devops-set-default-project tool ([0fb4a15](https://github.com/WayfarerLabs/nerftools/commit/0fb4a15347edd279481f51a85506e3ad254a7479))
9
+ * **azdo:** --project everywhere, new pipelines/repos tools, area listing ([a42f7e7](https://github.com/WayfarerLabs/nerftools/commit/a42f7e71eab7e3d5dcc04de50377ef504c7fefaa))
10
+ * **azdo:** --project everywhere, new tools, set-default-project ([2dab02d](https://github.com/WayfarerLabs/nerftools/commit/2dab02df9d885d6636e37bfe718b57a3617dbded))
11
+ * **gh:** differentiate the four PR comment surfaces ([567b64d](https://github.com/WayfarerLabs/nerftools/commit/567b64dc18444ff3df17e2f0ee04e67d24469dfc))
12
+ * **gh:** differentiate the four PR comment surfaces; add reviews tool ([ca9ab91](https://github.com/WayfarerLabs/nerftools/commit/ca9ab910ebd7e426b4704b47994cbdc1b4518232))
13
+ * **manifest:** add path_tests for filesystem-typed parameters ([e035eac](https://github.com/WayfarerLabs/nerftools/commit/e035eac70eabf84a6b02ef508b7995fe943708ec))
14
+ * **manifest:** add path_tests for filesystem-typed parameters ([fdb64cd](https://github.com/WayfarerLabs/nerftools/commit/fdb64cde6201f3d567cdfb04ff8e1c955c08d0a7))
15
+ * massive add of az-related default tools ([818fe04](https://github.com/WayfarerLabs/nerftools/commit/818fe04326be536924de4e7450e202db759df362))
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * address PR review feedback on az and kubectl tools ([4395484](https://github.com/WayfarerLabs/nerftools/commit/4395484f4388f99ee760a774ae7be406d40d586b))
21
+ * address two minor PR review nits ([adad61d](https://github.com/WayfarerLabs/nerftools/commit/adad61d071fc325325e12148b8e58104def93b0e))
22
+ * **az-aks:** split admin credential fetch, mark command-invoke admin, fix variadic ([f152896](https://github.com/WayfarerLabs/nerftools/commit/f152896f4af595b235be0d3af1d5d1e1b7e1cd91))
23
+ * **az-keyvault:** drop secret fingerprint and tighten masked output ([242f8d7](https://github.com/WayfarerLabs/nerftools/commit/242f8d79e4c9a3d3a34a59dd6ab58d12476409b5))
24
+ * **az-monitor:** dry-run honors validation; --interval allows P1D and FULL ([c246266](https://github.com/WayfarerLabs/nerftools/commit/c2462661def1d26d9556925b359ef79d2fa43b88))
25
+ * **builder:** add hint lines to path_tests errors; doc symlink semantics ([a1e602b](https://github.com/WayfarerLabs/nerftools/commit/a1e602b691091c1b08f5017074467d397f3bb382))
26
+ * **builder:** preserve shell quoting in dry-run output via printf %q ([5ef4816](https://github.com/WayfarerLabs/nerftools/commit/5ef4816f086833445310674d4f9d157c609ad91d))
27
+ * **builder:** reject --nerf-dry-run tokens inside variadic+allow_flags args ([854519c](https://github.com/WayfarerLabs/nerftools/commit/854519c4070a35592b0f5358e223e270d812ad3d))
28
+ * **builder:** reject trailing tokens after declared positionals ([9580f8b](https://github.com/WayfarerLabs/nerftools/commit/9580f8b32dcc41332caca08d7bbebffd2a643409))
29
+ * **builder:** revert ineffective set -e in _nerf_pre, document the limitation ([7e6787a](https://github.com/WayfarerLabs/nerftools/commit/7e6787a788a58b37ae63bd5486c068af2238ea17))
30
+ * **builder:** under_cwd accepts paths under root when cwd is "/" ([3b05ccd](https://github.com/WayfarerLabs/nerftools/commit/3b05ccd02c0ffa8e91cefcad6a3112228b281d0a))
31
+ * cross-platform date in az-monitor, drop None aggregation, simplify timeout msg ([616385d](https://github.com/WayfarerLabs/nerftools/commit/616385d7f411cfc091c6c8ef81ecbcd94b33ca45))
32
+ * **gh-pr-reviews:** use --paginate; fix Changes-requested wording ([97e5f41](https://github.com/WayfarerLabs/nerftools/commit/97e5f412d9d37378e366b25b8044b2cd8274ec10))
33
+ * **gh:** add --slurp so paginated jq aggregates across pages ([8ebd3eb](https://github.com/WayfarerLabs/nerftools/commit/8ebd3eb00bcb3b7687306fdcdde5263599b8dac5))
34
+ * high-impact security and correctness from second-pass review ([022af82](https://github.com/WayfarerLabs/nerftools/commit/022af82533d88258680c7ca02b9d9b95302e35e1))
35
+ * **kubectl:** convert read-only tools from passthrough to template ([782b3a7](https://github.com/WayfarerLabs/nerftools/commit/782b3a7c0f97fd9feda09d6c363c66c0d93c2768))
36
+ * **kubectl:** kubectl-config-use-context is admin-threat, tighten pattern ([f1265ce](https://github.com/WayfarerLabs/nerftools/commit/f1265ce1b67f5396829879a3c39d75f23f389edf))
37
+ * more PR review feedback (rename misleading tool, guard external deps) ([6c101a4](https://github.com/WayfarerLabs/nerftools/commit/6c101a48b08560acc44342dc0c3d763ce2e72a20))
38
+ * paginate the remaining gh read tools; tighten cross-refs and doc ([8d48ed5](https://github.com/WayfarerLabs/nerftools/commit/8d48ed5d8c11abb5c72c73aee032ac1d23ef1a82))
39
+ * require 3+ word tool descriptions to catch trivial placeholders ([3433ffd](https://github.com/WayfarerLabs/nerftools/commit/3433ffd6a79c92a91743968639311be9b199a6a9))
40
+ * smaller hardening from second-pass review ([5079b21](https://github.com/WayfarerLabs/nerftools/commit/5079b21039265787dfc63721a47c6b3cf358c089))
41
+ * stop appending "." to descriptions; require terminal punctuation in manifest ([2ce0f11](https://github.com/WayfarerLabs/nerftools/commit/2ce0f11f514e57e4e0a029a786686cb5b54cdd04))
42
+
43
+
44
+ ### Documentation
45
+
46
+ * address review feedback on coverage gap and template paragraph ([dec48de](https://github.com/WayfarerLabs/nerftools/commit/dec48def42011233452ed7b85d0e85697c78431a))
47
+ * **az-account:** document --subscription scope boundary ([b105f2b](https://github.com/WayfarerLabs/nerftools/commit/b105f2b008cafe9d548a743885c5fa93b2cf02b8))
48
+ * correct --nerf-dry-run position claim and warn against local in pre ([9231598](https://github.com/WayfarerLabs/nerftools/commit/923159816725486aa12c3f9f26442b75da5f04cb))
49
+ * document passthrough security limitations around alternative flag syntax ([44031d5](https://github.com/WayfarerLabs/nerftools/commit/44031d5a71864313a6dbc1362d547ac6ddb6ccca))
50
+
51
+ ## [1.0.0](https://github.com/WayfarerLabs/nerftools/compare/v0.3.2...v1.0.0) (2026-04-19)
52
+
53
+
54
+ ### ⚠ BREAKING CHANGES
55
+
56
+ * `--plugin-config` and `--prefix` flags are removed. Use `-c <path>` to pass a config file. `--prefix` is now configured via `defaults.prefix` in the config file.
57
+
58
+ ### Features
59
+
60
+ * introduce optional config file, drop --plugin-config and install script ([f6a1ab9](https://github.com/WayfarerLabs/nerftools/commit/f6a1ab95f7f1e22fc84d6fea111390db38ef6ebb))
61
+
62
+
63
+ ### Bug Fixes
64
+
65
+ * address review feedback from Copilot ([60f4bc5](https://github.com/WayfarerLabs/nerftools/commit/60f4bc53ca87607b40873554a48ba7984a7b6c9e))
66
+ * **ci:** sync uv.lock during release to prevent version drift ([6eef9b8](https://github.com/WayfarerLabs/nerftools/commit/6eef9b8d6dfd2ccc0646cca71bdcc95fff779f48))
67
+
68
+
69
+ ### Documentation
70
+
71
+ * **sdd:** capture the refactor sdd as it defined the fundamental structure ([5c7cad4](https://github.com/WayfarerLabs/nerftools/commit/5c7cad4248c3320cd7d67848d4963376dd8f24ee))
72
+
73
+ ## [0.3.2](https://github.com/WayfarerLabs/nerftools/compare/v0.3.1...v0.3.2) (2026-04-14)
74
+
75
+
76
+ ### Documentation
77
+
78
+ * clean up pypi description ([d2b5f7f](https://github.com/WayfarerLabs/nerftools/commit/d2b5f7fef31e4ac0048a0a35059b2d24ea3e07ac))
79
+ * clean up pypi description ([d2ab29d](https://github.com/WayfarerLabs/nerftools/commit/d2ab29d03366f92e1e6660ba99745b7d2a0469f5))
80
+
81
+ ## [0.3.1](https://github.com/WayfarerLabs/nerftools/compare/v0.3.0...v0.3.1) (2026-04-14)
82
+
83
+
84
+ ### Bug Fixes
85
+
86
+ * use app token for regenerate-dist pushes so CI triggers on release PRs ([e78ae87](https://github.com/WayfarerLabs/nerftools/commit/e78ae875208a100d77cde6cb0881186e61b83e60))
87
+
88
+ ## [0.3.0](https://github.com/WayfarerLabs/nerftools/compare/v0.2.0...v0.3.0) (2026-04-14)
89
+
90
+
91
+ ### Features
92
+
93
+ * add --embed-marketplace option for standalone plugin deployment ([d00ae28](https://github.com/WayfarerLabs/nerftools/commit/d00ae28170857702a29141f24bec15c62e034c8b))
94
+ * initial nerftools repo with Python package and pre-built Claude Code plugin ([55eee79](https://github.com/WayfarerLabs/nerftools/commit/55eee79eb462dfb996568d42e05b86fe3a11ce3a))
95
+ * templatize plugin metadata via nerf-plugin.yaml config ([05086d6](https://github.com/WayfarerLabs/nerftools/commit/05086d63214351f2f9cef21fd4b6dc0679a52bd4))
96
+
97
+
98
+ ### Bug Fixes
99
+
100
+ * doc update as fix to trigger release pipeline ([79ede3c](https://github.com/WayfarerLabs/nerftools/commit/79ede3c0f7fad1446e960bef3f943c5ca83e1a08))
101
+ * drop component prefix from release-please tags to match release … ([ac70693](https://github.com/WayfarerLabs/nerftools/commit/ac70693efa1e418348e5b7f10b964ebed82258db))
102
+ * drop component prefix from release-please tags to match release workflow ([6f92386](https://github.com/WayfarerLabs/nerftools/commit/6f92386f6fdc3dab9b63cc12ad9fcfead327382b))
103
+
104
+
105
+ ### Documentation
106
+
107
+ * additional readme tweaks ([4f7267f](https://github.com/WayfarerLabs/nerftools/commit/4f7267f8112c215ffc0fd50d0cdd2a9d6430ea87))
108
+ * document the release process in CONTRIBUTING.md ([cfd29c8](https://github.com/WayfarerLabs/nerftools/commit/cfd29c8b144d17d58232c6b8677451c427627d8a))
109
+ * fix manifest spec link and split threat model content between README and spec ([60493c8](https://github.com/WayfarerLabs/nerftools/commit/60493c846bb9fbffde8875a576a4698e4ae2e461))
110
+ * move manifest guide and ref from readme ([6392c0b](https://github.com/WayfarerLabs/nerftools/commit/6392c0b716892080137b133487f3a536650590b3))
111
+ * polish README intro and update quick start with --plugin-config ([6cd3dde](https://github.com/WayfarerLabs/nerftools/commit/6cd3dde8c3b98dc8be7c57b1d0a3de84429bd9d0))
112
+ * update readme with additional context ([a93632d](https://github.com/WayfarerLabs/nerftools/commit/a93632dd217d5dad44ee4df3c86a31c282640636))
113
+
114
+ ## [0.2.0](https://github.com/WayfarerLabs/nerftools/compare/nerftools-v0.1.0...nerftools-v0.2.0) (2026-04-14)
115
+
116
+
117
+ ### Features
118
+
119
+ * add --embed-marketplace option for standalone plugin deployment ([d00ae28](https://github.com/WayfarerLabs/nerftools/commit/d00ae28170857702a29141f24bec15c62e034c8b))
120
+ * initial nerftools repo with Python package and pre-built Claude Code plugin ([55eee79](https://github.com/WayfarerLabs/nerftools/commit/55eee79eb462dfb996568d42e05b86fe3a11ce3a))
121
+ * templatize plugin metadata via nerf-plugin.yaml config ([05086d6](https://github.com/WayfarerLabs/nerftools/commit/05086d63214351f2f9cef21fd4b6dc0679a52bd4))
122
+
123
+
124
+ ### Bug Fixes
125
+
126
+ * doc update as fix to trigger release pipeline ([79ede3c](https://github.com/WayfarerLabs/nerftools/commit/79ede3c0f7fad1446e960bef3f943c5ca83e1a08))
127
+
128
+
129
+ ### Documentation
130
+
131
+ * additional readme tweaks ([4f7267f](https://github.com/WayfarerLabs/nerftools/commit/4f7267f8112c215ffc0fd50d0cdd2a9d6430ea87))
132
+ * document the release process in CONTRIBUTING.md ([cfd29c8](https://github.com/WayfarerLabs/nerftools/commit/cfd29c8b144d17d58232c6b8677451c427627d8a))
133
+ * fix manifest spec link and split threat model content between README and spec ([60493c8](https://github.com/WayfarerLabs/nerftools/commit/60493c846bb9fbffde8875a576a4698e4ae2e461))
134
+ * move manifest guide and ref from readme ([6392c0b](https://github.com/WayfarerLabs/nerftools/commit/6392c0b716892080137b133487f3a536650590b3))
135
+ * polish README intro and update quick start with --plugin-config ([6cd3dde](https://github.com/WayfarerLabs/nerftools/commit/6cd3dde8c3b98dc8be7c57b1d0a3de84429bd9d0))
136
+ * update readme with additional context ([a93632d](https://github.com/WayfarerLabs/nerftools/commit/a93632dd217d5dad44ee4df3c86a31c282640636))
@@ -38,7 +38,7 @@ After changing manifests or plugin generation code, you can rebuild the pre-buil
38
38
  to preview the output:
39
39
 
40
40
  ```bash
41
- uv run nerf generate --target claude-plugin --plugin-config nerf-plugin.yaml --outdir ./out/claude-plugin
41
+ uv run nerf generate --target claude-plugin -c nerf.yaml --outdir ./out/claude-plugin
42
42
  ```
43
43
 
44
44
  You don't need to commit the regenerated `out/` -- CI regenerates it as part of the release PR.
@@ -55,7 +55,7 @@ and conventional commits. No one manually bumps versions or creates tags.
55
55
  2. The `release-please` workflow keeps an open PR titled `chore(main): release X.Y.Z` that
56
56
  accumulates changes. On each push to `main` it:
57
57
  - Computes the next version from the conventional commits since the last release.
58
- - Updates the version in `pyproject.toml`, `nerf-plugin.yaml`, and `.release-please-manifest.json`.
58
+ - Updates the version in `pyproject.toml`, `nerf.yaml`, and `.release-please-manifest.json`.
59
59
  - Updates `CHANGELOG.md`.
60
60
  - Regenerates `out/claude-plugin/` with the new version baked into `plugin.json`.
61
61
  3. When you're ready to release, merge the release PR.
@@ -75,7 +75,7 @@ and conventional commits. No one manually bumps versions or creates tags.
75
75
  - Don't create tags by hand. `release-please` creates tags on merge of the release PR.
76
76
  - Don't edit `CHANGELOG.md` by hand. It's regenerated from commit messages.
77
77
  - Don't edit `out/claude-plugin/` by hand. Edit the source (`nerftools/`, manifests, or
78
- `nerf-plugin.yaml`) and the release PR will regenerate it.
78
+ `nerf.yaml`) and the release PR will regenerate it.
79
79
 
80
80
  ### Breaking changes
81
81
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nerftools
3
- Version: 0.3.2
3
+ Version: 1.1.0
4
4
  Summary: Define and generate nerf tools: limited-scope wrappers for common CLI utilities that allow for fine-grained control over agent execution
5
5
  Project-URL: Homepage, https://github.com/WayfarerLabs/nerftools
6
6
  Project-URL: Repository, https://github.com/WayfarerLabs/nerftools
@@ -100,14 +100,23 @@ uv run nerf generate --target bin --outdir ./bin
100
100
  # Generate rulesync skills
101
101
  uv run nerf generate --target skills --outdir ./skills
102
102
 
103
- # Generate a Claude Code plugin (requires a plugin metadata config)
104
- uv run nerf generate --target claude-plugin \
105
- --plugin-config nerf-plugin.yaml \
106
- --outdir ./claude-plugin
103
+ # Generate a Claude Code plugin (uses built-in defaults if no config)
104
+ uv run nerf generate --target claude-plugin --outdir ./claude-plugin
105
+
106
+ # Generate a Claude Code plugin with custom identity
107
+ uv run nerf generate --target claude-plugin -c nerf.yaml --outdir ./claude-plugin
107
108
  ```
108
109
 
109
- Plugin metadata is sourced from an external file to make it easy for teams to personalize the output
110
- plugin for their needs. See [nerf-plugin.yaml](nerf-plugin.yaml) for the plugin metadata format.
110
+ Package identity and per-target settings live in an optional config file passed via `-c <path>`.
111
+ When omitted, sensible defaults produce an installable plugin. See [nerf.yaml](nerf.yaml) for an
112
+ example.
113
+
114
+ To install the generated plugin:
115
+
116
+ ```bash
117
+ claude plugin marketplace add <plugin-dir>
118
+ claude plugin install <plugin-name>@<marketplace-name>
119
+ ```
111
120
 
112
121
  ## Default Manifests/Packages
113
122
 
@@ -183,6 +192,7 @@ nerftools/ Python package
183
192
  rendering.py Shared display helpers (maps-to, usage tokens)
184
193
  skill.py Rulesync skill generation
185
194
  formats.py Claude Code plugin builder
195
+ config.py Config loader, plugin metadata, defaults resolution
186
196
  cli.py CLI (validate + generate)
187
197
  nerfctl/claude/ Grant management shell scripts
188
198
  default_manifests/ Default tool package manifests (YAML)
@@ -235,6 +235,18 @@ Rules:
235
235
  - A variadic argument's `{{kind.name}}` must be the last element of `command`.
236
236
  - The generated script ends with `exec`, replacing the process.
237
237
 
238
+ **Literal command tokens are passed unquoted to bash.** Placeholder substitutions
239
+ (`{{switches.x}}`, `{{options.x}}`, `{{arguments.x}}`) emit shell-quoted variable references and
240
+ are always safe -- a value like `*.md` passed via `{{arguments.target}}` reaches the wrapped tool
241
+ verbatim, with no glob expansion. The unquoted-token concern applies *only* to the static literal
242
+ strings you put in `template.command`. The codegen lays each literal token down unquoted in the
243
+ generated `exec` line, so bash sees them raw. This works for simple words, flags, and
244
+ comma-separated lists (e.g. `--json title,body,state`), which covers the vast majority of cases.
245
+ It does *not* work for literal tokens containing shell-special characters -- braces, parens,
246
+ brackets, glob characters (`*`, `?`), tilde, redirects, pipes, dollar signs, backticks, quotes,
247
+ whitespace, etc. If you need a literal token like that (a `jq` expression, etc.), or if you need
248
+ any pipe / redirection / transformation logic, use `script` mode instead.
249
+
238
250
  Example:
239
251
 
240
252
  ```yaml
@@ -299,6 +311,33 @@ safe-find:
299
311
  prefix: [.]
300
312
  ```
301
313
 
314
+ #### Known security limitations
315
+
316
+ Passthrough deny operates on whole tokens, so it cannot enforce restrictions when the wrapped
317
+ tool accepts alternative flag syntax:
318
+
319
+ - **Short-flag stacking.** Tools that use POSIX-style or `pflag` short flags (notably `kubectl`,
320
+ many `getopt`-based utilities) allow combining boolean short flags into one token: `-Aw` is
321
+ parsed as `-A -w`. A deny entry of `-w` matches only the exact token `-w`, not `-Aw`, `-wA`,
322
+ `-Aow`, or any other stack containing `w`.
323
+ - **Inline value forms.** For a flag that takes a value, the deny patterns `--watch` and `-w`
324
+ do not catch `--watch=true`, `-w=true`, or `-wtrue` (BSD-style short flag with concatenated
325
+ value). The first two can be partially mitigated with glob denies like `--watch=*` and
326
+ `-w=*`. The concatenated form `-wtrue` is syntactically indistinguishable from a short-flag
327
+ stack and cannot be reliably denied at the token level.
328
+
329
+ **When this matters.** Use `template` mode when the wrapped tool is an agent-escape vector and
330
+ supports either of the above syntaxes. Templates declare the entire surface up front, so any
331
+ flag not declared in the manifest cannot reach the underlying command. Use passthrough only
332
+ when the wrapped tool's flag surface is well-understood, or when an undeclared flag slipping
333
+ through is purely an ergonomic issue rather than a safety one.
334
+
335
+ **Future direction.** A future opt-in deny extension may recognize tokens matching
336
+ `^-[a-zA-Z]{2,}$` and decompose them for deny matching, closing the short-flag-stacking gap.
337
+ The concatenated-value form is likely to remain a passthrough limitation because it cannot be
338
+ distinguished from a stack without per-tool flag knowledge. When in doubt, prefer template
339
+ mode.
340
+
302
341
  ### script
303
342
 
304
343
  Run an inline bash script. Best for tools that need custom logic beyond wrapping a single command.
@@ -386,6 +425,8 @@ options:
386
425
  pattern: <string> # Regex the value must match (auto-anchored with ^...$)
387
426
  allow: [<string>, ...] # Exhaustive list of allowed values
388
427
  deny: [<string>, ...] # Values to reject
428
+ path_tests: [<test>, ...] # Mark as a filesystem path; see "Path tests" below
429
+ default: <string> # Default value seeded into the bash variable when the flag is omitted
389
430
  ```
390
431
 
391
432
  Rules:
@@ -396,6 +437,12 @@ Rules:
396
437
  - `pattern` is automatically anchored to a full match in the generated bash script.
397
438
  - When `repeatable: true`, the option can be passed multiple times. The generated script accumulates
398
439
  flag-value pairs in an array so `"${VAR[@]}"` expands to `--flag val1 --flag val2`.
440
+ - `default` seeds the bash variable so inline placeholder substitutions like
441
+ `"{{options.x}}/foo"` see the value even when the agent omits the flag. `default` is
442
+ validated at manifest-load time: it must satisfy `pattern` / `allow` / `deny`, and is
443
+ mutually exclusive with `required: true`, `repeatable: true`, and `path_tests`
444
+ (path tests only evaluate against runtime cwd, so they cannot validate a load-time
445
+ default). `default` must be a string; YAML `null`, `true`, `0`, etc. are rejected.
399
446
 
400
447
  ### arguments
401
448
 
@@ -411,6 +458,7 @@ arguments:
411
458
  pattern: <string> # Regex the value must match (auto-anchored)
412
459
  allow: [<string>, ...] # Exhaustive list of allowed values
413
460
  deny: [<string>, ...] # Values to reject
461
+ path_tests: [<test>, ...] # Mark as a filesystem path; see "Path tests" below
414
462
  ```
415
463
 
416
464
  Rules:
@@ -421,6 +469,104 @@ Rules:
421
469
  - Variadic arguments become bash arrays; all others become scalar variables.
422
470
  - By default, variadic arguments reject tokens starting with `-` to prevent flag injection. Set
423
471
  `allow_flags: true` when forwarding to a tool that expects its own flags (e.g. pytest, ruff).
472
+ - Arguments do not have a `default` field. Required positional arguments always receive a value;
473
+ optional positionals are exposed to the wrapped tool only when the agent supplies one.
474
+
475
+ ## Path tests
476
+
477
+ Mark an option or argument as a filesystem path by setting `path_tests` to a non-empty list of
478
+ test names. The generated script applies a baseline check (control characters rejected,
479
+ canonicalization succeeds) plus the listed tests in a deterministic order.
480
+
481
+ ```yaml
482
+ options:
483
+ directory:
484
+ description: Directory to run in
485
+ flag: -C
486
+ path_tests: [under_cwd, dir]
487
+ arguments:
488
+ target:
489
+ description: File to format
490
+ required: true
491
+ path_tests: [under_cwd, file]
492
+ ```
493
+
494
+ ### Test catalog
495
+
496
+ | Test | Meaning | Bash primitive |
497
+ | ------------- | --------------------------------------------------------------- | -------------- |
498
+ | `under_cwd` | Canonicalized path is `$PWD` itself or under it (symlink-aware) | `realpath -m` |
499
+ | `exists` | Path exists | `[[ -e ]]` |
500
+ | `not_exists` | Path does not exist (e.g. for new-file targets) | `[[ ! -e ]]` |
501
+ | `file` | Exists and is a regular file (implies `exists`) | `[[ -f ]]` |
502
+ | `dir` | Exists and is a directory (implies `exists`) | `[[ -d ]]` |
503
+ | `readable` | Readable by the current user (implies `exists`) | `[[ -r ]]` |
504
+ | `writable` | Writable by the current user (implies `exists`) | `[[ -w ]]` |
505
+ | `executable` | Executable by the current user (implies `exists`) | `[[ -x ]]` |
506
+ | `symlink` | Path is a symlink | `[[ -L ]]` |
507
+ | `not_symlink` | Path is not a symlink | `! [[ -L ]]` |
508
+
509
+ **Symlinks behave differently across tests.** `under_cwd` follows symlinks via `realpath -m`,
510
+ so a symlink whose target is outside the workspace fails the boundary check even if the link
511
+ itself is inside. The `exists`/`file`/`dir`/`readable`/`writable`/`executable` tests also follow
512
+ symlinks (they check the target, not the link). Only `symlink` and `not_symlink` test the path
513
+ itself without following the link. Combine them deliberately if you mean both, e.g.
514
+ `[under_cwd, file]` requires the resolved target to be a regular file inside the workspace,
515
+ while `[under_cwd, not_symlink, file]` additionally rejects symlinks even when their targets
516
+ would qualify.
517
+
518
+ ### Evaluation order
519
+
520
+ For each path-typed parameter, the helper runs:
521
+
522
+ 1. **Baseline** -- reject `\n` / `\r` / `\t` in the input, canonicalize `$PWD` and the input.
523
+ 2. **Boundary** -- `under_cwd`.
524
+ 3. **Existence** -- `exists`, `not_exists`.
525
+ 4. **Type** -- `file`, `dir`, `symlink`, `not_symlink`.
526
+ 5. **Access** -- `readable`, `writable`, `executable`.
527
+
528
+ The helper short-circuits on the first failure and reports the failed test name.
529
+
530
+ ### Rules
531
+
532
+ - `path_tests` only applies to `options` and `arguments`, not `switches`.
533
+ - An empty list is rejected at validation time. Omit the field entirely if you do not want path
534
+ validation.
535
+ - Mutually exclusive: `exists` and `not_exists`; `file` and `dir`; `symlink` and `not_symlink`.
536
+ - `not_exists` cannot be combined with `file`, `dir`, `readable`, `writable`, `executable`, or
537
+ `symlink` -- those tests require the path to exist.
538
+ - Unknown test names are rejected at validation time.
539
+ - For variadic arguments the helper runs once per element.
540
+ - Optional parameters are skipped when unset; required parameters are checked after the
541
+ required-value check.
542
+
543
+ ### Threat-scope implication
544
+
545
+ A parameter with `path_tests: [under_cwd, ...]` is constrained to the workspace, so the tool can
546
+ credibly claim `read: workspace` or `write: workspace` rather than `read: machine` or
547
+ `write: machine` for that filesystem-touching surface.
548
+
549
+ ### Don't duplicate the wrapped tool's own checks
550
+
551
+ `path_tests` exists to enforce *boundaries* (workspace containment, control characters, basic
552
+ canonicalization). It is not a place to recreate validation that the wrapped tool already does.
553
+ For most cases, `[under_cwd]` alone is the right answer: it locks the path to the workspace and
554
+ delegates type, existence, and content checks to the tool you're calling.
555
+
556
+ For example, `git -C <dir>` already produces a clear `fatal: cannot change to '...': Not a
557
+ directory` if the path is wrong. Adding `dir` to `path_tests` would only duplicate that check
558
+ and produce a less informative error than git's. Reach for the longer test lists only when the
559
+ wrapped tool's behavior on the failure mode is genuinely worse than failing at the boundary
560
+ (e.g. silently no-oping, hanging, or modifying state).
561
+
562
+ ### Caveats
563
+
564
+ - Symlink resolution uses `realpath -m`, which follows symlinks. A symlink inside `$PWD` whose
565
+ target is outside `$PWD` fails `under_cwd`. This is intentional.
566
+ - The check is not a security boundary against an adversarial filesystem actor (TOCTOU between
567
+ validation and use is possible).
568
+ - `realpath` is required and is part of GNU coreutils on Linux and modern macOS coreutils. Pure
569
+ BSD environments are not supported.
424
570
 
425
571
  ## Lifecycle
426
572
 
@@ -462,7 +608,14 @@ The pre script is wrapped in a shell function (`_nerf_pre`). Key points:
462
608
  - **Print your own error messages.** The fallback message is generic. Write `echo "error: ..." >&2`
463
609
  before `return 1`.
464
610
  - **Shell variables set in pre are visible to main.** Functions execute in the caller's scope.
611
+ Do **not** use `local` -- a `local` declaration limits scope to the function body and the
612
+ variable will be empty when main runs.
465
613
  - **`{{kind.name}}` placeholders work.** Parameters are parsed before pre runs.
614
+ - **`set -e` does NOT abort pre on bare command failure.** Bash suppresses errexit inside any
615
+ function whose return code is being tested by the caller, and the wrapper invokes pre via
616
+ `_nerf_pre || _nerf_pre_rc=$?`. Even adding `set -e` inside the function body has no effect
617
+ per POSIX/bash semantics. **Always check command results explicitly with `if`/`||` and
618
+ `return 1`.**
466
619
 
467
620
  Example:
468
621
 
@@ -543,7 +696,8 @@ error: nerf-safe-find: token '-exec' is not allowed (matched deny pattern '-exec
543
696
 
544
697
  ## Dry-run mode
545
698
 
546
- Every generated tool supports `--nerf-dry-run`. When passed as the first argument, the tool runs all
699
+ Every generated tool supports `--nerf-dry-run`. When passed in the flag region (before any
700
+ positional argument), the tool runs all
547
701
  validation, guards, pre-hooks, and deny scans as normal, but instead of executing the final command
548
702
  it prints what would be run and exits.
549
703
 
@@ -565,8 +719,12 @@ $ nerf-find-cwd --nerf-dry-run -exec echo {} \;
565
719
  error: nerf-find-cwd: token '-exec' is not allowed (matched deny pattern '-exec')
566
720
  ```
567
721
 
568
- `--nerf-dry-run` must be the first token because the parser stops consuming flags at the first
569
- unrecognized argument.
722
+ `--nerf-dry-run` may appear anywhere in the flag region (before the first positional argument);
723
+ like other declared flags it is recognized in any order. The parser stops consuming flags at the
724
+ first non-flag token, so `--nerf-dry-run` placed after a positional argument is captured into
725
+ that argument (or rejected as an extra) and does not enable dry-run. For tools with
726
+ variadic+allow_flags arguments, the codegen rejects `--nerf-dry-run` tokens inside the variadic
727
+ explicitly to prevent silent dry-run bypass.
570
728
 
571
729
  ## Generated documentation
572
730
 
@@ -606,3 +764,9 @@ Generated skill files follow the same structure formatted as markdown for AI ass
606
764
  | `pattern` is a valid regex | options, arguments |
607
765
  | `env` keys match `[A-Z_][A-Z0-9_]*` | env |
608
766
  | Guard has exactly one of `command` or `script` | guards |
767
+ | `path_tests` is non-empty if present | options, arguments |
768
+ | `path_tests` entries are known names | options, arguments |
769
+ | `path_tests` mutual exclusions enforced | options, arguments |
770
+ | `default` must be a string | options |
771
+ | `default` mutually exclusive with `required`, `repeatable`, `path_tests` | options |
772
+ | `default` must satisfy `pattern` / `allow` / `deny` if present | options |