ai-cmds 0.1.1 → 0.2.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.
package/README.md CHANGED
@@ -5,14 +5,16 @@ AI-powered CLI tool that uses OpenAI and Google Gemini models to review code cha
5
5
  ## Features
6
6
 
7
7
  - Multiple AI models: GPT-5, GPT-5-mini, GPT-4o-mini, Gemini 2.5 Pro, Gemini 2.0 Flash
8
- - Configurable review setups from very light to heavy
9
- - Custom setups with full control over reviewer, validator, and formatter models
10
- - Three commands: `review-code-changes` for local development, `review-pr` for CI, `create-pr` for PR creation
11
- - Parallel reviews with validation pass for higher accuracy
8
+ - Configurable review setups from light to heavy
9
+ - Custom setups with full control over reviewer and validator models
10
+ - Four commands: `review-code-changes` for local development, `advanced-review-changes` for guided/customized local review focus, `review-pr` for CI, `create-pr` for PR creation
11
+ - Parallel reviews with a single structured validation pass for higher accuracy
12
+ - Optional provider-aware concurrency limits for reviewer fan-out
12
13
  - AI-generated PR titles and descriptions
13
14
  - Automatic filtering of import-only changes
14
15
  - Custom review instructions support
15
16
  - Token usage tracking and cost awareness
17
+ - Improved review visualization with severity totals, issue IDs (`C1`, `P1`, `S1`), and impacted file counts
16
18
 
17
19
  ## Installation
18
20
 
@@ -47,12 +49,45 @@ ai-cmds review-code-changes --setup light
47
49
 
48
50
  # Specify base branch
49
51
  ai-cmds review-code-changes --scope all --base-branch develop
52
+
53
+ # Save review to a custom file path
54
+ ai-cmds review-code-changes --scope all --output reviews/local-review.md
50
55
  ```
51
56
 
52
57
  **Arguments:**
53
58
  - `--scope` - Review scope: `all`, `staged`, `globs`, `unViewed`, or custom scope id
54
59
  - `--setup` - Review setup: `light`, `medium`, `heavy`, or custom setup id
55
60
  - `--base-branch` - Base branch for diff comparison (if not specified, prompts for selection)
61
+ - `--output` - Output file path for the generated review markdown (default: `pr-review.md`)
62
+
63
+ ### `advanced-review-changes` - Advanced Local Development
64
+
65
+ Review local code changes with the same flow as `review-code-changes`, plus extra control over review guidance.
66
+
67
+ ```bash
68
+ # Guided mode (prompts for custom instruction and instruction inclusion)
69
+ ai-cmds advanced-review-changes
70
+
71
+ # Pass a custom review focus instruction
72
+ ai-cmds advanced-review-changes --custom-review-instruction "Focus on authentication and authorization issues"
73
+
74
+ # Disable default/configured instructions and only use your custom instruction
75
+ ai-cmds advanced-review-changes \
76
+ --custom-review-instruction "Focus on performance bottlenecks and N+1 queries" \
77
+ --include-default-review-instructions false
78
+ ```
79
+
80
+ **Arguments:**
81
+ - `--scope` - Review scope: `all`, `staged`, `globs`, `unViewed`, or custom scope id
82
+ - `--setup` - Review setup: `light`, `medium`, `heavy`, or custom setup id
83
+ - `--base-branch` - Base branch for diff comparison (if not specified, prompts for selection)
84
+ - `--output` - Output file path for the generated review markdown (default: `pr-review.md`)
85
+ - `--custom-review-instruction` - Extra custom instruction that tells reviewers what to focus on
86
+ - `--include-default-review-instructions` - Whether to include configured/default instructions (`true` or `false`)
87
+
88
+ **Interactive behavior:**
89
+ - If `--include-default-review-instructions` is not provided, the CLI shows a confirm dialog.
90
+ - If `--custom-review-instruction` is not provided, the CLI asks whether you want to add one and prompts for it if confirmed.
56
91
 
57
92
  ### `review-pr` - CI/PR Review
58
93
 
@@ -71,13 +106,15 @@ ai-cmds review-pr --pr 123 --setup heavy
71
106
 
72
107
  **Arguments:**
73
108
  - `--pr` - PR number to review (**required**)
74
- - `--setup` - Review setup: `light`, `medium`, `heavy`, or custom setup label
109
+ - `--setup` - Review setup: `light`, `medium`, `heavy`, or custom setup id
75
110
  - `--test` - Test mode: skip posting review to PR, just save to file
76
111
  - `--skip-previous-check` - Skip checking if previous review issues are still present
77
112
 
78
113
  **Behavior:**
79
114
  - In GitHub Actions (`GITHUB_ACTIONS` env set): Posts review as PR comment
80
115
  - With `--test` flag or locally: Saves review to `pr-review-test.md`
116
+ - If the filtered diff has no reviewable code (for example import/export-only changes), the command skips AI calls and emits a no-issues review
117
+ - Reviewer fan-out respects `codeReview.concurrencyPerProvider` when configured
81
118
 
82
119
  **Previous Review Check:**
83
120
 
@@ -127,12 +164,9 @@ ai-cmds create-pr --title "Fix login validation"
127
164
 
128
165
  | Setup | Reviewers | Description |
129
166
  |-------|-----------|-------------|
130
- | `veryLight` | 1× GPT-5-mini | Fastest, lowest cost |
131
167
  | `light` | 1× GPT-5 | Balanced |
132
168
  | `medium` | 2× GPT-5 (high reasoning) | More thorough |
133
169
  | `heavy` | 4× GPT-5 (high reasoning) | Most comprehensive |
134
- | `lightGoogle` | 1× Gemini 2.5 Pro | Google alternative |
135
- | `mediumGoogle` | 2× Gemini 2.5 Pro | Google thorough |
136
170
 
137
171
  ## Review Scopes
138
172
 
@@ -169,7 +203,7 @@ This requires an open PR for the current branch. It uses the GitHub GraphQL API
169
203
 
170
204
  ## Configuration
171
205
 
172
- Create `ai-cli.config.ts` in your project root:
206
+ Create `ai-cmds.config.ts` in your project root:
173
207
 
174
208
  ```typescript
175
209
  import { defineConfig } from 'ai-cmds';
@@ -179,6 +213,11 @@ export default defineConfig({
179
213
  baseBranch: 'main',
180
214
  codeReviewDiffExcludePatterns: ['pnpm-lock.yaml', '**/*.svg', '**/*.test.ts'],
181
215
  reviewInstructionsPath: '.github/PR_REVIEW_AGENT.md',
216
+ includeAgentsFileInReviewPrompt: true,
217
+ concurrencyPerProvider: {
218
+ 'openai.responses': 2,
219
+ 'google.generative-ai': 1,
220
+ },
182
221
  },
183
222
  createPR: {
184
223
  baseBranch: 'main',
@@ -224,11 +263,13 @@ By default, `.env` is loaded automatically before the config file is imported, a
224
263
  | `baseBranch` | Base branch for diff comparison. Can be a string or function `(currentBranch) => string`. If not set, prompts for selection |
225
264
  | `codeReviewDiffExcludePatterns` | Glob patterns for files to exclude from review |
226
265
  | `reviewInstructionsPath` | Path to custom review instructions markdown file |
266
+ | `includeAgentsFileInReviewPrompt` | Include `<git-root>/AGENTS.md` content in reviewer prompts (default: `true`) |
267
+ | `reviewOutputPath` | Default output file path for `review-code-changes` (can be overridden by `--output`) |
227
268
  | `setup` | Array of custom named setups (see below) |
228
269
  | `scope` | Array of custom named scopes (see below) |
229
270
  | `defaultValidator` | Default validator model for custom setups |
230
- | `defaultFormatter` | Default formatter model for custom setups |
231
- | `logsDir` | Directory for logs (can also use `AI_CLI_LOGS_DIR` env var) |
271
+ | `concurrencyPerProvider` | Reviewer concurrency limit. Use a number for all providers or `{ [providerId]: number }` for per-provider limits (keys come from `model.provider`, e.g. `openai.responses`; unspecified providers default to unlimited) |
272
+ | `logsDir` | Directory for review run artifacts (can also use `AI_CLI_LOGS_DIR` env var) |
232
273
 
233
274
  #### `createPR` Options
234
275
 
@@ -241,6 +282,14 @@ By default, `.env` is loaded automatically before the config file is imported, a
241
282
  | `diffExcludePatterns` | Glob patterns for files to exclude from diff |
242
283
  | `maxDiffTokens` | Maximum tokens from diff to include in AI prompt (default: 50000) |
243
284
 
285
+ When `codeReview.logsDir` (or `AI_CLI_LOGS_DIR`) is set, each review run stores artifacts under:
286
+
287
+ - `<logsDir>/advanced-review-changes/<run-id>/...` for advanced local reviews
288
+ - `<logsDir>/review-code-changes/<run-id>/...` for local reviews
289
+ - `<logsDir>/review-pr/<run-id>/...` for PR reviews
290
+
291
+ Each run includes `context.yaml`, `changed-files.txt`, `diff.diff`, `reviewers/*.md`, `reviewers/*-debug.yaml`, `validator.yaml`, `final-review.md`, and `summary.yaml`.
292
+
244
293
  ### Dynamic Base Branch
245
294
 
246
295
  The `baseBranch` option can be a function that receives the current branch name:
@@ -256,7 +305,7 @@ export default defineConfig({
256
305
 
257
306
  ### Custom Setups
258
307
 
259
- Define custom named setups with full control over which models are used. **When custom setups are configured, they replace built-in options** (veryLight, light, medium, heavy).
308
+ Define custom named setups with full control over which models are used. **When custom setups are configured, they replace built-in options** (light, medium, heavy).
260
309
 
261
310
  ```typescript
262
311
  import { defineConfig } from 'ai-cmds';
@@ -267,24 +316,24 @@ export default defineConfig({
267
316
  codeReview: {
268
317
  setup: [
269
318
  {
319
+ id: 'myCustomSetup',
270
320
  label: 'myCustomSetup',
271
321
  reviewers: [
272
322
  { label: 'GPT-5', model: openai('gpt-5.2'), providerOptions: { reasoningEffort: 'high' } },
273
323
  { model: google('gemini-2.5-pro') },
274
324
  ],
275
325
  validator: { model: openai('gpt-5.2') },
276
- formatter: { model: openai('gpt-5-mini') },
277
326
  },
278
327
  {
328
+ id: 'fastReview',
279
329
  label: 'fastReview',
280
330
  reviewers: [{ model: openai('gpt-5-mini') }],
281
- // validator and formatter use defaults
331
+ // validator uses defaultValidator
282
332
  },
283
333
  ],
284
334
 
285
- // Defaults for custom setups that don't specify validator/formatter
335
+ // Default validator for custom setups that don't specify one
286
336
  defaultValidator: { model: openai('gpt-5.2'), providerOptions: { reasoningEffort: 'high' } },
287
- defaultFormatter: { model: openai('gpt-5-mini') },
288
337
  },
289
338
  });
290
339
  ```
@@ -324,11 +373,13 @@ export default defineConfig({
324
373
  {
325
374
  id: 'src-only',
326
375
  label: 'Source files only',
376
+ diffSource: 'branch',
327
377
  getFiles: (ctx) => ctx.allFiles.filter((f) => f.startsWith('src/')),
328
378
  },
329
379
  {
330
380
  id: 'no-tests',
331
381
  label: 'Exclude tests',
382
+ diffSource: 'branch',
332
383
  getFiles: (ctx) => ctx.allFiles.filter((f) => !f.includes('.test.')),
333
384
  },
334
385
  ],
@@ -340,6 +391,10 @@ The `getFiles` function receives a context object with:
340
391
  - `stagedFiles`: Files currently staged for commit
341
392
  - `allFiles`: All files changed compared to base branch
342
393
 
394
+ The optional `diffSource` field controls which git diff source the scope uses:
395
+ - `'branch'` (default): compare against selected base branch
396
+ - `'staged'`: use staged changes
397
+
343
398
  To include built-in options alongside your custom scopes, use `BUILT_IN_SCOPE_OPTIONS`:
344
399
 
345
400
  ```typescript
@@ -26,9 +26,13 @@ type SetupConfig = {
26
26
  reviewers: CustomModelConfig[];
27
27
  /** Model that validates and consolidates findings from all reviewers. Defaults to first reviewer if not specified. */
28
28
  validator?: CustomModelConfig;
29
- /** Model that formats the final output to structured JSON. Defaults to gpt-5-mini if not specified. */
30
- formatter?: CustomModelConfig;
31
29
  };
30
+ /**
31
+ * Review concurrency settings.
32
+ * - number: applies the same concurrency limit to all providers
33
+ * - object: sets per-provider concurrency limits (fallback for unspecified providers is unlimited)
34
+ */
35
+ type ReviewConcurrencyConfig = number | Record<string, number>;
32
36
  /**
33
37
  * Context provided to scope's getFiles function with all available file lists.
34
38
  */
@@ -47,6 +51,13 @@ type ScopeConfig = {
47
51
  id: string;
48
52
  /** Display label shown in UI */
49
53
  label: string;
54
+ /**
55
+ * Which git diff source this scope should use.
56
+ * - `branch` compares against the selected base branch
57
+ * - `staged` reviews staged changes
58
+ * @default 'branch'
59
+ */
60
+ diffSource?: 'branch' | 'staged';
50
61
  /** Function that receives available file lists and returns the files to review */
51
62
  getFiles: (ctx: ScopeContext) => string[] | Promise<string[]>;
52
63
  showFileCount?: boolean;
@@ -73,7 +84,21 @@ type ReviewCodeChangesConfig = {
73
84
  */
74
85
  reviewInstructionsPath?: string;
75
86
  /**
76
- * Array of custom named setups with full control over reviewer, validator, and formatter models.
87
+ * Whether to include the repository AGENTS.md content in reviewer prompts.
88
+ * Uses `<git-root>/AGENTS.md` when available.
89
+ * @default true
90
+ */
91
+ includeAgentsFileInReviewPrompt?: boolean;
92
+ /**
93
+ * Output file path for local review markdown generated by
94
+ * `review-code-changes` or `advanced-review-changes`.
95
+ * Can be overridden via `--output`.
96
+ * @default 'pr-review.md'
97
+ * @example './reviews/local-review.md'
98
+ */
99
+ reviewOutputPath?: string;
100
+ /**
101
+ * Array of custom named setups with full control over reviewer and validator models.
77
102
  * Each setup has a label that can be selected via the CLI --setup flag.
78
103
  * Custom setups take precedence over built-in presets when labels match.
79
104
  */
@@ -89,17 +114,26 @@ type ReviewCodeChangesConfig = {
89
114
  * Falls back to first reviewer in the setup if not specified.
90
115
  */
91
116
  defaultValidator?: CustomModelConfig;
92
- /**
93
- * Default formatter model used when a setup doesn't specify one.
94
- * Falls back to gpt-5-mini if not specified.
95
- */
96
- defaultFormatter?: CustomModelConfig;
97
117
  /**
98
118
  * Directory for storing review logs.
99
119
  * Can also be set via `AI_CLI_LOGS_DIR` environment variable.
100
120
  * Config value takes precedence over env var.
101
121
  */
102
122
  logsDir?: string;
123
+ /**
124
+ * Concurrency limit for running independent reviewer models.
125
+ *
126
+ * - `number`: same limit for all providers
127
+ * - `Record<string, number>`: per-provider limits keyed by provider id
128
+ *
129
+ * Provider ids come from `model.provider` (for example, `openai.responses` and `google.generative-ai`).
130
+ * Unspecified providers default to unlimited concurrency.
131
+ *
132
+ * @default Number.POSITIVE_INFINITY
133
+ * @example 2
134
+ * @example { 'openai.responses': 2, 'google.generative-ai': 1 }
135
+ */
136
+ concurrencyPerProvider?: ReviewConcurrencyConfig;
103
137
  };
104
138
  type CreatePRConfig = {
105
139
  /**
@@ -139,7 +173,8 @@ type CreatePRConfig = {
139
173
  };
140
174
  type Config = {
141
175
  /**
142
- * Configuration for the review-code-changes and review-pr commands.
176
+ * Configuration for the review-code-changes, advanced-review-changes, and
177
+ * review-pr commands.
143
178
  */
144
179
  codeReview?: ReviewCodeChangesConfig;
145
180
  /**
@@ -178,24 +213,28 @@ declare const DEFAULT_SCOPES: {
178
213
  readonly all: {
179
214
  readonly id: "all";
180
215
  readonly label: "All changes";
216
+ readonly diffSource: "branch";
181
217
  readonly showFileCount: true;
182
218
  readonly getFiles: (ctx: ScopeContext) => string[];
183
219
  };
184
220
  readonly staged: {
185
221
  readonly id: "staged";
186
222
  readonly label: "Staged changes";
223
+ readonly diffSource: "staged";
187
224
  readonly showFileCount: true;
188
225
  readonly getFiles: (ctx: ScopeContext) => string[];
189
226
  };
190
227
  readonly globs: {
191
228
  readonly id: "globs";
192
229
  readonly label: "Select files using glob patterns (use !pattern to exclude)";
230
+ readonly diffSource: "branch";
193
231
  readonly showFileCount: false;
194
232
  readonly getFiles: (ctx: ScopeContext) => Promise<string[]>;
195
233
  };
196
234
  readonly unViewed: {
197
235
  readonly id: "unViewed";
198
236
  readonly label: "Unviewed files in PR";
237
+ readonly diffSource: "branch";
199
238
  readonly showFileCount: false;
200
239
  readonly getFiles: () => Promise<string[]>;
201
240
  };
@@ -233,7 +272,57 @@ declare const BUILT_IN_SETUP_OPTIONS: SetupConfig[];
233
272
  * Converts setup configs to CLI select options.
234
273
  */
235
274
  //#endregion
236
- //#region src/commands/create-pr/index.d.ts
275
+ //#region src/commands/advanced-review-changes/advanced-review-changes.d.ts
276
+ declare const advancedReviewChangesCommand: {
277
+ short: string | undefined;
278
+ description: string;
279
+ run: (cmdArgs: {
280
+ setup: string | undefined;
281
+ scope: string | undefined;
282
+ baseBranch: string | undefined;
283
+ output: string | undefined;
284
+ customReviewInstruction: string | undefined;
285
+ includeDefaultReviewInstructions: string | undefined;
286
+ }) => Promise<void> | void;
287
+ args: {
288
+ setup: {
289
+ type: "value-string-flag";
290
+ name: string;
291
+ description: string;
292
+ };
293
+ scope: {
294
+ type: "value-string-flag";
295
+ name: string;
296
+ description: string;
297
+ };
298
+ baseBranch: {
299
+ type: "value-string-flag";
300
+ name: string;
301
+ description: string;
302
+ };
303
+ output: {
304
+ type: "value-string-flag";
305
+ name: string;
306
+ description: string;
307
+ };
308
+ customReviewInstruction: {
309
+ type: "value-string-flag";
310
+ name: string;
311
+ description: string;
312
+ };
313
+ includeDefaultReviewInstructions: {
314
+ type: "value-string-flag";
315
+ name: string;
316
+ description: string;
317
+ };
318
+ } | undefined;
319
+ examples: {
320
+ args: string[];
321
+ description: string;
322
+ }[] | undefined;
323
+ };
324
+ //#endregion
325
+ //#region src/commands/create-pr/create-pr.d.ts
237
326
  declare const createPRCommand: {
238
327
  short: string | undefined;
239
328
  description: string;
@@ -271,7 +360,7 @@ declare const createPRCommand: {
271
360
  }[] | undefined;
272
361
  };
273
362
  //#endregion
274
- //#region src/commands/review-code-changes/index.d.ts
363
+ //#region src/commands/review-code-changes/review-code-changes.d.ts
275
364
  declare const reviewCodeChangesCommand: {
276
365
  short: string | undefined;
277
366
  description: string;
@@ -279,6 +368,7 @@ declare const reviewCodeChangesCommand: {
279
368
  setup: string | undefined;
280
369
  scope: string | undefined;
281
370
  baseBranch: string | undefined;
371
+ output: string | undefined;
282
372
  }) => Promise<void> | void;
283
373
  args: {
284
374
  setup: {
@@ -296,6 +386,11 @@ declare const reviewCodeChangesCommand: {
296
386
  name: string;
297
387
  description: string;
298
388
  };
389
+ output: {
390
+ type: "value-string-flag";
391
+ name: string;
392
+ description: string;
393
+ };
299
394
  } | undefined;
300
395
  examples: {
301
396
  args: string[];
@@ -303,7 +398,7 @@ declare const reviewCodeChangesCommand: {
303
398
  }[] | undefined;
304
399
  };
305
400
  //#endregion
306
- //#region src/commands/review-pr/index.d.ts
401
+ //#region src/commands/review-pr/review-pr.d.ts
307
402
  declare const reviewPRCommand: {
308
403
  short: string | undefined;
309
404
  description: string;
@@ -341,4 +436,4 @@ declare const reviewPRCommand: {
341
436
  }[] | undefined;
342
437
  };
343
438
  //#endregion
344
- export { BUILT_IN_SCOPE_OPTIONS, BUILT_IN_SETUP_OPTIONS, type Config, type CreatePRConfig, type CustomModelConfig, DEFAULT_SCOPES, type ReviewCodeChangesConfig, type ScopeConfig, type ScopeContext, type SetupConfig, createPRCommand, defineConfig, reviewCodeChangesCommand, reviewPRCommand };
439
+ export { BUILT_IN_SCOPE_OPTIONS, BUILT_IN_SETUP_OPTIONS, type Config, type CreatePRConfig, type CustomModelConfig, DEFAULT_SCOPES, type ReviewCodeChangesConfig, type ReviewConcurrencyConfig, type ScopeConfig, type ScopeContext, type SetupConfig, advancedReviewChangesCommand, createPRCommand, defineConfig, reviewCodeChangesCommand, reviewPRCommand };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import { a as BUILT_IN_SCOPE_OPTIONS, i as BUILT_IN_SETUP_OPTIONS, n as reviewCodeChangesCommand, o as DEFAULT_SCOPES, r as createPRCommand, s as defineConfig, t as reviewPRCommand } from "./review-pr-Dh5esOtl.js";
1
+ import { a as BUILT_IN_SETUP_OPTIONS, c as defineConfig, i as reviewCodeChangesCommand, n as createPRCommand, o as BUILT_IN_SCOPE_OPTIONS, r as advancedReviewChangesCommand, s as DEFAULT_SCOPES, t as reviewPRCommand } from "./review-pr-MkD-Pu9b.js";
2
2
 
3
- export { BUILT_IN_SCOPE_OPTIONS, BUILT_IN_SETUP_OPTIONS, DEFAULT_SCOPES, createPRCommand, defineConfig, reviewCodeChangesCommand, reviewPRCommand };
3
+ export { BUILT_IN_SCOPE_OPTIONS, BUILT_IN_SETUP_OPTIONS, DEFAULT_SCOPES, advancedReviewChangesCommand, createPRCommand, defineConfig, reviewCodeChangesCommand, reviewPRCommand };
package/dist/main.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as reviewCodeChangesCommand, r as createPRCommand, t as reviewPRCommand } from "./review-pr-Dh5esOtl.js";
2
+ import { i as reviewCodeChangesCommand, n as createPRCommand, r as advancedReviewChangesCommand, t as reviewPRCommand } from "./review-pr-MkD-Pu9b.js";
3
3
  import { createCLI } from "@ls-stack/cli";
4
4
 
5
5
  //#region src/main.ts
@@ -9,7 +9,8 @@ await createCLI({
9
9
  }, {
10
10
  "review-code-changes": reviewCodeChangesCommand,
11
11
  "review-pr": reviewPRCommand,
12
- "create-pr": createPRCommand
12
+ "create-pr": createPRCommand,
13
+ "advanced-review-changes": advancedReviewChangesCommand
13
14
  });
14
15
 
15
16
  //#endregion