ralph-cli-sandboxed 0.4.1 β†’ 0.4.2

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 (69) hide show
  1. package/README.md +30 -0
  2. package/dist/commands/action.js +9 -9
  3. package/dist/commands/chat.js +13 -12
  4. package/dist/commands/config.js +2 -1
  5. package/dist/commands/daemon.js +4 -3
  6. package/dist/commands/docker.js +102 -66
  7. package/dist/commands/fix-config.js +2 -1
  8. package/dist/commands/fix-prd.js +2 -2
  9. package/dist/commands/init.js +78 -17
  10. package/dist/commands/listen.js +3 -1
  11. package/dist/commands/notify.js +1 -1
  12. package/dist/commands/once.js +17 -9
  13. package/dist/commands/prd.js +4 -1
  14. package/dist/commands/run.js +40 -25
  15. package/dist/commands/slack.js +2 -2
  16. package/dist/config/responder-presets.json +69 -0
  17. package/dist/index.js +1 -1
  18. package/dist/providers/discord.d.ts +28 -0
  19. package/dist/providers/discord.js +227 -14
  20. package/dist/providers/slack.d.ts +41 -1
  21. package/dist/providers/slack.js +389 -8
  22. package/dist/providers/telegram.d.ts +30 -0
  23. package/dist/providers/telegram.js +185 -5
  24. package/dist/responders/claude-code-responder.d.ts +48 -0
  25. package/dist/responders/claude-code-responder.js +203 -0
  26. package/dist/responders/cli-responder.d.ts +62 -0
  27. package/dist/responders/cli-responder.js +298 -0
  28. package/dist/responders/llm-responder.d.ts +135 -0
  29. package/dist/responders/llm-responder.js +582 -0
  30. package/dist/templates/macos-scripts.js +2 -4
  31. package/dist/templates/prompts.js +4 -2
  32. package/dist/tui/ConfigEditor.js +19 -5
  33. package/dist/tui/components/ArrayEditor.js +1 -1
  34. package/dist/tui/components/EditorPanel.js +10 -6
  35. package/dist/tui/components/HelpPanel.d.ts +1 -1
  36. package/dist/tui/components/HelpPanel.js +1 -1
  37. package/dist/tui/components/JsonSnippetEditor.js +8 -5
  38. package/dist/tui/components/KeyValueEditor.js +54 -9
  39. package/dist/tui/components/LLMProvidersEditor.d.ts +22 -0
  40. package/dist/tui/components/LLMProvidersEditor.js +357 -0
  41. package/dist/tui/components/ObjectEditor.js +1 -1
  42. package/dist/tui/components/Preview.js +1 -1
  43. package/dist/tui/components/RespondersEditor.d.ts +22 -0
  44. package/dist/tui/components/RespondersEditor.js +437 -0
  45. package/dist/tui/components/SectionNav.js +27 -3
  46. package/dist/utils/chat-client.d.ts +4 -0
  47. package/dist/utils/chat-client.js +12 -5
  48. package/dist/utils/config.d.ts +84 -0
  49. package/dist/utils/config.js +78 -1
  50. package/dist/utils/daemon-client.d.ts +21 -0
  51. package/dist/utils/daemon-client.js +28 -1
  52. package/dist/utils/llm-client.d.ts +82 -0
  53. package/dist/utils/llm-client.js +185 -0
  54. package/dist/utils/message-queue.js +6 -6
  55. package/dist/utils/notification.d.ts +6 -1
  56. package/dist/utils/notification.js +103 -2
  57. package/dist/utils/prd-validator.js +60 -19
  58. package/dist/utils/prompt.js +22 -12
  59. package/dist/utils/responder-logger.d.ts +47 -0
  60. package/dist/utils/responder-logger.js +129 -0
  61. package/dist/utils/responder-presets.d.ts +92 -0
  62. package/dist/utils/responder-presets.js +156 -0
  63. package/dist/utils/responder.d.ts +88 -0
  64. package/dist/utils/responder.js +207 -0
  65. package/dist/utils/stream-json.js +6 -6
  66. package/docs/CHAT-RESPONDERS.md +785 -0
  67. package/docs/DEVELOPMENT.md +25 -0
  68. package/docs/chat-architecture.md +251 -0
  69. package/package.json +11 -1
@@ -146,6 +146,31 @@ docker run -v $(pwd):/workspace -v /workspace/node_modules your-image
146
146
  - Use async/await for asynchronous operations
147
147
  - Keep functions focused and small
148
148
 
149
+ ### Linting with Oxlint
150
+
151
+ Ralph uses [Oxlint](https://oxc.rs/docs/guide/usage/linter.html) for fast TypeScript-aware linting:
152
+
153
+ ```bash
154
+ npm run lint # Run linter
155
+ ```
156
+
157
+ Configuration is in `oxlintrc.json`. Oxlint is significantly faster than ESLint while providing TypeScript-aware rules.
158
+
159
+ ### Formatting with Oxfmt
160
+
161
+ Ralph uses [Oxfmt](https://oxc.rs/docs/guide/usage/formatter.html) for code formatting:
162
+
163
+ ```bash
164
+ npm run format # Format all files
165
+ npm run format:check # Check formatting without changes
166
+ ```
167
+
168
+ Configuration is in `.oxfmtrc.json`:
169
+ - 2 spaces indentation
170
+ - Double quotes
171
+ - Semicolons
172
+ - 100 character line width
173
+
149
174
  ## Submitting Changes
150
175
 
151
176
  1. Fork the repository
@@ -0,0 +1,251 @@
1
+ # Ralph Chat Architecture
2
+
3
+ ## Overview
4
+
5
+ The Ralph CLI chat system enables external control of Ralph projects via chat platforms (Slack, Discord, Telegram). It consists of two main components that communicate via a file-based message queue.
6
+
7
+ ## High-Level Architecture
8
+
9
+ ```
10
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
11
+ β”‚ SLACK / DISCORD β”‚
12
+ β”‚ β”‚
13
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
14
+ β”‚ β”‚ /ralph cmd β”‚ β”‚ @bot mention β”‚ β”‚ @qa @review β”‚ β”‚ Thread replies β”‚ β”‚
15
+ β”‚ β”‚ (slash cmd) β”‚ β”‚ (app_mention)β”‚ β”‚ (responders) β”‚ β”‚ (continuation) β”‚ β”‚
16
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
17
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
18
+ β”‚ β”‚ β”‚ β”‚
19
+ β–Ό β–Ό β–Ό β–Ό
20
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
21
+ β”‚ HOST: ralph chat start β”‚
22
+ β”‚ β”‚
23
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
24
+ β”‚ β”‚ CHAT PROVIDER (Slack/Discord) β”‚ β”‚
25
+ β”‚ β”‚ β”‚ β”‚
26
+ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
27
+ β”‚ β”‚ β”‚ Event │───▢│ ResponderMatcher │───▢│ Thread Conversations β”‚ β”‚ β”‚
28
+ β”‚ β”‚ β”‚ Handlers β”‚ β”‚ (@qa, @review) β”‚ β”‚ (multi-turn memory) β”‚ β”‚ β”‚
29
+ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
30
+ β”‚ β”‚ β”‚ β”‚ β”‚
31
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
32
+ β”‚ β”‚ β”‚
33
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
34
+ β”‚ β–Ό β–Ό β–Ό β”‚
35
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
36
+ β”‚ β”‚ LLM β”‚ β”‚ Claude Code β”‚ β”‚ CLI Responder β”‚ β”‚
37
+ β”‚ β”‚ Responder β”‚ β”‚ Responder β”‚ β”‚ (shell commands) β”‚ β”‚
38
+ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
39
+ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ claude -p "..." β”‚ β”‚ eslint, etc. β”‚ β”‚
40
+ β”‚ β”‚ β”‚Anthropicβ”‚ β”‚ β”‚ --print β”‚ β”‚ β”‚ β”‚
41
+ β”‚ β”‚ β”‚ OpenAI β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
42
+ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
43
+ β”‚ β”‚ β”‚ β”‚
44
+ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
45
+ β”‚ β”‚ β”‚Git Diff β”‚ β”‚ /ralph commands (run, status, exec, etc.) β”‚
46
+ β”‚ β”‚ β”‚Keywords β”‚ β”‚ β”‚ β”‚
47
+ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”‚
48
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
49
+ β”‚ β”‚ Command Handler β”‚ β”‚
50
+ β”‚ β”‚ run, stop, status, exec, add, claude β”‚ β”‚
51
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
52
+ β”‚ β”‚ β”‚
53
+ β”‚ β–Ό β”‚
54
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
55
+ β”‚ β”‚ .ralph/messages.json β”‚ β”‚
56
+ β”‚ β”‚ (Message Queue) β”‚ β”‚
57
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
58
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
59
+ β”‚
60
+ ══════════════════════β•ͺ══════════════════════
61
+ DOCKER BOUNDARY β”‚ (volume mount)
62
+ ══════════════════════β•ͺ══════════════════════
63
+ β”‚
64
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
65
+ β”‚ β–Ό β”‚
66
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
67
+ β”‚ β”‚ /workspace/.ralph/messages.json β”‚ β”‚
68
+ β”‚ β”‚ (same file via mount) β”‚ β”‚
69
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
70
+ β”‚ β”‚ β”‚
71
+ β”‚ β–Ό β”‚
72
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
73
+ β”‚ β”‚ ralph listen β”‚ β”‚
74
+ β”‚ β”‚ (polls for pending messages) β”‚ β”‚
75
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
76
+ β”‚ β”‚ β”‚
77
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
78
+ β”‚ β–Ό β–Ό β–Ό β”‚
79
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
80
+ β”‚ β”‚ ralph run β”‚ β”‚ exec command β”‚ β”‚ ralph β”‚ β”‚
81
+ β”‚ β”‚ --category β”‚ β”‚ (shell) β”‚ β”‚ status β”‚ β”‚
82
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
83
+ β”‚ β”‚
84
+ β”‚ CONTAINER: ralph listen β”‚
85
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
86
+ ```
87
+
88
+ ## Responder Flow
89
+
90
+ ```
91
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
92
+ β”‚ Message: "@review last" β”‚
93
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
94
+ β”‚
95
+ β–Ό
96
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
97
+ β”‚ ResponderMatcher β”‚
98
+ β”‚ β”‚
99
+ β”‚ 1. Check @mention triggers: @qa, @review, @explain, @code β”‚
100
+ β”‚ 2. Check keyword triggers: !lint, help β”‚
101
+ β”‚ 3. Fall back to default responder β”‚
102
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
103
+ β”‚
104
+ β–Ό
105
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
106
+ β”‚ Match: @review β†’ "reviewer" β”‚
107
+ β”‚ Args: "last" β”‚
108
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
109
+ β”‚
110
+ β–Ό
111
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
112
+ β”‚ LLM Responder β”‚
113
+ β”‚ β”‚
114
+ β”‚ 1. Detect git keyword: "last" β†’ git show HEAD β”‚
115
+ β”‚ 2. Fetch git diff content β”‚
116
+ β”‚ 3. Build message with diff β”‚
117
+ β”‚ 4. Load conversation history (if thread) β”‚
118
+ β”‚ 5. Send to LLM (Anthropic/OpenAI) β”‚
119
+ β”‚ 6. Log to .ralph/logs/responder-YYYY-MM-DD.log β”‚
120
+ β”‚ 7. Return response β”‚
121
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
122
+ β”‚
123
+ β–Ό
124
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
125
+ β”‚ Store in Thread Conversation β”‚
126
+ β”‚ β”‚
127
+ β”‚ threadConversations.set(threadTs, { β”‚
128
+ β”‚ responderName: "reviewer", β”‚
129
+ β”‚ messages: [ β”‚
130
+ β”‚ { role: "user", content: "..." }, β”‚
131
+ β”‚ { role: "assistant", content: "..." } β”‚
132
+ β”‚ ] β”‚
133
+ β”‚ }) β”‚
134
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
135
+ β”‚
136
+ β–Ό
137
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
138
+ β”‚ Reply in Slack Thread β”‚
139
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
140
+ ```
141
+
142
+ ## Thread Conversation Flow
143
+
144
+ ```
145
+ Thread Start Thread Continuation
146
+ ───────────── ───────────────────
147
+
148
+ User: @review diff User: What about security?
149
+ β”‚ β”‚
150
+ β–Ό β–Ό
151
+ ResponderMatcher Check threadConversations
152
+ matches "@review" ─────────────────────────
153
+ β”‚ Found existing conversation
154
+ β–Ό for this thread_ts
155
+ Execute LLM with β”‚
156
+ git diff content β–Ό
157
+ β”‚ Execute LLM with:
158
+ β–Ό - Previous messages (history)
159
+ Store conversation - New user message
160
+ in threadConversations β”‚
161
+ β”‚ β–Ό
162
+ β–Ό Append to conversation
163
+ Reply in thread history (max 20 messages)
164
+ β”‚
165
+ β–Ό
166
+ Reply in thread
167
+ ```
168
+
169
+ ## Message Queue Format
170
+
171
+ ```json
172
+ {
173
+ "messages": [
174
+ {
175
+ "id": "uuid-1234",
176
+ "from": "host",
177
+ "action": "run",
178
+ "args": ["feature"],
179
+ "timestamp": 1706789012345,
180
+ "status": "pending"
181
+ },
182
+ {
183
+ "id": "uuid-1234",
184
+ "from": "host",
185
+ "action": "run",
186
+ "args": ["feature"],
187
+ "timestamp": 1706789012345,
188
+ "status": "done",
189
+ "response": {
190
+ "success": true,
191
+ "output": "Ralph run started (category: feature)"
192
+ }
193
+ }
194
+ ]
195
+ }
196
+ ```
197
+
198
+ ## Git Diff Keywords
199
+
200
+ | Keyword | Git Command | Description |
201
+ |---------|-------------|-------------|
202
+ | `diff` / `changes` | `git diff` | Unstaged changes |
203
+ | `staged` | `git diff --cached` | Staged changes |
204
+ | `last` / `last commit` | `git show HEAD` | Last commit |
205
+ | `all` | `git diff HEAD` | All uncommitted |
206
+ | `HEAD~N` | `git show HEAD~N` | N commits ago |
207
+
208
+ ## Responder Types
209
+
210
+ | Type | Description | Example Trigger |
211
+ |------|-------------|-----------------|
212
+ | `llm` | Send to LLM (Anthropic/OpenAI) | `@qa`, `@review` |
213
+ | `claude-code` | Spawn Claude Code CLI | `@code` |
214
+ | `cli` | Run shell command | `!lint` |
215
+
216
+ ## Configuration
217
+
218
+ ```json
219
+ {
220
+ "chat": {
221
+ "provider": "slack",
222
+ "slack": {
223
+ "botToken": "xoxb-...",
224
+ "appToken": "xapp-...",
225
+ "signingSecret": "...",
226
+ "allowedChannelIds": ["C1234567890"]
227
+ },
228
+ "responders": {
229
+ "qa": {
230
+ "type": "llm",
231
+ "trigger": "@qa",
232
+ "provider": "anthropic",
233
+ "systemPrompt": "You are a QA assistant for {{project}}..."
234
+ }
235
+ }
236
+ }
237
+ }
238
+ ```
239
+
240
+ ## File Locations
241
+
242
+ ```
243
+ Host Machine Container
244
+ ──────────── ─────────
245
+ .ralph/
246
+ β”œβ”€β”€ config.json /workspace/.ralph/
247
+ β”œβ”€β”€ chat-state.json β”œβ”€β”€ messages.json (shared)
248
+ β”œβ”€β”€ messages.json ◄──── mount ────► β”œβ”€β”€ run.pid
249
+ └── logs/ └── ...
250
+ └── responder-YYYY-MM-DD.log
251
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ralph-cli-sandboxed",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "AI-driven development automation CLI for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,22 +17,29 @@
17
17
  "copy-config": "mkdir -p dist/config && cp src/config/*.json dist/config/",
18
18
  "dev": "npx tsx src/index.ts",
19
19
  "typecheck": "tsc --noEmit",
20
+ "lint": "oxlint src/",
21
+ "format": "oxfmt src/",
22
+ "format:check": "oxfmt --check src/",
20
23
  "prepublishOnly": "npm run build",
21
24
  "prepare": "npm run build"
22
25
  },
23
26
  "dependencies": {
27
+ "@anthropic-ai/sdk": "^0.39.0",
24
28
  "@inkjs/ui": "^2.0.0",
25
29
  "@slack/bolt": "^4.6.0",
26
30
  "@slack/web-api": "^7.13.0",
27
31
  "discord.js": "^14.16.0",
28
32
  "ink": "^5.0.1",
29
33
  "ink-text-input": "^6.0.0",
34
+ "openai": "^4.77.0",
30
35
  "react": "^18.3.1",
31
36
  "readline": "^1.3.0"
32
37
  },
33
38
  "devDependencies": {
34
39
  "@types/node": "^20.0.0",
35
40
  "@types/react": "^18.3.12",
41
+ "oxfmt": "^0.27.0",
42
+ "oxlint": "^1.42.0",
36
43
  "tsx": "^4.0.0",
37
44
  "typescript": "^5.0.0"
38
45
  },
@@ -60,5 +67,8 @@
60
67
  },
61
68
  "engines": {
62
69
  "node": ">=18.0.0"
70
+ },
71
+ "overrides": {
72
+ "undici": "^6.23.0"
63
73
  }
64
74
  }