gitwise-cli 0.26.0__tar.gz → 0.27.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 (172) hide show
  1. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/CHANGELOG.md +12 -0
  2. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/PKG-INFO +22 -4
  3. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/README.md +21 -3
  4. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/__init__.py +1 -1
  5. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/__main__.py +31 -0
  6. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/_cli_setup_agents.py +31 -0
  7. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/_i18n_data.json +12 -0
  8. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/install.sh +6 -2
  9. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/pyproject.toml +1 -1
  10. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/conftest.py +6 -0
  11. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_adapters.py +13 -0
  12. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/.gitignore +0 -0
  13. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/LICENSE +0 -0
  14. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/bin/gitwise +0 -0
  15. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/_cli_completions.py +0 -0
  16. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/_cli_dispatch.py +0 -0
  17. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/_cli_introspection.py +0 -0
  18. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/_cli_parser.py +0 -0
  19. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/_paths.py +0 -0
  20. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/_runtime_config.py +0 -0
  21. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/audit.py +0 -0
  22. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/branches.py +0 -0
  23. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/clean.py +0 -0
  24. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/commit.py +0 -0
  25. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/conflicts.py +0 -0
  26. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/context.py +0 -0
  27. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/design.py +0 -0
  28. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/diff.py +0 -0
  29. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/doctor.py +0 -0
  30. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/git.py +0 -0
  31. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/health.py +0 -0
  32. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/i18n.py +0 -0
  33. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/log.py +0 -0
  34. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/merge.py +0 -0
  35. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/optimize.py +0 -0
  36. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/output.py +0 -0
  37. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/pick.py +0 -0
  38. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/pr.py +0 -0
  39. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/py.typed +0 -0
  40. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/schema.py +0 -0
  41. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup.py +0 -0
  42. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/__init__.py +0 -0
  43. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/adapters/__init__.py +0 -0
  44. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/adapters/aider.py +0 -0
  45. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/adapters/base.py +0 -0
  46. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/adapters/codex.py +0 -0
  47. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/adapters/continue_adapter.py +0 -0
  48. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/adapters/cursor.py +0 -0
  49. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/adapters/opencode.py +0 -0
  50. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/adapters/pi.py +0 -0
  51. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/exec.py +0 -0
  52. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/format.py +0 -0
  53. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/plan.py +0 -0
  54. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/plan_gitfiles.py +0 -0
  55. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/plan_skills.py +0 -0
  56. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/providers/__init__.py +0 -0
  57. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/providers/aider.py +0 -0
  58. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/providers/base.py +0 -0
  59. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/providers/claude.py +0 -0
  60. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/providers/codex.py +0 -0
  61. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/providers/continue_adapter.py +0 -0
  62. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/providers/cursor.py +0 -0
  63. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/providers/opencode.py +0 -0
  64. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/providers/pi.py +0 -0
  65. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/state.py +0 -0
  66. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/setup_agents/types.py +0 -0
  67. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/show.py +0 -0
  68. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/snapshot.py +0 -0
  69. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/stash.py +0 -0
  70. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/status.py +0 -0
  71. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/suggest.py +0 -0
  72. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/summarize.py +0 -0
  73. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/sync.py +0 -0
  74. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/tag.py +0 -0
  75. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/undo.py +0 -0
  76. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/update.py +0 -0
  77. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/utils/__init__.py +0 -0
  78. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/utils/git_output.py +0 -0
  79. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/utils/json_envelope.py +0 -0
  80. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/utils/parsing.py +0 -0
  81. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/gitwise/worktree.py +0 -0
  82. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/agents/skills/git-audit/SKILL.md +0 -0
  83. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/agents/skills/git-clean/SKILL.md +0 -0
  84. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/agents/skills/git-optimize/SKILL.md +0 -0
  85. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/aider/CONVENTIONS.md.template +0 -0
  86. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/aider/aider.conf.yml.template +0 -0
  87. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/claude/CLAUDE.md.template +0 -0
  88. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/claude/rules/gitwise.md +0 -0
  89. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/claude/settings.json.template +0 -0
  90. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/claude/skills/git-audit/SKILL.md +0 -0
  91. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/claude/skills/git-clean/SKILL.md +0 -0
  92. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/claude/skills/git-optimize/SKILL.md +0 -0
  93. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/codex/agents/gitwise.toml.template +0 -0
  94. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/continue/rules/gitwise.md.template +0 -0
  95. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/cursor/rules/gitwise.mdc.template +0 -0
  96. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/git-config-modern.txt +0 -0
  97. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/hooks/commit-msg +0 -0
  98. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/hooks/pre-commit +0 -0
  99. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/opencode/agents/gitwise.md.template +0 -0
  100. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/pi/skills/gitwise.md.template +0 -0
  101. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/audit.json +0 -0
  102. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/branches.json +0 -0
  103. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/clean.json +0 -0
  104. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/commands.json +0 -0
  105. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/commit.json +0 -0
  106. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/completions.json +0 -0
  107. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/conflicts.json +0 -0
  108. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/context.json +0 -0
  109. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/diff.json +0 -0
  110. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/doctor.json +0 -0
  111. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/health.json +0 -0
  112. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/log.json +0 -0
  113. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/merge.json +0 -0
  114. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/optimize.json +0 -0
  115. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/pick.json +0 -0
  116. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/pr.json +0 -0
  117. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/schema.json +0 -0
  118. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/setup-agents.json +0 -0
  119. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/setup.json +0 -0
  120. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/show.json +0 -0
  121. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/snapshot.json +0 -0
  122. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/stash.json +0 -0
  123. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/status.json +0 -0
  124. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/suggest.json +0 -0
  125. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/summarize.json +0 -0
  126. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/sync.json +0 -0
  127. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/tag.json +0 -0
  128. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/undo.json +0 -0
  129. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/update.json +0 -0
  130. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/share/schemas/v1/input/worktree.json +0 -0
  131. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/__init__.py +0 -0
  132. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_audit.py +0 -0
  133. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_branches.py +0 -0
  134. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_clean.py +0 -0
  135. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_commit.py +0 -0
  136. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_conflicts.py +0 -0
  137. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_context.py +0 -0
  138. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_design.py +0 -0
  139. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_diff.py +0 -0
  140. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_doctor.py +0 -0
  141. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_edge_cases.py +0 -0
  142. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_git.py +0 -0
  143. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_git_output_utils.py +0 -0
  144. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_health.py +0 -0
  145. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_i18n.py +0 -0
  146. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_json_envelope_utils.py +0 -0
  147. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_log.py +0 -0
  148. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_main.py +0 -0
  149. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_md_links_script.py +0 -0
  150. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_merge.py +0 -0
  151. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_optimize.py +0 -0
  152. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_output.py +0 -0
  153. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_parsing_utils.py +0 -0
  154. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_pick.py +0 -0
  155. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_pr.py +0 -0
  156. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_roadmap_baseline_script.py +0 -0
  157. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_sa_plan.py +0 -0
  158. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_sa_unit.py +0 -0
  159. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_schema_catalog.py +0 -0
  160. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_setup.py +0 -0
  161. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_setup_agents.py +0 -0
  162. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_show.py +0 -0
  163. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_snapshot.py +0 -0
  164. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_stash.py +0 -0
  165. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_status.py +0 -0
  166. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_suggest.py +0 -0
  167. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_summarize.py +0 -0
  168. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_sync.py +0 -0
  169. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_sync_changelog_es_script.py +0 -0
  170. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_tag.py +0 -0
  171. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_undo.py +0 -0
  172. {gitwise_cli-0.26.0 → gitwise_cli-0.27.0}/tests/test_worktree.py +0 -0
@@ -3,6 +3,18 @@
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.27.0 (2026-06-19)
7
+
8
+ ### Feat
9
+
10
+ - **install**: Windows installer + extend audit to detect unpinned uses: (#63)
11
+
12
+ ## v0.26.1 (2026-06-18)
13
+
14
+ ### Fix
15
+
16
+ - **ci**: bump all actions to Node 24 + document Homebrew install path (#62)
17
+
6
18
  ## v0.26.0 (2026-06-18)
7
19
 
8
20
  ### Feat
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitwise-cli
3
- Version: 0.26.0
3
+ Version: 0.27.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
@@ -60,7 +60,15 @@ gitwise addresses three daily pain points:
60
60
 
61
61
  Pick one:
62
62
 
63
- **curl | bash** (recommended, auto-installs `uv` if missing):
63
+ **Homebrew** (macOS/Linux, recommended if you already use [Homebrew](https://brew.sh)):
64
+
65
+ ```bash
66
+ brew install drzioner/tap/gitwise
67
+ ```
68
+
69
+ Update later with `brew upgrade gitwise`. Uninstall with `brew uninstall gitwise`.
70
+
71
+ **curl | bash** (auto-installs `uv` if missing, no package manager required):
64
72
 
65
73
  ```bash
66
74
  curl -fsSL https://raw.githubusercontent.com/drzioner/gitwise/main/install.sh | bash
@@ -81,17 +89,27 @@ uv sync
81
89
  uv run python -m gitwise doctor
82
90
  ```
83
91
 
92
+ **Windows** (PowerShell 5.1+, auto-installs `uv` if missing):
93
+
94
+ ```powershell
95
+ irm https://raw.githubusercontent.com/drzioner/gitwise/main/install.ps1 | iex
96
+ ```
97
+
98
+ For a version-pinned install (e.g. for reproducible setups), see `Get-Help .\install.ps1 -Detailed` after download.
99
+
84
100
  Update an existing installation:
85
101
 
86
102
  ```bash
87
- uv tool upgrade gitwise-cli # if installed via uv
103
+ brew upgrade gitwise # if installed via Homebrew (macOS/Linux)
104
+ uv tool upgrade gitwise-cli # if installed via uv (any OS)
88
105
  # or re-run the curl | bash installer, which always pulls latest
89
106
  ```
90
107
 
91
108
  Uninstall:
92
109
 
93
110
  ```bash
94
- uv tool uninstall gitwise-cli
111
+ brew uninstall gitwise # if installed via Homebrew
112
+ uv tool uninstall gitwise-cli # if installed via uv (any OS)
95
113
  ```
96
114
 
97
115
  ## Quick Start
@@ -27,7 +27,15 @@ gitwise addresses three daily pain points:
27
27
 
28
28
  Pick one:
29
29
 
30
- **curl | bash** (recommended, auto-installs `uv` if missing):
30
+ **Homebrew** (macOS/Linux, recommended if you already use [Homebrew](https://brew.sh)):
31
+
32
+ ```bash
33
+ brew install drzioner/tap/gitwise
34
+ ```
35
+
36
+ Update later with `brew upgrade gitwise`. Uninstall with `brew uninstall gitwise`.
37
+
38
+ **curl | bash** (auto-installs `uv` if missing, no package manager required):
31
39
 
32
40
  ```bash
33
41
  curl -fsSL https://raw.githubusercontent.com/drzioner/gitwise/main/install.sh | bash
@@ -48,17 +56,27 @@ uv sync
48
56
  uv run python -m gitwise doctor
49
57
  ```
50
58
 
59
+ **Windows** (PowerShell 5.1+, auto-installs `uv` if missing):
60
+
61
+ ```powershell
62
+ irm https://raw.githubusercontent.com/drzioner/gitwise/main/install.ps1 | iex
63
+ ```
64
+
65
+ For a version-pinned install (e.g. for reproducible setups), see `Get-Help .\install.ps1 -Detailed` after download.
66
+
51
67
  Update an existing installation:
52
68
 
53
69
  ```bash
54
- uv tool upgrade gitwise-cli # if installed via uv
70
+ brew upgrade gitwise # if installed via Homebrew (macOS/Linux)
71
+ uv tool upgrade gitwise-cli # if installed via uv (any OS)
55
72
  # or re-run the curl | bash installer, which always pulls latest
56
73
  ```
57
74
 
58
75
  Uninstall:
59
76
 
60
77
  ```bash
61
- uv tool uninstall gitwise-cli
78
+ brew uninstall gitwise # if installed via Homebrew
79
+ uv tool uninstall gitwise-cli # if installed via uv (any OS)
62
80
  ```
63
81
 
64
82
  ## Quick Start
@@ -1,4 +1,4 @@
1
- __version__ = "0.26.0"
1
+ __version__ = "0.27.0"
2
2
 
3
3
 
4
4
  def get_version() -> str:
@@ -32,12 +32,36 @@ def _install_rich_traceback() -> None:
32
32
  return
33
33
 
34
34
 
35
+ def _ensure_utf8_stdio() -> None:
36
+ """Force stdout/stderr to UTF-8.
37
+
38
+ Windows defaults to a system codepage (often cp1252) for the Python
39
+ embedded in console apps. That codepage cannot encode characters like
40
+ U+2713 (✓) used throughout gitwise's status output, causing
41
+ UnicodeEncodeError when the user is not running through a wrapper that
42
+ sets PYTHONIOENCODING. macOS/Linux are already UTF-8 by default, so
43
+ this reconfigure is a no-op there.
44
+ """
45
+ for stream_name in ("stdout", "stderr"):
46
+ stream = getattr(sys, stream_name, None)
47
+ # TextIOWrapper.reconfigure exists on Python 3.7+; guard just in case
48
+ # the stream has been replaced with something non-standard.
49
+ reconfigure = getattr(stream, "reconfigure", None)
50
+ if callable(reconfigure):
51
+ try:
52
+ reconfigure(encoding="utf-8", errors="replace")
53
+ except (TypeError, ValueError):
54
+ # Stream does not accept these kwargs or is closed; ignore.
55
+ pass
56
+
57
+
35
58
  def main() -> int:
36
59
  import os
37
60
 
38
61
  from ._runtime_config import reset_runtime_config
39
62
  from .i18n import set_locale
40
63
 
64
+ _ensure_utf8_stdio()
41
65
  _install_rich_traceback()
42
66
 
43
67
  parser = build_parser()
@@ -93,6 +117,13 @@ def main() -> int:
93
117
  except Exception:
94
118
  if _should_show_rich_traceback():
95
119
  raise
120
+ # No Rich traceback available (CI / non-tty / LOG_JSON mode).
121
+ # Still emit the raw traceback to stderr so CI logs are
122
+ # diagnostic. Otherwise the user only sees "unexpected error"
123
+ # and has no way to identify the root cause.
124
+ import traceback as _traceback
125
+
126
+ _traceback.print_exc()
96
127
  from .output import error as _error
97
128
 
98
129
  _error(t("unexpected_error"))
@@ -385,6 +385,37 @@ def run_setup_agents(
385
385
  adapters_legacy_used: bool = False,
386
386
  ) -> int:
387
387
  """Dispatcher: global mode (default) or per-repo mode (--local)."""
388
+ import platform
389
+
390
+ if platform.system() == "Windows":
391
+ if not local:
392
+ # Global mode creates symlinks in ~/.claude/ (skills, CLAUDE.md
393
+ # pointer, etc.). Windows does not support POSIX-style symlinks
394
+ # without Developer Mode, and even with it the semantics around
395
+ # relative targets differ enough that the existing setup_agents
396
+ # code produces broken links. Fail fast with a clear workaround
397
+ # instead of letting the user hit a confusing traceback.
398
+ if as_json:
399
+ print_json(
400
+ {
401
+ "ok": False,
402
+ "error": "windows_global_unsupported",
403
+ "message": t("setup_agents_windows_global_unsupported"),
404
+ "workaround": "gitwise setup-agents --local --no-symlinks",
405
+ }
406
+ )
407
+ else:
408
+ error(t("setup_agents_windows_global_unsupported"))
409
+ info(t("setup_agents_windows_workaround_local"))
410
+ return 1
411
+ if not no_symlinks:
412
+ # Local mode auto-enables --no-symlinks on Windows. Same root
413
+ # cause: os.symlink() either errors out (no Developer Mode) or
414
+ # produces links that do not behave like POSIX symlinks for our
415
+ # sandbox check (os.path.realpath over a not-yet-existing target).
416
+ warn(t("setup_agents_windows_auto_no_symlinks"))
417
+ no_symlinks = True
418
+
388
419
  if local:
389
420
  return _run_setup_local(
390
421
  target,
@@ -519,6 +519,18 @@
519
519
  "es": "fsmonitor integrado no está soportado en Linux (solo macOS y Windows)",
520
520
  "en": "built-in fsmonitor not supported on Linux (macOS and Windows only)"
521
521
  },
522
+ "setup_agents_windows_global_unsupported": {
523
+ "es": "setup-agents en modo global no está soportado en Windows (requiere symlinks POSIX en ~/.claude/).",
524
+ "en": "setup-agents global mode is not supported on Windows (requires POSIX symlinks in ~/.claude/)."
525
+ },
526
+ "setup_agents_windows_workaround_local": {
527
+ "es": "Workaround: usá 'gitwise setup-agents --local --no-symlinks' dentro del repo donde quieras configurar los agentes.",
528
+ "en": "Workaround: use 'gitwise setup-agents --local --no-symlinks' inside the repo where you want to set up agents."
529
+ },
530
+ "setup_agents_windows_auto_no_symlinks": {
531
+ "es": "Windows detectado: activando --no-symlinks automáticamente (los symlinks POSIX no son confiables en Windows).",
532
+ "en": "Windows detected: auto-enabling --no-symlinks (POSIX symlinks are not reliable on Windows)."
533
+ },
522
534
  "gc_already_running": {
523
535
  "es": "git gc/maintenance ya está en ejecución — esperá a que termine",
524
536
  "en": "git gc/maintenance already running — wait for it to finish"
@@ -5,12 +5,15 @@
5
5
  # Remote one-liner:
6
6
  # curl -fsSL https://raw.githubusercontent.com/drzioner/gitwise/main/install.sh | bash
7
7
  #
8
+ # Windows? Use install.ps1 instead:
9
+ # irm https://raw.githubusercontent.com/drzioner/gitwise/main/install.ps1 | iex
10
+ #
8
11
  # This installer:
9
12
  # 1. Installs uv if not present (via https://astral.sh/uv/install.sh).
10
13
  # 2. Runs `uv tool install --upgrade gitwise-cli` (isolated venv, no PyPI pollution).
11
14
  # 3. Prints PATH guidance if `gitwise` is not yet on PATH.
12
15
  #
13
- # Supported OS: macOS, Linux. Windows users: see README for alternatives.
16
+ # Supported OS: macOS, Linux. Windows users: see install.ps1 or README.
14
17
 
15
18
  set -Eeuo pipefail
16
19
 
@@ -66,7 +69,8 @@ case "$OS" in
66
69
  Linux) printf 'gitwise installer - Linux (%s)\n' "$ARCH" ;;
67
70
  *)
68
71
  echo "error: unsupported OS '$OS'. This installer supports macOS and Linux." >&2
69
- echo "Windows users: see README for alternative install methods." >&2
72
+ echo "Windows users: use install.ps1 -> https://raw.githubusercontent.com/drzioner/gitwise/main/install.ps1" >&2
73
+ echo "Or: irm https://raw.githubusercontent.com/drzioner/gitwise/main/install.ps1 | iex" >&2
70
74
  exit 1
71
75
  ;;
72
76
  esac
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "gitwise-cli"
3
- version = "0.26.0"
3
+ version = "0.27.0"
4
4
  description = "Python CLI for optimizing git workflows and Claude Code integration"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -34,6 +34,12 @@ def run_gitwise(
34
34
  [sys.executable, "-m", "gitwise"] + list(args),
35
35
  capture_output=True,
36
36
  text=True,
37
+ # gitwise forces UTF-8 stdio on Windows (see _ensure_utf8_stdio in
38
+ # __main__.py); the test harness must decode the captured stream as
39
+ # UTF-8 too, otherwise locale.getpreferredencoding() (cp1252 on
40
+ # English Windows) mangles non-ASCII characters in the assertion
41
+ # strings (e.g. "huérfanos" in the worktree-clean success message).
42
+ encoding="utf-8",
37
43
  cwd=cwd or PROJECT_ROOT,
38
44
  env=base_env,
39
45
  )
@@ -1,6 +1,9 @@
1
1
  """Tests for the adapter registry and planning system."""
2
2
 
3
3
  import json
4
+ import sys
5
+
6
+ import pytest
4
7
 
5
8
  from conftest import run_gitwise
6
9
 
@@ -196,6 +199,11 @@ class TestAdapterDryRun:
196
199
  assert any(a.get("file") == ".claude/settings.json" for a in data.get("actions", []))
197
200
  assert any("deprecated alias" in w for w in data.get("warnings", []))
198
201
 
202
+ @pytest.mark.skipif(
203
+ sys.platform == "win32",
204
+ reason="setup-agents global mode is intentionally blocked on Windows "
205
+ "(see run_setup_agents Windows guard); test asserts the POSIX behavior.",
206
+ )
199
207
  def test_adapters_claude_only_warns_in_global_mode(self, tmp_path):
200
208
  result = run_gitwise(
201
209
  "setup-agents",
@@ -212,6 +220,11 @@ class TestAdapterDryRun:
212
220
  assert data["mode"] == "global"
213
221
  assert any("deprecated alias" in w for w in data.get("warnings", []))
214
222
 
223
+ @pytest.mark.skipif(
224
+ sys.platform == "win32",
225
+ reason="setup-agents global mode is intentionally blocked on Windows "
226
+ "(see run_setup_agents Windows guard); test asserts the POSIX behavior.",
227
+ )
215
228
  def test_global_mode_allows_adapters(self, tmp_path):
216
229
  result = run_gitwise(
217
230
  "setup-agents",
File without changes
File without changes
File without changes
File without changes