agentpack-cli 0.3.28__tar.gz → 0.3.30__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 (176) hide show
  1. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/.gitignore +18 -3
  2. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/PKG-INFO +1 -1
  3. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/pyproject.toml +1 -1
  4. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/__init__.py +1 -1
  5. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/adapters/codex.py +3 -0
  6. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/application/pack_service.py +77 -0
  7. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/cli.py +2 -0
  8. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/doctor.py +19 -12
  9. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/hook_cmd.py +85 -51
  10. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/init.py +14 -2
  11. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/install.py +16 -9
  12. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/learn.py +2 -0
  13. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/memory.py +31 -0
  14. agentpack_cli-0.3.30/src/agentpack/commands/review_cmd.py +315 -0
  15. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/config.py +5 -5
  16. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/context_pack.py +2 -0
  17. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/models.py +1 -0
  18. agentpack_cli-0.3.30/src/agentpack/core/pack_handoff.py +77 -0
  19. agentpack_cli-0.3.30/src/agentpack/data/agentpack-learn.md +66 -0
  20. agentpack_cli-0.3.30/src/agentpack/data/agentpack-review.md +29 -0
  21. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/data/codex_plugin/.codex-plugin/plugin.json +3 -1
  22. agentpack_cli-0.3.30/src/agentpack/data/codex_plugin/.codexignore +3 -0
  23. agentpack_cli-0.3.30/src/agentpack/data/codex_plugin/LICENSE +21 -0
  24. agentpack_cli-0.3.30/src/agentpack/data/codex_plugin/README.md +20 -0
  25. agentpack_cli-0.3.30/src/agentpack/data/codex_plugin/SECURITY.md +9 -0
  26. agentpack_cli-0.3.30/src/agentpack/data/codex_plugin/assets/icon.svg +10 -0
  27. agentpack_cli-0.3.30/src/agentpack/data/codex_plugin/skills/agentpack-learn.md +67 -0
  28. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/data/codex_plugin/skills/agentpack-refresh.md +1 -1
  29. agentpack_cli-0.3.30/src/agentpack/data/codex_plugin/skills/agentpack-review.md +25 -0
  30. agentpack_cli-0.3.30/src/agentpack/data/review/stage1-understanding.md +97 -0
  31. agentpack_cli-0.3.30/src/agentpack/data/review/stage2-judge.md +78 -0
  32. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/installers/claude.py +3 -4
  33. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/installers/codex.py +48 -1
  34. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/integrations/agents.py +31 -1
  35. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/learning/collector.py +6 -0
  36. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/learning/extractor.py +2 -0
  37. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/learning/models.py +2 -0
  38. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/learning/renderers.py +5 -2
  39. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/renderers/markdown.py +55 -0
  40. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/router/service.py +46 -3
  41. agentpack_cli-0.3.30/src/agentpack/session/references.py +288 -0
  42. agentpack_cli-0.3.28/src/agentpack/data/codex_plugin/skills/agentpack-review.md +0 -32
  43. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/LICENSE +0 -0
  44. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/README.md +0 -0
  45. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/adapters/__init__.py +0 -0
  46. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/adapters/antigravity.py +0 -0
  47. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/adapters/base.py +0 -0
  48. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/adapters/claude.py +0 -0
  49. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/adapters/cursor.py +0 -0
  50. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/adapters/detect.py +0 -0
  51. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/adapters/generic.py +0 -0
  52. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/adapters/windsurf.py +0 -0
  53. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/analysis/__init__.py +0 -0
  54. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/analysis/dependency_graph.py +0 -0
  55. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/analysis/go_imports.py +0 -0
  56. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/analysis/java_imports.py +0 -0
  57. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/analysis/js_ts_imports.py +0 -0
  58. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/analysis/monorepo.py +0 -0
  59. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/analysis/naming_signals.py +0 -0
  60. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/analysis/python_ast.py +0 -0
  61. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/analysis/python_imports.py +0 -0
  62. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/analysis/ranking.py +0 -0
  63. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/analysis/repo_map.py +0 -0
  64. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/analysis/role_inference.py +0 -0
  65. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/analysis/rust_imports.py +0 -0
  66. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/analysis/symbols.py +0 -0
  67. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/analysis/task_classifier.py +0 -0
  68. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/analysis/tests.py +0 -0
  69. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/application/__init__.py +0 -0
  70. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/__init__.py +0 -0
  71. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/_shared.py +0 -0
  72. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/benchmark.py +0 -0
  73. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/ci_cmd.py +0 -0
  74. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/claude_cmd.py +0 -0
  75. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/compress_output.py +0 -0
  76. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/dashboard.py +0 -0
  77. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/dev_check.py +0 -0
  78. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/diagnose_selection.py +0 -0
  79. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/diff.py +0 -0
  80. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/eval_cmd.py +0 -0
  81. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/explain.py +0 -0
  82. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/guard.py +0 -0
  83. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/ignore_cmd.py +0 -0
  84. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/mcp_cmd.py +0 -0
  85. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/migrate.py +0 -0
  86. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/monitor.py +0 -0
  87. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/next_cmd.py +0 -0
  88. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/pack.py +0 -0
  89. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/perf.py +0 -0
  90. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/quickstart.py +0 -0
  91. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/release_check.py +0 -0
  92. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/release_cmd.py +0 -0
  93. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/repair.py +0 -0
  94. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/retrieve.py +0 -0
  95. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/route.py +0 -0
  96. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/scan.py +0 -0
  97. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/skills.py +0 -0
  98. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/start_cmd.py +0 -0
  99. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/state_cmd.py +0 -0
  100. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/stats.py +0 -0
  101. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/status.py +0 -0
  102. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/summarize.py +0 -0
  103. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/task_cmd.py +0 -0
  104. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/threads.py +0 -0
  105. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/tune.py +0 -0
  106. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/upgrade.py +0 -0
  107. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/verify_wheel.py +0 -0
  108. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/watch.py +0 -0
  109. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/workflow_cmd.py +0 -0
  110. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/commands/wrap.py +0 -0
  111. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/__init__.py +0 -0
  112. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/bootstrap.py +0 -0
  113. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/cache.py +0 -0
  114. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/changed_paths.py +0 -0
  115. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/command_surface.py +0 -0
  116. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/diff.py +0 -0
  117. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/e2e_benchmark.py +0 -0
  118. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/evals.py +0 -0
  119. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/execution_state.py +0 -0
  120. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/git.py +0 -0
  121. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/git_hooks.py +0 -0
  122. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/global_install.py +0 -0
  123. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/ignore.py +0 -0
  124. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/loop_protocol.py +0 -0
  125. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/merkle.py +0 -0
  126. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/modes.py +0 -0
  127. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/pack_registry.py +0 -0
  128. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/redactor.py +0 -0
  129. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/scanner.py +0 -0
  130. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/snapshot.py +0 -0
  131. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/task_freshness.py +0 -0
  132. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/thread_context.py +0 -0
  133. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/token_estimator.py +0 -0
  134. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/core/vscode_tasks.py +0 -0
  135. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/dashboard/__init__.py +0 -0
  136. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/dashboard/collectors.py +0 -0
  137. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/dashboard/models.py +0 -0
  138. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/dashboard/renderers.py +0 -0
  139. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/data/agentpack.md +0 -0
  140. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/data/codex_plugin/skills/agentpack-pack.md +0 -0
  141. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/data/codex_plugin/skills/agentpack-route.md +0 -0
  142. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/data/codex_plugin/skills/agentpack.md +0 -0
  143. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/installers/__init__.py +0 -0
  144. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/installers/antigravity.py +0 -0
  145. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/installers/cursor.py +0 -0
  146. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/installers/windsurf.py +0 -0
  147. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/integrations/__init__.py +0 -0
  148. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/integrations/git_hooks.py +0 -0
  149. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/integrations/global_install.py +0 -0
  150. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/integrations/platform.py +0 -0
  151. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/integrations/vscode_tasks.py +0 -0
  152. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/learning/__init__.py +0 -0
  153. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/learning/feedback.py +0 -0
  154. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/learning/lesson_ranker.py +0 -0
  155. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/learning/provider.py +0 -0
  156. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/learning/quality.py +0 -0
  157. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/learning/skill_map.py +0 -0
  158. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/mcp_server.py +0 -0
  159. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/output_compression/__init__.py +0 -0
  160. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/output_compression/core.py +0 -0
  161. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/renderers/__init__.py +0 -0
  162. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/renderers/compact.py +0 -0
  163. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/renderers/receipts.py +0 -0
  164. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/router/__init__.py +0 -0
  165. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/router/discovery.py +0 -0
  166. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/router/models.py +0 -0
  167. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/router/parser.py +0 -0
  168. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/router/prompt_builder.py +0 -0
  169. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/router/scoring.py +0 -0
  170. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/router/skills_index.py +0 -0
  171. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/session/__init__.py +0 -0
  172. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/session/events.py +0 -0
  173. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/session/state.py +0 -0
  174. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/summaries/__init__.py +0 -0
  175. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/summaries/base.py +0 -0
  176. {agentpack_cli-0.3.28 → agentpack_cli-0.3.30}/src/agentpack/summaries/offline.py +0 -0
@@ -18,17 +18,32 @@ env/
18
18
  .agentpack/snapshots/
19
19
  .agentpack/context*
20
20
  .agentpack/metrics.jsonl
21
+ .agentpack/session-events.jsonl
21
22
  .agentpack/pack_metadata.json
23
+ .agentpack/pack-registry.json
24
+ .agentpack/learning.md
25
+ .agentpack/daily-summary.md
26
+ .agentpack/skills-progress.json
27
+ .agentpack/agent-lessons.md
28
+ .agentpack/learning.prompt.md
29
+ .agentpack/pr-learning-comment.md
30
+ .agentpack/learning-dashboard.html
31
+ .agentpack/team-lessons.md
32
+ .agentpack/learning-feedback.jsonl
33
+ .agentpack/ranking-feedback.jsonl
34
+ .agentpack/learning-inputs.json
22
35
  .agentpack/activity.log
23
36
  .agentpack/.gitignore
24
37
  .agentpack/.mcp_reminded
25
38
  .agentpack/session.json
26
39
  .agentpack/task.md
27
40
  .agentpack/benchmark_results.jsonl
28
- .agentignore
41
+ .agentpack/loop_state.json
42
+ .agentpack/progress.md
43
+ .agentpack/loop_events.jsonl
44
+ .agentpack/loop_failures.jsonl
29
45
  .agent/skills/agentpack/
30
- .vscode/tasks.json
31
- GEMINI.md
46
+ .agentignore
32
47
  # agentpack:end
33
48
  .pytest_cache/
34
49
  .mypy_cache/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentpack-cli
3
- Version: 0.3.28
3
+ Version: 0.3.30
4
4
  Summary: Local context engine for AI coding agents that ranks relevant repo files and builds compact task-focused context packs for Claude Code, Codex, Cursor, Windsurf, MCP, and CI workflows.
5
5
  Project-URL: Homepage, https://github.com/vishal2612200/agentpack
6
6
  Project-URL: Documentation, https://vishal2612200.github.io/agentpack/
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agentpack-cli"
3
- version = "0.3.28"
3
+ version = "0.3.30"
4
4
  description = "Local context engine for AI coding agents that ranks relevant repo files and builds compact task-focused context packs for Claude Code, Codex, Cursor, Windsurf, MCP, and CI workflows."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -1,3 +1,3 @@
1
1
  """AgentPack — task-aware context packing for AI coding agents."""
2
2
 
3
- __version__ = "0.3.28"
3
+ __version__ = "0.3.30"
@@ -25,5 +25,8 @@ class CodexAdapter(BaseAdapter):
25
25
  def patch_codex_hooks(self, root: Path) -> str:
26
26
  return CodexInstaller().patch_codex_hooks(root)
27
27
 
28
+ def patch_codex_mcp_config(self, *, codex_home: Path | None = None) -> str:
29
+ return CodexInstaller().patch_codex_mcp_config(codex_home=codex_home)
30
+
28
31
  def install_auto_repack(self, root: Path) -> dict[str, str]:
29
32
  return CodexInstaller().install_auto_repack(root)
@@ -3,6 +3,8 @@ from __future__ import annotations
3
3
  import json
4
4
  import hashlib
5
5
  import re
6
+ import shutil
7
+ import subprocess
6
8
  import time
7
9
  from dataclasses import dataclass, field, replace
8
10
  from datetime import datetime, timezone
@@ -20,6 +22,7 @@ from agentpack.core import git
20
22
  from agentpack.core.command_surface import refresh_commands
21
23
  from agentpack.core.context_pack import enrich_call_site_scores, select_files, save_pack_metadata, load_pack_metadata
22
24
  from agentpack.core.execution_state import build_execution_state, compact_execution_state
25
+ from agentpack.core.pack_handoff import build_pack_handoff
23
26
  from agentpack.core.models import (
24
27
  ContextPack,
25
28
  DependencyGraph,
@@ -67,6 +70,7 @@ from agentpack.analysis.tests import find_related_tests
67
70
  from agentpack.analysis import dependency_graph as dep_graph_mod
68
71
  from agentpack.summaries.base import build_all_summaries
69
72
  from agentpack.session.events import record_event
73
+ from agentpack.session.references import collect_repo_issue_references
70
74
 
71
75
 
72
76
  @dataclass
@@ -476,6 +480,8 @@ class PackPlanner:
476
480
 
477
481
  t0 = time.perf_counter()
478
482
  changes = ChangeDetector().detect(packable, root, request.since, previous_snap=previous_snap)
483
+ pr_paths = _github_pr_paths(root, request.task) if _is_pr_review_task(request.task) else set()
484
+ changes = _apply_github_pr_changed_paths(changes, pr_paths, packable)
479
485
  changes.current_snap["metadata"] = {
480
486
  **scan_metadata,
481
487
  "scan_mode": scan_result.scan_mode,
@@ -497,6 +503,8 @@ class PackPlanner:
497
503
  workspace_roots=workspace_roots,
498
504
  workspace_dependency_edges=workspace_dependency_edges,
499
505
  )
506
+ if pr_paths:
507
+ rank_result.scored = _boost_github_pr_paths(rank_result.scored, pr_paths)
500
508
  rank_result.scored = _apply_scope_penalties(
501
509
  rank_result.scored,
502
510
  request.task,
@@ -779,6 +787,7 @@ class PackService:
779
787
  selected_files=plan.selected,
780
788
  receipts=plan.receipts if cfg.context.include_receipts else [],
781
789
  omitted_relevant_files=plan.omitted_relevant_files,
790
+ pack_handoff_omitted_relevant_files=plan.omitted_relevant_files,
782
791
  redaction_warnings=all_redaction_warnings,
783
792
  stale=False,
784
793
  freshness=freshness,
@@ -818,6 +827,7 @@ class PackService:
818
827
  freshness=pack_obj.freshness,
819
828
  freshness_warnings=pack_obj.freshness_warnings,
820
829
  selected_files=_selected_file_metadata(pack_obj.selected_files),
830
+ pack_handoff=build_pack_handoff(pack_obj),
821
831
  execution_state=pack_obj.execution_state,
822
832
  concurrent_context=pack_obj.concurrent_context,
823
833
  metadata_path=scoped_paths.metadata if scoped_paths else None,
@@ -829,11 +839,14 @@ class PackService:
829
839
  output_path=cfg.runtime.pack_registry_output,
830
840
  max_records=cfg.runtime.max_registry_records,
831
841
  )
842
+ issue_reference_details = collect_repo_issue_references(root, request.task)
832
843
  record_event(
833
844
  root,
834
845
  "pack",
835
846
  {
836
847
  "task": request.task,
848
+ "issue_references": [item.ref for item in issue_reference_details],
849
+ "issue_reference_details": [item.to_dict() for item in issue_reference_details],
837
850
  "agent": request.agent,
838
851
  "mode": plan.mode,
839
852
  "packed_tokens": packed_tokens,
@@ -1564,6 +1577,70 @@ def _change_source(root: Path, since: str | None, snapshot_changed: set[str], gi
1564
1577
  return "no live changes; ranking used task keywords and history"
1565
1578
 
1566
1579
 
1580
+ def _is_pr_review_task(task: str) -> bool:
1581
+ lower = task.lower()
1582
+ return any(term in lower for term in ("pr ", "pull request", "review", "diff", "review comment"))
1583
+
1584
+
1585
+ def _github_pr_paths(root: Path, task: str) -> set[str]:
1586
+ if shutil.which("gh") is None:
1587
+ return set()
1588
+ pr_number = _pr_number(task)
1589
+ cmd = ["gh", "pr", "view"]
1590
+ if pr_number:
1591
+ cmd.append(pr_number)
1592
+ cmd += ["--json", "files", "--jq", ".files[].path"]
1593
+ try:
1594
+ result = subprocess.run(
1595
+ cmd,
1596
+ cwd=root,
1597
+ capture_output=True,
1598
+ text=True,
1599
+ timeout=4,
1600
+ )
1601
+ except (OSError, subprocess.TimeoutExpired):
1602
+ return set()
1603
+ if result.returncode != 0:
1604
+ return set()
1605
+ return {line.strip() for line in result.stdout.splitlines() if line.strip()}
1606
+
1607
+
1608
+ def _pr_number(task: str) -> str | None:
1609
+ match = re.search(r"(?:pr|pull request)\s*#?\s*(\d+)", task, re.IGNORECASE)
1610
+ return match.group(1) if match else None
1611
+
1612
+
1613
+ def _apply_github_pr_changed_paths(
1614
+ changes: ChangeSet,
1615
+ pr_paths: set[str],
1616
+ packable: list[FileInfo],
1617
+ ) -> ChangeSet:
1618
+ packable_paths = {fi.path for fi in packable}
1619
+ pr_packable = pr_paths & packable_paths
1620
+ if not pr_packable:
1621
+ return changes
1622
+ source = "GitHub PR files" if changes.source.startswith("no live changes") else f"{changes.source} + GitHub PR files"
1623
+ return replace(
1624
+ changes,
1625
+ all_changed=changes.all_changed | pr_packable,
1626
+ source=source,
1627
+ )
1628
+
1629
+
1630
+ def _boost_github_pr_paths(
1631
+ scored: list[tuple[Any, float, list[str]]],
1632
+ pr_paths: set[str],
1633
+ ) -> list[tuple[Any, float, list[str]]]:
1634
+ adjusted: list[tuple[Any, float, list[str]]] = []
1635
+ for fi, score, reasons in scored:
1636
+ if fi.path in pr_paths:
1637
+ boosted_reasons = reasons if "GitHub PR file" in reasons else ["GitHub PR file", *reasons]
1638
+ adjusted.append((fi, max(score, 1000.0), boosted_reasons))
1639
+ continue
1640
+ adjusted.append((fi, score, reasons))
1641
+ return adjusted
1642
+
1643
+
1567
1644
  def _task_md_body(root: Path) -> str | None:
1568
1645
  return read_task_md(root)
1569
1646
 
@@ -27,6 +27,7 @@ from agentpack.commands import (
27
27
  pack,
28
28
  perf,
29
29
  quickstart,
30
+ review_cmd,
30
31
  release_cmd,
31
32
  release_check,
32
33
  retrieve,
@@ -106,6 +107,7 @@ for mod in [
106
107
  mcp_cmd,
107
108
  hook_cmd,
108
109
  quickstart,
110
+ review_cmd,
109
111
  skills,
110
112
  release_check,
111
113
  release_cmd,
@@ -334,18 +334,25 @@ def register(app: typer.Typer) -> None:
334
334
  else:
335
335
  console.print(" [green]✓[/] npm publish token available in environment")
336
336
 
337
- # --- Slash command ---
338
- console.print("\n[bold]Slash command (/agentpack)[/]")
339
- local_cmd = root / ".claude" / "commands" / "agentpack.md"
340
- global_cmd = Path.home() / ".claude" / "commands" / "agentpack.md"
341
- if local_cmd.exists():
342
- console.print(f" [green]✓[/] Slash command installed (local): {local_cmd}")
343
- else:
344
- console.print(" [dim]-[/] Slash command not installed locally — run: agentpack install --agent claude")
345
- if global_cmd.exists():
346
- console.print(f" [green][/] Slash command installed (global): {global_cmd}")
347
- else:
348
- console.print(" [dim]-[/] Slash command not installed globally — run: agentpack install --agent claude --global")
337
+ # --- Slash commands ---
338
+ console.print("\n[bold]Slash commands (/agentpack, /agentpack-review, /agentpack-learn)[/]")
339
+ for filename in ("agentpack.md", "agentpack-review.md", "agentpack-learn.md"):
340
+ local_cmd = root / ".claude" / "commands" / filename
341
+ global_cmd = Path.home() / ".claude" / "commands" / filename
342
+ if local_cmd.exists():
343
+ console.print(f" [green]✓[/] Slash command installed (local): {local_cmd}")
344
+ else:
345
+ console.print(
346
+ f" [dim]-[/] Slash command not installed locally: {local_cmd}"
347
+ "run: agentpack install --agent claude"
348
+ )
349
+ if global_cmd.exists():
350
+ console.print(f" [green]✓[/] Slash command installed (global): {global_cmd}")
351
+ else:
352
+ console.print(
353
+ f" [dim]-[/] Slash command not installed globally: {global_cmd} — "
354
+ "run: agentpack install --agent claude --global"
355
+ )
349
356
 
350
357
  _print_summary(ok)
351
358
 
@@ -111,6 +111,15 @@ def _load_task_md(root: Path) -> str:
111
111
  return (read_task_md(root) or "")[:200]
112
112
 
113
113
 
114
+ def _emit_additional_context(message: str) -> None:
115
+ print(json.dumps({
116
+ "hookSpecificOutput": {
117
+ "hookEventName": "UserPromptSubmit",
118
+ "additionalContext": message,
119
+ }
120
+ }))
121
+
122
+
114
123
  def _looks_like_coding_prompt(prompt: str) -> bool:
115
124
  """Return True if prompt looks like a coding task (not a slash command or chat)."""
116
125
  stripped = prompt.strip()
@@ -219,29 +228,32 @@ def _load_top_files(root: Path, n: int = 5) -> list[dict]:
219
228
  return _load_hints(root, n)
220
229
 
221
230
 
222
- def _load_pack_task(root: Path) -> str:
231
+ def _load_pack_metadata(root: Path) -> dict:
223
232
  meta_path = root / ".agentpack" / "pack_metadata.json"
224
233
  if not meta_path.exists():
225
- return ""
234
+ return {}
226
235
  try:
227
- return json.loads(meta_path.read_text()).get("task", "")
236
+ return json.loads(meta_path.read_text(encoding="utf-8"))
228
237
  except Exception:
229
- return ""
238
+ return {}
239
+
240
+
241
+ def _load_pack_task(root: Path) -> str:
242
+ return str(_load_pack_metadata(root).get("task", "") or "")
230
243
 
231
244
 
232
245
  def _load_delta_summary(root: Path) -> str:
233
- meta_path = root / ".agentpack" / "pack_metadata.json"
234
- if not meta_path.exists():
235
- return ""
236
- try:
237
- meta = json.loads(meta_path.read_text(encoding="utf-8"))
238
- except Exception:
239
- return ""
246
+ meta = _load_pack_metadata(root)
240
247
  freshness = meta.get("freshness") or {}
241
248
  delta = freshness.get("delta_summary", "")
242
249
  return str(delta).splitlines()[0][:240] if delta else ""
243
250
 
244
251
 
252
+ def _packed_root_hash(root: Path) -> str | None:
253
+ value = _load_pack_metadata(root).get("snapshot_root_hash")
254
+ return str(value) if value else None
255
+
256
+
245
257
  def _infer_live_task(root: Path) -> str:
246
258
  """Live task: git priority chain (no stale metadata). Falls back to 'unknown'."""
247
259
  try:
@@ -270,6 +282,7 @@ def _run_session_start(root: Path) -> None:
270
282
  for sentinel in [
271
283
  root / ".agentpack" / ".mcp_reminded",
272
284
  root / ".agentpack" / ".context_injected",
285
+ root / ".agentpack" / ".no_task_reminded",
273
286
  ]:
274
287
  try:
275
288
  sentinel.unlink(missing_ok=True)
@@ -305,8 +318,6 @@ def _run_blocking_pack(root: Path) -> tuple[bool, str]:
305
318
 
306
319
 
307
320
  def _run_user_prompt_submit(root: Path) -> None:
308
- snap_sentinel = root / ".agentpack" / ".mcp_reminded"
309
-
310
321
  try:
311
322
  hook_data = json.loads(sys.stdin.read())
312
323
  prompt = hook_data.get("prompt", "")
@@ -315,6 +326,20 @@ def _run_user_prompt_submit(root: Path) -> None:
315
326
 
316
327
  cfg = load_config(root)
317
328
  task_md = _load_task_md(root)
329
+ if not task_md:
330
+ if _looks_like_coding_prompt(prompt):
331
+ reminder = root / ".agentpack" / ".no_task_reminded"
332
+ if not reminder.exists():
333
+ try:
334
+ reminder.write_text("1", encoding="utf-8")
335
+ except Exception:
336
+ pass
337
+ _emit_additional_context(
338
+ "AgentPack idle. No active task in `.agentpack/task.md`.\n"
339
+ "Run `agentpack start \"describe the task\"` to enable prompt-time hints."
340
+ )
341
+ return
342
+
318
343
  task_switched = bool(
319
344
  cfg.hooks.task_switch_detection
320
345
  and _looks_like_task_switch(
@@ -336,43 +361,36 @@ def _run_user_prompt_submit(root: Path) -> None:
336
361
  pass
337
362
 
338
363
  current_hash = _current_root_hash(root)
339
- reminded_hash = snap_sentinel.read_text().strip() if snap_sentinel.exists() else None
340
- repo_changed = current_hash != reminded_hash
341
364
  packed_task = _load_pack_task(root)
365
+ packed_root_hash = _packed_root_hash(root)
366
+ repo_changed = bool(current_hash and packed_root_hash and current_hash != packed_root_hash)
367
+ pack_missing = not packed_task or not packed_root_hash
342
368
  pack_task_changed = bool(task != "auto" and packed_task and packed_task != task)
343
369
 
344
- should_repack = repo_changed or task_switched or pack_task_changed
345
- blocking_refresh = bool(
346
- cfg.hooks.blocking_task_refresh and (task_switched or pack_task_changed)
347
- )
370
+ context_stale = pack_missing or repo_changed or task_switched or pack_task_changed
371
+ blocking_refresh = bool(cfg.hooks.blocking_task_refresh and context_stale)
348
372
  refresh_state = "fresh"
349
373
  refresh_error = ""
350
374
 
351
- if should_repack:
352
- if task != "auto":
353
- try:
354
- _write_task_md(root, task)
355
- except Exception:
356
- pass
375
+ if context_stale:
376
+ refresh_state = "refresh pending"
357
377
  if blocking_refresh:
358
378
  ok, detail = _run_blocking_pack(root)
359
379
  refresh_state = "refreshed" if ok else "refresh failed"
360
380
  refresh_error = detail
361
- else:
362
- detached_popen(
363
- cli_module_argv("pack", "--task", "auto", "--mode", "balanced", "--since", "HEAD~1"),
364
- cwd=root,
365
- )
366
- refresh_state = "repacking"
367
- try:
368
- snap_sentinel.write_text(current_hash or "1")
369
- except Exception:
370
- pass
381
+ if ok:
382
+ pack_missing = False
383
+ pack_task_changed = False
384
+ repo_changed = False
385
+ task_switched = False
371
386
 
372
387
  has_mcp = _mcp_installed(root)
388
+ current_task = _load_task_md(root) or _infer_live_task(root)
389
+ delta = _load_delta_summary(root)
390
+ safe_hints = not pack_missing and not pack_task_changed and not task_switched
391
+ hints = _load_hints(root, n=5 if has_mcp else 8) if safe_hints else []
373
392
 
374
393
  if has_mcp:
375
- hints = _load_hints(root, n=5)
376
394
  if hints:
377
395
  files_lines = "\n".join(
378
396
  f" - {h['path']}" + (f" — {h['why']}" if h.get("why") else "")
@@ -382,12 +400,10 @@ def _run_user_prompt_submit(root: Path) -> None:
382
400
  status_note = "(refreshed for current task)"
383
401
  elif refresh_state == "refresh failed":
384
402
  status_note = "(refresh failed — call pack_context to retry)"
385
- elif refresh_state == "repacking":
386
- status_note = "(repacking — call pack_context for fresh results)"
403
+ elif refresh_state == "refresh pending":
404
+ status_note = "(refresh pending — call get_context for fresh results)"
387
405
  else:
388
406
  status_note = "(index fresh)"
389
- current_task = _load_task_md(root) or _infer_live_task(root)
390
- delta = _load_delta_summary(root)
391
407
  msg = (
392
408
  f"AgentPack {status_note}\n"
393
409
  f"task: {current_task}\n"
@@ -397,16 +413,26 @@ def _run_user_prompt_submit(root: Path) -> None:
397
413
  f"top files:\n{files_lines}\n"
398
414
  f"Call agentpack_get_delta_context() for delta or agentpack_pack_context(task=\"...\") for full ranked context."
399
415
  )
416
+ elif refresh_state == "refresh pending":
417
+ msg = (
418
+ "AgentPack active (refresh pending)\n"
419
+ f"task: {current_task}\n"
420
+ "Call agentpack_get_context() to refresh the current task pack."
421
+ )
422
+ elif refresh_state == "refresh failed":
423
+ msg = (
424
+ "AgentPack active (refresh failed)\n"
425
+ f"task: {current_task}\n"
426
+ + (f"refresh error: {refresh_error}\n" if refresh_error else "")
427
+ + "Call agentpack_pack_context(task=\"...\") to rebuild the current task pack."
428
+ )
400
429
  else:
401
430
  msg = (
402
431
  "AgentPack active. No pack yet — call agentpack_pack_context(task=\"...\") "
403
432
  "to build context for this task."
404
433
  )
405
434
  else:
406
- hints = _load_hints(root, n=8)
407
- current_task = _load_task_md(root) or _infer_live_task(root)
408
435
  if hints:
409
- delta = _load_delta_summary(root)
410
436
  files_lines = "\n".join(
411
437
  f" - {h['path']}" + (f" — {h['why']}" if h.get("why") else "")
412
438
  for h in hints
@@ -415,8 +441,8 @@ def _run_user_prompt_submit(root: Path) -> None:
415
441
  changed_note = " (refreshed)"
416
442
  elif refresh_state == "refresh failed":
417
443
  changed_note = " (refresh failed)"
418
- elif refresh_state == "repacking":
419
- changed_note = " (repacking in background)"
444
+ elif refresh_state == "refresh pending":
445
+ changed_note = " (refresh pending)"
420
446
  else:
421
447
  changed_note = ""
422
448
  msg = (
@@ -428,6 +454,19 @@ def _run_user_prompt_submit(root: Path) -> None:
428
454
  f"top files:\n{files_lines}\n\n"
429
455
  f"For richer context, install MCP: agentpack install --agent claude"
430
456
  )
457
+ elif refresh_state == "refresh pending":
458
+ msg = (
459
+ "AgentPack active (refresh pending)\n"
460
+ f"task: {current_task}\n"
461
+ "Run `agentpack pack --task auto` or install MCP and call `agentpack_get_context()`."
462
+ )
463
+ elif refresh_state == "refresh failed":
464
+ msg = (
465
+ "AgentPack active (refresh failed)\n"
466
+ f"task: {current_task}\n"
467
+ + (f"refresh error: {refresh_error}\n" if refresh_error else "")
468
+ + "Run `agentpack pack --task auto` to rebuild the current task pack."
469
+ )
431
470
  else:
432
471
  msg = (
433
472
  "AgentPack active. Write `.agentpack/task.md`, then run `agentpack pack --task auto` to build context.\n"
@@ -437,9 +476,4 @@ def _run_user_prompt_submit(root: Path) -> None:
437
476
  if len(msg) > 3000:
438
477
  msg = msg[:2970] + "\n... [truncated]"
439
478
 
440
- print(json.dumps({
441
- "hookSpecificOutput": {
442
- "hookEventName": "UserPromptSubmit",
443
- "additionalContext": msg,
444
- }
445
- }))
479
+ _emit_additional_context(msg)
@@ -25,7 +25,7 @@ _INIT_AGENTS = ("auto", "claude", "cursor", "windsurf", "codex", "antigravity",
25
25
  _AGENT_GITIGNORE_ENTRIES = {
26
26
  "cursor": (".vscode/tasks.json",),
27
27
  "windsurf": (".vscode/tasks.json",),
28
- "antigravity": (".agent/skills/agentpack/", ".vscode/tasks.json", "GEMINI.md"),
28
+ "antigravity": (".vscode/tasks.json", "GEMINI.md"),
29
29
  }
30
30
 
31
31
 
@@ -80,6 +80,7 @@ def _repo_gitignore_entries(share_cache: bool = False, agent: str = "generic") -
80
80
  ".agentpack/progress.md",
81
81
  ".agentpack/loop_events.jsonl",
82
82
  ".agentpack/loop_failures.jsonl",
83
+ ".agent/skills/agentpack/",
83
84
  ".agentignore",
84
85
  ]
85
86
  )
@@ -206,6 +207,10 @@ def _patch_agentignore(
206
207
 
207
208
  def _install_agent_integration(root, agent: str) -> dict[str, str]:
208
209
  """Install repo-local agent integration files after `agentpack init`."""
210
+ if agent == "claude":
211
+ from agentpack.commands.install import _install_slash_command
212
+
213
+ return install_agent_integration(root, agent, install_slash_command=_install_slash_command)
209
214
  return install_agent_integration(root, agent)
210
215
 
211
216
 
@@ -246,7 +251,14 @@ def _resolve_init_agent(root: Path, agent: str, *, force: bool = False) -> str:
246
251
 
247
252
  def _agent_integration_paths(agent: str) -> tuple[str, ...]:
248
253
  if agent == "claude":
249
- return ("CLAUDE.md", ".claude/settings.json", ".mcp.json")
254
+ return (
255
+ "CLAUDE.md",
256
+ ".claude/settings.json",
257
+ ".mcp.json",
258
+ ".claude/commands/agentpack.md",
259
+ ".claude/commands/agentpack-review.md",
260
+ ".claude/commands/agentpack-learn.md",
261
+ )
250
262
  if agent == "cursor":
251
263
  return (".cursorrules", ".cursor/rules/agentpack.mdc", ".vscode/tasks.json")
252
264
  if agent == "windsurf":
@@ -47,8 +47,8 @@ def _print_install_results(agent: str, results: dict[str, str]) -> None:
47
47
  console.print(f"[green].git/hooks/{key[4:]} {action}.[/]")
48
48
  elif key == "vscode:tasks":
49
49
  console.print(f"[green].vscode/tasks.json {action}.[/]")
50
- elif key == "/agentpack":
51
- console.print(f"[green]/agentpack slash command {action}.[/]")
50
+ elif key.startswith("/"):
51
+ console.print(f"[green]{key} slash command {action}.[/]")
52
52
  else:
53
53
  console.print(f"[green]{key} {action}.[/]")
54
54
 
@@ -66,7 +66,7 @@ def _print_dry_run_agent(agent: str) -> None:
66
66
  elif agent == "windsurf":
67
67
  console.print("\n[dim]Would patch: .windsurfrules, VS Code task, git hooks[/]")
68
68
  elif agent == "codex":
69
- console.print("\n[dim]Would patch: AGENTS.md, .codex/hooks.json, git hooks[/]")
69
+ console.print("\n[dim]Would patch: AGENTS.md, .codex/hooks.json, Codex MCP config, git hooks[/]")
70
70
  elif agent == "antigravity":
71
71
  console.print("\n[dim]Would patch: GEMINI.md, VS Code task, git hooks[/]")
72
72
  elif agent == "generic":
@@ -256,18 +256,25 @@ def register(app: typer.Typer) -> None:
256
256
  console.print(" Current repo hooks now delegate through AgentPack's safe GitAutoRepack path.")
257
257
 
258
258
 
259
- def _install_slash_command(root: Path, global_install: bool) -> str:
260
- import importlib.resources
261
-
259
+ def _install_slash_command(root: Path, global_install: bool) -> dict[str, str]:
262
260
  commands_dir = Path.home() / ".claude" / "commands" if global_install else root / ".claude" / "commands"
263
261
  commands_dir.mkdir(parents=True, exist_ok=True)
264
- dest = commands_dir / "agentpack.md"
262
+ return {
263
+ "/agentpack": _install_slash_command_file(commands_dir, "agentpack.md"),
264
+ "/agentpack-review": _install_slash_command_file(commands_dir, "agentpack-review.md"),
265
+ "/agentpack-learn": _install_slash_command_file(commands_dir, "agentpack-learn.md"),
266
+ }
267
+
268
+
269
+ def _install_slash_command_file(commands_dir: Path, filename: str) -> str:
270
+ import importlib.resources
265
271
 
272
+ dest = commands_dir / filename
266
273
  try:
267
- pkg_files = importlib.resources.files("agentpack") / "data" / "agentpack.md"
274
+ pkg_files = importlib.resources.files("agentpack") / "data" / filename
268
275
  source_text = pkg_files.read_text(encoding="utf-8")
269
276
  except Exception:
270
- source_text = (Path(__file__).parent.parent / "data" / "agentpack.md").read_text(encoding="utf-8")
277
+ source_text = (Path(__file__).parent.parent / "data" / filename).read_text(encoding="utf-8")
271
278
 
272
279
  existed = dest.exists()
273
280
  if existed and dest.read_text(encoding="utf-8") == source_text:
@@ -248,6 +248,8 @@ def register(app: typer.Typer) -> None:
248
248
  "learn",
249
249
  {
250
250
  "task": report.task,
251
+ "issue_references": report.issue_references,
252
+ "issue_reference_details": report.issue_reference_details,
251
253
  "changed_files": len(report.source_files),
252
254
  "concepts": report.concepts,
253
255
  "selected_hits": len(report.selected_hits),