gitwise-cli 0.31.0__tar.gz → 0.33.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 (189) hide show
  1. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/CHANGELOG.md +16 -0
  2. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/PKG-INFO +15 -2
  3. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/README.md +14 -1
  4. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/__init__.py +1 -1
  5. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/_cli_completions.py +76 -1
  6. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/_cli_dispatch.py +122 -79
  7. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/_cli_parser.py +33 -8
  8. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/_cli_setup_agents.py +4 -0
  9. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/_i18n_data.json +28 -0
  10. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/audit.py +9 -8
  11. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/branches.py +7 -7
  12. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/clean.py +15 -11
  13. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/commit.py +13 -11
  14. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/conflicts.py +91 -12
  15. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/context.py +25 -15
  16. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/diff.py +79 -31
  17. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/doctor.py +12 -10
  18. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/health.py +7 -7
  19. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/log.py +117 -81
  20. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/merge.py +14 -13
  21. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/optimize.py +14 -11
  22. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/output.py +8 -0
  23. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/pick.py +10 -10
  24. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/pr.py +13 -12
  25. gitwise_cli-0.33.0/gitwise/schema.py +110 -0
  26. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup.py +17 -13
  27. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/format.py +8 -0
  28. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/show.py +7 -7
  29. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/snapshot.py +6 -6
  30. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/stash.py +15 -13
  31. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/status.py +83 -35
  32. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/suggest.py +17 -8
  33. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/summarize.py +9 -9
  34. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/sync.py +14 -9
  35. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/tag.py +45 -18
  36. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/undo.py +7 -6
  37. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/update.py +13 -13
  38. gitwise_cli-0.33.0/gitwise/utils/json_envelope.py +76 -0
  39. gitwise_cli-0.33.0/gitwise/utils/types.py +80 -0
  40. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/worktree.py +41 -9
  41. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/pyproject.toml +1 -1
  42. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/completions.json +2 -1
  43. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/conflicts.json +5 -0
  44. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/diff.json +5 -0
  45. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/log.json +5 -0
  46. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/schema.json +5 -0
  47. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/worktree.json +2 -1
  48. gitwise_cli-0.33.0/share/schemas/v1/output/diff.json +79 -0
  49. gitwise_cli-0.33.0/share/schemas/v1/output/log.json +57 -0
  50. gitwise_cli-0.33.0/share/schemas/v1/output/setup-agents.json +49 -0
  51. gitwise_cli-0.33.0/share/schemas/v1/output/status.json +103 -0
  52. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_audit.py +15 -14
  53. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_branches.py +2 -2
  54. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_clean.py +9 -9
  55. gitwise_cli-0.33.0/tests/test_conflicts.py +86 -0
  56. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_context.py +7 -6
  57. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_diff.py +43 -10
  58. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_doctor.py +12 -8
  59. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_edge_cases.py +10 -7
  60. gitwise_cli-0.33.0/tests/test_envelope_contract.py +69 -0
  61. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_git.py +6 -6
  62. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_health.py +5 -5
  63. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_i18n.py +1 -1
  64. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_in_progress.py +4 -4
  65. gitwise_cli-0.33.0/tests/test_json_envelope_utils.py +76 -0
  66. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_log.py +65 -9
  67. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_main.py +58 -22
  68. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_merge.py +4 -4
  69. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_optimize.py +10 -8
  70. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_output.py +3 -3
  71. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_pick.py +4 -4
  72. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_pr.py +7 -7
  73. gitwise_cli-0.33.0/tests/test_schema_catalog.py +99 -0
  74. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_setup.py +13 -11
  75. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_stash.py +3 -3
  76. gitwise_cli-0.33.0/tests/test_status.py +116 -0
  77. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_suggest.py +4 -4
  78. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_summarize.py +11 -9
  79. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_sync.py +2 -2
  80. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_tag.py +12 -12
  81. gitwise_cli-0.33.0/tests/test_types.py +59 -0
  82. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_worktree.py +28 -3
  83. gitwise_cli-0.31.0/gitwise/schema.py +0 -54
  84. gitwise_cli-0.31.0/gitwise/utils/json_envelope.py +0 -75
  85. gitwise_cli-0.31.0/tests/test_conflicts.py +0 -45
  86. gitwise_cli-0.31.0/tests/test_json_envelope_utils.py +0 -36
  87. gitwise_cli-0.31.0/tests/test_schema_catalog.py +0 -45
  88. gitwise_cli-0.31.0/tests/test_status.py +0 -52
  89. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/.gitignore +0 -0
  90. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/LICENSE +0 -0
  91. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/bin/gitwise +0 -0
  92. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/__main__.py +0 -0
  93. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/_cli_introspection.py +0 -0
  94. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/_paths.py +0 -0
  95. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/_runtime_config.py +0 -0
  96. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/design.py +0 -0
  97. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/git.py +0 -0
  98. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/i18n.py +0 -0
  99. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/py.typed +0 -0
  100. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/__init__.py +0 -0
  101. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/adapters/__init__.py +0 -0
  102. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/adapters/aider.py +0 -0
  103. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/adapters/base.py +0 -0
  104. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/adapters/codex.py +0 -0
  105. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/adapters/continue_adapter.py +0 -0
  106. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/adapters/cursor.py +0 -0
  107. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/adapters/opencode.py +0 -0
  108. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/adapters/pi.py +0 -0
  109. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/exec.py +0 -0
  110. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/plan.py +0 -0
  111. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/plan_gitfiles.py +0 -0
  112. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/plan_skills.py +0 -0
  113. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/providers/__init__.py +0 -0
  114. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/providers/aider.py +0 -0
  115. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/providers/base.py +0 -0
  116. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/providers/claude.py +0 -0
  117. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/providers/codex.py +0 -0
  118. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/providers/continue_adapter.py +0 -0
  119. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/providers/cursor.py +0 -0
  120. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/providers/opencode.py +0 -0
  121. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/providers/pi.py +0 -0
  122. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/state.py +0 -0
  123. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/setup_agents/types.py +0 -0
  124. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/utils/__init__.py +0 -0
  125. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/utils/git_output.py +0 -0
  126. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/utils/in_progress.py +0 -0
  127. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/utils/parsing.py +0 -0
  128. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/gitwise/utils/secret_scan.py +0 -0
  129. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/install.sh +0 -0
  130. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/agents/skills/git-audit/SKILL.md +0 -0
  131. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/agents/skills/git-clean/SKILL.md +0 -0
  132. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/agents/skills/git-optimize/SKILL.md +0 -0
  133. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/aider/CONVENTIONS.md.template +0 -0
  134. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/aider/aider.conf.yml.template +0 -0
  135. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/claude/CLAUDE.md.template +0 -0
  136. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/claude/rules/gitwise.md +0 -0
  137. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/claude/settings.json.template +0 -0
  138. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/claude/skills/git-audit/SKILL.md +0 -0
  139. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/claude/skills/git-clean/SKILL.md +0 -0
  140. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/claude/skills/git-optimize/SKILL.md +0 -0
  141. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/codex/agents/gitwise.toml.template +0 -0
  142. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/continue/rules/gitwise.md.template +0 -0
  143. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/cursor/rules/gitwise.mdc.template +0 -0
  144. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/git-config-modern.txt +0 -0
  145. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/hooks/commit-msg +0 -0
  146. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/hooks/pre-commit +0 -0
  147. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/opencode/agents/gitwise.md.template +0 -0
  148. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/pi/skills/gitwise.md.template +0 -0
  149. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/audit.json +0 -0
  150. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/branches.json +0 -0
  151. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/clean.json +0 -0
  152. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/commands.json +0 -0
  153. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/commit.json +0 -0
  154. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/context.json +0 -0
  155. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/doctor.json +0 -0
  156. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/health.json +0 -0
  157. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/merge.json +0 -0
  158. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/optimize.json +0 -0
  159. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/pick.json +0 -0
  160. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/pr.json +0 -0
  161. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/setup-agents.json +0 -0
  162. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/setup.json +0 -0
  163. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/show.json +0 -0
  164. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/snapshot.json +0 -0
  165. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/stash.json +0 -0
  166. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/status.json +0 -0
  167. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/suggest.json +0 -0
  168. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/summarize.json +0 -0
  169. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/sync.json +0 -0
  170. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/tag.json +0 -0
  171. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/undo.json +0 -0
  172. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/share/schemas/v1/input/update.json +0 -0
  173. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/__init__.py +0 -0
  174. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/conftest.py +0 -0
  175. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_adapters.py +0 -0
  176. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_commit.py +0 -0
  177. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_design.py +0 -0
  178. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_git_output_utils.py +0 -0
  179. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_md_links_script.py +0 -0
  180. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_parsing_utils.py +0 -0
  181. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_roadmap_baseline_script.py +0 -0
  182. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_sa_plan.py +0 -0
  183. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_sa_unit.py +0 -0
  184. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_secret_scan.py +0 -0
  185. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_setup_agents.py +0 -0
  186. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_show.py +0 -0
  187. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_snapshot.py +0 -0
  188. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_sync_changelog_es_script.py +0 -0
  189. {gitwise_cli-0.31.0 → gitwise_cli-0.33.0}/tests/test_undo.py +0 -0
@@ -3,6 +3,22 @@
3
3
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
4
4
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5
5
 
6
+ ## v0.33.0 (2026-06-20)
7
+
8
+ ### Feat
9
+
10
+ - Sprint 4 DX polish -- worktree list, conflicts --union, powershell, ndjson (#71)
11
+
12
+ ## v0.32.0 (2026-06-20)
13
+
14
+ ### BREAKING CHANGE
15
+
16
+ - all --json command outputs now nest fields under data with the v3 envelope {v,ok,command,data,hints,errors}; status.files are FileEntry objects with a new data.conflicted bucket (UU/AA/DD no longer counted in staged/unstaged); log.parents and log.stats are arrays (was space-joined string and raw --stat blob); doctor/audit override top-level ok to reflect computed health. Consumers parsing the old flat v2 shape must read command-specific fields from data.
17
+
18
+ ### Feat
19
+
20
+ - v3 JSON envelope -- nested data, FileEntry, output schemas (Sprint 3) (#70)
21
+
6
22
  ## v0.31.0 (2026-06-19)
7
23
 
8
24
  ### Feat
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitwise-cli
3
- Version: 0.31.0
3
+ Version: 0.33.0
4
4
  Summary: Python CLI for optimizing git workflows and Claude Code integration
5
5
  Project-URL: Homepage, https://github.com/drzioner/gitwise
6
6
  Project-URL: Repository, https://github.com/drzioner/gitwise
@@ -135,7 +135,7 @@ gitwise summarize
135
135
  | `gitwise status` | Enhanced status with staged/unstaged and ahead/behind |
136
136
  | `gitwise commands --json` | List subcommands with aliases and metadata |
137
137
  | `gitwise schema <command> --json` | Return versioned JSON Schema for command inputs |
138
- | `gitwise completions <shell>` | Generate shell completion scripts (bash/zsh/fish) |
138
+ | `gitwise completions <shell>` | Generate shell completion scripts (bash/zsh/fish/powershell) |
139
139
  | `gitwise pr` | List/check/view PRs via GitHub CLI |
140
140
 
141
141
  For all commands, examples, aliases, and JSON usage, see:
@@ -188,6 +188,19 @@ gitwise completions zsh > ~/.zsh/completions/_gitwise
188
188
  gitwise completions fish > ~/.config/fish/completions/gitwise.fish
189
189
  ```
190
190
 
191
+ **PowerShell** (Windows / PowerShell Core): generate and dot-source the
192
+ `Register-ArgumentCompleter` script. Add it to your `$PROFILE` for persistence:
193
+
194
+ ```powershell
195
+ gitwise completions powershell > gitwise.ps1
196
+ . .\gitwise.ps1
197
+ # or, to load on every session:
198
+ Add-Content $PROFILE ('. ' + ((Resolve-Path 'gitwise.ps1').Path))
199
+ ```
200
+
201
+ Completion covers subcommands as the first token and per-command flags
202
+ (`--json`, `--dry-run`, `--max-count`, etc.) thereafter.
203
+
191
204
  ## Demo
192
205
 
193
206
  [![asciicast](https://asciinema.org/a/6tm4TnYMygEQT7ef.svg)](https://asciinema.org/a/6tm4TnYMygEQT7ef)
@@ -102,7 +102,7 @@ gitwise summarize
102
102
  | `gitwise status` | Enhanced status with staged/unstaged and ahead/behind |
103
103
  | `gitwise commands --json` | List subcommands with aliases and metadata |
104
104
  | `gitwise schema <command> --json` | Return versioned JSON Schema for command inputs |
105
- | `gitwise completions <shell>` | Generate shell completion scripts (bash/zsh/fish) |
105
+ | `gitwise completions <shell>` | Generate shell completion scripts (bash/zsh/fish/powershell) |
106
106
  | `gitwise pr` | List/check/view PRs via GitHub CLI |
107
107
 
108
108
  For all commands, examples, aliases, and JSON usage, see:
@@ -155,6 +155,19 @@ gitwise completions zsh > ~/.zsh/completions/_gitwise
155
155
  gitwise completions fish > ~/.config/fish/completions/gitwise.fish
156
156
  ```
157
157
 
158
+ **PowerShell** (Windows / PowerShell Core): generate and dot-source the
159
+ `Register-ArgumentCompleter` script. Add it to your `$PROFILE` for persistence:
160
+
161
+ ```powershell
162
+ gitwise completions powershell > gitwise.ps1
163
+ . .\gitwise.ps1
164
+ # or, to load on every session:
165
+ Add-Content $PROFILE ('. ' + ((Resolve-Path 'gitwise.ps1').Path))
166
+ ```
167
+
168
+ Completion covers subcommands as the first token and per-command flags
169
+ (`--json`, `--dry-run`, `--max-count`, etc.) thereafter.
170
+
158
171
  ## Demo
159
172
 
160
173
  [![asciicast](https://asciinema.org/a/6tm4TnYMygEQT7ef.svg)](https://asciinema.org/a/6tm4TnYMygEQT7ef)
@@ -1,6 +1,6 @@
1
1
  """gitwise -- CLI for optimizing git workflows and coding-agent integration."""
2
2
 
3
- __version__ = "0.31.0"
3
+ __version__ = "0.33.0"
4
4
 
5
5
 
6
6
  def get_version() -> str:
@@ -1,4 +1,4 @@
1
- """Shell completions generation: bash, zsh, fish."""
1
+ """Shell completions generation: bash, zsh, fish, powershell."""
2
2
 
3
3
  import argparse
4
4
 
@@ -20,6 +20,9 @@ def build_completions_script(*, shell: str, prog: str) -> str:
20
20
  if shell == "fish":
21
21
  return _build_fish_completions_script(parser=parser, prog=prog)
22
22
 
23
+ if shell == "powershell":
24
+ return _build_powershell_completions_script(parser=parser, prog=prog)
25
+
23
26
  raise ValueError(f"unsupported shell: {shell}")
24
27
 
25
28
 
@@ -90,3 +93,75 @@ def _build_fish_completions_script(*, parser: argparse.ArgumentParser, prog: str
90
93
  lines.append(line)
91
94
 
92
95
  return "\n".join(lines) + "\n"
96
+
97
+
98
+ def _collect_flags(action: argparse.Action) -> list[str]:
99
+ """Return the long/short option strings for an argparse action."""
100
+ return [flag for flag in action.option_strings if flag.startswith("-")]
101
+
102
+
103
+ def _build_powershell_completions_script(*, parser: argparse.ArgumentParser, prog: str) -> str:
104
+ """Generate a PowerShell ``Register-ArgumentCompleter`` script from the parser tree.
105
+
106
+ Completes subcommands as the first token and per-command flags thereafter.
107
+ Hand-built because ``shtab`` has no PowerShell backend.
108
+ """
109
+ sub_action = _subparsers_action(parser)
110
+ command_names = sorted(sub_action.choices.keys()) if sub_action else []
111
+
112
+ per_command_flags: dict[str, list[str]] = {}
113
+ global_flags: list[str] = []
114
+ for action in parser._actions:
115
+ if action.dest == "help" or isinstance(action, argparse._SubParsersAction):
116
+ continue
117
+ global_flags.extend(_collect_flags(action))
118
+
119
+ if sub_action is not None:
120
+ for command, command_parser in sorted(sub_action.choices.items()):
121
+ flags: list[str] = []
122
+ for action in command_parser._actions:
123
+ if action.dest == "help" or isinstance(action, argparse._SubParsersAction):
124
+ continue
125
+ flags.extend(_collect_flags(action))
126
+ per_command_flags[command] = sorted(set(flags))
127
+
128
+ commands_ps = ",".join(f"'{c}'" for c in command_names)
129
+ global_flags_ps = ",".join(f"'{f}'" for f in sorted(set(global_flags)))
130
+ per_command_block = "\n".join(
131
+ " '{}' = @({})".format(cmd, ", ".join(f'"{f}"' for f in flags))
132
+ for cmd, flags in per_command_flags.items()
133
+ )
134
+
135
+ return f"""# PowerShell completion for {prog}
136
+ # Source it from your PowerShell profile:
137
+ # Add-Content $PROFILE ('. ' + ((Resolve-Path 'path/to/{prog}.ps1').Path))
138
+ # or dot-source: . ./{prog}.ps1
139
+ Register-ArgumentCompleter -Native -CommandName '{prog}' -ScriptBlock {{
140
+ param($wordToComplete, $commandAst, $cursorPosition)
141
+
142
+ $commands = @({commands_ps})
143
+ $globalFlags = @({global_flags_ps})
144
+ $perCommandFlags = @{{
145
+ {per_command_block}
146
+ }}
147
+
148
+ # Only tokens fully before the cursor are "completed"; the word at the
149
+ # cursor is being typed and must not be mistaken for the subcommand.
150
+ $priorTokens = @($commandAst.CommandElements | Select-Object -Skip 1 | Where-Object {{ $_.Extent.EndOffset -lt $cursorPosition }})
151
+ $subcommand = ($priorTokens | Where-Object {{ $_.Value -notlike '-*' }} | Select-Object -First 1).Value
152
+
153
+ if (-not $subcommand) {{
154
+ $candidates = $commands + $globalFlags
155
+ }}
156
+ elseif ($perCommandFlags.ContainsKey($subcommand)) {{
157
+ $candidates = $perCommandFlags[$subcommand] + $globalFlags
158
+ }}
159
+ else {{
160
+ $candidates = @()
161
+ }}
162
+
163
+ $candidates | Where-Object {{ $_ -like "$wordToComplete*" }} |
164
+ Sort-Object -Unique |
165
+ ForEach-Object {{ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) }}
166
+ }}
167
+ """
@@ -4,29 +4,29 @@ import argparse
4
4
  import sys
5
5
  from collections.abc import Callable
6
6
 
7
- from . import __version__
8
- from ._cli_completions import build_completions_script
9
- from ._cli_introspection import (
7
+ from gitwise import __version__
8
+ from gitwise._cli_completions import build_completions_script
9
+ from gitwise._cli_introspection import (
10
10
  canonical_command_name,
11
11
  commands_metadata,
12
12
  resolve_command_parser,
13
13
  )
14
- from ._cli_parser import build_parser
15
- from .i18n import t
16
- from .output import print_json
17
- from .utils.json_envelope import error_envelope
14
+ from gitwise._cli_parser import build_parser
15
+ from gitwise.i18n import t
16
+ from gitwise.output import print_json
17
+ from gitwise.utils.json_envelope import error_envelope, ok_envelope
18
18
 
19
19
 
20
20
  def _run_update(args: argparse.Namespace) -> int:
21
21
  """Dispatch to ``update`` subcommand."""
22
- from .update import run_update
22
+ from gitwise.update import run_update
23
23
 
24
24
  return run_update(dry_run=args.dry_run, as_json=args.json)
25
25
 
26
26
 
27
27
  def _run_doctor(args: argparse.Namespace) -> int:
28
28
  """Dispatch to ``doctor`` subcommand."""
29
- from .doctor import run_doctor
29
+ from gitwise.doctor import run_doctor
30
30
 
31
31
  return run_doctor(as_json=args.json)
32
32
 
@@ -34,14 +34,25 @@ def _run_doctor(args: argparse.Namespace) -> int:
34
34
  def _run_setup_agents(args: argparse.Namespace) -> int:
35
35
  """Dispatch to ``setup-agents`` subcommand, handling provider listing."""
36
36
  if getattr(args, "list_providers", False) or getattr(args, "list_adapters", False):
37
- from .i18n import t as _t
38
- from .setup_agents.providers import list_providers
37
+ from gitwise.i18n import t as _t
38
+ from gitwise.setup_agents.providers import list_providers
39
39
 
40
40
  adapter_list = list_providers()
41
41
  if args.json:
42
- print_json({"providers": adapter_list, "adapters": adapter_list})
42
+ print_json(
43
+ {
44
+ "v": 3,
45
+ "v_compat": [1, 2, 3],
46
+ "command": "setup-agents",
47
+ "hints": [],
48
+ "errors": [],
49
+ "ok": True,
50
+ "providers": adapter_list,
51
+ "adapters": adapter_list,
52
+ }
53
+ )
43
54
  else:
44
- from .output import info
55
+ from gitwise.output import info
45
56
 
46
57
  info(_t("providers_available", list=", ".join(adapter_list)))
47
58
  return 0
@@ -52,7 +63,7 @@ def _run_setup_agents(args: argparse.Namespace) -> int:
52
63
  adapters_legacy_used = True
53
64
  providers = args.adapters if providers is None else providers + args.adapters
54
65
 
55
- from ._cli_setup_agents import run_setup_agents
66
+ from gitwise._cli_setup_agents import run_setup_agents
56
67
 
57
68
  return run_setup_agents(
58
69
  local=args.local,
@@ -73,7 +84,7 @@ def _run_setup_agents(args: argparse.Namespace) -> int:
73
84
 
74
85
  def _run_setup(args: argparse.Namespace) -> int:
75
86
  """Dispatch to ``setup`` subcommand."""
76
- from .setup import run_setup
87
+ from gitwise.setup import run_setup
77
88
 
78
89
  return run_setup(
79
90
  dry_run=args.dry_run,
@@ -85,28 +96,28 @@ def _run_setup(args: argparse.Namespace) -> int:
85
96
 
86
97
  def _run_audit(args: argparse.Namespace) -> int:
87
98
  """Dispatch to ``audit`` subcommand."""
88
- from .audit import run_audit
99
+ from gitwise.audit import run_audit
89
100
 
90
101
  return run_audit(quick=args.quick, as_json=args.json)
91
102
 
92
103
 
93
104
  def _run_summarize(args: argparse.Namespace) -> int:
94
105
  """Dispatch to ``summarize`` subcommand."""
95
- from .summarize import run_summarize
106
+ from gitwise.summarize import run_summarize
96
107
 
97
108
  return run_summarize(as_json=args.json, diff=args.diff, max_commits=args.max_commits)
98
109
 
99
110
 
100
111
  def _run_snapshot(args: argparse.Namespace) -> int:
101
112
  """Dispatch to ``snapshot`` subcommand."""
102
- from .snapshot import run_snapshot
113
+ from gitwise.snapshot import run_snapshot
103
114
 
104
115
  return run_snapshot(as_json=args.json)
105
116
 
106
117
 
107
118
  def _run_clean(args: argparse.Namespace) -> int:
108
119
  """Dispatch to ``clean`` subcommand."""
109
- from .clean import run_clean
120
+ from gitwise.clean import run_clean
110
121
 
111
122
  return run_clean(
112
123
  branches=args.branches,
@@ -119,14 +130,14 @@ def _run_clean(args: argparse.Namespace) -> int:
119
130
 
120
131
  def _run_optimize(args: argparse.Namespace) -> int:
121
132
  """Dispatch to ``optimize`` subcommand."""
122
- from .optimize import run_optimize
133
+ from gitwise.optimize import run_optimize
123
134
 
124
135
  return run_optimize(dry_run=args.dry_run, yes=args.yes, as_json=args.json)
125
136
 
126
137
 
127
138
  def _run_worktree(args: argparse.Namespace) -> int:
128
139
  """Dispatch to ``worktree`` subcommand."""
129
- from .worktree import run_worktree
140
+ from gitwise.worktree import run_worktree
130
141
 
131
142
  return run_worktree(
132
143
  args.action, getattr(args, "branch", None), dry_run=args.dry_run, as_json=args.json
@@ -165,8 +176,8 @@ def _recover_diff_pathspec_boundary() -> tuple[str | None, list[str] | None]:
165
176
 
166
177
  def _run_diff(args: argparse.Namespace) -> int:
167
178
  """Dispatch to ``diff`` subcommand."""
168
- from .diff import run_diff
169
- from .output import error as error_out
179
+ from gitwise.diff import run_diff
180
+ from gitwise.output import error as error_out
170
181
 
171
182
  refspec = args.refspec
172
183
  paths = args.paths
@@ -177,7 +188,7 @@ def _run_diff(args: argparse.Namespace) -> int:
177
188
  recovered_refspec, recovered_paths = _recover_diff_pathspec_boundary()
178
189
  except ValueError as exc:
179
190
  if args.json:
180
- print_json(error_envelope(error=str(exc), code="too_many_refs"))
191
+ print_json(error_envelope("diff", error=str(exc), code="too_many_refs"))
181
192
  else:
182
193
  error_out(str(exc))
183
194
  return 1
@@ -195,15 +206,17 @@ def _run_diff(args: argparse.Namespace) -> int:
195
206
  summary=args.summary,
196
207
  scan_secrets=args.scan_secrets,
197
208
  as_json=args.json,
209
+ json_lines=getattr(args, "json_lines", False),
198
210
  )
199
211
 
200
212
 
201
213
  def _run_log(args: argparse.Namespace) -> int:
202
214
  """Dispatch to ``log`` subcommand."""
203
- from .log import run_log
215
+ from gitwise.log import run_log
204
216
 
205
217
  return run_log(
206
218
  as_json=args.json,
219
+ json_lines=getattr(args, "json_lines", False),
207
220
  oneline=args.oneline,
208
221
  graph=args.graph,
209
222
  author=args.author,
@@ -217,14 +230,14 @@ def _run_log(args: argparse.Namespace) -> int:
217
230
 
218
231
  def _run_show(args: argparse.Namespace) -> int:
219
232
  """Dispatch to ``show`` subcommand."""
220
- from .show import run_show
233
+ from gitwise.show import run_show
221
234
 
222
235
  return run_show(ref=args.ref, stat=args.stat, as_json=args.json)
223
236
 
224
237
 
225
238
  def _run_commit(args: argparse.Namespace) -> int:
226
239
  """Dispatch to ``commit`` subcommand."""
227
- from .commit import run_commit
240
+ from gitwise.commit import run_commit
228
241
 
229
242
  return run_commit(
230
243
  message=args.message,
@@ -240,14 +253,14 @@ def _run_commit(args: argparse.Namespace) -> int:
240
253
 
241
254
  def _run_branches(args: argparse.Namespace) -> int:
242
255
  """Dispatch to ``branches`` subcommand."""
243
- from .branches import run_branches
256
+ from gitwise.branches import run_branches
244
257
 
245
258
  return run_branches(stale=args.stale, remote=args.remote, sort=args.sort, as_json=args.json)
246
259
 
247
260
 
248
261
  def _run_sync(args: argparse.Namespace) -> int:
249
262
  """Dispatch to ``sync`` subcommand."""
250
- from .sync import run_sync
263
+ from gitwise.sync import run_sync
251
264
 
252
265
  return run_sync(
253
266
  pull=args.pull,
@@ -260,14 +273,14 @@ def _run_sync(args: argparse.Namespace) -> int:
260
273
 
261
274
  def _run_pr(args: argparse.Namespace) -> int:
262
275
  """Dispatch to ``pr`` subcommand."""
263
- from .pr import run_pr
276
+ from gitwise.pr import run_pr
264
277
 
265
278
  return run_pr(action=args.action, selector=args.selector, as_json=args.json)
266
279
 
267
280
 
268
281
  def _run_undo(args: argparse.Namespace) -> int:
269
282
  """Dispatch to ``undo`` subcommand."""
270
- from .undo import run_undo
283
+ from gitwise.undo import run_undo
271
284
 
272
285
  return run_undo(
273
286
  ref=args.ref,
@@ -281,21 +294,21 @@ def _run_undo(args: argparse.Namespace) -> int:
281
294
 
282
295
  def _run_context(args: argparse.Namespace) -> int:
283
296
  """Dispatch to ``context`` subcommand."""
284
- from .context import run_context
297
+ from gitwise.context import run_context
285
298
 
286
299
  return run_context(as_json=args.json)
287
300
 
288
301
 
289
302
  def _run_health(args: argparse.Namespace) -> int:
290
303
  """Dispatch to ``health`` subcommand."""
291
- from .health import run_health
304
+ from gitwise.health import run_health
292
305
 
293
306
  return run_health(as_json=args.json)
294
307
 
295
308
 
296
309
  def _run_stash(args: argparse.Namespace) -> int:
297
310
  """Dispatch to ``stash`` subcommand."""
298
- from .stash import run_stash
311
+ from gitwise.stash import run_stash
299
312
 
300
313
  return run_stash(
301
314
  action=args.action,
@@ -309,7 +322,7 @@ def _run_stash(args: argparse.Namespace) -> int:
309
322
 
310
323
  def _run_tag(args: argparse.Namespace) -> int:
311
324
  """Dispatch to ``tag`` subcommand."""
312
- from .tag import run_tag
325
+ from gitwise.tag import run_tag
313
326
 
314
327
  return run_tag(
315
328
  action=args.action,
@@ -324,7 +337,7 @@ def _run_tag(args: argparse.Namespace) -> int:
324
337
 
325
338
  def _run_merge(args: argparse.Namespace) -> int:
326
339
  """Dispatch to ``merge`` subcommand."""
327
- from .merge import run_merge
340
+ from gitwise.merge import run_merge
328
341
 
329
342
  return run_merge(
330
343
  args.branch,
@@ -340,21 +353,21 @@ def _run_merge(args: argparse.Namespace) -> int:
340
353
 
341
354
  def _run_conflicts(args: argparse.Namespace) -> int:
342
355
  """Dispatch to ``conflicts`` subcommand."""
343
- from .conflicts import run_conflicts
356
+ from gitwise.conflicts import run_conflicts
344
357
 
345
- return run_conflicts(ours=args.ours, theirs=args.theirs, as_json=args.json)
358
+ return run_conflicts(ours=args.ours, theirs=args.theirs, union=args.union, as_json=args.json)
346
359
 
347
360
 
348
361
  def _run_suggest(args: argparse.Namespace) -> int:
349
362
  """Dispatch to ``suggest`` subcommand."""
350
- from .suggest import run_suggest
363
+ from gitwise.suggest import run_suggest
351
364
 
352
365
  return run_suggest(as_json=args.json)
353
366
 
354
367
 
355
368
  def _run_pick(args: argparse.Namespace) -> int:
356
369
  """Dispatch to ``pick`` / ``cherry-pick`` subcommand."""
357
- from .pick import run_pick
370
+ from gitwise.pick import run_pick
358
371
 
359
372
  return run_pick(
360
373
  args.refs,
@@ -368,7 +381,7 @@ def _run_pick(args: argparse.Namespace) -> int:
368
381
 
369
382
  def _run_status(args: argparse.Namespace) -> int:
370
383
  """Dispatch to ``status`` subcommand."""
371
- from .status import run_status
384
+ from gitwise.status import run_status
372
385
 
373
386
  return run_status(as_json=args.json)
374
387
 
@@ -384,46 +397,49 @@ def _run_completions(args: argparse.Namespace) -> int:
384
397
  try:
385
398
  script = build_completions_script(shell=shell, prog=prog)
386
399
  except ModuleNotFoundError:
387
- from .output import error as _error
400
+ from gitwise.output import error as _error
388
401
 
389
402
  hint = t("missing_dependency_hint")
390
403
  message = t("missing_dependency_completions_shtab")
391
404
  if args.json:
392
- print_json(error_envelope(error=message, code="missing_dependency", hint=hint))
405
+ print_json(
406
+ error_envelope("completions", error=message, code="missing_dependency", hint=hint)
407
+ )
393
408
  else:
394
409
  _error(message, hint=hint)
395
410
  return 1
396
411
  except RuntimeError as e:
397
412
  message = str(e)
398
413
  if args.json:
399
- print_json(error_envelope(error=message, code="runtime_error"))
414
+ print_json(error_envelope("completions", error=message, code="runtime_error"))
400
415
  else:
401
- from .output import error as _error
416
+ from gitwise.output import error as _error
402
417
 
403
418
  _error(message)
404
419
  return 1
405
420
  except ValueError:
406
421
  message = t("completions_unsupported_shell", shell=shell)
407
422
  if args.json:
408
- print_json(error_envelope(error=message, code="unsupported_shell"))
423
+ print_json(error_envelope("completions", error=message, code="unsupported_shell"))
409
424
  else:
410
- from .output import error as _error
425
+ from gitwise.output import error as _error
411
426
 
412
427
  _error(message)
413
428
  return 1
414
429
 
415
430
  if args.json:
416
431
  print_json(
417
- {
418
- "v": 2,
419
- "ok": True,
420
- "kind": "completions",
421
- "schema": "gitwise/completions/v1",
422
- "version": __version__,
423
- "shell": shell,
424
- "prog": prog,
425
- "script": script,
426
- }
432
+ ok_envelope(
433
+ "completions",
434
+ data={
435
+ "kind": "completions",
436
+ "schema": "gitwise/completions/v1",
437
+ "version": __version__,
438
+ "shell": shell,
439
+ "prog": prog,
440
+ "script": script,
441
+ },
442
+ )
427
443
  )
428
444
  return 0
429
445
 
@@ -435,14 +451,15 @@ def _run_commands(args: argparse.Namespace) -> int:
435
451
  """List all registered subcommands with aliases."""
436
452
  parser = build_parser()
437
453
  commands = commands_metadata(parser)
438
- payload = {
439
- "v": 2,
440
- "ok": True,
441
- "kind": "commands",
442
- "schema": "gitwise/commands/v1",
443
- "version": __version__,
444
- "commands": commands,
445
- }
454
+ payload = ok_envelope(
455
+ "commands",
456
+ data={
457
+ "kind": "commands",
458
+ "schema": "gitwise/commands/v1",
459
+ "version": __version__,
460
+ "commands": commands,
461
+ },
462
+ )
446
463
 
447
464
  if args.json:
448
465
  print_json(payload)
@@ -465,7 +482,7 @@ def _run_schema(args: argparse.Namespace) -> int:
465
482
 
466
483
  Returns 1 when the command is unknown or its schema file is missing.
467
484
  """
468
- from .schema import load_command_input_schema
485
+ from gitwise.schema import load_command_input_schema
469
486
 
470
487
  parser = build_parser()
471
488
  command_parser = resolve_command_parser(parser=parser, name=args.name)
@@ -475,6 +492,7 @@ def _run_schema(args: argparse.Namespace) -> int:
475
492
  if args.json:
476
493
  print_json(
477
494
  error_envelope(
495
+ "schema",
478
496
  error=message,
479
497
  code="unknown_command",
480
498
  hint=hint,
@@ -483,12 +501,35 @@ def _run_schema(args: argparse.Namespace) -> int:
483
501
  )
484
502
  )
485
503
  else:
486
- from .output import error as _error
504
+ from gitwise.output import error as _error
487
505
 
488
506
  _error(message, hint=hint)
489
507
  return 1
490
508
 
491
509
  name = canonical_command_name(command_parser)
510
+
511
+ if getattr(args, "output", False):
512
+ from gitwise.schema import generic_output_schema, load_command_output_schema
513
+
514
+ output_schema = load_command_output_schema(command=name, version=args.version)
515
+ if output_schema is None:
516
+ output_schema = generic_output_schema(command=name, version=args.version)
517
+ print_json(
518
+ ok_envelope(
519
+ "schema",
520
+ data={
521
+ "kind": "schema",
522
+ "schema": "gitwise/schema/v1",
523
+ "version": __version__,
524
+ "schema_version": args.version,
525
+ "command": name,
526
+ "schema_kind": "cli_output",
527
+ "json_schema": output_schema,
528
+ },
529
+ )
530
+ )
531
+ return 0
532
+
492
533
  schema = load_command_input_schema(command=name, version=args.version)
493
534
  if schema is None:
494
535
  message = t("schema_file_missing", command=name, version=args.version)
@@ -496,6 +537,7 @@ def _run_schema(args: argparse.Namespace) -> int:
496
537
  if args.json:
497
538
  print_json(
498
539
  error_envelope(
540
+ "schema",
499
541
  error=message,
500
542
  code="schema_not_found",
501
543
  hint=hint,
@@ -504,22 +546,23 @@ def _run_schema(args: argparse.Namespace) -> int:
504
546
  )
505
547
  )
506
548
  else:
507
- from .output import error as _error
549
+ from gitwise.output import error as _error
508
550
 
509
551
  _error(message, hint=hint)
510
552
  return 1
511
553
 
512
- payload = {
513
- "v": 2,
514
- "ok": True,
515
- "kind": "schema",
516
- "schema": "gitwise/schema/v1",
517
- "version": __version__,
518
- "schema_version": args.version,
519
- "command": name,
520
- "schema_kind": "cli_input",
521
- "json_schema": schema,
522
- }
554
+ payload = ok_envelope(
555
+ "schema",
556
+ data={
557
+ "kind": "schema",
558
+ "schema": "gitwise/schema/v1",
559
+ "version": __version__,
560
+ "schema_version": args.version,
561
+ "command": name,
562
+ "schema_kind": "cli_input",
563
+ "json_schema": schema,
564
+ },
565
+ )
523
566
 
524
567
  print_json(payload)
525
568
  return 0