@ariso-ai/ivan 1.0.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 (150) hide show
  1. package/README.md +412 -0
  2. package/dist/agent.d.ts +11 -0
  3. package/dist/agent.d.ts.map +1 -0
  4. package/dist/agent.js +48 -0
  5. package/dist/agent.js.map +1 -0
  6. package/dist/config/config.d.ts +20 -0
  7. package/dist/config/config.d.ts.map +1 -0
  8. package/dist/config/config.js +187 -0
  9. package/dist/config/config.js.map +1 -0
  10. package/dist/config.d.ts +46 -0
  11. package/dist/config.d.ts.map +1 -0
  12. package/dist/config.js +414 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/database/database.d.ts +12 -0
  15. package/dist/database/database.d.ts.map +1 -0
  16. package/dist/database/database.js +45 -0
  17. package/dist/database/database.js.map +1 -0
  18. package/dist/database/migration.d.ts +11 -0
  19. package/dist/database/migration.d.ts.map +1 -0
  20. package/dist/database/migration.js +64 -0
  21. package/dist/database/migration.js.map +1 -0
  22. package/dist/database/migrations/001_create_jobs_table.d.ts +3 -0
  23. package/dist/database/migrations/001_create_jobs_table.d.ts.map +1 -0
  24. package/dist/database/migrations/001_create_jobs_table.js +14 -0
  25. package/dist/database/migrations/001_create_jobs_table.js.map +1 -0
  26. package/dist/database/migrations/001_initial_schema.d.ts +3 -0
  27. package/dist/database/migrations/001_initial_schema.d.ts.map +1 -0
  28. package/dist/database/migrations/001_initial_schema.js +66 -0
  29. package/dist/database/migrations/001_initial_schema.js.map +1 -0
  30. package/dist/database/migrations/002_create_tasks_table.d.ts +3 -0
  31. package/dist/database/migrations/002_create_tasks_table.d.ts.map +1 -0
  32. package/dist/database/migrations/002_create_tasks_table.js +16 -0
  33. package/dist/database/migrations/002_create_tasks_table.js.map +1 -0
  34. package/dist/database/migrations/003_add_log_to_tasks.d.ts +3 -0
  35. package/dist/database/migrations/003_add_log_to_tasks.d.ts.map +1 -0
  36. package/dist/database/migrations/003_add_log_to_tasks.js +11 -0
  37. package/dist/database/migrations/003_add_log_to_tasks.js.map +1 -0
  38. package/dist/database/migrations/004_add_branch_to_tasks.d.ts +3 -0
  39. package/dist/database/migrations/004_add_branch_to_tasks.d.ts.map +1 -0
  40. package/dist/database/migrations/004_add_branch_to_tasks.js +11 -0
  41. package/dist/database/migrations/004_add_branch_to_tasks.js.map +1 -0
  42. package/dist/database/migrations/005_add_type_to_tasks.d.ts +3 -0
  43. package/dist/database/migrations/005_add_type_to_tasks.d.ts.map +1 -0
  44. package/dist/database/migrations/005_add_type_to_tasks.js +11 -0
  45. package/dist/database/migrations/005_add_type_to_tasks.js.map +1 -0
  46. package/dist/database/migrations/006_add_comment_url_and_commit_to_tasks.d.ts +3 -0
  47. package/dist/database/migrations/006_add_comment_url_and_commit_to_tasks.d.ts.map +1 -0
  48. package/dist/database/migrations/006_add_comment_url_and_commit_to_tasks.js +15 -0
  49. package/dist/database/migrations/006_add_comment_url_and_commit_to_tasks.js.map +1 -0
  50. package/dist/database/migrations/006_add_comment_url_to_tasks.d.ts +3 -0
  51. package/dist/database/migrations/006_add_comment_url_to_tasks.d.ts.map +1 -0
  52. package/dist/database/migrations/006_add_comment_url_to_tasks.js +14 -0
  53. package/dist/database/migrations/006_add_comment_url_to_tasks.js.map +1 -0
  54. package/dist/database/migrations/007_add_commit_to_tasks.d.ts +3 -0
  55. package/dist/database/migrations/007_add_commit_to_tasks.d.ts.map +1 -0
  56. package/dist/database/migrations/007_add_commit_to_tasks.js +13 -0
  57. package/dist/database/migrations/007_add_commit_to_tasks.js.map +1 -0
  58. package/dist/database/migrations/008_add_lint_and_test_task_type.d.ts +3 -0
  59. package/dist/database/migrations/008_add_lint_and_test_task_type.d.ts.map +1 -0
  60. package/dist/database/migrations/008_add_lint_and_test_task_type.js +42 -0
  61. package/dist/database/migrations/008_add_lint_and_test_task_type.js.map +1 -0
  62. package/dist/database/migrations/index.d.ts +3 -0
  63. package/dist/database/migrations/index.d.ts.map +1 -0
  64. package/dist/database/migrations/index.js +19 -0
  65. package/dist/database/migrations/index.js.map +1 -0
  66. package/dist/database/types.d.ts +34 -0
  67. package/dist/database/types.d.ts.map +1 -0
  68. package/dist/database/types.js +2 -0
  69. package/dist/database/types.js.map +1 -0
  70. package/dist/database.d.ts +13 -0
  71. package/dist/database.d.ts.map +1 -0
  72. package/dist/database.js +32 -0
  73. package/dist/database.js.map +1 -0
  74. package/dist/index.d.ts +3 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +285 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/scripts/task-executor.d.ts +3 -0
  79. package/dist/scripts/task-executor.d.ts.map +1 -0
  80. package/dist/scripts/task-executor.js +139 -0
  81. package/dist/scripts/task-executor.js.map +1 -0
  82. package/dist/scripts/task-planner.d.ts +3 -0
  83. package/dist/scripts/task-planner.d.ts.map +1 -0
  84. package/dist/scripts/task-planner.js +81 -0
  85. package/dist/scripts/task-planner.js.map +1 -0
  86. package/dist/services/address-executor.d.ts +13 -0
  87. package/dist/services/address-executor.d.ts.map +1 -0
  88. package/dist/services/address-executor.js +202 -0
  89. package/dist/services/address-executor.js.map +1 -0
  90. package/dist/services/address-task-executor.d.ts +19 -0
  91. package/dist/services/address-task-executor.d.ts.map +1 -0
  92. package/dist/services/address-task-executor.js +736 -0
  93. package/dist/services/address-task-executor.js.map +1 -0
  94. package/dist/services/claude-cli-executor.d.ts +14 -0
  95. package/dist/services/claude-cli-executor.d.ts.map +1 -0
  96. package/dist/services/claude-cli-executor.js +241 -0
  97. package/dist/services/claude-cli-executor.js.map +1 -0
  98. package/dist/services/claude-executor.d.ts +14 -0
  99. package/dist/services/claude-executor.d.ts.map +1 -0
  100. package/dist/services/claude-executor.js +274 -0
  101. package/dist/services/claude-executor.js.map +1 -0
  102. package/dist/services/claude-planner.d.ts +15 -0
  103. package/dist/services/claude-planner.d.ts.map +1 -0
  104. package/dist/services/claude-planner.js +107 -0
  105. package/dist/services/claude-planner.js.map +1 -0
  106. package/dist/services/docker-orchestrator.d.ts +11 -0
  107. package/dist/services/docker-orchestrator.d.ts.map +1 -0
  108. package/dist/services/docker-orchestrator.js +85 -0
  109. package/dist/services/docker-orchestrator.js.map +1 -0
  110. package/dist/services/executor-factory.d.ts +14 -0
  111. package/dist/services/executor-factory.d.ts.map +1 -0
  112. package/dist/services/executor-factory.js +14 -0
  113. package/dist/services/executor-factory.js.map +1 -0
  114. package/dist/services/git-manager.d.ts +36 -0
  115. package/dist/services/git-manager.d.ts.map +1 -0
  116. package/dist/services/git-manager.js +728 -0
  117. package/dist/services/git-manager.js.map +1 -0
  118. package/dist/services/index.d.ts +9 -0
  119. package/dist/services/index.d.ts.map +1 -0
  120. package/dist/services/index.js +9 -0
  121. package/dist/services/index.js.map +1 -0
  122. package/dist/services/job-manager.d.ts +30 -0
  123. package/dist/services/job-manager.d.ts.map +1 -0
  124. package/dist/services/job-manager.js +337 -0
  125. package/dist/services/job-manager.js.map +1 -0
  126. package/dist/services/openai-service.d.ts +14 -0
  127. package/dist/services/openai-service.d.ts.map +1 -0
  128. package/dist/services/openai-service.js +186 -0
  129. package/dist/services/openai-service.js.map +1 -0
  130. package/dist/services/pr-service.d.ts +31 -0
  131. package/dist/services/pr-service.d.ts.map +1 -0
  132. package/dist/services/pr-service.js +291 -0
  133. package/dist/services/pr-service.js.map +1 -0
  134. package/dist/services/repository-manager.d.ts +12 -0
  135. package/dist/services/repository-manager.d.ts.map +1 -0
  136. package/dist/services/repository-manager.js +101 -0
  137. package/dist/services/repository-manager.js.map +1 -0
  138. package/dist/services/task-executor.d.ts +20 -0
  139. package/dist/services/task-executor.d.ts.map +1 -0
  140. package/dist/services/task-executor.js +717 -0
  141. package/dist/services/task-executor.js.map +1 -0
  142. package/dist/types/non-interactive-config.d.ts +28 -0
  143. package/dist/types/non-interactive-config.d.ts.map +1 -0
  144. package/dist/types/non-interactive-config.js +2 -0
  145. package/dist/types/non-interactive-config.js.map +1 -0
  146. package/dist/web-server.d.ts +16 -0
  147. package/dist/web-server.d.ts.map +1 -0
  148. package/dist/web-server.js +488 -0
  149. package/dist/web-server.js.map +1 -0
  150. package/package.json +71 -0
package/README.md ADDED
@@ -0,0 +1,412 @@
1
+ # Ivan šŸ¤–
2
+
3
+ ## Your AI-Powered Development Assistant
4
+
5
+ Ivan is an intelligent CLI tool that automates complex development workflows by breaking down high-level requests into executable tasks, implementing them with AI assistance, and creating pull requests with properly formatted commits and descriptions.
6
+
7
+ ## Key Features
8
+
9
+ - **🧠 Intelligent Task Breakdown**: Analyzes your request and automatically breaks it down into manageable, PR-ready tasks
10
+ - **šŸ¤– Flexible Claude Execution**: Choose between SDK (API-based) or CLI (Claude Max) execution modes
11
+ - **šŸ”„ Automated Git Workflow**: Creates branches, commits changes, and opens pull requests automatically
12
+ - **šŸ“ Smart Commit Messages**: Generates conventional commit messages using OpenAI's GPT-4
13
+ - **šŸ’¬ PR Comment Handling**: Automatically addresses PR review comments with `ivan address` command
14
+ - **šŸ” Smart Review Requests**: Generates context-specific review instructions for each PR using AI
15
+ - **ā° Optional Review Monitoring**: Can wait 30 minutes after task completion to automatically address incoming PR comments
16
+ - **šŸŽÆ Repository-Specific Instructions**: Set coding guidelines and patterns that are automatically applied to every task
17
+ - **šŸ“Š Progress Tracking**: SQLite database tracks all jobs, tasks, execution history, and tool calls
18
+ - **🌐 Web Interface**: Built-in web server to view and monitor jobs and tasks in your browser
19
+ - **⚔ Interactive Prompting**: Automatically prompts for missing configuration instead of failing
20
+
21
+ ## Prerequisites
22
+
23
+ - Node.js 20+
24
+ - Git repository
25
+ - GitHub CLI (`gh`) installed and authenticated
26
+ - OpenAI API key (for commit messages and PR descriptions)
27
+ - **One of the following**:
28
+ - **SDK Mode**: Anthropic API key (for direct API access)
29
+ - **CLI Mode**: Claude Code CLI installed (for Claude Max users)
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ # Clone the repository
35
+ git clone https://github.com/yourusername/ivan.git
36
+ cd ivan
37
+
38
+ # Install dependencies
39
+ npm install
40
+
41
+ # Build the project
42
+ npm run build
43
+
44
+ # Link globally for system-wide access
45
+ npm link
46
+
47
+ # Or run directly from the project directory
48
+ node dist/index.js
49
+ ```
50
+
51
+ ## Configuration
52
+
53
+ Ivan will automatically prompt for configuration on first use. You can also reconfigure at any time:
54
+
55
+ ```bash
56
+ # Reconfigure API keys and settings
57
+ ivan reconfigure
58
+ ```
59
+
60
+ ### Configuration includes:
61
+ - **Executor Type**: Choose between SDK (API-based) or CLI (Claude Max) mode
62
+ - **OpenAI API Key**: For generating commit messages and PR descriptions
63
+ - **Anthropic API Key**: For Claude Code execution (SDK mode only)
64
+ - **Repository Instructions**: Optional coding guidelines specific to each repository
65
+ - **Tool Permissions**: Configure which tools Claude Code can use per repository
66
+ - **Model Selection**: Choose which Claude model to use for tasks
67
+
68
+ Configuration is stored in `~/.ivan/config.json` and the database in `~/.ivan/db.sqlite`
69
+
70
+ ### Executor Modes
71
+
72
+ Ivan supports two ways to run Claude Code:
73
+
74
+ #### SDK Mode (Default)
75
+ - Uses the Anthropic API directly via TypeScript SDK
76
+ - Requires an Anthropic API key
77
+ - Best for users with API access
78
+
79
+ #### CLI Mode
80
+ - Uses the Claude Code CLI installed on your machine
81
+ - Perfect for Claude Max subscribers (no API key needed)
82
+ - Provides real-time streaming output
83
+ - Requires Claude Code CLI to be installed
84
+
85
+ **Switch between modes at any time:**
86
+ ```bash
87
+ # Configure executor type
88
+ ivan configure-executor
89
+
90
+ # View current executor setting
91
+ ivan show-config
92
+ ```
93
+
94
+ ## Usage
95
+
96
+ ### Running Tasks
97
+
98
+ Simply run `ivan` in any git repository:
99
+
100
+ ```bash
101
+ ivan
102
+ ```
103
+
104
+ Then describe what you want to accomplish. Ivan will:
105
+ 1. Break down your request into individual tasks
106
+ 2. Ask if you want to wait for PR reviews after completion
107
+ 3. Execute each task using Claude Code
108
+ 4. Create pull requests with proper commits and AI-generated review instructions
109
+ 5. Optionally wait 30 minutes and automatically address any PR comments
110
+
111
+ ### CLI Commands
112
+
113
+ #### Main Commands
114
+
115
+ ```bash
116
+ # Run Ivan to execute tasks (default command)
117
+ ivan
118
+
119
+ # Reconfigure API keys and settings
120
+ ivan reconfigure
121
+
122
+ # Address PR review comments and failing checks
123
+ ivan address
124
+
125
+ # Start the web interface
126
+ ivan web [--port <port>]
127
+
128
+ # Stop the web interface
129
+ ivan web-stop [--port <port>]
130
+ ```
131
+
132
+ #### Repository Configuration
133
+
134
+ ```bash
135
+ # Set or update repository-specific instructions
136
+ ivan edit-repo-instructions
137
+
138
+ # Configure allowed tools for Claude Code in current repository
139
+ ivan config-tools
140
+
141
+ # Show current repository configuration
142
+ ivan show-config
143
+
144
+ # Choose which Claude model to use for tasks
145
+ ivan choose-model
146
+
147
+ # Configure executor type (SDK vs CLI)
148
+ ivan configure-executor
149
+ ```
150
+
151
+ ### Addressing PR Comments
152
+
153
+ Automatically handle PR review comments:
154
+
155
+ ```bash
156
+ # Scan all open PRs for unaddressed comments and failing checks
157
+ ivan address
158
+ ```
159
+
160
+ This will:
161
+ 1. Find all open PRs with unaddressed inline code comments
162
+ 2. Let you select which PRs to address
163
+ 3. Create tasks for each unaddressed comment
164
+ 4. Automatically implement fixes using Claude Code
165
+ 5. Commit changes with co-author attribution
166
+ 6. Reply to each comment with the commit that fixed it
167
+ 7. Add a review request with specific instructions
168
+
169
+ ### Example Requests
170
+
171
+ - "Add user authentication with JWT tokens"
172
+ - "Refactor the database module to use TypeScript"
173
+ - "Add comprehensive test coverage for the API endpoints"
174
+ - "Implement a caching layer with Redis"
175
+ - "Fix all ESLint warnings and add proper error handling"
176
+
177
+ ### Web Interface
178
+
179
+ Start the web server to monitor jobs and tasks:
180
+
181
+ ```bash
182
+ # Start web server on default port 3000
183
+ ivan web
184
+
185
+ # Or specify a custom port
186
+ ivan web --port 8080
187
+
188
+ # Stop the web server
189
+ ivan web-stop
190
+ ```
191
+
192
+ Then open http://localhost:3000 in your browser to see:
193
+ - All jobs and their status
194
+ - Individual task progress
195
+ - Execution logs
196
+ - Pull request links
197
+
198
+ ### Repository-Specific Instructions
199
+
200
+ Set coding guidelines that will be automatically applied to every task:
201
+
202
+ ```bash
203
+ # Set or update repository instructions
204
+ ivan edit-repo-instructions
205
+
206
+ # Instructions can include:
207
+ - Coding style preferences
208
+ - Framework-specific patterns
209
+ - Testing requirements
210
+ - Documentation standards
211
+ ```
212
+
213
+ **Note**: Ivan will prompt for instructions the first time you use it in a repository. If you decline, it won't ask again, but you can always configure them later using `ivan edit-repo-instructions`.
214
+
215
+ ### Tool Configuration
216
+
217
+ Control which tools Claude Code can use in your repository:
218
+
219
+ ```bash
220
+ # Configure allowed tools
221
+ ivan config-tools
222
+
223
+ # View current configuration
224
+ ivan show-config
225
+ ```
226
+
227
+ By default, all tools are allowed. You can restrict to specific tools like `["Bash", "Read", "Write", "Edit"]` for enhanced security.
228
+
229
+ ### Model Selection
230
+
231
+ Choose which Claude model to use for task execution:
232
+
233
+ ```bash
234
+ # Select a Claude model
235
+ ivan choose-model
236
+ ```
237
+
238
+ Available models:
239
+ - **Claude Sonnet 4**: Default, balanced performance
240
+ - **Claude 3.5 Haiku**: Faster, good for simpler tasks
241
+ - **Claude Opus 4.1**: Most capable, but slower
242
+
243
+ ## How It Works
244
+
245
+ ### Standard Workflow
246
+ 1. **Task Analysis**: Claude Code analyzes your request and breaks it into PR-ready tasks
247
+ 2. **Review Options**: Asks if you want to wait for PR reviews (optional)
248
+ 3. **Branch Creation**: Creates a new branch for each task (`ivan/task-description-timestamp`)
249
+ 4. **Code Implementation**: Claude Code implements the changes using your repository context
250
+ 5. **Smart Commits**: Generates conventional commit messages based on the actual changes
251
+ 6. **Pull Request**: Creates a PR with detailed description and AI-generated review instructions
252
+ 7. **Review Monitoring** (optional): Waits 30 minutes for reviews, then automatically addresses comments
253
+ 8. **Cleanup**: Returns to main branch and syncs with upstream
254
+
255
+ ### Address Workflow
256
+ 1. **PR Scanning**: Finds all open PRs with unaddressed comments or failing checks
257
+ 2. **Comment Detection**: Uses GitHub GraphQL API to find unresolved inline code comments
258
+ 3. **Task Creation**: Creates address tasks for each comment with proper branch tracking
259
+ 4. **Automated Fixes**: Implements fixes using Claude Code with repository context
260
+ 5. **Smart Replies**: Replies to each comment with the commit that addressed it
261
+ 6. **Review Requests**: Adds context-specific review instructions based on changes
262
+
263
+ ## Architecture
264
+
265
+ ```
266
+ ivan/
267
+ ā”œā”€ā”€ src/
268
+ │ ā”œā”€ā”€ database/ # SQLite schema and migrations
269
+ │ ā”œā”€ā”€ services/ # Core services
270
+ │ │ ā”œā”€ā”€ claude-executor.ts # Claude Code SDK integration
271
+ │ │ ā”œā”€ā”€ claude-cli-executor.ts # Claude Code CLI integration
272
+ │ │ ā”œā”€ā”€ executor-factory.ts # Executor selection logic
273
+ │ │ ā”œā”€ā”€ openai-service.ts # OpenAI API for commits/PRs
274
+ │ │ ā”œā”€ā”€ job-manager.ts # Job and task management
275
+ │ │ ā”œā”€ā”€ git-manager.ts # Git operations and GitHub CLI
276
+ │ │ ā”œā”€ā”€ task-executor.ts # Main workflow orchestration
277
+ │ │ ā”œā”€ā”€ address-executor.ts # PR comment addressing workflow
278
+ │ │ ā”œā”€ā”€ address-task-executor.ts # Individual comment fix execution
279
+ │ │ └── pr-service.ts # PR comment and check detection
280
+ │ ā”œā”€ā”€ config.ts # Configuration management
281
+ │ ā”œā”€ā”€ web-server.ts # Web interface server
282
+ │ └── index.ts # CLI entry point
283
+ ā”œā”€ā”€ dist/ # Compiled JavaScript
284
+ └── ~/.ivan/ # User configuration and database
285
+ ā”œā”€ā”€ config.json # API keys and settings (includes executorType)
286
+ └── db.sqlite # Jobs and tasks database
287
+ ```
288
+
289
+ ## Database Schema
290
+
291
+ Ivan maintains a local SQLite database to track:
292
+ - **Jobs**: High-level user requests with timestamps and status
293
+ - **Tasks**: Individual tasks within a job, including:
294
+ - Task description
295
+ - Task type (build or address)
296
+ - Execution status (not_started, active, completed)
297
+ - Branch name tracking
298
+ - Pull request links
299
+ - Execution logs with tool calls
300
+ - Timestamps
301
+
302
+ ## Development
303
+
304
+ ```bash
305
+ # Run in development mode
306
+ npm run dev
307
+
308
+ # Watch mode for development
309
+ npm run watch
310
+
311
+ # Run linter
312
+ npm run lint
313
+
314
+ # Type checking
315
+ npm run typecheck
316
+ ```
317
+
318
+ ## Advanced Features
319
+
320
+ ### Execution Logs
321
+ - All Claude Code interactions are logged with tool calls
322
+ - Each response is separated with visual dividers for readability
323
+ - Tool inputs and outputs are captured for debugging
324
+ - Logs are stored in the database for each task
325
+
326
+ ### Smart Review Comments
327
+ - PRs are created with AI-generated review instructions
328
+ - Review comments are specific to the changes made
329
+ - Uses GPT-4o-mini to analyze diffs and generate contextual review requests
330
+ - Replies to PR comments include "Ivan:" prefix for clear attribution
331
+
332
+ ### Comment Detection
333
+ - Uses GitHub GraphQL API to detect resolved status
334
+ - Only processes unresolved inline code comments
335
+ - Ignores top-level PR comments
336
+ - Skips comments that already have replies
337
+
338
+ ## Security Considerations
339
+
340
+ - API keys are stored locally in `~/.ivan/config.json`
341
+ - No credentials are stored in the database
342
+ - Configuration prompts mask API key input
343
+ - Each task runs in the local environment with your git credentials
344
+ - GitHub CLI authentication is used for PR creation
345
+
346
+ ## Limitations
347
+
348
+ - Requires GitHub CLI (`gh`) for pull request creation
349
+ - Works with GitHub repositories (GitLab/Bitbucket support planned)
350
+ - Tasks must be completable by Claude Code
351
+ - Requires active internet connection for AI services
352
+
353
+ ## Contributing
354
+
355
+ Contributions are welcome! Please feel free to submit a Pull Request.
356
+
357
+ ## License
358
+
359
+ MIT
360
+
361
+ ## Support
362
+
363
+ For issues, questions, or suggestions, please open an issue on GitHub.
364
+
365
+ ## Troubleshooting
366
+
367
+ ### Common Issues
368
+
369
+ **GitHub CLI not authenticated:**
370
+ ```bash
371
+ gh auth login
372
+ ```
373
+
374
+ **API keys not working:**
375
+ ```bash
376
+ ivan reconfigure
377
+ ```
378
+
379
+ **Claude CLI not found (CLI mode):**
380
+ ```bash
381
+ # Install Claude Code CLI first
382
+ # See: https://docs.claude.com/en/docs/claude-code/installation
383
+
384
+ # Then configure Ivan to use CLI mode
385
+ ivan configure-executor
386
+ ```
387
+
388
+ **Executor hanging or not showing output (CLI mode):**
389
+ - Ensure you're using the latest version of Claude Code CLI
390
+ - Try switching to SDK mode with `ivan configure-executor`
391
+ - Check that `claude --print` works independently
392
+
393
+ **Want to switch between SDK and CLI mode:**
394
+ ```bash
395
+ # Switch executor type
396
+ ivan configure-executor
397
+
398
+ # View current configuration
399
+ ivan show-config
400
+ ```
401
+
402
+ **Permission denied errors:**
403
+ - Ensure you have write access to the repository
404
+ - Check that your SSH keys are properly configured
405
+
406
+ **Web server issues:**
407
+ - Check if port is already in use
408
+ - Try a different port with `--port` flag
409
+
410
+ ---
411
+
412
+ Built with ā¤ļø to make AI-powered development workflows more efficient and automated.
@@ -0,0 +1,11 @@
1
+ import { IvanConfig } from './config/config.js';
2
+ import { DatabaseManager } from './database/database.js';
3
+ export declare class OrchestrationAgent {
4
+ private config;
5
+ private dbManager;
6
+ private claudePlanner;
7
+ private jobManager;
8
+ constructor(config: IvanConfig, dbManager: DatabaseManager);
9
+ executeTask(task: string): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAMzD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,UAAU,CAAa;gBAEnB,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,eAAe;IAO7C,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CA8CtD"}
package/dist/agent.js ADDED
@@ -0,0 +1,48 @@
1
+ import { ClaudePlannerService } from './services/claude-planner.js';
2
+ import { JobManager } from './services/job-manager.js';
3
+ import { DockerOrchestrator } from './services/docker-orchestrator.js';
4
+ import chalk from 'chalk';
5
+ export class OrchestrationAgent {
6
+ config;
7
+ dbManager;
8
+ claudePlanner;
9
+ jobManager;
10
+ constructor(config, dbManager) {
11
+ this.config = config;
12
+ this.dbManager = dbManager;
13
+ this.claudePlanner = new ClaudePlannerService(config.repository, config.anthropicApiKey);
14
+ this.jobManager = new JobManager(dbManager.getDatabase());
15
+ }
16
+ async executeTask(task) {
17
+ console.log(chalk.gray('\nšŸ“ Task:'), task);
18
+ console.log(chalk.gray('─'.repeat(50)));
19
+ try {
20
+ // Step 1: Plan tasks with Claude
21
+ const taskPlan = await this.claudePlanner.planTasks(task);
22
+ // Step 2: Create job and tasks in database
23
+ const jobId = await this.jobManager.createJob(task, `User request: ${task}`, this.config.repository);
24
+ await this.jobManager.createTasks(jobId, taskPlan.tasks);
25
+ // Step 3: Update job status to in_progress
26
+ await this.jobManager.updateJobStatus(jobId, 'in_progress');
27
+ // Step 4: Run tasks in Docker containers
28
+ const orchestrator = new DockerOrchestrator(this.jobManager, this.config.repository, this.config.openAiApiKey);
29
+ await orchestrator.runAllTasks(jobId);
30
+ // Step 5: Update job status to completed
31
+ const tasks = await this.jobManager.getJobTasks(jobId);
32
+ const allCompleted = tasks.every(t => t.status === 'completed');
33
+ if (allCompleted) {
34
+ await this.jobManager.updateJobStatus(jobId, 'completed');
35
+ console.log(chalk.green(`\nāœ… Job #${jobId} completed successfully!`));
36
+ }
37
+ else {
38
+ await this.jobManager.updateJobStatus(jobId, 'failed');
39
+ console.log(chalk.yellow(`\nāš ļø Job #${jobId} completed with some failed tasks`));
40
+ }
41
+ }
42
+ catch (error) {
43
+ console.error(chalk.red('\nāŒ Task execution failed:'), error);
44
+ throw error;
45
+ }
46
+ }
47
+ }
48
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,OAAO,kBAAkB;IACrB,MAAM,CAAa;IACnB,SAAS,CAAkB;IAC3B,aAAa,CAAuB;IACpC,UAAU,CAAa;IAE/B,YAAY,MAAkB,EAAE,SAA0B;QACxD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,aAAa,GAAG,IAAI,oBAAoB,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;QACzF,IAAI,CAAC,UAAU,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5D,CAAC;IAEM,KAAK,CAAC,WAAW,CAAC,IAAY;QACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAExC,IAAI,CAAC;YACH,iCAAiC;YACjC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAE1D,2CAA2C;YAC3C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAC3C,IAAI,EACJ,iBAAiB,IAAI,EAAE,EACvB,IAAI,CAAC,MAAM,CAAC,UAAU,CACvB,CAAC;YAEF,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;YAEzD,2CAA2C;YAC3C,MAAM,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;YAE5D,yCAAyC;YACzC,MAAM,YAAY,GAAG,IAAI,kBAAkB,CACzC,IAAI,CAAC,UAAU,EACf,IAAI,CAAC,MAAM,CAAC,UAAU,EACtB,IAAI,CAAC,MAAM,CAAC,YAAY,CACzB,CAAC;YAEF,MAAM,YAAY,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAEtC,yCAAyC;YACzC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACvD,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;YAEhE,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;gBAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,KAAK,0BAA0B,CAAC,CAAC,CAAC;YACxE,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;gBACvD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,KAAK,mCAAmC,CAAC,CAAC,CAAC;YACpF,CAAC;QAEH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,4BAA4B,CAAC,EAAE,KAAK,CAAC,CAAC;YAC9D,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ import { DatabaseManager } from '../database/database.js';
2
+ export interface IvanConfig {
3
+ openAiApiKey: string;
4
+ anthropicApiKey: string;
5
+ repository: string;
6
+ }
7
+ export declare class ConfigManager {
8
+ private configDir;
9
+ private configPath;
10
+ private dbManager;
11
+ constructor();
12
+ initialize(): Promise<IvanConfig>;
13
+ private loadConfig;
14
+ private saveConfig;
15
+ getConfig(): IvanConfig | null;
16
+ getDatabase(): DatabaseManager;
17
+ forceReconfigure(): Promise<IvanConfig>;
18
+ private checkClaudeCodeInstallation;
19
+ }
20
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAI1D,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAkB;;IAQtB,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC;IA2E9C,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,UAAU;IAQX,SAAS,IAAI,UAAU,GAAG,IAAI;IAI9B,WAAW,IAAI,eAAe;IAIxB,gBAAgB,IAAI,OAAO,CAAC,UAAU,CAAC;YAiEtC,2BAA2B;CAyB1C"}
@@ -0,0 +1,187 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ import { exec } from 'child_process';
5
+ import { promisify } from 'util';
6
+ import inquirer from 'inquirer';
7
+ import chalk from 'chalk';
8
+ import { DatabaseManager } from '../database/database.js';
9
+ const execAsync = promisify(exec);
10
+ export class ConfigManager {
11
+ configDir;
12
+ configPath;
13
+ dbManager;
14
+ constructor() {
15
+ this.configDir = path.join(os.homedir(), '.ivan');
16
+ this.configPath = path.join(this.configDir, 'config.json');
17
+ this.dbManager = new DatabaseManager();
18
+ }
19
+ async initialize() {
20
+ await this.dbManager.initialize();
21
+ const existingConfig = this.loadConfig();
22
+ if (existingConfig) {
23
+ console.log(chalk.green('āœ“ Configuration found!'));
24
+ return existingConfig;
25
+ }
26
+ console.log(chalk.cyan('\nšŸ¤– Welcome to Ivan - Your Coding Orchestration Agent\n'));
27
+ console.log(chalk.yellow('Let\'s set up your configuration...\n'));
28
+ await this.checkClaudeCodeInstallation();
29
+ await this.dbManager.initialize();
30
+ const answers = await inquirer.prompt([
31
+ {
32
+ type: 'input',
33
+ name: 'repository',
34
+ message: 'Enter the SSH repository URL (e.g., git@github.com:user/repo.git):',
35
+ validate: (input) => {
36
+ if (!input || input.trim() === '') {
37
+ return 'Repository URL is required';
38
+ }
39
+ const trimmed = input.trim();
40
+ const sshUrlPattern = /^git@[\w.-]+:[\w.-]+\/[\w.-]+\.git$/;
41
+ if (!sshUrlPattern.test(trimmed)) {
42
+ return 'Please enter a valid SSH repository URL (e.g., git@github.com:user/repo.git)';
43
+ }
44
+ return true;
45
+ },
46
+ filter: (input) => input.trim()
47
+ },
48
+ {
49
+ type: 'password',
50
+ name: 'openAiApiKey',
51
+ message: 'Enter your OpenAI API key (for commit messages):',
52
+ mask: '*',
53
+ validate: (input) => {
54
+ if (!input || input.trim() === '') {
55
+ return 'OpenAI API key is required';
56
+ }
57
+ return true;
58
+ }
59
+ },
60
+ {
61
+ type: 'password',
62
+ name: 'anthropicApiKey',
63
+ message: 'Enter your Anthropic API key (for task planning):',
64
+ mask: '*',
65
+ validate: (input) => {
66
+ if (!input || input.trim() === '') {
67
+ return 'Anthropic API key is required';
68
+ }
69
+ return true;
70
+ }
71
+ }
72
+ ]);
73
+ const config = {
74
+ repository: answers.repository,
75
+ openAiApiKey: answers.openAiApiKey,
76
+ anthropicApiKey: answers.anthropicApiKey
77
+ };
78
+ this.saveConfig(config);
79
+ console.log(chalk.green('\nāœ“ Configuration saved successfully!\n'));
80
+ return config;
81
+ }
82
+ loadConfig() {
83
+ try {
84
+ if (fs.existsSync(this.configPath)) {
85
+ const configData = fs.readFileSync(this.configPath, 'utf-8');
86
+ return JSON.parse(configData);
87
+ }
88
+ }
89
+ catch (error) {
90
+ console.error(chalk.red('Error loading configuration:'), error);
91
+ }
92
+ return null;
93
+ }
94
+ saveConfig(config) {
95
+ if (!fs.existsSync(this.configDir)) {
96
+ fs.mkdirSync(this.configDir, { recursive: true });
97
+ }
98
+ fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2));
99
+ }
100
+ getConfig() {
101
+ return this.loadConfig();
102
+ }
103
+ getDatabase() {
104
+ return this.dbManager;
105
+ }
106
+ async forceReconfigure() {
107
+ console.log(chalk.cyan('\nšŸ”§ Reconfiguring Ivan...\n'));
108
+ await this.dbManager.initialize();
109
+ await this.checkClaudeCodeInstallation();
110
+ const answers = await inquirer.prompt([
111
+ {
112
+ type: 'input',
113
+ name: 'repository',
114
+ message: 'Enter the SSH repository URL (e.g., git@github.com:user/repo.git):',
115
+ validate: (input) => {
116
+ if (!input || input.trim() === '') {
117
+ return 'Repository URL is required';
118
+ }
119
+ const trimmed = input.trim();
120
+ const sshUrlPattern = /^git@[\w.-]+:[\w.-]+\/[\w.-]+\.git$/;
121
+ if (!sshUrlPattern.test(trimmed)) {
122
+ return 'Please enter a valid SSH repository URL (e.g., git@github.com:user/repo.git)';
123
+ }
124
+ return true;
125
+ },
126
+ filter: (input) => input.trim()
127
+ },
128
+ {
129
+ type: 'password',
130
+ name: 'openAiApiKey',
131
+ message: 'Enter your OpenAI API key (for commit messages):',
132
+ mask: '*',
133
+ validate: (input) => {
134
+ if (!input || input.trim() === '') {
135
+ return 'OpenAI API key is required';
136
+ }
137
+ return true;
138
+ }
139
+ },
140
+ {
141
+ type: 'password',
142
+ name: 'anthropicApiKey',
143
+ message: 'Enter your Anthropic API key (for task planning):',
144
+ mask: '*',
145
+ validate: (input) => {
146
+ if (!input || input.trim() === '') {
147
+ return 'Anthropic API key is required';
148
+ }
149
+ return true;
150
+ }
151
+ }
152
+ ]);
153
+ const config = {
154
+ repository: answers.repository,
155
+ openAiApiKey: answers.openAiApiKey,
156
+ anthropicApiKey: answers.anthropicApiKey
157
+ };
158
+ this.saveConfig(config);
159
+ console.log(chalk.green('\nāœ“ Configuration updated successfully!\n'));
160
+ return config;
161
+ }
162
+ async checkClaudeCodeInstallation() {
163
+ try {
164
+ console.log(chalk.gray('šŸ” Checking for Claude Code installation...'));
165
+ const { stdout } = await execAsync('claude --version');
166
+ console.log(chalk.green('āœ“ Claude Code is installed'));
167
+ console.log(chalk.gray(` Version: ${stdout.trim()}\n`));
168
+ }
169
+ catch {
170
+ console.log(chalk.red('āœ— Claude Code not found'));
171
+ console.log(chalk.yellow(' Please install Claude Code from: https://docs.anthropic.com/en/docs/claude-code\n'));
172
+ const { continueAnyway } = await inquirer.prompt([
173
+ {
174
+ type: 'confirm',
175
+ name: 'continueAnyway',
176
+ message: 'Continue setup without Claude Code?',
177
+ default: false
178
+ }
179
+ ]);
180
+ if (!continueAnyway) {
181
+ console.log(chalk.yellow('\nšŸ‘‹ Setup cancelled. Install Claude Code and try again.\n'));
182
+ process.exit(0);
183
+ }
184
+ }
185
+ }
186
+ }
187
+ //# sourceMappingURL=config.js.map