erk 0.4.5__py3-none-any.whl

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 (331) hide show
  1. erk/__init__.py +12 -0
  2. erk/__main__.py +6 -0
  3. erk/agent_docs/__init__.py +5 -0
  4. erk/agent_docs/models.py +123 -0
  5. erk/agent_docs/operations.py +666 -0
  6. erk/artifacts/__init__.py +5 -0
  7. erk/artifacts/artifact_health.py +623 -0
  8. erk/artifacts/detection.py +16 -0
  9. erk/artifacts/discovery.py +343 -0
  10. erk/artifacts/models.py +63 -0
  11. erk/artifacts/staleness.py +56 -0
  12. erk/artifacts/state.py +100 -0
  13. erk/artifacts/sync.py +624 -0
  14. erk/cli/__init__.py +0 -0
  15. erk/cli/activation.py +132 -0
  16. erk/cli/alias.py +53 -0
  17. erk/cli/cli.py +221 -0
  18. erk/cli/commands/__init__.py +0 -0
  19. erk/cli/commands/admin.py +153 -0
  20. erk/cli/commands/artifact/__init__.py +1 -0
  21. erk/cli/commands/artifact/check.py +260 -0
  22. erk/cli/commands/artifact/group.py +31 -0
  23. erk/cli/commands/artifact/list_cmd.py +89 -0
  24. erk/cli/commands/artifact/show.py +62 -0
  25. erk/cli/commands/artifact/sync_cmd.py +39 -0
  26. erk/cli/commands/branch/__init__.py +26 -0
  27. erk/cli/commands/branch/assign_cmd.py +152 -0
  28. erk/cli/commands/branch/checkout_cmd.py +357 -0
  29. erk/cli/commands/branch/create_cmd.py +161 -0
  30. erk/cli/commands/branch/list_cmd.py +82 -0
  31. erk/cli/commands/branch/unassign_cmd.py +197 -0
  32. erk/cli/commands/cc/__init__.py +15 -0
  33. erk/cli/commands/cc/jsonl_cmd.py +20 -0
  34. erk/cli/commands/cc/session/AGENTS.md +30 -0
  35. erk/cli/commands/cc/session/CLAUDE.md +1 -0
  36. erk/cli/commands/cc/session/__init__.py +15 -0
  37. erk/cli/commands/cc/session/list_cmd.py +167 -0
  38. erk/cli/commands/cc/session/show_cmd.py +175 -0
  39. erk/cli/commands/completion.py +89 -0
  40. erk/cli/commands/completions.py +165 -0
  41. erk/cli/commands/config.py +327 -0
  42. erk/cli/commands/docs/__init__.py +1 -0
  43. erk/cli/commands/docs/group.py +16 -0
  44. erk/cli/commands/docs/sync.py +121 -0
  45. erk/cli/commands/docs/validate.py +102 -0
  46. erk/cli/commands/doctor.py +243 -0
  47. erk/cli/commands/down.py +171 -0
  48. erk/cli/commands/exec/__init__.py +1 -0
  49. erk/cli/commands/exec/group.py +164 -0
  50. erk/cli/commands/exec/scripts/AGENTS.md +79 -0
  51. erk/cli/commands/exec/scripts/CLAUDE.md +1 -0
  52. erk/cli/commands/exec/scripts/__init__.py +5 -0
  53. erk/cli/commands/exec/scripts/add_reaction_to_comment.py +69 -0
  54. erk/cli/commands/exec/scripts/add_remote_execution_note.py +68 -0
  55. erk/cli/commands/exec/scripts/check_impl.py +152 -0
  56. erk/cli/commands/exec/scripts/ci_update_pr_body.py +294 -0
  57. erk/cli/commands/exec/scripts/create_extraction_branch.py +138 -0
  58. erk/cli/commands/exec/scripts/create_extraction_plan.py +242 -0
  59. erk/cli/commands/exec/scripts/create_issue_from_session.py +103 -0
  60. erk/cli/commands/exec/scripts/create_plan_from_context.py +103 -0
  61. erk/cli/commands/exec/scripts/create_worker_impl_from_issue.py +93 -0
  62. erk/cli/commands/exec/scripts/detect_trunk_branch.py +121 -0
  63. erk/cli/commands/exec/scripts/exit_plan_mode_hook.py +777 -0
  64. erk/cli/commands/exec/scripts/extract_latest_plan.py +49 -0
  65. erk/cli/commands/exec/scripts/extract_session_from_issue.py +150 -0
  66. erk/cli/commands/exec/scripts/find_project_dir.py +214 -0
  67. erk/cli/commands/exec/scripts/generate_pr_summary.py +112 -0
  68. erk/cli/commands/exec/scripts/get_closing_text.py +98 -0
  69. erk/cli/commands/exec/scripts/get_embedded_prompt.py +62 -0
  70. erk/cli/commands/exec/scripts/get_plan_metadata.py +95 -0
  71. erk/cli/commands/exec/scripts/get_pr_body_footer.py +70 -0
  72. erk/cli/commands/exec/scripts/get_pr_discussion_comments.py +149 -0
  73. erk/cli/commands/exec/scripts/get_pr_review_comments.py +155 -0
  74. erk/cli/commands/exec/scripts/impl_init.py +158 -0
  75. erk/cli/commands/exec/scripts/impl_signal.py +375 -0
  76. erk/cli/commands/exec/scripts/impl_verify.py +49 -0
  77. erk/cli/commands/exec/scripts/issue_title_to_filename.py +34 -0
  78. erk/cli/commands/exec/scripts/list_sessions.py +296 -0
  79. erk/cli/commands/exec/scripts/mark_impl_ended.py +188 -0
  80. erk/cli/commands/exec/scripts/mark_impl_started.py +188 -0
  81. erk/cli/commands/exec/scripts/marker.py +163 -0
  82. erk/cli/commands/exec/scripts/objective_save_to_issue.py +109 -0
  83. erk/cli/commands/exec/scripts/plan_save_to_issue.py +269 -0
  84. erk/cli/commands/exec/scripts/plan_update_issue.py +147 -0
  85. erk/cli/commands/exec/scripts/post_extraction_comment.py +237 -0
  86. erk/cli/commands/exec/scripts/post_or_update_pr_summary.py +133 -0
  87. erk/cli/commands/exec/scripts/post_pr_inline_comment.py +143 -0
  88. erk/cli/commands/exec/scripts/post_workflow_started_comment.py +168 -0
  89. erk/cli/commands/exec/scripts/preprocess_session.py +777 -0
  90. erk/cli/commands/exec/scripts/quick_submit.py +32 -0
  91. erk/cli/commands/exec/scripts/rebase_with_conflict_resolution.py +260 -0
  92. erk/cli/commands/exec/scripts/reply_to_discussion_comment.py +173 -0
  93. erk/cli/commands/exec/scripts/resolve_review_thread.py +170 -0
  94. erk/cli/commands/exec/scripts/session_id_injector_hook.py +52 -0
  95. erk/cli/commands/exec/scripts/setup_impl_from_issue.py +159 -0
  96. erk/cli/commands/exec/scripts/slot_objective.py +102 -0
  97. erk/cli/commands/exec/scripts/tripwires_reminder_hook.py +20 -0
  98. erk/cli/commands/exec/scripts/update_dispatch_info.py +116 -0
  99. erk/cli/commands/exec/scripts/user_prompt_hook.py +113 -0
  100. erk/cli/commands/exec/scripts/validate_plan_content.py +98 -0
  101. erk/cli/commands/exec/scripts/wrap_plan_in_metadata_block.py +34 -0
  102. erk/cli/commands/implement.py +695 -0
  103. erk/cli/commands/implement_shared.py +649 -0
  104. erk/cli/commands/info/__init__.py +14 -0
  105. erk/cli/commands/info/release_notes_cmd.py +128 -0
  106. erk/cli/commands/init.py +801 -0
  107. erk/cli/commands/land_cmd.py +690 -0
  108. erk/cli/commands/log_cmd.py +137 -0
  109. erk/cli/commands/md/__init__.py +5 -0
  110. erk/cli/commands/md/check.py +118 -0
  111. erk/cli/commands/md/group.py +14 -0
  112. erk/cli/commands/navigation_helpers.py +430 -0
  113. erk/cli/commands/objective/__init__.py +16 -0
  114. erk/cli/commands/objective/list_cmd.py +47 -0
  115. erk/cli/commands/objective_helpers.py +132 -0
  116. erk/cli/commands/plan/__init__.py +32 -0
  117. erk/cli/commands/plan/check_cmd.py +174 -0
  118. erk/cli/commands/plan/close_cmd.py +69 -0
  119. erk/cli/commands/plan/create_cmd.py +120 -0
  120. erk/cli/commands/plan/docs/__init__.py +18 -0
  121. erk/cli/commands/plan/docs/extract_cmd.py +53 -0
  122. erk/cli/commands/plan/docs/unextract_cmd.py +38 -0
  123. erk/cli/commands/plan/docs/unextracted_cmd.py +72 -0
  124. erk/cli/commands/plan/extraction/__init__.py +16 -0
  125. erk/cli/commands/plan/extraction/complete_cmd.py +101 -0
  126. erk/cli/commands/plan/extraction/create_raw_cmd.py +63 -0
  127. erk/cli/commands/plan/get.py +71 -0
  128. erk/cli/commands/plan/list_cmd.py +754 -0
  129. erk/cli/commands/plan/log_cmd.py +440 -0
  130. erk/cli/commands/plan/start_cmd.py +459 -0
  131. erk/cli/commands/planner/__init__.py +40 -0
  132. erk/cli/commands/planner/configure_cmd.py +73 -0
  133. erk/cli/commands/planner/connect_cmd.py +96 -0
  134. erk/cli/commands/planner/create_cmd.py +148 -0
  135. erk/cli/commands/planner/list_cmd.py +51 -0
  136. erk/cli/commands/planner/register_cmd.py +105 -0
  137. erk/cli/commands/planner/set_default_cmd.py +23 -0
  138. erk/cli/commands/planner/unregister_cmd.py +43 -0
  139. erk/cli/commands/pr/__init__.py +23 -0
  140. erk/cli/commands/pr/check_cmd.py +112 -0
  141. erk/cli/commands/pr/checkout_cmd.py +165 -0
  142. erk/cli/commands/pr/fix_conflicts_cmd.py +82 -0
  143. erk/cli/commands/pr/parse_pr_reference.py +10 -0
  144. erk/cli/commands/pr/submit_cmd.py +360 -0
  145. erk/cli/commands/pr/sync_cmd.py +181 -0
  146. erk/cli/commands/prepare_cwd_recovery.py +60 -0
  147. erk/cli/commands/project/__init__.py +16 -0
  148. erk/cli/commands/project/init_cmd.py +91 -0
  149. erk/cli/commands/run/__init__.py +17 -0
  150. erk/cli/commands/run/list_cmd.py +189 -0
  151. erk/cli/commands/run/logs_cmd.py +54 -0
  152. erk/cli/commands/run/shared.py +19 -0
  153. erk/cli/commands/shell_integration.py +29 -0
  154. erk/cli/commands/slot/__init__.py +23 -0
  155. erk/cli/commands/slot/check_cmd.py +277 -0
  156. erk/cli/commands/slot/common.py +314 -0
  157. erk/cli/commands/slot/init_pool_cmd.py +157 -0
  158. erk/cli/commands/slot/list_cmd.py +228 -0
  159. erk/cli/commands/slot/repair_cmd.py +190 -0
  160. erk/cli/commands/stack/__init__.py +23 -0
  161. erk/cli/commands/stack/consolidate_cmd.py +470 -0
  162. erk/cli/commands/stack/list_cmd.py +79 -0
  163. erk/cli/commands/stack/move_cmd.py +309 -0
  164. erk/cli/commands/stack/split_old/README.md +64 -0
  165. erk/cli/commands/stack/split_old/__init__.py +5 -0
  166. erk/cli/commands/stack/split_old/command.py +233 -0
  167. erk/cli/commands/stack/split_old/display.py +116 -0
  168. erk/cli/commands/stack/split_old/plan.py +216 -0
  169. erk/cli/commands/status.py +58 -0
  170. erk/cli/commands/submit.py +768 -0
  171. erk/cli/commands/up.py +154 -0
  172. erk/cli/commands/upgrade.py +82 -0
  173. erk/cli/commands/wt/__init__.py +29 -0
  174. erk/cli/commands/wt/checkout_cmd.py +110 -0
  175. erk/cli/commands/wt/create_cmd.py +998 -0
  176. erk/cli/commands/wt/current_cmd.py +35 -0
  177. erk/cli/commands/wt/delete_cmd.py +573 -0
  178. erk/cli/commands/wt/list_cmd.py +332 -0
  179. erk/cli/commands/wt/rename_cmd.py +66 -0
  180. erk/cli/config.py +242 -0
  181. erk/cli/constants.py +29 -0
  182. erk/cli/core.py +65 -0
  183. erk/cli/debug.py +9 -0
  184. erk/cli/ensure-conversion-tasks.md +288 -0
  185. erk/cli/ensure.py +628 -0
  186. erk/cli/github_parsing.py +96 -0
  187. erk/cli/graphite.py +81 -0
  188. erk/cli/graphite_command.py +80 -0
  189. erk/cli/help_formatter.py +345 -0
  190. erk/cli/output.py +361 -0
  191. erk/cli/presets/dagster.toml +12 -0
  192. erk/cli/presets/generic.toml +12 -0
  193. erk/cli/prompt_hooks_templates/README.md +68 -0
  194. erk/cli/script_output.py +32 -0
  195. erk/cli/shell_integration/bash_wrapper.sh +32 -0
  196. erk/cli/shell_integration/fish_wrapper.fish +39 -0
  197. erk/cli/shell_integration/handler.py +338 -0
  198. erk/cli/shell_integration/zsh_wrapper.sh +32 -0
  199. erk/cli/shell_utils.py +171 -0
  200. erk/cli/subprocess_utils.py +92 -0
  201. erk/cli/uvx_detection.py +59 -0
  202. erk/core/__init__.py +0 -0
  203. erk/core/claude_executor.py +511 -0
  204. erk/core/claude_settings.py +317 -0
  205. erk/core/command_log.py +406 -0
  206. erk/core/commit_message_generator.py +234 -0
  207. erk/core/completion.py +10 -0
  208. erk/core/consolidation_utils.py +177 -0
  209. erk/core/context.py +570 -0
  210. erk/core/display/__init__.py +4 -0
  211. erk/core/display/abc.py +24 -0
  212. erk/core/display/real.py +30 -0
  213. erk/core/display_utils.py +526 -0
  214. erk/core/file_utils.py +87 -0
  215. erk/core/health_checks.py +1315 -0
  216. erk/core/health_checks_dogfooder/__init__.py +85 -0
  217. erk/core/health_checks_dogfooder/deprecated_dot_agent_config.py +64 -0
  218. erk/core/health_checks_dogfooder/legacy_claude_docs.py +69 -0
  219. erk/core/health_checks_dogfooder/legacy_config_locations.py +122 -0
  220. erk/core/health_checks_dogfooder/legacy_erk_docs_agent.py +61 -0
  221. erk/core/health_checks_dogfooder/legacy_erk_kits_folder.py +60 -0
  222. erk/core/health_checks_dogfooder/legacy_hook_settings.py +104 -0
  223. erk/core/health_checks_dogfooder/legacy_kit_yaml.py +78 -0
  224. erk/core/health_checks_dogfooder/legacy_kits_toml.py +43 -0
  225. erk/core/health_checks_dogfooder/outdated_erk_skill.py +43 -0
  226. erk/core/implementation_queue/__init__.py +1 -0
  227. erk/core/implementation_queue/github/__init__.py +8 -0
  228. erk/core/implementation_queue/github/abc.py +7 -0
  229. erk/core/implementation_queue/github/noop.py +38 -0
  230. erk/core/implementation_queue/github/printing.py +43 -0
  231. erk/core/implementation_queue/github/real.py +119 -0
  232. erk/core/init_utils.py +227 -0
  233. erk/core/output_filter.py +338 -0
  234. erk/core/plan_store/__init__.py +6 -0
  235. erk/core/planner/__init__.py +1 -0
  236. erk/core/planner/registry_abc.py +8 -0
  237. erk/core/planner/registry_fake.py +129 -0
  238. erk/core/planner/registry_real.py +195 -0
  239. erk/core/planner/types.py +7 -0
  240. erk/core/pr_utils.py +30 -0
  241. erk/core/release_notes.py +263 -0
  242. erk/core/repo_discovery.py +126 -0
  243. erk/core/script_writer.py +41 -0
  244. erk/core/services/__init__.py +1 -0
  245. erk/core/services/plan_list_service.py +94 -0
  246. erk/core/shell.py +51 -0
  247. erk/core/user_feedback.py +11 -0
  248. erk/core/version_check.py +55 -0
  249. erk/core/workflow_display.py +75 -0
  250. erk/core/worktree_pool.py +190 -0
  251. erk/core/worktree_utils.py +300 -0
  252. erk/data/CHANGELOG.md +438 -0
  253. erk/data/__init__.py +1 -0
  254. erk/data/claude/agents/devrun.md +180 -0
  255. erk/data/claude/commands/erk/__init__.py +0 -0
  256. erk/data/claude/commands/erk/create-extraction-plan.md +360 -0
  257. erk/data/claude/commands/erk/fix-conflicts.md +25 -0
  258. erk/data/claude/commands/erk/git-pr-push.md +345 -0
  259. erk/data/claude/commands/erk/implement-stacked-plan.md +96 -0
  260. erk/data/claude/commands/erk/land.md +193 -0
  261. erk/data/claude/commands/erk/objective-create.md +370 -0
  262. erk/data/claude/commands/erk/objective-list.md +34 -0
  263. erk/data/claude/commands/erk/objective-next-plan.md +220 -0
  264. erk/data/claude/commands/erk/objective-update-with-landed-pr.md +216 -0
  265. erk/data/claude/commands/erk/plan-implement.md +202 -0
  266. erk/data/claude/commands/erk/plan-save.md +45 -0
  267. erk/data/claude/commands/erk/plan-submit.md +39 -0
  268. erk/data/claude/commands/erk/pr-address.md +367 -0
  269. erk/data/claude/commands/erk/pr-submit.md +58 -0
  270. erk/data/claude/skills/dignified-python/SKILL.md +48 -0
  271. erk/data/claude/skills/dignified-python/cli-patterns.md +155 -0
  272. erk/data/claude/skills/dignified-python/dignified-python-core.md +1190 -0
  273. erk/data/claude/skills/dignified-python/subprocess.md +99 -0
  274. erk/data/claude/skills/dignified-python/versions/python-3.10.md +517 -0
  275. erk/data/claude/skills/dignified-python/versions/python-3.11.md +536 -0
  276. erk/data/claude/skills/dignified-python/versions/python-3.12.md +662 -0
  277. erk/data/claude/skills/dignified-python/versions/python-3.13.md +653 -0
  278. erk/data/claude/skills/erk-diff-analysis/SKILL.md +27 -0
  279. erk/data/claude/skills/erk-diff-analysis/references/commit-message-prompt.md +78 -0
  280. erk/data/claude/skills/learned-docs/SKILL.md +362 -0
  281. erk/data/github/actions/setup-claude-erk/action.yml +11 -0
  282. erk/data/github/prompts/dignified-python-review.md +125 -0
  283. erk/data/github/workflows/dignified-python-review.yml +61 -0
  284. erk/data/github/workflows/erk-impl.yml +251 -0
  285. erk/hooks/__init__.py +1 -0
  286. erk/hooks/decorators.py +319 -0
  287. erk/status/__init__.py +8 -0
  288. erk/status/collectors/__init__.py +9 -0
  289. erk/status/collectors/base.py +52 -0
  290. erk/status/collectors/git.py +76 -0
  291. erk/status/collectors/github.py +81 -0
  292. erk/status/collectors/graphite.py +80 -0
  293. erk/status/collectors/impl.py +145 -0
  294. erk/status/models/__init__.py +4 -0
  295. erk/status/models/status_data.py +404 -0
  296. erk/status/orchestrator.py +169 -0
  297. erk/status/renderers/__init__.py +5 -0
  298. erk/status/renderers/simple.py +322 -0
  299. erk/tui/AGENTS.md +193 -0
  300. erk/tui/CLAUDE.md +1 -0
  301. erk/tui/__init__.py +1 -0
  302. erk/tui/app.py +1404 -0
  303. erk/tui/commands/__init__.py +1 -0
  304. erk/tui/commands/executor.py +66 -0
  305. erk/tui/commands/provider.py +165 -0
  306. erk/tui/commands/real_executor.py +63 -0
  307. erk/tui/commands/registry.py +121 -0
  308. erk/tui/commands/types.py +36 -0
  309. erk/tui/data/__init__.py +1 -0
  310. erk/tui/data/provider.py +492 -0
  311. erk/tui/data/types.py +104 -0
  312. erk/tui/filtering/__init__.py +1 -0
  313. erk/tui/filtering/logic.py +43 -0
  314. erk/tui/filtering/types.py +55 -0
  315. erk/tui/jsonl_viewer/__init__.py +1 -0
  316. erk/tui/jsonl_viewer/app.py +61 -0
  317. erk/tui/jsonl_viewer/models.py +208 -0
  318. erk/tui/jsonl_viewer/widgets.py +204 -0
  319. erk/tui/sorting/__init__.py +6 -0
  320. erk/tui/sorting/logic.py +55 -0
  321. erk/tui/sorting/types.py +68 -0
  322. erk/tui/styles/dash.tcss +95 -0
  323. erk/tui/widgets/__init__.py +1 -0
  324. erk/tui/widgets/command_output.py +112 -0
  325. erk/tui/widgets/plan_table.py +276 -0
  326. erk/tui/widgets/status_bar.py +116 -0
  327. erk-0.4.5.dist-info/METADATA +376 -0
  328. erk-0.4.5.dist-info/RECORD +331 -0
  329. erk-0.4.5.dist-info/WHEEL +4 -0
  330. erk-0.4.5.dist-info/entry_points.txt +2 -0
  331. erk-0.4.5.dist-info/licenses/LICENSE.md +3 -0
@@ -0,0 +1,345 @@
1
+ ---
2
+ description: Create git commit and push branch as PR using git + GitHub CLI
3
+ argument-hint: <description>
4
+ ---
5
+
6
+ # Push PR (Git Only)
7
+
8
+ Automatically create a git commit with a helpful summary message and push the current branch as a pull request using standard git + GitHub CLI (no Graphite required).
9
+
10
+ ## Usage
11
+
12
+ ```bash
13
+ # Invoke the command (description argument is optional but recommended)
14
+ /erk:git-pr-push "Add user authentication feature"
15
+
16
+ # Without argument (will analyze changes automatically)
17
+ /erk:git-pr-push
18
+ ```
19
+
20
+ ## What This Command Does
21
+
22
+ Handles the complete git-only push-pr workflow:
23
+
24
+ 1. Check for uncommitted changes and stage/commit them if needed
25
+ 2. Analyze git diff to generate meaningful commit message
26
+ 3. Create commit with AI-generated message
27
+ 4. Push to origin with upstream tracking
28
+ 5. Create GitHub PR (or find existing one)
29
+ 6. Report results with PR URL
30
+
31
+ ## Key Differences from /gt:submit-branch
32
+
33
+ - Uses standard `git push` instead of `gt submit`
34
+ - Uses `gh pr create` instead of Graphite's PR submission
35
+ - No stack operations (no restack, no stack metadata updates)
36
+ - Simpler workflow: git -> push -> PR (no Graphite layer)
37
+ - Works in any git repository (not just Graphite-enabled repos)
38
+
39
+ ## Prerequisites
40
+
41
+ - Git repository with remote configured
42
+ - GitHub CLI (`gh`) installed and authenticated
43
+ - Run `gh auth status` to verify authentication
44
+ - Run `gh auth login` if not authenticated
45
+
46
+ ## Implementation
47
+
48
+ Execute the git-only push-pr workflow with the following steps:
49
+
50
+ ### Step 1: Verify Prerequisites
51
+
52
+ Check GitHub CLI authentication and get current git state:
53
+
54
+ ```bash
55
+ # Check GitHub CLI authentication (show status for verification)
56
+ gh auth status
57
+
58
+ # Get current branch name
59
+ current_branch=$(git branch --show-current)
60
+
61
+ # Check for uncommitted changes
62
+ has_changes=$(git status --porcelain)
63
+ ```
64
+
65
+ If `gh auth status` fails, report error and tell user to run `gh auth login`.
66
+
67
+ ### Step 2: Stage Changes (if needed)
68
+
69
+ If `has_changes` is non-empty, stage all changes:
70
+
71
+ ```bash
72
+ git add .
73
+ ```
74
+
75
+ ### Step 3: Analyze Staged Diff
76
+
77
+ Get the staged diff and analyze it to generate a commit message:
78
+
79
+ ```bash
80
+ # Get repository root for relative paths
81
+ repo_root=$(git rev-parse --show-toplevel)
82
+
83
+ # Get staged diff for analysis
84
+ git diff --staged
85
+ ```
86
+
87
+ Load the `erk-diff-analysis` skill for commit message generation guidance.
88
+
89
+ ### Step 4: Create Commit
90
+
91
+ Create the commit with your AI-generated message using heredoc:
92
+
93
+ ```bash
94
+ git commit -m "$(cat <<'COMMIT_MSG'
95
+ [Your generated commit message here]
96
+ COMMIT_MSG
97
+ )"
98
+ ```
99
+
100
+ ### Step 5: Push to Remote
101
+
102
+ Push the branch to origin with upstream tracking:
103
+
104
+ ```bash
105
+ git push -u origin "$(git branch --show-current)"
106
+ ```
107
+
108
+ ### Step 6: Get Closing Text
109
+
110
+ Get the issue closing text if this worktree was created from a GitHub issue:
111
+
112
+ ```bash
113
+ closing_text=$(erk exec get-closing-text 2>/dev/null || echo "")
114
+ ```
115
+
116
+ This reads `.impl/issue.json` and returns `Closes #N` if an issue reference exists.
117
+
118
+ ### Step 6.5: Check for Existing PR
119
+
120
+ Before creating a new PR, check if one already exists for the current branch:
121
+
122
+ ```bash
123
+ existing_pr=$(gh pr list --head "$(git branch --show-current)" --state open --json number,url,isDraft --jq '.[0]')
124
+ ```
125
+
126
+ **Decision logic:**
127
+
128
+ - If `existing_pr` is empty or null: No existing PR, proceed to Step 7
129
+ - If `existing_pr` has data: PR exists, skip Step 7 and go directly to Step 8
130
+
131
+ If an existing PR was found, extract its details for reporting:
132
+
133
+ ```bash
134
+ pr_url=$(echo "$existing_pr" | jq -r '.url')
135
+ pr_number=$(echo "$existing_pr" | jq -r '.number')
136
+ is_draft=$(echo "$existing_pr" | jq -r '.isDraft')
137
+ ```
138
+
139
+ ### Step 7: Create GitHub PR (if no existing PR)
140
+
141
+ **Skip this step if an existing PR was found in Step 6.5.** The push in Step 5 already updated the existing PR with new commits.
142
+
143
+ Extract PR title (first line) and body (remaining lines) from commit message, then create PR with closing text appended:
144
+
145
+ ```bash
146
+ # Get the commit message
147
+ commit_msg=$(git log -1 --pretty=%B)
148
+
149
+ # Extract first line as title
150
+ pr_title=$(echo "$commit_msg" | head -n 1)
151
+
152
+ # Extract remaining lines as body (skip empty first line after title)
153
+ commit_body=$(echo "$commit_msg" | tail -n +2)
154
+
155
+ # Append closing text if present
156
+ if [ -n "$closing_text" ]; then
157
+ pr_body="${commit_body}
158
+
159
+ ${closing_text}"
160
+ else
161
+ pr_body="${commit_body}"
162
+ fi
163
+
164
+ # Create PR using GitHub CLI
165
+ gh pr create --title "$pr_title" --body "$pr_body"
166
+ ```
167
+
168
+ ### Step 8: Validate PR Rules
169
+
170
+ Run the PR check command to validate the PR was created correctly:
171
+
172
+ ```bash
173
+ erk pr check
174
+ ```
175
+
176
+ This validates:
177
+
178
+ - Issue closing reference (Closes #N) is present when `.impl/issue.json` exists
179
+ - PR body contains the standard checkout footer
180
+
181
+ If any checks fail, display the output and warn the user, but continue to Step 9.
182
+
183
+ ### Step 9: Report Results
184
+
185
+ Display a clear summary based on whether a PR was created or found:
186
+
187
+ **If a NEW PR was created (Step 7 was executed):**
188
+
189
+ ```
190
+ ## Branch Submission Complete
191
+
192
+ ### What Was Done
193
+
194
+ ✓ Staged all uncommitted changes
195
+ ✓ Created commit with AI-generated message
196
+ ✓ Pushed branch to origin with upstream tracking
197
+ ✓ Created GitHub PR
198
+ ✓ Linked to issue #N (will auto-close on merge) [only if closing_text was present]
199
+
200
+ ### View PR
201
+
202
+ [PR URL from gh pr create output]
203
+ ```
204
+
205
+ **If an EXISTING PR was found (Step 7 was skipped):**
206
+
207
+ ```
208
+ ## Branch Submission Complete
209
+
210
+ ### What Was Done
211
+
212
+ ✓ Staged all uncommitted changes
213
+ ✓ Created commit with AI-generated message
214
+ ✓ Pushed branch to origin with upstream tracking
215
+ ✓ Found existing PR #N for this branch (skipped PR creation)
216
+ ✓ Linked to issue #M (will auto-close on merge) [only if closing_text was present]
217
+
218
+ ### Note
219
+
220
+ [If is_draft is true]: This is a draft PR. When ready for review, run: `gh pr ready`
221
+
222
+ ### View PR
223
+
224
+ [PR URL extracted from existing_pr]
225
+ ```
226
+
227
+ **Conditional lines:**
228
+
229
+ - The "Linked to issue" line should only appear if `closing_text` was non-empty
230
+ - The "Note" section with draft guidance should only appear if `is_draft` is true
231
+
232
+ **CRITICAL**: The PR URL MUST be the absolute last line of your output. Do not add any text after it.
233
+
234
+ ## Error Handling
235
+
236
+ When errors occur, provide clear guidance:
237
+
238
+ **GitHub CLI not authenticated:**
239
+
240
+ ```
241
+ ❌ GitHub CLI is not authenticated
242
+
243
+ To use this command, authenticate with GitHub:
244
+ gh auth login
245
+ ```
246
+
247
+ **Nothing to commit:**
248
+
249
+ ```
250
+ ❌ No changes to commit
251
+
252
+ Your working directory is clean. Make some changes first.
253
+ ```
254
+
255
+ **Push failed (diverged branches):**
256
+
257
+ ```
258
+ ❌ Push failed: branch has diverged
259
+
260
+ Option 1: Pull and merge
261
+ git pull origin [branch]
262
+
263
+ Option 2: Force push (⚠️ overwrites remote)
264
+ git push -f origin [branch]
265
+ ```
266
+
267
+ Note: The "PR already exists" case is now handled automatically in Step 6.5. If a PR exists for the current branch, the command will skip PR creation and report the existing PR URL instead.
268
+
269
+ ## Best Practices
270
+
271
+ ### Never Change Directory
272
+
273
+ **NEVER use `cd` during execution.** Always use absolute paths or git's `-C` flag.
274
+
275
+ ```bash
276
+ # ❌ WRONG
277
+ cd /path/to/repo && git status
278
+
279
+ # ✅ CORRECT
280
+ git -C /path/to/repo status
281
+ ```
282
+
283
+ **Rationale:** Changing directories pollutes the execution context and makes it harder to reason about state. The working directory should remain stable throughout the entire workflow.
284
+
285
+ ### Never Write to Temporary Files
286
+
287
+ **NEVER write commit messages or other content to temporary files.** Always use in-context manipulation and shell built-ins.
288
+
289
+ ```bash
290
+ # ❌ WRONG - Triggers permission prompts
291
+ echo "$message" > "${TMPDIR:-/tmp}/commit_msg.txt"
292
+ git commit -F "${TMPDIR:-/tmp}/commit_msg.txt"
293
+
294
+ # ✅ CORRECT - In-memory heredoc
295
+ git commit -m "$(cat <<'EOF'
296
+ $message
297
+ EOF
298
+ )"
299
+ ```
300
+
301
+ **Rationale:** Temporary files require filesystem permissions and create unnecessary I/O. Since agents operate in isolated contexts, there's no risk of context pollution from in-memory manipulation.
302
+
303
+ ## Quality Standards
304
+
305
+ ### Always
306
+
307
+ - Be concise and strategic in analysis
308
+ - Use component-level descriptions
309
+ - Highlight breaking changes prominently
310
+ - Note test coverage patterns
311
+ - Use relative paths from repository root
312
+ - Provide clear error guidance
313
+ - Use standard git + GitHub CLI commands (no Graphite dependencies)
314
+
315
+ ### Never
316
+
317
+ - Add Claude attribution or footer to commit messages
318
+ - Speculate about intentions without code evidence
319
+ - Provide exhaustive lists of every function touched
320
+ - Include implementation details (specific variable names, line numbers)
321
+ - Provide time estimates
322
+ - Use vague language like "various changes"
323
+ - Retry failed operations automatically
324
+ - Write to temporary files (use in-context quoting and shell built-ins instead)
325
+ - Use Graphite-specific commands (`gt submit`, `gt restack`, etc.)
326
+
327
+ ## Self-Verification
328
+
329
+ Before completing, verify:
330
+
331
+ - [ ] GitHub CLI authentication checked
332
+ - [ ] Git status verified
333
+ - [ ] Uncommitted changes staged (if any existed)
334
+ - [ ] Staged diff analyzed
335
+ - [ ] Diff analysis is concise and strategic (3-5 key changes max)
336
+ - [ ] Commit message has no Claude footer
337
+ - [ ] File paths are relative to repository root
338
+ - [ ] Commit created successfully
339
+ - [ ] Branch pushed to origin with upstream tracking
340
+ - [ ] Closing text obtained (if issue reference exists)
341
+ - [ ] GitHub PR created successfully (or existing PR found)
342
+ - [ ] PR URL extracted from output
343
+ - [ ] Results displayed with "What Was Done" section listing actions
344
+ - [ ] PR URL placed at end under "View PR" section
345
+ - [ ] Any errors handled with helpful guidance
@@ -0,0 +1,96 @@
1
+ ---
2
+ description: Create a stacked branch and implement a saved plan
3
+ ---
4
+
5
+ # /erk:implement-stacked-plan
6
+
7
+ Create a graphite-stacked branch from a saved plan issue and implement it in the current worktree.
8
+
9
+ ## Usage
10
+
11
+ ```
12
+ /erk:implement-stacked-plan <issue-number>
13
+ ```
14
+
15
+ ## When to Use This Command
16
+
17
+ ✅ **Use when**: You have a saved plan (GitHub issue) and want to implement it as a stacked branch on top of your current branch.
18
+
19
+ ❌ **Don't use when**:
20
+
21
+ - You just finished planning and want to save + implement → Use `/erk:plan-implement`
22
+ - You want to implement in a new worktree → Use `erk implement <issue-number>`
23
+
24
+ ## Prerequisites
25
+
26
+ - Must be in a git repository managed by erk
27
+ - Must have a saved plan issue on GitHub (with `erk-plan` label)
28
+ - GitHub CLI (`gh`) must be authenticated
29
+ - Graphite CLI (`gt`) must be available
30
+
31
+ ---
32
+
33
+ ## Agent Instructions
34
+
35
+ ### Step 1: Validate Argument
36
+
37
+ Extract the issue number from the argument (handles `#123` or `123` format).
38
+
39
+ If no issue number provided, display usage and stop:
40
+
41
+ ```
42
+ Usage: /erk:implement-stacked-plan <issue-number>
43
+
44
+ Example: /erk:implement-stacked-plan 4128
45
+ ```
46
+
47
+ ### Step 2: Record Current Branch
48
+
49
+ Get the current branch name (this will be the parent for stacking):
50
+
51
+ ```bash
52
+ git branch --show-current
53
+ ```
54
+
55
+ Save this as `parent_branch`.
56
+
57
+ ### Step 3: Setup Implementation
58
+
59
+ Run the setup command to fetch the plan, create the branch, and set up `.impl/`:
60
+
61
+ ```bash
62
+ erk exec setup-impl-from-issue <issue-number>
63
+ ```
64
+
65
+ Parse the output to get the `branch` name from the JSON.
66
+
67
+ If this fails, display the error and stop.
68
+
69
+ ### Step 4: Track with Graphite
70
+
71
+ Register the new branch with graphite, stacked on the parent:
72
+
73
+ ```bash
74
+ gt track --branch <branch-name> --parent <parent_branch>
75
+ ```
76
+
77
+ This makes the branch part of the graphite stack for proper PR management.
78
+
79
+ ### Step 5: Execute Implementation
80
+
81
+ Invoke the standard implementation workflow:
82
+
83
+ ```
84
+ /erk:plan-implement
85
+ ```
86
+
87
+ This handles all remaining steps: reading the plan, loading context, executing phases, running CI, and creating the PR.
88
+
89
+ ---
90
+
91
+ ## Notes
92
+
93
+ - The issue must have the `erk-plan` label
94
+ - The branch will be stacked on whatever branch you were on when you started
95
+ - Use this when you want to add a stacked change in the current worktree
96
+ - Differs from `erk implement` which creates a new worktree
@@ -0,0 +1,193 @@
1
+ ---
2
+ description: Land PR with objective awareness - updates objective after landing
3
+ argument-hint: "[branch|PR#|URL] [--skip-objective]"
4
+ ---
5
+
6
+ # /erk:pr-land
7
+
8
+ Objective-aware wrapper for `erk pr land`. Lands the PR first, then offers to update the linked objective if one exists.
9
+
10
+ ## Usage
11
+
12
+ ```bash
13
+ # Land PR for current branch
14
+ /erk:pr-land
15
+
16
+ # Land PR for specific branch
17
+ /erk:pr-land feature-branch
18
+
19
+ # Land PR by number
20
+ /erk:pr-land 123
21
+
22
+ # Land PR by URL
23
+ /erk:pr-land https://github.com/owner/repo/pull/123
24
+
25
+ # Skip objective update prompt
26
+ /erk:pr-land --skip-objective
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Agent Instructions
32
+
33
+ ### Step 1: Parse Arguments
34
+
35
+ Parse the command arguments:
36
+
37
+ - `$ARGUMENTS` may contain: branch name, PR number, PR URL, or be empty (use current branch)
38
+ - Check for `--skip-objective` flag
39
+
40
+ ### Step 2: Determine Branch Name
41
+
42
+ If no branch argument provided, get current branch:
43
+
44
+ ```bash
45
+ git branch --show-current
46
+ ```
47
+
48
+ If argument is a PR number or URL, extract the branch name:
49
+
50
+ ```bash
51
+ # For PR number
52
+ gh pr view <number> --json headRefName -q '.headRefName'
53
+
54
+ # For PR URL (extract number first, then use above)
55
+ ```
56
+
57
+ ### Step 3: Resolve to PR Number
58
+
59
+ **Critical:** Always resolve the branch to a PR number. The `erk pr land` command only accepts PR numbers or URLs, not branch names.
60
+
61
+ ```bash
62
+ # Get PR number for branch
63
+ gh pr list --head <branch-name> --state open --json number -q '.[0].number'
64
+ ```
65
+
66
+ If no open PR found, check all states:
67
+
68
+ ```bash
69
+ gh pr list --head <branch-name> --state all --limit 1 --json number -q '.[0].number'
70
+ ```
71
+
72
+ **If no PR found:** Report error and exit - cannot land without a PR.
73
+
74
+ ### Step 4: Extract Plan Issue Number (P-prefix Detection)
75
+
76
+ Parse the plan issue number from the branch name pattern `P<number>-...`
77
+
78
+ Example: `P3699-objective-aware-pr-land` -> Plan Issue #3699
79
+
80
+ **If branch doesn't have P-prefix:** Record that there's no plan link. Continue to Step 6.
81
+
82
+ ### Step 5: Check for Objective Link
83
+
84
+ If branch has P-prefix, use the `get-plan-metadata` exec command to extract the objective issue:
85
+
86
+ ```bash
87
+ erk exec get-plan-metadata <plan-number> objective_issue
88
+ ```
89
+
90
+ **Output format:**
91
+
92
+ ```json
93
+ {
94
+ "success": true,
95
+ "value": 3400,
96
+ "issue_number": 3509,
97
+ "field": "objective_issue"
98
+ }
99
+ ```
100
+
101
+ - If `success` is `true` and `value` is an integer, record that objective issue number
102
+ - If `success` is `true` and `value` is `null`, there's no objective link
103
+ - If `success` is `false`, warn and skip objective workflow (fail-open behavior)
104
+
105
+ ### Step 6: Execute erk pr land
106
+
107
+ Land the PR using the resolved PR number. Use `--force` to skip interactive confirmation (required for non-TTY execution):
108
+
109
+ ```bash
110
+ erk pr land <PR_NUMBER> --force
111
+ ```
112
+
113
+ **If landing fails:** Report the error and exit.
114
+
115
+ ### Step 7: Post-Land Objective Update
116
+
117
+ **Only runs if:** Landing succeeded AND plan has `objective_issue` AND `--skip-objective` not passed
118
+
119
+ 1. Display: "PR #`<pr>` landed successfully."
120
+ 2. Display: "This PR is part of Objective #`<objective>`."
121
+ 3. Prompt user with AskUserQuestion:
122
+
123
+ ```
124
+ Would you like to update the objective now?
125
+
126
+ Options:
127
+ 1. Yes, update objective (Recommended)
128
+ 2. Skip - I'll update it later
129
+ ```
130
+
131
+ **If user selects "Yes":**
132
+
133
+ Run the `/erk:objective-update-with-landed-pr` workflow inline:
134
+
135
+ 1. Post an action comment to the objective issue with:
136
+ - What was done (infer from PR title/description)
137
+ - Lessons learned (infer from implementation)
138
+ - Roadmap updates (which steps are now done)
139
+
140
+ 2. Update the objective body:
141
+ - Mark relevant roadmap steps as `done`
142
+ - Add PR number to the step
143
+ - Update "Current Focus" section
144
+
145
+ 3. Check if all steps are complete - if so, offer to close the objective.
146
+
147
+ **If user selects "Skip":** Just report success and remind them to update later.
148
+
149
+ ### Step 8: Report Results
150
+
151
+ Display final status:
152
+
153
+ - PR landing result
154
+ - Objective update result (if applicable)
155
+ - Link to objective issue (if applicable)
156
+
157
+ ---
158
+
159
+ ## Fail-Open Behavior
160
+
161
+ The command lands normally (no blocking) when:
162
+
163
+ | Scenario | Action |
164
+ | --------------------------------- | ------------------------------- |
165
+ | Branch has no P-prefix | Land normally, skip objective |
166
+ | Plan issue not found | Warn, land normally |
167
+ | `objective_issue` is null/missing | Land normally, skip objective |
168
+ | `--skip-objective` flag passed | Land normally, skip objective |
169
+ | Objective update fails | Warn but report landing success |
170
+ | Any parsing/API error | Warn, continue with landing |
171
+
172
+ **Principle:** Landing always proceeds. Objective update is post-land and optional.
173
+
174
+ ---
175
+
176
+ ## Output Format
177
+
178
+ - **Start:** "Resolving PR for branch..."
179
+ - **No PR found:** "Error: No PR found for branch `<branch>`"
180
+ - **Landing:** "Landing PR #`<number>`..."
181
+ - **Success:** "PR #`<number>` landed successfully."
182
+ - **Objective prompt:** (as shown above)
183
+ - **Objective updated:** "Objective #`<number>` updated."
184
+ - **End:** Show final status and any relevant links
185
+
186
+ ---
187
+
188
+ ## Error Handling
189
+
190
+ - **No PR found:** Report error and exit (cannot land without PR)
191
+ - **Landing fails:** Report `erk pr land` error output and exit
192
+ - **Objective update fails:** Warn but report landing as successful
193
+ - **API errors during objective check:** Warn and skip objective workflow