gencode-ai 0.1.0

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 (274) hide show
  1. package/.env.example +11 -0
  2. package/CLAUDE.md +70 -0
  3. package/LICENSE +21 -0
  4. package/README.md +117 -0
  5. package/dist/agent/agent.d.ts +84 -0
  6. package/dist/agent/agent.d.ts.map +1 -0
  7. package/dist/agent/agent.js +233 -0
  8. package/dist/agent/agent.js.map +1 -0
  9. package/dist/agent/index.d.ts +6 -0
  10. package/dist/agent/index.d.ts.map +1 -0
  11. package/dist/agent/index.js +6 -0
  12. package/dist/agent/index.js.map +1 -0
  13. package/dist/agent/types.d.ts +47 -0
  14. package/dist/agent/types.d.ts.map +1 -0
  15. package/dist/agent/types.js +5 -0
  16. package/dist/agent/types.js.map +1 -0
  17. package/dist/cli/components/App.d.ts +14 -0
  18. package/dist/cli/components/App.d.ts.map +1 -0
  19. package/dist/cli/components/App.js +395 -0
  20. package/dist/cli/components/App.js.map +1 -0
  21. package/dist/cli/components/CommandSuggestions.d.ts +13 -0
  22. package/dist/cli/components/CommandSuggestions.d.ts.map +1 -0
  23. package/dist/cli/components/CommandSuggestions.js +32 -0
  24. package/dist/cli/components/CommandSuggestions.js.map +1 -0
  25. package/dist/cli/components/Header.d.ts +9 -0
  26. package/dist/cli/components/Header.d.ts.map +1 -0
  27. package/dist/cli/components/Header.js +13 -0
  28. package/dist/cli/components/Header.js.map +1 -0
  29. package/dist/cli/components/Input.d.ts +13 -0
  30. package/dist/cli/components/Input.d.ts.map +1 -0
  31. package/dist/cli/components/Input.js +27 -0
  32. package/dist/cli/components/Input.js.map +1 -0
  33. package/dist/cli/components/Logo.d.ts +2 -0
  34. package/dist/cli/components/Logo.d.ts.map +1 -0
  35. package/dist/cli/components/Logo.js +8 -0
  36. package/dist/cli/components/Logo.js.map +1 -0
  37. package/dist/cli/components/Messages.d.ts +37 -0
  38. package/dist/cli/components/Messages.d.ts.map +1 -0
  39. package/dist/cli/components/Messages.js +106 -0
  40. package/dist/cli/components/Messages.js.map +1 -0
  41. package/dist/cli/components/ModelSelector.d.ts +13 -0
  42. package/dist/cli/components/ModelSelector.d.ts.map +1 -0
  43. package/dist/cli/components/ModelSelector.js +72 -0
  44. package/dist/cli/components/ModelSelector.js.map +1 -0
  45. package/dist/cli/components/Spinner.d.ts +12 -0
  46. package/dist/cli/components/Spinner.d.ts.map +1 -0
  47. package/dist/cli/components/Spinner.js +45 -0
  48. package/dist/cli/components/Spinner.js.map +1 -0
  49. package/dist/cli/components/index.d.ts +12 -0
  50. package/dist/cli/components/index.d.ts.map +1 -0
  51. package/dist/cli/components/index.js +12 -0
  52. package/dist/cli/components/index.js.map +1 -0
  53. package/dist/cli/components/theme.d.ts +31 -0
  54. package/dist/cli/components/theme.d.ts.map +1 -0
  55. package/dist/cli/components/theme.js +36 -0
  56. package/dist/cli/components/theme.js.map +1 -0
  57. package/dist/cli/index-legacy.d.ts +7 -0
  58. package/dist/cli/index-legacy.d.ts.map +1 -0
  59. package/dist/cli/index-legacy.js +431 -0
  60. package/dist/cli/index-legacy.js.map +1 -0
  61. package/dist/cli/index.d.ts +7 -0
  62. package/dist/cli/index.d.ts.map +1 -0
  63. package/dist/cli/index.js +116 -0
  64. package/dist/cli/index.js.map +1 -0
  65. package/dist/cli/ink-cli.d.ts +7 -0
  66. package/dist/cli/ink-cli.d.ts.map +1 -0
  67. package/dist/cli/ink-cli.js +105 -0
  68. package/dist/cli/ink-cli.js.map +1 -0
  69. package/dist/cli/session-picker.d.ts +16 -0
  70. package/dist/cli/session-picker.d.ts.map +1 -0
  71. package/dist/cli/session-picker.js +280 -0
  72. package/dist/cli/session-picker.js.map +1 -0
  73. package/dist/cli/ui.d.ts +61 -0
  74. package/dist/cli/ui.d.ts.map +1 -0
  75. package/dist/cli/ui.js +364 -0
  76. package/dist/cli/ui.js.map +1 -0
  77. package/dist/config/index.d.ts +7 -0
  78. package/dist/config/index.d.ts.map +1 -0
  79. package/dist/config/index.js +6 -0
  80. package/dist/config/index.js.map +1 -0
  81. package/dist/config/manager.d.ts +31 -0
  82. package/dist/config/manager.d.ts.map +1 -0
  83. package/dist/config/manager.js +65 -0
  84. package/dist/config/manager.js.map +1 -0
  85. package/dist/config/types.d.ts +22 -0
  86. package/dist/config/types.d.ts.map +1 -0
  87. package/dist/config/types.js +6 -0
  88. package/dist/config/types.js.map +1 -0
  89. package/dist/index.d.ts +12 -0
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +21 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/memory/index.d.ts +10 -0
  94. package/dist/memory/index.d.ts.map +1 -0
  95. package/dist/memory/index.js +9 -0
  96. package/dist/memory/index.js.map +1 -0
  97. package/dist/memory/init.d.ts +20 -0
  98. package/dist/memory/init.d.ts.map +1 -0
  99. package/dist/memory/init.js +332 -0
  100. package/dist/memory/init.js.map +1 -0
  101. package/dist/memory/manager.d.ts +85 -0
  102. package/dist/memory/manager.d.ts.map +1 -0
  103. package/dist/memory/manager.js +234 -0
  104. package/dist/memory/manager.js.map +1 -0
  105. package/dist/memory/types.d.ts +74 -0
  106. package/dist/memory/types.d.ts.map +1 -0
  107. package/dist/memory/types.js +6 -0
  108. package/dist/memory/types.js.map +1 -0
  109. package/dist/permissions/index.d.ts +7 -0
  110. package/dist/permissions/index.d.ts.map +1 -0
  111. package/dist/permissions/index.js +6 -0
  112. package/dist/permissions/index.js.map +1 -0
  113. package/dist/permissions/manager.d.ts +32 -0
  114. package/dist/permissions/manager.d.ts.map +1 -0
  115. package/dist/permissions/manager.js +79 -0
  116. package/dist/permissions/manager.js.map +1 -0
  117. package/dist/permissions/types.d.ts +14 -0
  118. package/dist/permissions/types.d.ts.map +1 -0
  119. package/dist/permissions/types.js +17 -0
  120. package/dist/permissions/types.js.map +1 -0
  121. package/dist/providers/anthropic.d.ts +20 -0
  122. package/dist/providers/anthropic.d.ts.map +1 -0
  123. package/dist/providers/anthropic.js +185 -0
  124. package/dist/providers/anthropic.js.map +1 -0
  125. package/dist/providers/gemini.d.ts +21 -0
  126. package/dist/providers/gemini.d.ts.map +1 -0
  127. package/dist/providers/gemini.js +241 -0
  128. package/dist/providers/gemini.js.map +1 -0
  129. package/dist/providers/index.d.ts +34 -0
  130. package/dist/providers/index.d.ts.map +1 -0
  131. package/dist/providers/index.js +72 -0
  132. package/dist/providers/index.js.map +1 -0
  133. package/dist/providers/openai.d.ts +19 -0
  134. package/dist/providers/openai.d.ts.map +1 -0
  135. package/dist/providers/openai.js +221 -0
  136. package/dist/providers/openai.js.map +1 -0
  137. package/dist/providers/types.d.ts +125 -0
  138. package/dist/providers/types.d.ts.map +1 -0
  139. package/dist/providers/types.js +6 -0
  140. package/dist/providers/types.js.map +1 -0
  141. package/dist/session/index.d.ts +6 -0
  142. package/dist/session/index.d.ts.map +1 -0
  143. package/dist/session/index.js +6 -0
  144. package/dist/session/index.js.map +1 -0
  145. package/dist/session/manager.d.ts +101 -0
  146. package/dist/session/manager.d.ts.map +1 -0
  147. package/dist/session/manager.js +295 -0
  148. package/dist/session/manager.js.map +1 -0
  149. package/dist/session/types.d.ts +39 -0
  150. package/dist/session/types.d.ts.map +1 -0
  151. package/dist/session/types.js +10 -0
  152. package/dist/session/types.js.map +1 -0
  153. package/dist/tools/builtin/bash.d.ts +7 -0
  154. package/dist/tools/builtin/bash.d.ts.map +1 -0
  155. package/dist/tools/builtin/bash.js +80 -0
  156. package/dist/tools/builtin/bash.js.map +1 -0
  157. package/dist/tools/builtin/edit.d.ts +7 -0
  158. package/dist/tools/builtin/edit.d.ts.map +1 -0
  159. package/dist/tools/builtin/edit.js +32 -0
  160. package/dist/tools/builtin/edit.js.map +1 -0
  161. package/dist/tools/builtin/glob.d.ts +7 -0
  162. package/dist/tools/builtin/glob.d.ts.map +1 -0
  163. package/dist/tools/builtin/glob.js +36 -0
  164. package/dist/tools/builtin/glob.js.map +1 -0
  165. package/dist/tools/builtin/grep.d.ts +7 -0
  166. package/dist/tools/builtin/grep.d.ts.map +1 -0
  167. package/dist/tools/builtin/grep.js +59 -0
  168. package/dist/tools/builtin/grep.js.map +1 -0
  169. package/dist/tools/builtin/read.d.ts +7 -0
  170. package/dist/tools/builtin/read.d.ts.map +1 -0
  171. package/dist/tools/builtin/read.js +29 -0
  172. package/dist/tools/builtin/read.js.map +1 -0
  173. package/dist/tools/builtin/write.d.ts +7 -0
  174. package/dist/tools/builtin/write.d.ts.map +1 -0
  175. package/dist/tools/builtin/write.js +24 -0
  176. package/dist/tools/builtin/write.js.map +1 -0
  177. package/dist/tools/index.d.ts +38 -0
  178. package/dist/tools/index.d.ts.map +1 -0
  179. package/dist/tools/index.js +32 -0
  180. package/dist/tools/index.js.map +1 -0
  181. package/dist/tools/registry.d.ts +22 -0
  182. package/dist/tools/registry.d.ts.map +1 -0
  183. package/dist/tools/registry.js +71 -0
  184. package/dist/tools/registry.js.map +1 -0
  185. package/dist/tools/types.d.ts +62 -0
  186. package/dist/tools/types.d.ts.map +1 -0
  187. package/dist/tools/types.js +126 -0
  188. package/dist/tools/types.js.map +1 -0
  189. package/docs/README.md +16 -0
  190. package/docs/proposals/0001-web-fetch-tool.md +293 -0
  191. package/docs/proposals/0002-web-search-tool.md +306 -0
  192. package/docs/proposals/0003-task-subagents.md +333 -0
  193. package/docs/proposals/0004-plan-mode.md +338 -0
  194. package/docs/proposals/0005-todo-system.md +299 -0
  195. package/docs/proposals/0006-memory-system.md +539 -0
  196. package/docs/proposals/0007-context-management.md +429 -0
  197. package/docs/proposals/0008-checkpointing.md +327 -0
  198. package/docs/proposals/0009-hooks-system.md +343 -0
  199. package/docs/proposals/0010-mcp-integration.md +382 -0
  200. package/docs/proposals/0011-custom-commands.md +374 -0
  201. package/docs/proposals/0012-ask-user-question.md +317 -0
  202. package/docs/proposals/0013-multi-edit-tool.md +345 -0
  203. package/docs/proposals/0014-lsp-tool.md +478 -0
  204. package/docs/proposals/0015-ls-tool.md +407 -0
  205. package/docs/proposals/0016-kill-shell-tool.md +455 -0
  206. package/docs/proposals/0017-background-tasks.md +489 -0
  207. package/docs/proposals/0018-parallel-tool-execution.md +415 -0
  208. package/docs/proposals/0019-session-enhancements.md +462 -0
  209. package/docs/proposals/0020-session-summarization.md +447 -0
  210. package/docs/proposals/0021-skills-system.md +409 -0
  211. package/docs/proposals/0022-plugin-system.md +467 -0
  212. package/docs/proposals/0023-permission-enhancements.md +470 -0
  213. package/docs/proposals/0024-keyboard-shortcuts.md +443 -0
  214. package/docs/proposals/0025-cost-tracking.md +447 -0
  215. package/docs/proposals/0026-git-integration.md +475 -0
  216. package/docs/proposals/0027-enhanced-read-tool.md +514 -0
  217. package/docs/proposals/0028-enhanced-bash-tool.md +511 -0
  218. package/docs/proposals/0029-notebook-edit-tool.md +413 -0
  219. package/docs/proposals/0030-plugin-marketplace.md +360 -0
  220. package/docs/proposals/0031-command-suggestions.md +295 -0
  221. package/docs/proposals/0032-ide-integrations.md +328 -0
  222. package/docs/proposals/0033-enterprise-deployment.md +221 -0
  223. package/docs/proposals/0034-sandboxing.md +273 -0
  224. package/docs/proposals/0035-auto-updater.md +311 -0
  225. package/docs/proposals/0036-enhanced-glob-tool.md +267 -0
  226. package/docs/proposals/0037-enhanced-grep-tool.md +360 -0
  227. package/docs/proposals/0038-interactive-cli-ui.md +373 -0
  228. package/docs/proposals/0039-streaming-enhancements.md +359 -0
  229. package/docs/proposals/0040-multi-provider-enhancements.md +369 -0
  230. package/docs/proposals/README.md +84 -0
  231. package/docs/proposals/TEMPLATE.md +57 -0
  232. package/docs/proposals/research/claude-code-research.md +307 -0
  233. package/examples/agent-demo.ts +115 -0
  234. package/examples/basic.ts +166 -0
  235. package/package.json +50 -0
  236. package/src/agent/agent.ts +276 -0
  237. package/src/agent/index.ts +6 -0
  238. package/src/agent/types.ts +62 -0
  239. package/src/cli/components/App.tsx +565 -0
  240. package/src/cli/components/CommandSuggestions.tsx +58 -0
  241. package/src/cli/components/Header.tsx +36 -0
  242. package/src/cli/components/Input.tsx +60 -0
  243. package/src/cli/components/Logo.tsx +16 -0
  244. package/src/cli/components/Messages.tsx +210 -0
  245. package/src/cli/components/ModelSelector.tsx +135 -0
  246. package/src/cli/components/Spinner.tsx +72 -0
  247. package/src/cli/components/index.ts +21 -0
  248. package/src/cli/components/theme.ts +36 -0
  249. package/src/cli/index.tsx +136 -0
  250. package/src/config/index.ts +7 -0
  251. package/src/config/manager.ts +77 -0
  252. package/src/config/types.ts +25 -0
  253. package/src/index.ts +86 -0
  254. package/src/permissions/index.ts +7 -0
  255. package/src/permissions/manager.ts +97 -0
  256. package/src/permissions/types.ts +29 -0
  257. package/src/providers/anthropic.ts +224 -0
  258. package/src/providers/gemini.ts +295 -0
  259. package/src/providers/index.ts +97 -0
  260. package/src/providers/openai.ts +261 -0
  261. package/src/providers/types.ts +181 -0
  262. package/src/session/index.ts +6 -0
  263. package/src/session/manager.ts +354 -0
  264. package/src/session/types.ts +49 -0
  265. package/src/tools/builtin/bash.ts +92 -0
  266. package/src/tools/builtin/edit.ts +37 -0
  267. package/src/tools/builtin/glob.ts +42 -0
  268. package/src/tools/builtin/grep.ts +67 -0
  269. package/src/tools/builtin/read.ts +34 -0
  270. package/src/tools/builtin/write.ts +27 -0
  271. package/src/tools/index.ts +36 -0
  272. package/src/tools/registry.ts +83 -0
  273. package/src/tools/types.ts +172 -0
  274. package/tsconfig.json +21 -0
@@ -0,0 +1,475 @@
1
+ # Proposal: Git Integration
2
+
3
+ - **Proposal ID**: 0026
4
+ - **Author**: mycode team
5
+ - **Status**: Draft
6
+ - **Created**: 2025-01-15
7
+ - **Updated**: 2025-01-15
8
+
9
+ ## Summary
10
+
11
+ Implement native Git integration with specialized tools and workflows for version control operations. This provides the agent with git-aware context and safe commit/PR creation capabilities.
12
+
13
+ ## Motivation
14
+
15
+ Currently, mycode uses Bash for all git operations:
16
+
17
+ 1. **No git awareness**: Agent doesn't know repo state
18
+ 2. **Unsafe operations**: Easy to run destructive commands
19
+ 3. **Manual workflows**: PR creation is multi-step
20
+ 4. **No diff context**: Agent doesn't see changes
21
+ 5. **Repetitive prompts**: Same git patterns repeated
22
+
23
+ Native git integration enables safe, efficient version control.
24
+
25
+ ## Claude Code Reference
26
+
27
+ Claude Code provides extensive git integration:
28
+
29
+ ### Git Safety Protocol
30
+ ```
31
+ - NEVER update the git config
32
+ - NEVER run destructive/irreversible commands (force push, hard reset)
33
+ - NEVER skip hooks (--no-verify)
34
+ - NEVER force push to main/master
35
+ - Avoid git commit --amend unless conditions are met
36
+ - NEVER commit unless explicitly asked
37
+ ```
38
+
39
+ ### Commit Workflow
40
+ ```
41
+ 1. Run git status (never use -uall flag)
42
+ 2. Run git diff for staged/unstaged changes
43
+ 3. Run git log for recent commit style
44
+ 4. Analyze changes, draft commit message
45
+ 5. Add files, create commit with:
46
+ Co-Authored-By: Claude <noreply@anthropic.com>
47
+ 6. Run git status to verify
48
+ ```
49
+
50
+ ### PR Creation Workflow
51
+ ```
52
+ 1. git status, git diff, check remote tracking
53
+ 2. git log and git diff [base]...HEAD for commit history
54
+ 3. Create branch if needed
55
+ 4. Push with -u flag
56
+ 5. Create PR with gh pr create
57
+ ```
58
+
59
+ ## Detailed Design
60
+
61
+ ### API Design
62
+
63
+ ```typescript
64
+ // src/git/types.ts
65
+ interface GitContext {
66
+ isRepo: boolean;
67
+ branch: string;
68
+ remoteBranch?: string;
69
+ defaultBranch: string;
70
+ hasUncommittedChanges: boolean;
71
+ hasUntrackedFiles: boolean;
72
+ aheadBehind?: { ahead: number; behind: number };
73
+ lastCommit?: {
74
+ hash: string;
75
+ message: string;
76
+ author: string;
77
+ date: Date;
78
+ };
79
+ }
80
+
81
+ interface GitStatus {
82
+ staged: FileChange[];
83
+ unstaged: FileChange[];
84
+ untracked: string[];
85
+ }
86
+
87
+ interface FileChange {
88
+ path: string;
89
+ status: 'added' | 'modified' | 'deleted' | 'renamed';
90
+ oldPath?: string; // For renames
91
+ }
92
+
93
+ interface CommitOptions {
94
+ message: string;
95
+ files?: string[]; // Specific files (default: staged)
96
+ coAuthor?: string; // Co-author for attribution
97
+ signOff?: boolean; // DCO sign-off
98
+ allowEmpty?: boolean;
99
+ }
100
+
101
+ interface PROptions {
102
+ title: string;
103
+ body: string;
104
+ base?: string; // Base branch
105
+ draft?: boolean;
106
+ labels?: string[];
107
+ reviewers?: string[];
108
+ }
109
+
110
+ // Safety constraints
111
+ interface GitSafetyConfig {
112
+ blockDestructive: boolean; // Block force push, hard reset
113
+ requireConfirmation: string[]; // Commands needing confirmation
114
+ protectedBranches: string[]; // Branches that can't be modified
115
+ requireSignOff: boolean;
116
+ }
117
+ ```
118
+
119
+ ### Git Tool
120
+
121
+ ```typescript
122
+ // src/tools/git/git-tool.ts
123
+ const gitTool: Tool<GitInput> = {
124
+ name: 'Git',
125
+ description: `Perform git operations safely.
126
+
127
+ Operations:
128
+ - status: Get repository status
129
+ - diff: Show changes (staged, unstaged, or between refs)
130
+ - log: Show commit history
131
+ - add: Stage files for commit
132
+ - commit: Create a commit
133
+ - branch: List, create, or switch branches
134
+ - push: Push commits to remote
135
+ - pull: Pull changes from remote
136
+ - stash: Stash/unstash changes
137
+ - pr: Create a pull request (requires gh)
138
+
139
+ Safety features:
140
+ - Blocks destructive operations (force push, hard reset)
141
+ - Requires confirmation for commits
142
+ - Never modifies git config
143
+ - Protects main/master branches
144
+
145
+ Use this tool instead of Bash for git operations.
146
+ `,
147
+ parameters: z.object({
148
+ operation: z.enum([
149
+ 'status', 'diff', 'log', 'add', 'commit',
150
+ 'branch', 'push', 'pull', 'stash', 'pr'
151
+ ]),
152
+ args: z.record(z.unknown()).optional()
153
+ }),
154
+ execute: async (input, context) => {
155
+ return await gitService.execute(input.operation, input.args, context);
156
+ }
157
+ };
158
+ ```
159
+
160
+ ### Git Service
161
+
162
+ ```typescript
163
+ // src/git/service.ts
164
+ class GitService {
165
+ private safety: GitSafetyConfig;
166
+ private gitContext: GitContext | null = null;
167
+
168
+ constructor(safety?: Partial<GitSafetyConfig>) {
169
+ this.safety = {
170
+ blockDestructive: true,
171
+ requireConfirmation: ['commit', 'push', 'reset'],
172
+ protectedBranches: ['main', 'master'],
173
+ requireSignOff: false,
174
+ ...safety
175
+ };
176
+ }
177
+
178
+ async execute(
179
+ operation: string,
180
+ args: Record<string, unknown> = {},
181
+ context: ToolContext
182
+ ): Promise<ToolResult> {
183
+ // Refresh context
184
+ this.gitContext = await this.getContext(context.cwd);
185
+
186
+ if (!this.gitContext.isRepo) {
187
+ return { success: false, error: 'Not a git repository' };
188
+ }
189
+
190
+ switch (operation) {
191
+ case 'status':
192
+ return this.status(context.cwd);
193
+ case 'diff':
194
+ return this.diff(args, context.cwd);
195
+ case 'log':
196
+ return this.log(args, context.cwd);
197
+ case 'add':
198
+ return this.add(args, context.cwd);
199
+ case 'commit':
200
+ return this.commit(args as CommitOptions, context.cwd);
201
+ case 'branch':
202
+ return this.branch(args, context.cwd);
203
+ case 'push':
204
+ return this.push(args, context.cwd);
205
+ case 'pull':
206
+ return this.pull(context.cwd);
207
+ case 'stash':
208
+ return this.stash(args, context.cwd);
209
+ case 'pr':
210
+ return this.createPR(args as PROptions, context.cwd);
211
+ default:
212
+ return { success: false, error: `Unknown operation: ${operation}` };
213
+ }
214
+ }
215
+
216
+ private async status(cwd: string): Promise<ToolResult> {
217
+ const result = await this.runGit(['status', '--porcelain=v2', '--branch'], cwd);
218
+
219
+ if (!result.success) return result;
220
+
221
+ const status = this.parseStatus(result.output);
222
+
223
+ return {
224
+ success: true,
225
+ output: this.formatStatus(status)
226
+ };
227
+ }
228
+
229
+ private async diff(args: Record<string, unknown>, cwd: string): Promise<ToolResult> {
230
+ const gitArgs = ['diff'];
231
+
232
+ if (args.staged) gitArgs.push('--staged');
233
+ if (args.ref) gitArgs.push(args.ref as string);
234
+ if (args.stat) gitArgs.push('--stat');
235
+
236
+ return this.runGit(gitArgs, cwd);
237
+ }
238
+
239
+ private async commit(options: CommitOptions, cwd: string): Promise<ToolResult> {
240
+ // Safety checks
241
+ if (!options.message) {
242
+ return { success: false, error: 'Commit message required' };
243
+ }
244
+
245
+ // Build commit message with co-author
246
+ let message = options.message;
247
+ if (options.coAuthor) {
248
+ message += `\n\nCo-Authored-By: ${options.coAuthor}`;
249
+ }
250
+ if (options.signOff || this.safety.requireSignOff) {
251
+ // Add DCO sign-off
252
+ const user = await this.getGitConfig('user.name', cwd);
253
+ const email = await this.getGitConfig('user.email', cwd);
254
+ message += `\n\nSigned-off-by: ${user} <${email}>`;
255
+ }
256
+
257
+ // Add specific files if provided
258
+ if (options.files?.length) {
259
+ const addResult = await this.runGit(['add', ...options.files], cwd);
260
+ if (!addResult.success) return addResult;
261
+ }
262
+
263
+ // Create commit using heredoc for message
264
+ const commitArgs = ['commit', '-m', message];
265
+ if (options.allowEmpty) commitArgs.push('--allow-empty');
266
+
267
+ return this.runGit(commitArgs, cwd);
268
+ }
269
+
270
+ private async createPR(options: PROptions, cwd: string): Promise<ToolResult> {
271
+ // Check for gh CLI
272
+ const ghCheck = await this.runCommand('which', ['gh'], cwd);
273
+ if (!ghCheck.success) {
274
+ return { success: false, error: 'GitHub CLI (gh) not installed' };
275
+ }
276
+
277
+ const args = [
278
+ 'pr', 'create',
279
+ '--title', options.title,
280
+ '--body', options.body
281
+ ];
282
+
283
+ if (options.base) args.push('--base', options.base);
284
+ if (options.draft) args.push('--draft');
285
+ if (options.labels?.length) args.push('--label', options.labels.join(','));
286
+ if (options.reviewers?.length) args.push('--reviewer', options.reviewers.join(','));
287
+
288
+ return this.runCommand('gh', args, cwd);
289
+ }
290
+
291
+ private async push(args: Record<string, unknown>, cwd: string): Promise<ToolResult> {
292
+ // Safety: block force push
293
+ if (args.force && this.safety.blockDestructive) {
294
+ return { success: false, error: 'Force push is blocked for safety. Use --force explicitly in Bash if needed.' };
295
+ }
296
+
297
+ // Safety: protect main branches
298
+ const branch = this.gitContext?.branch;
299
+ if (branch && this.safety.protectedBranches.includes(branch) && args.force) {
300
+ return { success: false, error: `Force push to ${branch} is not allowed` };
301
+ }
302
+
303
+ const gitArgs = ['push'];
304
+ if (args.upstream) gitArgs.push('-u', 'origin', branch || 'HEAD');
305
+ if (args.tags) gitArgs.push('--tags');
306
+
307
+ return this.runGit(gitArgs, cwd);
308
+ }
309
+
310
+ async getContext(cwd: string): Promise<GitContext> {
311
+ // ... implementation
312
+ }
313
+
314
+ private async runGit(args: string[], cwd: string): Promise<ToolResult> {
315
+ return this.runCommand('git', args, cwd);
316
+ }
317
+ }
318
+
319
+ export const gitService = new GitService();
320
+ ```
321
+
322
+ ### File Changes
323
+
324
+ | File | Action | Description |
325
+ |------|--------|-------------|
326
+ | `src/git/types.ts` | Create | Type definitions |
327
+ | `src/git/service.ts` | Create | Git operations |
328
+ | `src/git/safety.ts` | Create | Safety checks |
329
+ | `src/git/parsers.ts` | Create | Output parsing |
330
+ | `src/git/index.ts` | Create | Module exports |
331
+ | `src/tools/git/git-tool.ts` | Create | Git tool |
332
+ | `src/agent/agent.ts` | Modify | Inject git context |
333
+
334
+ ## User Experience
335
+
336
+ ### Git Status in Prompt
337
+ ```
338
+ ┌─ mycode [main ↑2] ────────────────────────────────────────┐
339
+ │ > help me commit these changes │
340
+ └───────────────────────────────────────────────────────────┘
341
+ ```
342
+
343
+ ### Safe Commit Workflow
344
+ ```
345
+ User: Commit these changes
346
+
347
+ Agent: Let me check the current repository status.
348
+
349
+ [Git: status]
350
+
351
+ Current branch: feature/auth
352
+ Changes to commit:
353
+ M src/auth.ts
354
+ M src/auth.test.ts
355
+ A src/types/auth.ts
356
+
357
+ [Git: diff staged]
358
+
359
+ I can see you've:
360
+ - Added JWT token validation
361
+ - Created new auth types
362
+ - Updated tests
363
+
364
+ Suggested commit message:
365
+ "feat: add JWT token validation to auth module"
366
+
367
+ [Git: commit message="feat: add JWT token validation..." coAuthor="Claude..."]
368
+
369
+ ✓ Commit created: abc1234
370
+
371
+ [Git: status]
372
+
373
+ Branch is ahead of origin/feature/auth by 1 commit.
374
+ Push to remote?
375
+ ```
376
+
377
+ ### PR Creation
378
+ ```
379
+ User: Create a PR for this
380
+
381
+ Agent: I'll create a pull request for your changes.
382
+
383
+ [Git: log base=main]
384
+ [Git: diff main...HEAD stat=true]
385
+
386
+ This PR includes 3 commits:
387
+ - feat: add JWT validation
388
+ - test: add auth tests
389
+ - docs: update auth README
390
+
391
+ [Git: pr
392
+ title="feat: JWT token validation"
393
+ body="## Summary\n- Added JWT validation..."
394
+ base="main"
395
+ ]
396
+
397
+ ✓ Pull request created: https://github.com/org/repo/pull/123
398
+ ```
399
+
400
+ ### Safety Block
401
+ ```
402
+ Agent: [Git: push force=true]
403
+
404
+ ⚠️ Operation Blocked
405
+
406
+ Force push is not allowed for safety.
407
+ If you really need to force push, use Bash:
408
+ bash: git push --force
409
+
410
+ This requires explicit user confirmation.
411
+ ```
412
+
413
+ ## Alternatives Considered
414
+
415
+ ### Alternative 1: Bash Only
416
+ Continue using Bash for all git operations.
417
+
418
+ **Pros**: Simpler, full git access
419
+ **Cons**: No safety, no context awareness
420
+ **Decision**: Rejected - Safety is important
421
+
422
+ ### Alternative 2: Read-only Git
423
+ Only provide git status/diff/log.
424
+
425
+ **Pros**: Maximum safety
426
+ **Cons**: Too limiting for workflows
427
+ **Decision**: Rejected - Need commit/push
428
+
429
+ ### Alternative 3: External Git UI
430
+ Integrate with GitKraken/Tower.
431
+
432
+ **Pros**: Rich UI
433
+ **Cons**: Heavy dependency
434
+ **Decision**: Rejected - CLI-first approach
435
+
436
+ ## Security Considerations
437
+
438
+ 1. **Credential Handling**: Use git credential helpers
439
+ 2. **Remote Validation**: Verify remote URLs
440
+ 3. **Branch Protection**: Honor branch rules
441
+ 4. **Commit Signing**: Support GPG signing
442
+ 5. **Token Exposure**: Don't log auth tokens
443
+
444
+ ## Testing Strategy
445
+
446
+ 1. **Unit Tests**:
447
+ - Status parsing
448
+ - Safety checks
449
+ - Command building
450
+
451
+ 2. **Integration Tests**:
452
+ - Full commit workflow
453
+ - PR creation
454
+ - Branch operations
455
+
456
+ 3. **Safety Tests**:
457
+ - Destructive command blocking
458
+ - Protected branch enforcement
459
+
460
+ ## Migration Path
461
+
462
+ 1. **Phase 1**: Basic status/diff/log
463
+ 2. **Phase 2**: Add/commit with safety
464
+ 3. **Phase 3**: Push/pull operations
465
+ 4. **Phase 4**: PR creation (gh integration)
466
+ 5. **Phase 5**: Advanced workflows
467
+
468
+ Bash git commands remain available.
469
+
470
+ ## References
471
+
472
+ - [Git Documentation](https://git-scm.com/doc)
473
+ - [GitHub CLI](https://cli.github.com/)
474
+ - [Conventional Commits](https://www.conventionalcommits.org/)
475
+ - [DCO Sign-off](https://developercertificate.org/)