agex-cli 0.22.0__tar.gz → 0.23.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 (216) hide show
  1. {agex_cli-0.22.0 → agex_cli-0.23.0}/.github/workflows/publish.yml +19 -13
  2. {agex_cli-0.22.0 → agex_cli-0.23.0}/CHANGELOG.md +17 -0
  3. {agex_cli-0.22.0 → agex_cli-0.23.0}/CLAUDE.md +1 -1
  4. {agex_cli-0.22.0 → agex_cli-0.23.0}/PKG-INFO +6 -6
  5. agex_cli-0.23.0/README.md +29 -0
  6. {agex_cli-0.22.0 → agex_cli-0.23.0}/pyproject.toml +4 -3
  7. {agex_cli-0.22.0 → agex_cli-0.23.0}/sonar-project.properties +2 -2
  8. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/__init__.py +8 -7
  9. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/cli.py +23 -15
  10. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/doctor/assets/report.md.j2 +2 -2
  11. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/doctor/scripts/doctor.py +12 -9
  12. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/explain/assets/topics/agex.md +1 -1
  13. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/explain/scripts/explain.py +2 -1
  14. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/gamify/scripts/install.py +7 -5
  15. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/hook/scripts/write.py +2 -1
  16. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/learn/assets/menu.md.j2 +1 -1
  17. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/learn/scripts/learn.py +3 -2
  18. agex_cli-0.23.0/src/agent_experience/commands/pr/assets/backends/acp.yaml +20 -0
  19. agex_cli-0.23.0/src/agent_experience/commands/pr/assets/backends/claude-code.yaml +20 -0
  20. agex_cli-0.23.0/src/agent_experience/commands/pr/assets/backends/codex.yaml +20 -0
  21. agex_cli-0.23.0/src/agent_experience/commands/pr/assets/backends/copilot.yaml +20 -0
  22. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/assets/templates/delta.md.j2 +1 -1
  23. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/assets/templates/lint_result.md.j2 +2 -2
  24. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/assets/templates/pr_briefing.md.j2 +1 -1
  25. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/assets/templates/pr_open_result.md.j2 +1 -1
  26. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/assets/templates/pr_reply_result.md.j2 +1 -1
  27. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/scripts/_readiness.py +5 -1
  28. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/scripts/delta.py +4 -2
  29. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/scripts/reply.py +6 -4
  30. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/core/capabilities.py +1 -1
  31. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/core/hook_io.py +1 -1
  32. agex_cli-0.23.0/src/agent_experience/core/prog.py +44 -0
  33. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/core/render.py +9 -1
  34. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/pr/test_footer.py +16 -0
  35. agex_cli-0.23.0/tests/commands/test_prog_propagation.py +45 -0
  36. agex_cli-0.23.0/tests/core/test_prog.py +39 -0
  37. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/core/test_version_lookup.py +13 -6
  38. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/test_cli_dispatch.py +11 -0
  39. {agex_cli-0.22.0 → agex_cli-0.23.0}/uv.lock +1 -1
  40. agex_cli-0.22.0/README.md +0 -29
  41. agex_cli-0.22.0/src/agent_experience/commands/pr/assets/backends/acp.yaml +0 -20
  42. agex_cli-0.22.0/src/agent_experience/commands/pr/assets/backends/claude-code.yaml +0 -20
  43. agex_cli-0.22.0/src/agent_experience/commands/pr/assets/backends/codex.yaml +0 -20
  44. agex_cli-0.22.0/src/agent_experience/commands/pr/assets/backends/copilot.yaml +0 -20
  45. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/agent-config/SKILL.md +0 -0
  46. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/agent-config/data/backend-fingerprints.yaml +0 -0
  47. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/agent-config/scripts/show.sh +0 -0
  48. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/assign-to-workforce/SKILL.md +0 -0
  49. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh +0 -0
  50. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/cicd/SKILL.md +0 -0
  51. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/cicd/scripts/workflow.sh +0 -0
  52. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/communicate/SKILL.md +0 -0
  53. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
  54. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
  55. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
  56. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
  57. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
  58. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
  59. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/pypi-maintainer/SKILL.md +0 -0
  60. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/pypi-maintainer/scripts/switch-source.sh +0 -0
  61. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/run-tests/SKILL.md +0 -0
  62. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
  63. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/sonarclaude/SKILL.md +0 -0
  64. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
  65. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/spec-to-plan/SKILL.md +0 -0
  66. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +0 -0
  67. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/think/SKILL.md +0 -0
  68. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/think/scripts/think.sh +0 -0
  69. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/version-bump/SKILL.md +0 -0
  70. {agex_cli-0.22.0 → agex_cli-0.23.0}/.claude/skills/version-bump/scripts/bump.py +0 -0
  71. {agex_cli-0.22.0 → agex_cli-0.23.0}/.flake8 +0 -0
  72. {agex_cli-0.22.0 → agex_cli-0.23.0}/.github/workflows/test.yml +0 -0
  73. {agex_cli-0.22.0 → agex_cli-0.23.0}/.gitignore +0 -0
  74. {agex_cli-0.22.0 → agex_cli-0.23.0}/.python-version +0 -0
  75. {agex_cli-0.22.0 → agex_cli-0.23.0}/LICENSE +0 -0
  76. {agex_cli-0.22.0 → agex_cli-0.23.0}/culture.yaml +0 -0
  77. {agex_cli-0.22.0 → agex_cli-0.23.0}/docs/skill-sources.md +0 -0
  78. {agex_cli-0.22.0 → agex_cli-0.23.0}/docs/superpowers/plans/2026-04-18-agex-v0.1.md +0 -0
  79. {agex_cli-0.22.0 → agex_cli-0.23.0}/docs/superpowers/plans/2026-05-10-agex-pr.md +0 -0
  80. {agex_cli-0.22.0 → agex_cli-0.23.0}/docs/superpowers/specs/2026-04-18-agex-design.md +0 -0
  81. {agex_cli-0.22.0 → agex_cli-0.23.0}/docs/superpowers/specs/2026-04-26-agex-doctor.md +0 -0
  82. {agex_cli-0.22.0 → agex_cli-0.23.0}/docs/superpowers/specs/2026-05-10-agex-pr-design.md +0 -0
  83. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/__main__.py +0 -0
  84. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/backends/__init__.py +0 -0
  85. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/backends/acp/__init__.py +0 -0
  86. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/backends/acp/probe.py +0 -0
  87. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/backends/capabilities/acp.yaml +0 -0
  88. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/backends/capabilities/claude-code.yaml +0 -0
  89. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/backends/capabilities/codex.yaml +0 -0
  90. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/backends/capabilities/copilot.yaml +0 -0
  91. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/backends/claude_code/__init__.py +0 -0
  92. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/backends/claude_code/probe.py +0 -0
  93. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/backends/codex/__init__.py +0 -0
  94. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/backends/codex/probe.py +0 -0
  95. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/backends/copilot/__init__.py +0 -0
  96. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/backends/copilot/probe.py +0 -0
  97. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/__init__.py +0 -0
  98. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/doctor/SKILL.md +0 -0
  99. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/doctor/__init__.py +0 -0
  100. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/doctor/references/design.md +0 -0
  101. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/doctor/scripts/__init__.py +0 -0
  102. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/explain/SKILL.md +0 -0
  103. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/explain/__init__.py +0 -0
  104. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/explain/references/.gitkeep +0 -0
  105. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/explain/scripts/__init__.py +0 -0
  106. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/gamify/SKILL.md +0 -0
  107. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/gamify/__init__.py +0 -0
  108. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/gamify/assets/hooks/claude-code.json +0 -0
  109. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/gamify/references/.gitkeep +0 -0
  110. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/gamify/scripts/__init__.py +0 -0
  111. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/hook/SKILL.md +0 -0
  112. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/hook/__init__.py +0 -0
  113. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/hook/assets/table.md.j2 +0 -0
  114. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/hook/references/.gitkeep +0 -0
  115. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/hook/scripts/__init__.py +0 -0
  116. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/hook/scripts/read.py +0 -0
  117. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/learn/SKILL.md +0 -0
  118. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/learn/__init__.py +0 -0
  119. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/learn/assets/topics/cicd/SKILL.md +0 -0
  120. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/learn/assets/topics/gamify/SKILL.md +0 -0
  121. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/learn/assets/topics/gamify/assets/skill-template/claude-code/SKILL.md +0 -0
  122. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/learn/assets/topics/introspect/SKILL.md +0 -0
  123. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/learn/assets/topics/introspect/assets/skill-template/claude-code/SKILL.md +0 -0
  124. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/learn/assets/topics/levelup/SKILL.md +0 -0
  125. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/learn/assets/topics/levelup/assets/skill-template/claude-code/SKILL.md +0 -0
  126. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/learn/assets/topics/visualize/SKILL.md +0 -0
  127. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/learn/assets/topics/visualize/assets/skill-template/claude-code/SKILL.md +0 -0
  128. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/learn/references/.gitkeep +0 -0
  129. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/learn/scripts/__init__.py +0 -0
  130. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/overview/SKILL.md +0 -0
  131. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/overview/__init__.py +0 -0
  132. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/overview/assets/backends/acp.yaml +0 -0
  133. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/overview/assets/backends/claude-code.yaml +0 -0
  134. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/overview/assets/backends/codex.yaml +0 -0
  135. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/overview/assets/backends/copilot.yaml +0 -0
  136. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/overview/assets/sections.md.j2 +0 -0
  137. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/overview/references/.gitkeep +0 -0
  138. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/overview/scripts/__init__.py +0 -0
  139. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/overview/scripts/overview.py +0 -0
  140. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/SKILL.md +0 -0
  141. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/__init__.py +0 -0
  142. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/assets/__init__.py +0 -0
  143. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/assets/backends/__init__.py +0 -0
  144. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/assets/rules/__init__.py +0 -0
  145. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/assets/rules/lint_rules.py +0 -0
  146. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/assets/rules/next_step_rules.py +0 -0
  147. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/assets/templates/__init__.py +0 -0
  148. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/assets/templates/footer.md.j2 +0 -0
  149. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/scripts/__init__.py +0 -0
  150. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/scripts/_footer.py +0 -0
  151. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/scripts/_journal.py +0 -0
  152. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/scripts/_qodo.py +0 -0
  153. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/scripts/_sonar.py +0 -0
  154. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/scripts/await_.py +0 -0
  155. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/scripts/lint.py +0 -0
  156. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/scripts/open_.py +0 -0
  157. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/commands/pr/scripts/read.py +0 -0
  158. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/core/__init__.py +0 -0
  159. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/core/backend.py +0 -0
  160. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/core/config.py +0 -0
  161. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/core/github.py +0 -0
  162. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/core/journal.py +0 -0
  163. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/core/paths.py +0 -0
  164. {agex_cli-0.22.0 → agex_cli-0.23.0}/src/agent_experience/core/skill_loader.py +0 -0
  165. {agex_cli-0.22.0 → agex_cli-0.23.0}/tester-agents/claude/.claude/settings.json +0 -0
  166. {agex_cli-0.22.0 → agex_cli-0.23.0}/tester-agents/claude/CLAUDE.md +0 -0
  167. {agex_cli-0.22.0 → agex_cli-0.23.0}/tester-agents/claude/README.md +0 -0
  168. {agex_cli-0.22.0 → agex_cli-0.23.0}/tester-agents/claude/culture.yaml +0 -0
  169. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/__init__.py +0 -0
  170. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/backends/__init__.py +0 -0
  171. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/backends/test_claude_code_probe.py +0 -0
  172. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/backends/test_stub_probes.py +0 -0
  173. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/__init__.py +0 -0
  174. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/pr/__init__.py +0 -0
  175. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/pr/fixtures/gh/.gitkeep +0 -0
  176. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/pr/fixtures/gh/pr_checks_42.json +0 -0
  177. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/pr/fixtures/gh/pr_comments_42.json +0 -0
  178. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/pr/fixtures/gh/qodo_summary_comment.html +0 -0
  179. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/pr/fixtures/journals/dogfood_40.jsonl +0 -0
  180. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/pr/test_await.py +0 -0
  181. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/pr/test_delta.py +0 -0
  182. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/pr/test_lint.py +0 -0
  183. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/pr/test_lint_rules.py +0 -0
  184. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/pr/test_open.py +0 -0
  185. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/pr/test_qodo.py +0 -0
  186. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/pr/test_read.py +0 -0
  187. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/pr/test_reply.py +0 -0
  188. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/test_doctor.py +0 -0
  189. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/test_explain.py +0 -0
  190. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/test_gamify.py +0 -0
  191. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/test_hook.py +0 -0
  192. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/test_learn.py +0 -0
  193. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/commands/test_overview.py +0 -0
  194. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/core/__init__.py +0 -0
  195. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/core/test_backend.py +0 -0
  196. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/core/test_capabilities.py +0 -0
  197. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/core/test_config.py +0 -0
  198. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/core/test_github.py +0 -0
  199. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/core/test_hook_io.py +0 -0
  200. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/core/test_journal.py +0 -0
  201. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/core/test_paths.py +0 -0
  202. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/core/test_render.py +0 -0
  203. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/core/test_resolve_backend.py +0 -0
  204. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/core/test_skill_loader.py +0 -0
  205. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/fixtures/claude-code/empty/.gitkeep +0 -0
  206. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/fixtures/claude-code/malformed/.claude/hooks.json +0 -0
  207. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/fixtures/claude-code/malformed/.claude/settings.json +0 -0
  208. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/fixtures/claude-code/malformed/.claude/skills/bad/SKILL.md +0 -0
  209. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/fixtures/claude-code/malformed/.claude/skills/broken-yaml/SKILL.md +0 -0
  210. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/fixtures/claude-code/typical/.claude/hooks.json +0 -0
  211. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/fixtures/claude-code/typical/.claude/settings.json +0 -0
  212. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/fixtures/claude-code/typical/.claude/skills/example/SKILL.md +0 -0
  213. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/fixtures/claude-code/typical/CLAUDE.md +0 -0
  214. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/test_cli_errors.py +0 -0
  215. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/test_cli_smoke.py +0 -0
  216. {agex_cli-0.22.0 → agex_cli-0.23.0}/tests/test_skill_md_consistency.py +0 -0
@@ -27,15 +27,20 @@ name: publish
27
27
  # One-time setup on pypi.org / test.pypi.org and in the repo's Environments
28
28
  # (`pypi`, `testpypi`) is documented in the original header below:
29
29
  #
30
- # - PyPI project `agex-cli` → Publishing → Add a GitHub pending publisher
31
- # Owner: OriNachum Repo: agex
30
+ # - For EACH PyPI project (`agex-cli`, `agent-devex`, `devex-cli`)
31
+ # Publishing → Add a GitHub pending publisher
32
+ # Owner: agentculture Repo: devex
32
33
  # Workflow: publish.yml Environment: pypi
33
34
  #
34
- # - TestPyPI project `agex-cli` same shape, Environment: testpypi
35
+ # - Same for EACH TestPyPI project, Environment: testpypi
35
36
  #
36
37
  # - GitHub repo → Settings → Environments → create `pypi` and `testpypi`
37
38
  # (any required reviewers / wait timers live there)
38
39
  #
40
+ # NOTE: the repo was renamed agentculture/agex-cli → agentculture/devex.
41
+ # The pre-existing `agex-cli` / `agent-devex` publishers must have their
42
+ # Repo updated to `devex` too, or those legs start failing OIDC.
43
+ #
39
44
  # The PR job rewrites `version = "X.Y.Z"` to `"X.Y.Z.devN"` where N is
40
45
  # the workflow run number. PEP 440's dev segment is a single integer
41
46
  # (internal dots aren't allowed), so run_attempt is NOT encoded in the
@@ -67,10 +72,11 @@ jobs:
67
72
  # pull_request -- the PR path has its own build inside `publish-pr-testpypi`
68
73
  # because it needs to rewrite the version before building.
69
74
  #
70
- # The matrix exists so we can publish the same code under two PyPI
71
- # distribution names: `agex-cli` (canonical) and `agent-devex` (alias).
72
- # Each leg rewrites `[project].name` in pyproject.toml before building so
73
- # each wheel is uploaded under its own Trusted Publishing project.
75
+ # The matrix exists so we can publish the same code under three PyPI
76
+ # distribution names: `agex-cli` (canonical) plus the `agent-devex` and
77
+ # `devex-cli` aliases. Each leg rewrites `[project].name` in pyproject.toml
78
+ # before building so each wheel is uploaded under its own Trusted Publishing
79
+ # project.
74
80
  # --------------------------------------------------------------------------
75
81
  build:
76
82
  if: github.event_name == 'push'
@@ -78,7 +84,7 @@ jobs:
78
84
  strategy:
79
85
  fail-fast: false
80
86
  matrix:
81
- dist_name: [agex-cli, agent-devex]
87
+ dist_name: [agex-cli, agent-devex, devex-cli]
82
88
  permissions:
83
89
  contents: read # actions/checkout
84
90
  steps:
@@ -93,8 +99,8 @@ jobs:
93
99
 
94
100
  # Rewrite `[project].name` to the matrix dist name. For `agex-cli`
95
101
  # (the canonical dist) the regex still has to match so we re-emit
96
- # the line; for `agent-devex` it produces an alias dist with
97
- # identical contents. The post-rewrite re-parse is a fail-closed
102
+ # the line; for `agent-devex` / `devex-cli` it produces an alias dist
103
+ # with identical contents. The post-rewrite re-parse is a fail-closed
98
104
  # check: if a future formatting change breaks the regex match (or
99
105
  # `[project].name` ends up wrong for any reason), the job aborts
100
106
  # before uploading mis-named artifacts.
@@ -150,7 +156,7 @@ jobs:
150
156
  strategy:
151
157
  fail-fast: false
152
158
  matrix:
153
- dist_name: [agex-cli, agent-devex]
159
+ dist_name: [agex-cli, agent-devex, devex-cli]
154
160
  environment: testpypi
155
161
  permissions:
156
162
  id-token: write # OIDC -- Trusted Publishing
@@ -273,7 +279,7 @@ jobs:
273
279
  strategy:
274
280
  fail-fast: false
275
281
  matrix:
276
- dist_name: [agex-cli, agent-devex]
282
+ dist_name: [agex-cli, agent-devex, devex-cli]
277
283
  environment: testpypi
278
284
  permissions:
279
285
  id-token: write # OIDC; no API token needed
@@ -372,7 +378,7 @@ jobs:
372
378
  strategy:
373
379
  fail-fast: false
374
380
  matrix:
375
- dist_name: [agex-cli, agent-devex]
381
+ dist_name: [agex-cli, agent-devex, devex-cli]
376
382
  environment: pypi
377
383
  permissions:
378
384
  id-token: write # OIDC; no API token needed
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.23.0] - 2026-05-28
11
+
12
+ ### Added
13
+
14
+ - `devex` console command — second entry point alongside `agex`; both invoke the same CLI and emitted output (Next-step footers, briefing/template headers, error prefixes) reflects whichever name was typed, via the new single-source-of-truth `core.prog.prog_name()` injected into the render context.
15
+ - Third PyPI distribution name `devex-cli` — the same wheel now publishes under `agex-cli` (canonical), `agent-devex`, and `devex-cli`; version resolution and the publish matrices cover all three.
16
+
17
+ ### Changed
18
+
19
+ - Repo renamed `agentculture/agex-cli` → `agentculture/devex`; updated in-code issue/repo URLs, README, CLAUDE.md, and the publish workflow OIDC setup notes.
20
+ - SonarCloud project key → `agentculture_devex` (display name `devex`; organization unchanged).
21
+
22
+ ### Fixed
23
+
24
+ - "Output follows invocation" now also covers **plain-string** stdout/stderr in command scripts (`explain`/`learn`/`hook`/`doctor`/`gamify`/`pr delta`/`pr reply` error prefixes, status lines, and command examples), not just Jinja-rendered templates — added `core.prog.error_prefix()` and routed those paths through `prog_name()` (agex-cli#61 Qodo review).
25
+ - `prog_name()` now strips entry-point wrapper suffixes (`.exe`, `.py`, `-script`) before matching, so a real `devex` invocation via the Windows console script `devex.exe` no longer falls back to `agex` (agex-cli#61 Qodo review).
26
+
10
27
  ## [0.22.0] - 2026-05-25
11
28
 
12
29
  ### Added
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
4
4
 
5
5
  ## Project
6
6
 
7
- `agex` — non-agentic Python CLI that emits deterministic per-backend markdown briefings for autonomous agents. PyPI distribution name: `agex-cli`. CLI entry point: `agex`. GitHub repo: `agentculture/agex-cli`. Python module (unchanged): `agent_experience`.
7
+ `agex` — non-agentic Python CLI that emits deterministic per-backend markdown briefings for autonomous agents. Published on PyPI under three distribution names: `agex-cli` (canonical), `agent-devex`, and `devex-cli` — the same wheel each time. CLI entry points: `agex` and `devex` (both invoke the same tool; emitted output reflects whichever name was typed). GitHub repo: `agentculture/devex`. Python module (unchanged): `agent_experience`.
8
8
 
9
9
  **Source-of-truth documents:**
10
10
 
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agex-cli
3
- Version: 0.22.0
3
+ Version: 0.23.0
4
4
  Summary: Agent-operated developer-experience CLI — deterministic per-backend markdown briefings for autonomous agents.
5
5
  Project-URL: Homepage, https://culture.dev/agex/
6
- Project-URL: Repository, https://github.com/agentculture/agex-cli
7
- Project-URL: Issues, https://github.com/agentculture/agex-cli/issues
6
+ Project-URL: Repository, https://github.com/agentculture/devex
7
+ Project-URL: Issues, https://github.com/agentculture/devex/issues
8
8
  Author: Ori Nachum
9
9
  License: MIT
10
10
  License-File: LICENSE
@@ -26,14 +26,14 @@ Description-Content-Type: text/markdown
26
26
 
27
27
  # agex
28
28
 
29
- Agent-operated developer-experience CLI. Non-agentic, deterministic, markdown-first. Distributed on PyPI as `agex-cli`; installs the `agex` command.
29
+ Agent-operated developer-experience CLI. Non-agentic, deterministic, markdown-first. The same wheel is published on PyPI under three distribution names — `agex-cli` (canonical), `agent-devex`, and `devex-cli` — and installs two equivalent commands, `agex` and `devex` (emitted output reflects whichever name you invoke).
30
30
 
31
31
  ## Install
32
32
 
33
33
  ```bash
34
- uv tool install agex-cli
34
+ uv tool install agex-cli # or: devex-cli
35
35
  # or
36
- pipx install agex-cli
36
+ pipx install agex-cli # or: pipx install devex-cli
37
37
  ```
38
38
 
39
39
  ## Quick start
@@ -0,0 +1,29 @@
1
+ # agex
2
+
3
+ Agent-operated developer-experience CLI. Non-agentic, deterministic, markdown-first. The same wheel is published on PyPI under three distribution names — `agex-cli` (canonical), `agent-devex`, and `devex-cli` — and installs two equivalent commands, `agex` and `devex` (emitted output reflects whichever name you invoke).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ uv tool install agex-cli # or: devex-cli
9
+ # or
10
+ pipx install agex-cli # or: pipx install devex-cli
11
+ ```
12
+
13
+ ## Quick start
14
+
15
+ ```bash
16
+ agex explain agex
17
+ agex overview --agent claude-code
18
+ agex learn --agent claude-code
19
+ ```
20
+
21
+ ## Docs
22
+
23
+ [culture.dev/agex](https://culture.dev/agex/).
24
+
25
+ Spec: `docs/superpowers/specs/2026-04-18-agex-design.md`.
26
+
27
+ ## License
28
+
29
+ MIT.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agex-cli"
3
- version = "0.22.0"
3
+ version = "0.23.0"
4
4
  description = "Agent-operated developer-experience CLI — deterministic per-backend markdown briefings for autonomous agents."
5
5
  authors = [{name = "Ori Nachum"}]
6
6
  license = {text = "MIT"}
@@ -27,11 +27,12 @@ dev = [
27
27
 
28
28
  [project.scripts]
29
29
  agex = "agent_experience.cli:_main_entrypoint"
30
+ devex = "agent_experience.cli:_main_entrypoint"
30
31
 
31
32
  [project.urls]
32
33
  Homepage = "https://culture.dev/agex/"
33
- Repository = "https://github.com/agentculture/agex-cli"
34
- Issues = "https://github.com/agentculture/agex-cli/issues"
34
+ Repository = "https://github.com/agentculture/devex"
35
+ Issues = "https://github.com/agentculture/devex/issues"
35
36
 
36
37
  [build-system]
37
38
  requires = ["hatchling"]
@@ -1,8 +1,8 @@
1
- sonar.projectKey=OriNachum_agex
1
+ sonar.projectKey=agentculture_devex
2
2
  sonar.organization=orinachum
3
3
 
4
4
  # Displayed in SonarCloud UI
5
- sonar.projectName=agex
5
+ sonar.projectName=devex
6
6
 
7
7
  # Source layout
8
8
  sonar.sources=src
@@ -2,13 +2,14 @@ from importlib.metadata import PackageNotFoundError, version
2
2
 
3
3
 
4
4
  def _resolve_version() -> str:
5
- # `agex-cli` is the canonical PyPI distribution name; `agent-devex` is an
6
- # alias distribution that ships the identical wheel under a different name.
7
- # Whichever one is installed, surface its metadata version. As a final
8
- # fallback for unbuilt source checkouts (no installed dist metadata),
9
- # read the version directly from the repo's pyproject.toml so the version
10
- # stays single-sourced from pyproject.toml in every reachable code path.
11
- for dist in ("agex-cli", "agent-devex"):
5
+ # `agex-cli` is the canonical PyPI distribution name; `agent-devex` and
6
+ # `devex-cli` are alias distributions that ship the identical wheel under
7
+ # different names. Whichever one is installed, surface its metadata
8
+ # version. As a final fallback for unbuilt source checkouts (no installed
9
+ # dist metadata), read the version directly from the repo's pyproject.toml
10
+ # so the version stays single-sourced from pyproject.toml in every
11
+ # reachable code path.
12
+ for dist in ("agex-cli", "agent-devex", "devex-cli"):
12
13
  try:
13
14
  return version(dist)
14
15
  except PackageNotFoundError:
@@ -28,11 +28,16 @@ from agent_experience.commands.pr.scripts import open_ as pr_open_script
28
28
  from agent_experience.commands.pr.scripts import read as pr_read_script
29
29
  from agent_experience.commands.pr.scripts import reply as pr_reply_script
30
30
  from agent_experience.core.backend import parse_backend
31
+ from agent_experience.core.prog import prog_name
31
32
 
32
- _GH_RERUN_HINT = "agex: rerun once network is reachable (gh failed)"
33
33
  _AGENT_HELP = "Backend: claude-code, codex, copilot, or acp."
34
34
 
35
35
 
36
+ def _gh_rerun_hint() -> str:
37
+ """``<prog>: rerun once network is reachable`` — phrased with the invoked name."""
38
+ return f"{prog_name()}: rerun once network is reachable (gh failed)"
39
+
40
+
36
41
  class _AgexArgumentParser(argparse.ArgumentParser):
37
42
  """ArgumentParser used everywhere via ``parser_class=``.
38
43
 
@@ -71,7 +76,7 @@ def _parse_backend_or_report(agent: Optional[str]):
71
76
  try:
72
77
  return parse_backend(agent), None
73
78
  except ValueError as exc:
74
- print(f"agex: error: {exc}", file=sys.stderr)
79
+ print(f"{prog_name()}: error: {exc}", file=sys.stderr)
75
80
  return None, 2
76
81
 
77
82
 
@@ -156,7 +161,7 @@ def _cmd_pr_lint(args: argparse.Namespace) -> int:
156
161
  agent=args.agent, project_dir=Path.cwd(), exit_on_violation=args.exit_on_violation
157
162
  )
158
163
  except ValueError as exc:
159
- print(f"agex: {exc}", file=sys.stderr)
164
+ print(f"{prog_name()}: {exc}", file=sys.stderr)
160
165
  return 2
161
166
  _emit(stdout, stderr)
162
167
  return exit_code
@@ -173,11 +178,12 @@ def _cmd_pr_open(args: argparse.Namespace) -> int:
173
178
  delayed_read=args.delayed_read,
174
179
  )
175
180
  except ValueError as exc:
176
- print(f"agex: {exc}", file=sys.stderr)
181
+ print(f"{prog_name()}: {exc}", file=sys.stderr)
177
182
  return 2
178
183
  except RuntimeError as exc:
184
+ prog = prog_name()
179
185
  print(str(exc), file=sys.stderr)
180
- print("agex: rerun 'agex pr open ...' once network is reachable", file=sys.stderr)
186
+ print(f"{prog}: rerun '{prog} pr open ...' once network is reachable", file=sys.stderr)
181
187
  return 1
182
188
  _emit(stdout, stderr)
183
189
  return exit_code
@@ -189,11 +195,11 @@ def _cmd_pr_reply(args: argparse.Namespace) -> int:
189
195
  agent=args.agent, project_dir=Path.cwd(), pr=args.pr
190
196
  )
191
197
  except ValueError as exc:
192
- print(f"agex: {exc}", file=sys.stderr)
198
+ print(f"{prog_name()}: {exc}", file=sys.stderr)
193
199
  return 2
194
200
  except RuntimeError as exc:
195
201
  print(str(exc), file=sys.stderr)
196
- print(_GH_RERUN_HINT, file=sys.stderr)
202
+ print(_gh_rerun_hint(), file=sys.stderr)
197
203
  return 1
198
204
  _emit(stdout, stderr, stderr_newline=False)
199
205
  return exit_code
@@ -205,11 +211,11 @@ def _cmd_pr_read(args: argparse.Namespace) -> int:
205
211
  agent=args.agent, project_dir=Path.cwd(), pr=args.pr, wait=args.wait
206
212
  )
207
213
  except ValueError as exc:
208
- print(f"agex: {exc}", file=sys.stderr)
214
+ print(f"{prog_name()}: {exc}", file=sys.stderr)
209
215
  return 2
210
216
  except RuntimeError as exc:
211
217
  print(str(exc), file=sys.stderr)
212
- print(_GH_RERUN_HINT, file=sys.stderr)
218
+ print(_gh_rerun_hint(), file=sys.stderr)
213
219
  return 1
214
220
  _emit(stdout, stderr)
215
221
  return exit_code
@@ -221,11 +227,11 @@ def _cmd_pr_await(args: argparse.Namespace) -> int:
221
227
  agent=args.agent, project_dir=Path.cwd(), pr=args.pr, max_wait=args.max_wait
222
228
  )
223
229
  except ValueError as exc:
224
- print(f"agex: {exc}", file=sys.stderr)
230
+ print(f"{prog_name()}: {exc}", file=sys.stderr)
225
231
  return 2
226
232
  except RuntimeError as exc:
227
233
  print(str(exc), file=sys.stderr)
228
- print(_GH_RERUN_HINT, file=sys.stderr)
234
+ print(_gh_rerun_hint(), file=sys.stderr)
229
235
  return 1
230
236
  _emit(stdout, stderr)
231
237
  return exit_code
@@ -235,11 +241,11 @@ def _cmd_pr_delta(args: argparse.Namespace) -> int:
235
241
  try:
236
242
  stdout, exit_code, stderr = pr_delta_script.run(agent=args.agent, project_dir=Path.cwd())
237
243
  except ValueError as exc:
238
- print(f"agex: {exc}", file=sys.stderr)
244
+ print(f"{prog_name()}: {exc}", file=sys.stderr)
239
245
  return 2
240
246
  except RuntimeError as exc:
241
247
  print(str(exc), file=sys.stderr)
242
- print(_GH_RERUN_HINT, file=sys.stderr)
248
+ print(_gh_rerun_hint(), file=sys.stderr)
243
249
  return 1
244
250
  _emit(stdout, stderr, stderr_newline=False)
245
251
  return exit_code
@@ -270,7 +276,7 @@ def _group_help(parser: argparse.ArgumentParser):
270
276
 
271
277
  def _build_parser() -> argparse.ArgumentParser:
272
278
  parser = _AgexArgumentParser(
273
- prog="agex",
279
+ prog=prog_name(),
274
280
  description="Agent-operated developer-experience CLI.",
275
281
  )
276
282
  parser.add_argument("--version", action="version", version=__version__)
@@ -441,7 +447,9 @@ def _main_entrypoint() -> None:
441
447
  """
442
448
  argv = sys.argv[1:]
443
449
  if argv and not argv[0].startswith("-") and argv[0] not in _KNOWN_COMMANDS:
444
- print(f"agex: error: unknown command '{argv[0]}'", file=sys.stderr)
450
+ print(f"{prog_name()}: error: unknown command '{argv[0]}'", file=sys.stderr)
451
+ # `agex` here is the explain-topic identifier (topics/agex.md), not the
452
+ # invoked command name — the canonical "what is this tool" page.
445
453
  stdout, _, _ = explain_script.run("agex")
446
454
  sys.stdout.write(stdout)
447
455
  sys.exit(2)
@@ -1,7 +1,7 @@
1
1
  {% set icon = {"ok": "✓", "warn": "⚠️", "fail": "✗", "info": "·"} -%}
2
- # agex doctor
2
+ # {{ prog }} doctor
3
3
 
4
- **agex:** `{{ version }}`
4
+ **{{ prog }}:** `{{ version }}`
5
5
  **Project:** `{{ project_dir }}`
6
6
 
7
7
  {% for cat in categories %}
@@ -24,6 +24,7 @@ from agent_experience.core.paths import (
24
24
  config_path,
25
25
  data_dir,
26
26
  )
27
+ from agent_experience.core.prog import error_prefix
27
28
  from agent_experience.core.render import render_string
28
29
  from agent_experience.core.skill_loader import load_skill
29
30
 
@@ -74,8 +75,8 @@ def _check_version() -> CheckResult:
74
75
  _NAME_AGEX_VERSION,
75
76
  "fail",
76
77
  "Could not resolve `agent_experience.__version__`. Reinstall with "
77
- "`uv pip install -e .[dev]`, `pipx install agex-cli`, or "
78
- "`pipx install agent-devex`.",
78
+ "`uv pip install -e .[dev]`, `pipx install agex-cli`, "
79
+ "`pipx install agent-devex`, or `pipx install devex-cli`.",
79
80
  )
80
81
  return CheckResult(_NAME_AGEX_VERSION, "ok", __version__)
81
82
 
@@ -341,24 +342,24 @@ def run(role: str | None = None) -> tuple[str, int, str]:
341
342
  Read-only. Never initializes ``.agex/``.
342
343
  """
343
344
  if role is not None and _ROLE_RE.match(role) is None:
344
- return ("", 2, f"agex: error: invalid role slug '{role}'")
345
+ return ("", 2, error_prefix(f"invalid role slug '{role}'"))
345
346
 
346
347
  role_section: str | None = None
347
348
  if role is not None:
348
349
  trav = _resolve_role(role)
349
350
  if trav is None:
350
- return ("", 2, f"agex: error: unknown role '{role}'")
351
+ return ("", 2, error_prefix(f"unknown role '{role}'"))
351
352
  try:
352
353
  role_text = trav.read_text(encoding="utf-8")
353
354
  except (OSError, UnicodeDecodeError) as exc:
354
- return ("", 1, f"agex: error: could not read role asset for '{role}': {exc}")
355
+ return ("", 1, error_prefix(f"could not read role asset for '{role}': {exc}"))
355
356
  # Role assets are Jinja templates per the addendum spec; v0.1 passes
356
357
  # an empty context but rendering still resolves any `{% raw %}` /
357
358
  # `{{ }}` markup the role file may use, rather than dumping it raw.
358
359
  try:
359
360
  role_section = render_string(role_text, {})
360
361
  except Exception as exc:
361
- return ("", 1, f"agex: error: failed to render role '{role}': {exc}")
362
+ return ("", 1, error_prefix(f"failed to render role '{role}': {exc}"))
362
363
 
363
364
  categories = _build_categories()
364
365
  summary = _summarize(categories)
@@ -369,8 +370,10 @@ def run(role: str | None = None) -> tuple[str, int, str]:
369
370
  return (
370
371
  "",
371
372
  1,
372
- f"agex: error: could not read `doctor/assets/report.md.j2`: {exc}. "
373
- "Reinstall the package.",
373
+ error_prefix(
374
+ f"could not read `doctor/assets/report.md.j2`: {exc}. "
375
+ "Reinstall the package."
376
+ ),
374
377
  )
375
378
  out = render_string(
376
379
  template_text,
@@ -386,6 +389,6 @@ def run(role: str | None = None) -> tuple[str, int, str]:
386
389
  )
387
390
 
388
391
  if summary["fail"] > 0:
389
- stderr = f"agex: error: {summary['fail']} health check(s) failed"
392
+ stderr = error_prefix(f"{summary['fail']} health check(s) failed")
390
393
  return (out, 1, stderr)
391
394
  return (out, 0, "")
@@ -34,4 +34,4 @@ agex overview --agent claude-code # what's in this project?
34
34
 
35
35
  ## Repo
36
36
 
37
- <https://github.com/agentculture/agex-cli>
37
+ <https://github.com/agentculture/devex>
@@ -2,6 +2,7 @@ import re
2
2
  from importlib.resources import files
3
3
  from importlib.resources.abc import Traversable
4
4
 
5
+ from agent_experience.core.prog import error_prefix
5
6
  from agent_experience.core.skill_loader import Skill, load_skill
6
7
 
7
8
  _TOPIC_RE = re.compile(r"^[a-z][a-z0-9-]*$")
@@ -54,7 +55,7 @@ def run(topic: str) -> tuple[str, int, str]:
54
55
  if resolved is None:
55
56
  agex_page = _commands_root().joinpath("explain", "assets", "topics", "agex.md")
56
57
  body = agex_page.read_text(encoding="utf-8") if agex_page.is_file() else ""
57
- return (body, 2, f"agex: error: unknown topic '{topic}'")
58
+ return (body, 2, error_prefix(f"unknown topic '{topic}'"))
58
59
 
59
60
  kind, trav = resolved
60
61
  if kind == "concept":
@@ -8,6 +8,7 @@ from agent_experience.core.backend import Backend
8
8
  from agent_experience.core.config import load as load_config
9
9
  from agent_experience.core.config import save as save_config
10
10
  from agent_experience.core.paths import ensure_init
11
+ from agent_experience.core.prog import error_prefix, prog_name
11
12
 
12
13
 
13
14
  def _fragments_file() -> Traversable:
@@ -110,7 +111,7 @@ def install(backend: Backend) -> tuple[str, int, str]:
110
111
  try:
111
112
  hooks = _load_hooks_file(hooks_file)
112
113
  except ValueError as e:
113
- return ("", 2, f"agex: error: {e}")
114
+ return ("", 2, error_prefix(str(e)))
114
115
 
115
116
  written_ids, added_count = _merge_fragments(hooks, fragments)
116
117
  if added_count:
@@ -142,7 +143,8 @@ def install(backend: Backend) -> tuple[str, int, str]:
142
143
  status_line,
143
144
  "- Fragment IDs: " + ", ".join(f"`{i}`" for i in written_ids),
144
145
  "",
145
- f"Next: run `agex learn gamify --agent {backend.value}` to set up the levelup skill.",
146
+ f"Next: run `{prog_name()} learn gamify --agent {backend.value}`"
147
+ " to set up the levelup skill.",
146
148
  "",
147
149
  ]
148
150
  return ("\n".join(lines), 0, "")
@@ -176,7 +178,7 @@ def uninstall(backend: Backend) -> tuple[str, int, str]:
176
178
  try:
177
179
  hooks = _load_hooks_file(hooks_file)
178
180
  except ValueError as e:
179
- return ("", 2, f"agex: error: {e}")
181
+ return ("", 2, error_prefix(str(e)))
180
182
 
181
183
  removed_count = _remove_ids_from_hooks(hooks, ids_to_remove)
182
184
  if removed_count:
@@ -196,6 +198,6 @@ def _unsupported_notice(backend: Backend) -> str:
196
198
  return (
197
199
  f"## `gamify` is not supported on {backend.value}\n\n"
198
200
  f"Hooks are required to track usage events, and {backend.value} does not expose "
199
- f"a hook interface agex can write to.\n\n"
200
- "Want this supported? Open an issue: <https://github.com/agentculture/agex-cli/issues>\n"
201
+ f"a hook interface {prog_name()} can write to.\n\n"
202
+ "Want this supported? Open an issue: <https://github.com/agentculture/devex/issues>\n"
201
203
  )
@@ -2,6 +2,7 @@ from datetime import datetime, timezone
2
2
 
3
3
  from agent_experience.core.hook_io import append_event
4
4
  from agent_experience.core.paths import ensure_init
5
+ from agent_experience.core.prog import error_prefix
5
6
 
6
7
 
7
8
  def run(event: str, args: list[str]) -> tuple[str, int, str]:
@@ -20,5 +21,5 @@ def run(event: str, args: list[str]) -> tuple[str, int, str]:
20
21
  except ValueError as e:
21
22
  # append_event → _stream_path rejects names that don't match the
22
23
  # `^[a-z][a-z0-9-]*$` slug whitelist (path-traversal guard).
23
- return ("", 2, f"agex: error: {e}")
24
+ return ("", 2, error_prefix(str(e)))
24
25
  return ("", 0, "")
@@ -1,6 +1,6 @@
1
1
  # Lessons — {{ backend }}
2
2
 
3
- Run `agex learn <topic> --agent {{ backend }}` to learn one.
3
+ Run `{{ prog }} learn <topic> --agent {{ backend }}` to learn one.
4
4
 
5
5
  {% for topic in topics -%}
6
6
  - **`{{ topic.name }}`** — {{ topic.description }}{% if topic.unsupported %} _(unsupported on {{ backend }}: {{ topic.unsupported }})_{% endif %}
@@ -3,6 +3,7 @@ from importlib.resources import as_file, files
3
3
  from importlib.resources.abc import Traversable
4
4
 
5
5
  from agent_experience.core.backend import Backend
6
+ from agent_experience.core.prog import error_prefix
6
7
  from agent_experience.core.render import render_string
7
8
  from agent_experience.core.skill_loader import Skill, load_skill
8
9
 
@@ -54,13 +55,13 @@ def run_topic(topic: str, backend: Backend) -> tuple[str, int, str]:
54
55
  """Return (stdout, exit_code, stderr) for a specific lesson topic."""
55
56
  if not _TOPIC_RE.match(topic):
56
57
  menu_out, _, _ = run_menu(backend)
57
- return (menu_out, 2, f"agex: error: unknown topic '{topic}'")
58
+ return (menu_out, 2, error_prefix(f"unknown topic '{topic}'"))
58
59
 
59
60
  topic_dir = _learn_assets().joinpath("topics", topic)
60
61
  skill_md = topic_dir.joinpath(_SKILL_FILENAME)
61
62
  if not skill_md.is_file():
62
63
  menu_out, _, _ = run_menu(backend)
63
- return (menu_out, 2, f"agex: error: unknown topic '{topic}'")
64
+ return (menu_out, 2, error_prefix(f"unknown topic '{topic}'"))
64
65
 
65
66
  skill = _load_skill_from_traversable(skill_md)
66
67
  template_path = topic_dir.joinpath("assets", "skill-template", backend.value, _SKILL_FILENAME)
@@ -0,0 +1,20 @@
1
+ hints:
2
+ lint_clean: "Commit, push, then `{{ prog }} pr open --title \"...\"`."
3
+ lint_clean_with_alignment: "Run `{{ prog }} pr delta` (this PR touches alignment files), then commit, push, and `{{ prog }} pr open --title \"...\"`."
4
+ lint_violations: "Fix the {{ violation_count }} violation(s) above and rerun `{{ prog }} pr lint`."
5
+ open_recommend_read: "`{{ prog }} pr read {{ pr }} --wait 180` (recommended) or `{{ prog }} pr read {{ pr }}` in ~3 min."
6
+ open_already_exists: "PR already open as #{{ pr }} — `{{ prog }} pr read {{ pr }} --wait 180` to fetch the briefing."
7
+ read_unresolved_after_commits: "Push fixes, then `{{ prog }} pr read {{ pr }} --wait 180`."
8
+ read_unresolved_no_commits: "Triage and prepare `replies.jsonl`, then `{{ prog }} pr reply {{ pr }} < replies.jsonl`."
9
+ read_ci_red: "Fix CI before requesting re-review (see failing checks above)."
10
+ read_clean: "Wait for human merge."
11
+ read_wait_timeout: "Still waiting on: {{ reviewers }}. Rerun `{{ prog }} pr read {{ pr }} --wait 180` to continue."
12
+ reply_with_failures: "Resubmit the failed lines (see table above) to `{{ prog }} pr reply {{ pr }}`."
13
+ reply_clean: "Push fixes (if any), then `{{ prog }} pr read {{ pr }} --wait 180`."
14
+ delta_done: "Triage each sibling — open follow-up PRs where alignment drifted; mention them in your reply."
15
+ await_clean: "PR #{{ pr }} is ready — wait for human merge."
16
+ await_gate_error: "SonarCloud quality gate is ERROR — fix the new issues above, push, then `{{ prog }} pr await {{ pr }}` again."
17
+ await_gate_unknown: "SonarCloud quality gate is UNKNOWN — analysis is pending or the project isn't analyzed yet; wait and re-run `{{ prog }} pr await {{ pr }}`."
18
+ await_unresolved_threads: "Triage and prepare `replies.jsonl`, then `{{ prog }} pr reply {{ pr }} < replies.jsonl`."
19
+ await_ci_red: "Fix CI before requesting re-review (see failing checks above)."
20
+ await_wait_timeout: "Still waiting on: {{ reviewers }}. Rerun `{{ prog }} pr await {{ pr }}` to keep waiting."
@@ -0,0 +1,20 @@
1
+ hints:
2
+ lint_clean: "Commit, push, then `{{ prog }} pr open --title \"...\"`."
3
+ lint_clean_with_alignment: "Run `{{ prog }} pr delta` (this PR touches alignment files), then commit, push, and `{{ prog }} pr open --title \"...\"`."
4
+ lint_violations: "Fix the {{ violation_count }} violation(s) above and rerun `{{ prog }} pr lint`."
5
+ open_recommend_read: "`{{ prog }} pr read {{ pr }} --wait 180` (recommended) or `{{ prog }} pr read {{ pr }}` in ~3 min."
6
+ open_already_exists: "PR already open as #{{ pr }} — `{{ prog }} pr read {{ pr }} --wait 180` to fetch the briefing."
7
+ read_unresolved_after_commits: "Push fixes, then `{{ prog }} pr read {{ pr }} --wait 180`."
8
+ read_unresolved_no_commits: "Triage and prepare `replies.jsonl`, then `{{ prog }} pr reply {{ pr }} < replies.jsonl`."
9
+ read_ci_red: "Fix CI before requesting re-review (see failing checks above)."
10
+ read_clean: "Wait for human merge."
11
+ read_wait_timeout: "Still waiting on: {{ reviewers }}. Rerun `{{ prog }} pr read {{ pr }} --wait 180` to continue."
12
+ reply_with_failures: "Resubmit the failed lines (see table above) to `{{ prog }} pr reply {{ pr }}`."
13
+ reply_clean: "Push fixes (if any), then `{{ prog }} pr read {{ pr }} --wait 180`."
14
+ delta_done: "Triage each sibling — open follow-up PRs where alignment drifted; mention them in your reply."
15
+ await_clean: "PR #{{ pr }} is ready — wait for human merge."
16
+ await_gate_error: "SonarCloud quality gate is ERROR — fix the new issues above, push, then `{{ prog }} pr await {{ pr }}` again."
17
+ await_gate_unknown: "SonarCloud quality gate is UNKNOWN — analysis is pending or the project isn't analyzed yet; wait and re-run `{{ prog }} pr await {{ pr }}`."
18
+ await_unresolved_threads: "Triage and prepare `replies.jsonl`, then `{{ prog }} pr reply {{ pr }} < replies.jsonl`."
19
+ await_ci_red: "Fix CI before requesting re-review (see failing checks above)."
20
+ await_wait_timeout: "Still waiting on: {{ reviewers }}. Rerun `{{ prog }} pr await {{ pr }}` to keep waiting."
@@ -0,0 +1,20 @@
1
+ hints:
2
+ lint_clean: "Commit, push, then `{{ prog }} pr open --title \"...\"`."
3
+ lint_clean_with_alignment: "Run `{{ prog }} pr delta` (this PR touches alignment files), then commit, push, and `{{ prog }} pr open --title \"...\"`."
4
+ lint_violations: "Fix the {{ violation_count }} violation(s) above and rerun `{{ prog }} pr lint`."
5
+ open_recommend_read: "`{{ prog }} pr read {{ pr }} --wait 180` (recommended) or `{{ prog }} pr read {{ pr }}` in ~3 min."
6
+ open_already_exists: "PR already open as #{{ pr }} — `{{ prog }} pr read {{ pr }} --wait 180` to fetch the briefing."
7
+ read_unresolved_after_commits: "Push fixes, then `{{ prog }} pr read {{ pr }} --wait 180`."
8
+ read_unresolved_no_commits: "Triage and prepare `replies.jsonl`, then `{{ prog }} pr reply {{ pr }} < replies.jsonl`."
9
+ read_ci_red: "Fix CI before requesting re-review (see failing checks above)."
10
+ read_clean: "Wait for human merge."
11
+ read_wait_timeout: "Still waiting on: {{ reviewers }}. Rerun `{{ prog }} pr read {{ pr }} --wait 180` to continue."
12
+ reply_with_failures: "Resubmit the failed lines (see table above) to `{{ prog }} pr reply {{ pr }}`."
13
+ reply_clean: "Push fixes (if any), then `{{ prog }} pr read {{ pr }} --wait 180`."
14
+ delta_done: "Triage each sibling — open follow-up PRs where alignment drifted; mention them in your reply."
15
+ await_clean: "PR #{{ pr }} is ready — wait for human merge."
16
+ await_gate_error: "SonarCloud quality gate is ERROR — fix the new issues above, push, then `{{ prog }} pr await {{ pr }}` again."
17
+ await_gate_unknown: "SonarCloud quality gate is UNKNOWN — analysis is pending or the project isn't analyzed yet; wait and re-run `{{ prog }} pr await {{ pr }}`."
18
+ await_unresolved_threads: "Triage and prepare `replies.jsonl`, then `{{ prog }} pr reply {{ pr }} < replies.jsonl`."
19
+ await_ci_red: "Fix CI before requesting re-review (see failing checks above)."
20
+ await_wait_timeout: "Still waiting on: {{ reviewers }}. Rerun `{{ prog }} pr await {{ pr }}` to keep waiting."