@aaronshaf/ger 0.1.3 → 0.1.5

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.
package/bun.lock CHANGED
@@ -4,7 +4,6 @@
4
4
  "": {
5
5
  "name": "ger",
6
6
  "dependencies": {
7
- "@anthropic-ai/claude-code": "^1.0.102",
8
7
  "@effect/platform": "^0.90.6",
9
8
  "@effect/platform-node": "^0.94.2",
10
9
  "@effect/schema": "^0.75.5",
@@ -32,8 +31,6 @@
32
31
  },
33
32
  },
34
33
  "packages": {
35
- "@anthropic-ai/claude-code": ["@anthropic-ai/claude-code@1.0.102", "", { "optionalDependencies": { "@img/sharp-darwin-arm64": "^0.33.5", "@img/sharp-darwin-x64": "^0.33.5", "@img/sharp-linux-arm": "^0.33.5", "@img/sharp-linux-arm64": "^0.33.5", "@img/sharp-linux-x64": "^0.33.5", "@img/sharp-win32-x64": "^0.33.5" }, "bin": { "claude": "cli.js" } }, "sha512-UIC6qNgKNZi1nLTf1bQvxNfd74xIAqJjIx6vggh3bJOMtuXBiFwrfPk1Pdf9CayYgwZYXgSmxYYaASt6i6ficQ=="],
36
-
37
34
  "@babel/code-frame": ["@babel/code-frame@7.0.0-beta.37", "", { "dependencies": { "chalk": "^2.0.0", "esutils": "^2.0.2", "js-tokens": "^3.0.0" } }, "sha512-LIpcKm+2otOOvOvhCbD6wkNYi8aUwHk73uWR+hxBdW2EFht5D0QX89n4me8nyeNGWr5zC3Pvmjq+9MvUof+jkg=="],
38
35
 
39
36
  "@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="],
@@ -96,28 +93,6 @@
96
93
 
97
94
  "@effect/workflow": ["@effect/workflow@0.8.3", "", { "peerDependencies": { "@effect/platform": "^0.90.0", "@effect/rpc": "^0.68.3", "effect": "^3.17.6" } }, "sha512-8X5IOemCb6I66GMd84w6NSmaQ+Ya3oXwItCUMelQAEuRtGzwqsw8PNNunQgK/poSRkmpszlsKOb6kEVNjSdFiQ=="],
98
95
 
99
- "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="],
100
-
101
- "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="],
102
-
103
- "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="],
104
-
105
- "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="],
106
-
107
- "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="],
108
-
109
- "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="],
110
-
111
- "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="],
112
-
113
- "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="],
114
-
115
- "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="],
116
-
117
- "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="],
118
-
119
- "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="],
120
-
121
96
  "@inquirer/checkbox": ["@inquirer/checkbox@4.2.2", "", { "dependencies": { "@inquirer/core": "^10.2.0", "@inquirer/figures": "^1.0.13", "@inquirer/type": "^3.0.8", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-E+KExNurKcUJJdxmjglTl141EwxWyAHplvsYJQgSwXf8qiNWkTxTuCCqmhFEmbIXd4zLaGMfQFJ6WrZ7fSeV3g=="],
122
97
 
123
98
  "@inquirer/confirm": ["@inquirer/confirm@5.1.16", "", { "dependencies": { "@inquirer/core": "^10.2.0", "@inquirer/type": "^3.0.8" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-j1a5VstaK5KQy8Mu8cHmuQvN1Zc62TbLhjJxwHvKPPKEoowSF6h/0UdOpA9DNdWZ+9Inq73+puRq1df6OJ8Sag=="],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aaronshaf/ger",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "bin": {
@@ -29,7 +29,6 @@
29
29
  "typescript": "^5.0.0"
30
30
  },
31
31
  "dependencies": {
32
- "@anthropic-ai/claude-code": "^1.0.102",
33
32
  "@effect/platform": "^0.90.6",
34
33
  "@effect/platform-node": "^0.94.2",
35
34
  "@effect/schema": "^0.75.5",
@@ -331,7 +331,7 @@ export const reviewCommand = (changeId: string, options: ReviewOptions = {}) =>
331
331
 
332
332
  if (availableStrategies.length === 0) {
333
333
  return yield* Effect.fail(
334
- new Error('No AI tools available. Please install claude, gemini, or codex CLI.'),
334
+ new Error('No AI tools available. Please install claude, gemini, or opencode CLI.'),
335
335
  )
336
336
  }
337
337
 
package/src/cli/index.ts CHANGED
@@ -368,15 +368,12 @@ program
368
368
  .option('-y, --yes', 'Skip confirmation prompts when posting comments')
369
369
  .option('--debug', 'Show debug output including AI responses')
370
370
  .option('--prompt <file>', 'Path to custom review prompt file (e.g., ~/prompts/review.md)')
371
- .option(
372
- '--provider <provider>',
373
- 'Preferred AI provider (claude-sdk, claude, gemini, codex, opencode)',
374
- )
371
+ .option('--provider <provider>', 'Preferred AI provider (claude-sdk, claude, gemini, opencode)')
375
372
  .option('--system-prompt <prompt>', 'Custom system prompt for the AI')
376
373
  .addHelpText(
377
374
  'after',
378
375
  `
379
- This command uses AI (Claude SDK, claude CLI, gemini CLI, codex CLI, or opencode CLI) to review a Gerrit change.
376
+ This command uses AI (Claude SDK, claude CLI, gemini CLI, or opencode CLI) to review a Gerrit change.
380
377
  It performs a two-stage review process:
381
378
 
382
379
  1. Generates inline comments for specific code issues
@@ -387,7 +384,7 @@ Use --comment to post the review to Gerrit (with confirmation prompts).
387
384
  Use --comment --yes to post without confirmation.
388
385
 
389
386
  Requirements:
390
- - One of these AI tools must be available: Claude SDK (ANTHROPIC_API_KEY), claude CLI, gemini CLI, codex CLI, or opencode CLI
387
+ - One of these AI tools must be available: Claude SDK (ANTHROPIC_API_KEY), claude CLI, gemini CLI, or opencode CLI
391
388
  - Gerrit credentials must be configured (run 'ger setup' first)
392
389
 
393
390
  Examples:
@@ -1,17 +1,9 @@
1
1
  import { Context, Data, Effect, Layer } from 'effect'
2
- import { Console } from 'effect'
3
2
  import { exec } from 'node:child_process'
4
3
  import { promisify } from 'node:util'
5
4
 
6
5
  const execAsync = promisify(exec)
7
6
 
8
- // Dynamic import for Claude SDK
9
- const getClaudeSDK = () =>
10
- Effect.tryPromise({
11
- try: () => import('@anthropic-ai/claude-code'),
12
- catch: () => null,
13
- }).pipe(Effect.orElseSucceed(() => null))
14
-
15
7
  // Simple strategy focused only on review needs
16
8
  export class ReviewStrategyError extends Data.TaggedError('ReviewStrategyError')<{
17
9
  message: string
@@ -205,90 +197,6 @@ export const openCodeCliStrategy: ReviewStrategy = {
205
197
  }),
206
198
  }
207
199
 
208
- export const codexCliStrategy: ReviewStrategy = {
209
- name: 'Codex CLI',
210
- isAvailable: () =>
211
- Effect.gen(function* () {
212
- const result = yield* Effect.tryPromise({
213
- try: () => execAsync('which codex'),
214
- catch: () => null,
215
- }).pipe(Effect.orElseSucceed(() => null))
216
-
217
- return Boolean(result && result.stdout.trim())
218
- }),
219
- executeReview: (prompt, options = {}) =>
220
- Effect.gen(function* () {
221
- const command = `codex exec "${prompt.replace(/"/g, '\\"')}"`
222
-
223
- const result = yield* Effect.tryPromise({
224
- try: () => execAsync(command, { cwd: options.cwd }),
225
- catch: (error) =>
226
- new ReviewStrategyError({
227
- message: `Codex CLI failed: ${error instanceof Error ? error.message : String(error)}`,
228
- cause: error,
229
- }),
230
- })
231
-
232
- return result.stdout.trim()
233
- }),
234
- }
235
-
236
- export const claudeSDKStrategy: ReviewStrategy = {
237
- name: 'Claude SDK',
238
- isAvailable: () =>
239
- Effect.gen(function* () {
240
- const sdk = yield* getClaudeSDK()
241
-
242
- // Check if we have ANTHROPIC_API_KEY
243
- const hasApiKey = Boolean(process.env.ANTHROPIC_API_KEY)
244
-
245
- return Boolean(sdk && hasApiKey)
246
- }),
247
- executeReview: (prompt, options = {}) =>
248
- Effect.gen(function* () {
249
- const sdk = yield* getClaudeSDK()
250
-
251
- if (!sdk) {
252
- return yield* Effect.fail(
253
- new ReviewStrategyError({
254
- message: 'Claude SDK not available',
255
- }),
256
- )
257
- }
258
-
259
- const result = yield* Effect.tryPromise({
260
- try: async () => {
261
- const messages = []
262
-
263
- for await (const message of sdk.query({
264
- prompt,
265
- options: {
266
- maxTurns: 3,
267
- customSystemPrompt:
268
- options.systemPrompt ||
269
- 'You are a code review expert. Analyze code changes and provide constructive feedback.',
270
- allowedTools: ['Read', 'Grep', 'Glob'],
271
- cwd: options.cwd,
272
- },
273
- })) {
274
- if (message.type === 'result' && message.subtype === 'success') {
275
- return message.result
276
- }
277
- }
278
-
279
- throw new Error('No result received from Claude SDK')
280
- },
281
- catch: (error) =>
282
- new ReviewStrategyError({
283
- message: `Claude SDK failed: ${error instanceof Error ? error.message : String(error)}`,
284
- cause: error,
285
- }),
286
- })
287
-
288
- return result
289
- }),
290
- }
291
-
292
200
  // Review service using strategy pattern
293
201
  export class ReviewStrategyService extends Context.Tag('ReviewStrategyService')<
294
202
  ReviewStrategyService,
@@ -310,13 +218,7 @@ export const ReviewStrategyServiceLive = Layer.succeed(
310
218
  ReviewStrategyService.of({
311
219
  getAvailableStrategies: () =>
312
220
  Effect.gen(function* () {
313
- const strategies = [
314
- claudeSDKStrategy,
315
- claudeCliStrategy,
316
- geminiCliStrategy,
317
- openCodeCliStrategy,
318
- codexCliStrategy,
319
- ]
221
+ const strategies = [claudeCliStrategy, geminiCliStrategy, openCodeCliStrategy]
320
222
  const available: ReviewStrategy[] = []
321
223
 
322
224
  for (const strategy of strategies) {
@@ -331,13 +233,7 @@ export const ReviewStrategyServiceLive = Layer.succeed(
331
233
 
332
234
  selectStrategy: (preferredName?: string) =>
333
235
  Effect.gen(function* () {
334
- const strategies = [
335
- claudeSDKStrategy,
336
- claudeCliStrategy,
337
- geminiCliStrategy,
338
- openCodeCliStrategy,
339
- codexCliStrategy,
340
- ]
236
+ const strategies = [claudeCliStrategy, geminiCliStrategy, openCodeCliStrategy]
341
237
  const available: ReviewStrategy[] = []
342
238
 
343
239
  for (const strategy of strategies) {
@@ -350,7 +246,7 @@ export const ReviewStrategyServiceLive = Layer.succeed(
350
246
  if (available.length === 0) {
351
247
  return yield* Effect.fail(
352
248
  new ReviewStrategyError({
353
- message: 'No AI tools available. Please install claude, gemini, or codex CLI.',
249
+ message: 'No AI tools available. Please install claude, gemini, or opencode CLI.',
354
250
  }),
355
251
  )
356
252
  }