diffowl 0.3.3 → 0.4.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 (4) hide show
  1. package/README.md +129 -345
  2. package/dist/cli.js +5488 -3871
  3. package/dist/cli.js.map +1 -1
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -7,447 +7,240 @@
7
7
  " "
8
8
  ```
9
9
 
10
- > **The verification layer for agent-written code.**
11
- >
12
- > An independent reviewer that runs locally on every commit — on the model you already use, no matter which agent (or human) wrote the code.
13
-
14
- Coding agents now write much of the code, but the agent that wrote a patch shouldn't be its only reviewer. DiffOwl is a separate, independent review pass: it builds bounded local context from your diff and asks a model for structured, durable findings. It works the same whether the change came from Claude Code, Cursor, OpenCode, or your own hands.
15
-
16
- Under the hood it drives a headless [OpenCode](https://opencode.ai/docs/server/) session for model execution, so you bring your own provider and pay no one but them — no DiffOwl account, no service in the loop.
17
-
18
- ---
19
-
20
- ## Features
21
-
22
- - **Agent-Agnostic**: Reviews code from any source — Claude Code, Cursor, OpenCode, or a human. The reviewer stays independent from whoever wrote the patch.
23
- - **Provider-Neutral**: Runs on whatever model and provider you have configured in OpenCode (Copilot, OpenAI, local, and more). No separate keys, no DiffOwl account, no per-seat bill.
24
- - **First-Class TypeScript Support**: Automatically extracts modified TypeScript AST nodes (functions, classes, interfaces, types, enums, methods, properties, and top-level const declarations) to feed rich, structured context to the AI reviewer.
25
- - **Automatic Git Hooks**: Reviews run on every commit and stay out of your way — results land in `.diffowl/` when they are ready.
26
- - **Review Chat Handoff**: Reopen the OpenCode session behind the latest or any selected review with `diffowl chat`.
27
- - **Review Depth Profiles**: Choose `shallow` or `default` context strategies to match fast hooks or normal reviews.
28
- - **Intelligent File Filtering**: Supports `include` and `exclude` glob patterns to focus reviews on source directories while skipping build artifacts, lockfiles, and node modules.
29
- - **Project-Specific Rules**: Inject custom guidelines directly into the reviewer's system prompt (e.g., "Check for SQL injection", "Ensure TypeScript types are explicit").
30
- - **Interactive Model Selector**: Automatically queries OpenCode to present a clean, interactive list of your connected providers and models.
31
- - **Local Reports**: Generates markdown reviews under `.diffowl/reviews/`, including durable finding IDs and hidden session metadata that makes reports chat-capable.
32
- - **Durable Findings (0.3)**: Persists reviews and findings in `.diffowl/state.db` with stable `fnd_*` IDs, occurrence tracking, and lifecycle commands for fix, dismiss, defer, and reopen.
33
- - **Agent-Assisted Resolution**: Includes an optional portable skill that lets coding agents investigate findings, fix confirmed issues, record dismissals, and archive handled reports.
34
- - **Hook Log Retention**: Bounds accumulated hook logs without deleting review history.
35
-
36
- ---
37
-
38
- ## Quick Start
39
-
40
- ### 1. Prerequisites
41
-
42
- 1. **Verify Node.js 22.14.0 or newer is installed**:
43
- ```bash
44
- node --version
45
- ```
46
- 2. **Install OpenCode CLI**:
47
- ```bash
48
- npm install --global opencode-ai
49
- ```
50
- 3. **Authenticate a provider and confirm a model is available**:
51
- ```bash
52
- opencode
53
- ```
54
- In OpenCode, connect or authenticate a provider such as GitHub Copilot, OpenAI, or Ollama. Confirm that at least one model is available before continuing.
55
-
56
- ### 2. Install DiffOwl
10
+ Review agent-written code with a second model before it ships.
57
11
 
58
- ```bash
59
- npm install --global diffowl
60
- ```
12
+ DiffOwl is a local code review CLI. It builds focused context from a Git diff, sends that context to a model through [OpenCode](https://opencode.ai/docs/server/), and records actionable findings in your repository.
61
13
 
62
- ### 3. Initialize DiffOwl in Your Repository
14
+ It works with changes from any coding agent or human. You choose the model and provider through OpenCode. DiffOwl does not require an account, another API key, or a hosted DiffOwl service.
63
15
 
64
- To set up DiffOwl for your project, navigate to your target git repository and run:
16
+ ## Why DiffOwl
65
17
 
66
- ```bash
67
- diffowl init
68
- ```
18
+ The agent that wrote a change should not be its only reviewer. Asking it to review its own work can repeat the same assumptions that produced the bug.
69
19
 
70
- This will:
20
+ DiffOwl adds an independent pass between writing code and shipping it:
71
21
 
72
- 1. Start an OpenCode server if needed and `server.auto_start` is enabled.
73
- 2. Fetch your connected providers and active models.
74
- 3. Allow you to select a model interactively.
75
- 4. Generate a `.diffowl.yml` configuration file in the current project.
22
+ - Review the last commit, staged changes, a specific commit, or a whole branch.
23
+ - Use any model already connected to OpenCode, including local models.
24
+ - Give the reviewer bounded local context instead of dumping the entire repository into a prompt.
25
+ - Keep findings after the review ends, with stable IDs and lifecycle states.
26
+ - Reopen the review session when a finding needs more investigation.
27
+ - Run reviews automatically after commits without blocking them.
76
28
 
77
- > [!IMPORTANT]
78
- > DiffOwl uses OpenCode's existing provider credentials. It does not configure provider keys itself. If initialization reports no active models, run `opencode`, connect or re-authenticate a provider, confirm a model is available, and rerun `diffowl init`.
29
+ TypeScript reviews include changed AST symbols, related tests, file excerpts, and bounded call-flow context. Other languages still get diff-centered review with targeted repository exploration.
79
30
 
80
- ### 4. Run Your First Review
31
+ ## How it works
81
32
 
82
- ```bash
83
- diffowl review
84
- ```
85
-
86
- Read the latest report at `.diffowl/reviews/latest.md`, or install the optional resolution skill below to let a coding agent investigate and handle findings.
33
+ 1. DiffOwl reads the Git change you selected.
34
+ 2. It filters files and assembles relevant local context.
35
+ 3. A separate model reviews the change through a headless OpenCode session.
36
+ 4. DiffOwl writes a Markdown report and persists findings in SQLite.
37
+ 5. You inspect the findings, continue the review chat, or hand them to a coding agent for resolution.
87
38
 
88
- If a review reports an authentication or provider failure:
39
+ The orchestration and state stay in your repository. Review context is sent to the provider you selected in OpenCode.
89
40
 
90
- 1. Run `opencode`.
91
- 2. Connect or re-authenticate the provider and confirm the configured model is available.
92
- 3. Retry with `diffowl review`.
41
+ ## Quick start
93
42
 
94
- For a timeout, retry with less context:
43
+ You need Node.js 22.14.0 or newer and an authenticated [OpenCode](https://opencode.ai/) provider.
95
44
 
96
45
  ```bash
97
- diffowl review --depth shallow
46
+ npm install --global opencode-ai
47
+ opencode
98
48
  ```
99
49
 
100
- ---
101
-
102
- ## Resolve Findings With an Agent
103
-
104
- DiffOwl can use an inexpensive model for review generation while a stronger coding agent verifies and resolves the resulting findings. The optional `diffowl-resolve` skill works with agents that support the open [Agent Skills](https://skills.sh/) format.
105
-
106
- ### Install the skill
107
-
108
- Install the `diffowl-resolve` skill:
50
+ Connect a provider in OpenCode, then install and initialize DiffOwl:
109
51
 
110
52
  ```bash
111
- npx skills add gutierrezje/diffowl --skill diffowl-resolve
53
+ npm install --global diffowl
54
+ cd your-repository
55
+ diffowl init
112
56
  ```
113
57
 
114
- The skills CLI installs into the current project by default. Restart or reload your agent if it does not immediately discover the new skill.
115
-
116
- ### Use the skill
58
+ `diffowl init` finds your available OpenCode models, lets you choose one, and writes `.diffowl.yml`.
117
59
 
118
- First generate a review:
60
+ Review the last commit:
119
61
 
120
62
  ```bash
121
- diffowl review
122
- ```
123
-
124
- Then ask your coding agent in plain language:
125
-
126
- ```text
127
- Resolve the latest DiffOwl review.
128
- ```
129
-
130
- Other useful prompts:
131
-
132
- ```text
133
- Investigate finding 2 in the latest DiffOwl review.
134
- Resolve all open DiffOwl reviews.
135
- Resolve the latest 3 DiffOwl reviews.
136
- Check whether the older DiffOwl findings have already been fixed.
137
- Archive fully resolved DiffOwl reviews.
63
+ diffowl
138
64
  ```
139
65
 
140
- The agent will:
141
-
142
- 1. Treat findings as candidates and verify them against the current code.
143
- 2. Fix confirmed issues using the repository's normal workflow.
144
- 3. For durable findings (0.3+), record lifecycle status with `diffowl findings fix`, `dismiss`, or `defer`.
145
- 4. For legacy reports, mark findings as fixed, already fixed, agent dismissed, user dismissed, deferred, or open in a `## Resolution` checklist.
146
- 5. Append or merge resolution state without rewriting the generated review body.
147
- 6. Move fully handled timestamped reports into `.diffowl/reviews/resolved/` when every finding is complete.
148
-
149
- `latest.md` is only a copy of the newest report and is overwritten by future reviews. Markdown reports from 0.3+ are immutable snapshots; SQLite is the authoritative backlog for durable findings.
150
-
151
- For legacy pre-0.3 reports, resolution state is appended under `## Resolution`. To reopen the OpenCode session for an archived report, pass its explicit path:
66
+ Or review work before committing:
152
67
 
153
68
  ```bash
154
- diffowl chat .diffowl/reviews/resolved/review-<timestamp>.md
69
+ git add -p
70
+ diffowl review --staged
155
71
  ```
156
72
 
157
- ### What the statuses mean
158
-
159
- | Status | Meaning | Complete? |
160
- | --------------- | ------------------------------------------------------------- | --------- |
161
- | Fixed | The agent changed code or configuration and verified the fix. | Yes |
162
- | Already fixed | Current code no longer exhibits the reported issue. | Yes |
163
- | Agent dismissed | Investigation showed the finding was noise or incorrect. | Yes |
164
- | User dismissed | You explicitly chose not to address the finding. | Yes |
165
- | Deferred | The issue is valid but intentionally left for later. | No |
166
- | Open | The finding has not been fully investigated. | No |
167
-
168
- Reports containing deferred or open findings remain in `.diffowl/reviews/`. DiffOwl never deletes review history automatically.
169
-
170
- ### Troubleshooting
171
-
172
- - **No review exists:** Run `diffowl review` first, or install `diffowl hook install` and make a commit.
173
- - **The agent does not load the skill:** Verify project installation with `npx skills list` or global installation with `npx skills list --global`, then restart or reload the agent.
174
- - **The skill is installed for the wrong agent:** Reinstall with `--agent <agent-name>`, or use `--agent '*'` to install for every detected agent.
175
- - **A hook review timed out:** Run the retry command shown by the next foreground DiffOwl command, or retry manually with `diffowl review --commit <sha> --depth shallow`.
176
- - **You prefer manual resolution:** Edit code normally; the skill is optional and does not affect the DiffOwl CLI.
177
-
178
- ---
179
-
180
- ## CLI Reference
181
-
182
- ### `diffowl` (or `diffowl review`)
73
+ The latest report is written to `.diffowl/reviews/latest.md`.
183
74
 
184
- Runs a code review on your repository.
75
+ ## Choose what to review
185
76
 
186
- - **Default**: Reviews the changes in the **last commit**.
187
- - `--staged`: Reviews currently **staged changes** instead of the last commit.
188
- - `--commit <ref>`: Reviews a specific commit ref instead of the last commit.
189
- - `--base [ref]`: Reviews all committed branch changes since the merge base with `ref`. With no
190
- ref, DiffOwl detects `origin/HEAD`, then local `main` or `master`.
191
- - `--hook`: Runs in background, non-blocking mode (used by Git hook).
192
- - `--depth <depth>`: Overrides configured review depth. Valid values: `shallow`, `default`.
193
- - `--reasoning <effort>`: Overrides configured OpenCode reasoning variant. Valid values: `auto`, `none`, `minimal`, `low`, `medium`, `high`, `max`, `xhigh`.
194
- - `--verbose`: Includes suppressed findings and extra review details in the report.
195
- - `--format <format>`: Output format: `text` (default) or `json`. JSON writes a versioned document to stdout and persists SQLite state. Review `status` is `open` when unsuppressed `error`/`warning` findings remain, `advisory` when only `info` findings remain, `resolved` when none remain, or `skipped`.
77
+ | Command | Reviews |
78
+ | ------------------------------- | ------------------------------------------------- |
79
+ | `diffowl` | The last commit |
80
+ | `diffowl review --staged` | Staged changes |
81
+ | `diffowl review --commit <ref>` | One commit |
82
+ | `diffowl review --base` | Committed branch changes since the default branch |
83
+ | `diffowl review --base <ref>` | Committed branch changes since an explicit base |
196
84
 
197
- Candidates below `min_confidence` or outside changed files are excluded from actionable finding counts and review status. When any are excluded, the report includes a short diagnostic summary and points to `diffowl chat` for investigation. Outside-file candidates are shown in full with `--verbose`; below-threshold candidates remain available in the OpenCode session.
198
-
199
- Rendered findings use stable `Finding N` headings. Reports from DiffOwl 0.3+ also include durable `fnd_*` IDs and observation classification (`new`, `existing`, `regressed`), making prompts such as “investigate finding 2” or `diffowl findings show fnd_abc` map directly to the backlog.
200
-
201
- Review depth controls both how much local context DiffOwl preloads and how much exploration the reviewer is expected to do:
202
-
203
- - `shallow`: Cheap, surface-level review. Uses a smaller diff-centered prompt with no AI tools enabled. It is expected to miss deeper issues, but can catch obvious local bugs such as off-by-one errors, inverted conditions, unsafe null handling, missing awaits, and implementation anti-patterns visible in the diff.
204
- - `default`: Normal review. Includes changed TypeScript AST symbols, small file excerpts, related tests, and bounded Potential Call Flow snippets from `git grep`. Permissionless read/search tools are enabled for targeted exploration when context is incomplete; permission prompts are rejected.
85
+ Useful review options:
205
86
 
206
87
  ```bash
207
- # Review last commit
208
- diffowl
209
-
210
- # Review staged files
211
- diffowl review --staged
212
-
213
- # Review a specific commit
214
- diffowl review --commit abc1234
88
+ # Faster review with less context
89
+ diffowl review --staged --depth shallow
215
90
 
216
- # Review this branch against the default branch
217
- diffowl review --base
91
+ # Use a different model once
92
+ diffowl review --staged --model openai/gpt-5.6-luna
218
93
 
219
- # Review this branch against an explicit base
220
- diffowl review --base main
94
+ # Emit a versioned JSON document for scripts
95
+ diffowl review --base --format json
221
96
 
222
- # Review a stacked branch against its parent branch
223
- diffowl review --base feature/parent-branch
224
-
225
- # Include suppressed outside-file findings in the report
226
- diffowl review --staged --verbose
227
-
228
- # Request a high reasoning variant for models that support it
229
- diffowl review --staged --reasoning high
97
+ # Exit 1 when actionable findings remain
98
+ diffowl review --base --fail-on-findings
230
99
  ```
231
100
 
232
- Branch review uses merge-base-to-`HEAD` semantics, matching the committed diff shown by a pull
233
- request. It never includes staged or unstaged changes. `--base` cannot be combined with `--staged`
234
- or `--commit`; use those as separate review surfaces.
101
+ Branch review uses the merge base through `HEAD`, matching the committed diff in a pull request. It does not include staged or unstaged changes.
235
102
 
236
- ### `diffowl model`
103
+ ## Work with findings
237
104
 
238
- View or change the active AI model. This stores a personal preference in the repository's shared,
239
- gitignored `.diffowl/preferences.yml`, so every linked worktree uses the same model without changing
240
- the committed `.diffowl.yml`.
105
+ DiffOwl stores durable findings in `.diffowl/state.db`. A finding stays open until someone records what happened to it. A later model review that fails to mention it does not silently mark it fixed.
241
106
 
242
107
  ```bash
243
- # Interactively pick a model
244
- diffowl model
245
-
246
- # Manually set a model
247
- diffowl model opencode/big-pickle
108
+ # List unresolved findings
109
+ diffowl findings
248
110
 
249
- # Remove the personal selection
250
- diffowl model --reset
111
+ # Inspect a finding by ID, ID prefix, or latest:N
112
+ diffowl findings show fnd_abc
251
113
 
252
- # Override the model for one review only
253
- diffowl review --model openai/gpt-5.6-luna
114
+ # Record the outcome
115
+ diffowl findings fix fnd_abc --note "Added a null guard." --verified-by "pnpm run test"
116
+ diffowl findings dismiss fnd_abc --reason "The caller already validates this value."
117
+ diffowl findings defer fnd_abc --reason "Blocked by an upstream change."
118
+ diffowl findings reopen fnd_abc --reason "The bug returned in a new path."
254
119
  ```
255
120
 
256
- Model precedence is `--model`, then `DIFFOWL_MODEL`, then the shared local preference. Without one,
257
- review commands ask you to configure a model rather than assuming provider access.
121
+ Use `--format json` with `findings list`, `show`, or `summary` when another tool needs the backlog.
258
122
 
259
- ### `diffowl chat [report]`
260
-
261
- Opens the OpenCode session associated with a review report. DiffOwl hands control to the OpenCode TUI rather than implementing a separate chat interface.
123
+ To continue the conversation behind a review:
262
124
 
263
125
  ```bash
264
- # Interactively select a review
265
126
  diffowl chat
266
-
267
- # Open a specific timestamped report directly
268
- diffowl chat review-2026-06-07T07-30-42-762Z.md
269
-
270
- # Use an explicit relative or absolute report path
271
- diffowl chat ./.diffowl/reviews/latest.md
127
+ diffowl chat .diffowl/reviews/review-<timestamp>.md
272
128
  ```
273
129
 
274
- Without an argument, DiffOwl displays active and resolved timestamped reports newest first. Bare filenames are resolved under `.diffowl/reviews/`, so agents and scripts can open a report deterministically without using the picker. Each chat-capable report stores its OpenCode session ID and project root in YAML frontmatter. Reports created before this feature and documentation-only skip reports do not have an OpenCode session to reopen.
275
-
276
- ### `diffowl hook install | status | uninstall`
130
+ ## Resolve findings with a coding agent
277
131
 
278
- Installs or removes a managed post-commit Git hook that runs reviews automatically and asynchronously in the background.
132
+ The optional `diffowl-resolve` skill lets a coding agent investigate findings instead of accepting the review at face value. It verifies each candidate against the current code, fixes confirmed problems, records dismissals or deferrals, and preserves the report history.
279
133
 
280
134
  ```bash
281
- # Install non-blocking post-commit review hook
282
- diffowl hook install
135
+ npx skills add gutierrezje/diffowl --skill diffowl-resolve
136
+ ```
283
137
 
284
- # Check whether the hook is installed and up to date
285
- diffowl hook status
138
+ Restart or reload the agent, then ask:
286
139
 
287
- # Uninstall the hook
288
- diffowl hook uninstall
140
+ ```text
141
+ Resolve the latest DiffOwl review.
289
142
  ```
290
143
 
291
- _Runs reviews asynchronously in the background, saving execution output to `.diffowl/hook.log` and the latest report to `.diffowl/reviews/latest.md`. Hook reviews use the configured `context.depth`, return control to your terminal instantly, and avoid clobbering any existing post-commit hook scripts._
292
-
293
- Only one hook review runs per project at a time. Each commit is recorded under `.diffowl/pending-reviews/`, and a background worker processes pending commits in order. Successful reviews remove their marker; failed reviews remain pending and are retried when a later commit triggers the hook. Review failures are recorded with their commit SHA in `.diffowl/last-hook-status.json` and reported on the next foreground review with commands to retry at default or shallow depth. Result files without a matching pending marker are removed automatically.
144
+ You can also ask it to investigate one finding, resolve every open review, or archive reports whose findings are fully handled.
294
145
 
295
- ### `diffowl server start | stop | status`
146
+ ## Run reviews automatically
296
147
 
297
- Manually manage the OpenCode server lifecycle.
148
+ Install the non-blocking post-commit hook:
298
149
 
299
150
  ```bash
300
- # Check if OpenCode serve is running
301
- diffowl server status
302
-
303
- # Start it manually
304
- diffowl server start
305
-
306
- # Stop the server
307
- diffowl server stop
151
+ diffowl hook install
308
152
  ```
309
153
 
310
- ### `diffowl findings [list] | show | dismiss | defer | fix | reopen`
311
-
312
- Inspect and manage the durable findings backlog stored in the repo's shared `.diffowl/state.db`.
154
+ The hook queues each commit, returns control to the terminal, and writes output to `.diffowl/hook.log`. Failed reviews remain pending and retry after a later commit.
313
155
 
314
156
  ```bash
315
- # List unresolved findings (open and regressed)
316
- diffowl findings
317
-
318
- # Machine-readable backlog for agents and scripts
319
- diffowl findings --format json
320
-
321
- # Inspect one finding by full id, id prefix, or latest:N
322
- diffowl findings show fnd_abc --format json
323
-
324
- # Mark fixed after verification
325
- diffowl findings fix fnd_abc --note "Added null guard." --verified-by "pnpm run test"
326
-
327
- # Dismiss a false positive
328
- diffowl findings dismiss fnd_abc --reason "Guarded by caller."
329
-
330
- # Defer intentionally
331
- diffowl findings defer fnd_abc --reason "Needs upstream change."
332
-
333
- # Reopen a previously fixed or dismissed finding
334
- diffowl findings reopen fnd_abc --reason "Regression in new path."
157
+ diffowl hook status
158
+ diffowl hook uninstall
335
159
  ```
336
160
 
337
- `list` and `show` default to text; the mutation commands (`fix`, `dismiss`, `defer`, `reopen`) default to JSON because they are primarily agent-invoked — pass `--format text` for human-readable output.
338
-
339
- The unresolved backlog is durable: a finding does not auto-resolve just because a later review fails to mention it. Absence from a later model review never marks a finding fixed.
161
+ Claude Code users can also show the current finding summary when a session starts:
340
162
 
341
- ---
163
+ ```bash
164
+ diffowl agent-hook install --client claude
165
+ ```
342
166
 
343
- ## Configuration (`.diffowl.yml`)
167
+ ## Configuration
344
168
 
345
- Your committed `.diffowl.yml` configures repository review policy. Model selection is deliberately
346
- absent because provider access belongs to each developer. Legacy `model` keys remain readable for
347
- compatibility but are ignored and removed the next time DiffOwl saves project config.
169
+ Project review policy lives in `.diffowl.yml`. Model selection is personal and stays in the shared, gitignored `.diffowl/preferences.yml`.
348
170
 
349
171
  ```yaml
350
- # OpenCode server settings
351
- server:
352
- port: 4096
353
- auto_start: true
354
-
355
- # Local review context strategy: shallow or default
356
172
  context:
357
173
  depth: default
358
174
 
359
- # OpenCode model variant for reasoning/thinking effort.
360
- # auto leaves the selected model/provider default alone.
361
175
  reasoning:
362
176
  effort: auto
363
177
 
364
- # Hook log retention. Set to 0 for unlimited retention.
365
- retention:
366
- # Before each hook review, retain approximately this many KiB
367
- # of previous hook.log output. The new run may exceed this target.
368
- hook_log_kb: 1024
178
+ gate:
179
+ fail_on_findings: false
369
180
 
370
- # Review timeout in seconds
371
181
  timeout: 300
372
-
373
- # Minimum confidence level of findings to report: low, medium, or high
374
182
  min_confidence: medium
375
-
376
- # Skip reviews when every changed file is documentation-like
377
183
  skip_doc_only: false
378
184
 
379
- # Include suppressed outside-file findings and extra details in reports
380
- verbose: false
381
-
382
- # Review scope
383
185
  include:
384
186
  - "src/**/*"
385
- - "lib/**/*"
386
187
 
387
188
  exclude:
388
189
  - "**/*.test.*"
389
- - "**/*.spec.*"
390
190
  - "**/*.lock"
391
- - "**/node_modules/**"
392
191
  - "**/dist/**"
393
- - "**/build/**"
394
192
 
395
- # Custom project-specific review rules
396
193
  rules:
397
- - "Check for potential security vulnerabilities like SQL injection or SSRF"
398
- - "Flag any hardcoded secrets, tokens, or private keys"
399
- - "Suggest readability and architectural improvements where relevant"
194
+ - "Flag hardcoded secrets."
195
+ - "Check authorization at every write boundary."
400
196
  ```
401
197
 
402
- ---
403
-
404
- ## Review Files
198
+ Choose or change your model without editing project policy:
405
199
 
406
- Each completed review starts with a timestamped report and an ephemeral `latest.md` copy. Durable state and reports are anchored to the repository's primary checkout, so linked Git worktrees share one backlog. Checkout-scoped runtime files such as hook status, hook logs, and `server.pid` stay in that checkout's local `.diffowl/`. The optional resolution skill moves fully handled timestamped reports into the resolved archive:
407
-
408
- ```text
409
- .diffowl/state.db # Authoritative review and finding state (0.3+)
410
- .diffowl/reviews/review-<timestamp>.md # Immutable markdown export snapshot
411
- .diffowl/reviews/latest.md # Ephemeral copy of the newest report
412
- .diffowl/reviews/resolved/review-<timestamp>.md # Fully handled report archived by the skill
413
- ```
414
-
415
- Review reports include YAML frontmatter similar to:
416
-
417
- ```yaml
418
- ---
419
- diffowl:
420
- schema_version: 1
421
- review_id: rev_...
422
- session_id: ses_...
423
- project_root: /path/to/project
424
- ---
200
+ ```bash
201
+ diffowl model
202
+ diffowl model provider/model
203
+ diffowl model --reset
425
204
  ```
426
205
 
427
- Finding headings in 0.3+ reports look like:
206
+ Configuration is deep-merged with defaults, so the file only needs the settings your repository changes.
428
207
 
429
- ```md
430
- #### Finding 1 (`fnd_...`) — **new**
208
+ ## Files DiffOwl creates
431
209
 
432
- **[WARNING] src/auth.ts:12**
433
- Missing null check
210
+ ```text
211
+ .diffowl.yml # Committed project policy
212
+ .diffowl/preferences.yml # Gitignored personal model choice
213
+ .diffowl/state.db # Authoritative findings backlog
214
+ .diffowl/reviews/review-<timestamp>.md # Immutable review snapshot
215
+ .diffowl/reviews/latest.md # Copy of the newest report
216
+ .diffowl/reviews/resolved/ # Reports archived by the resolution skill
434
217
  ```
435
218
 
436
- This metadata is used by `diffowl chat`. For legacy pre-0.3 reports, agents may append a `## Resolution` section. For 0.3+ reports, use `diffowl findings *` only—do not edit markdown. DiffOwl does not delete review history automatically.
219
+ Linked Git worktrees share the durable backlog and review reports from the primary checkout. Runtime files such as hook logs and server state remain checkout-specific.
437
220
 
438
- ### Upgrading to 0.3
221
+ ## Command reference
439
222
 
440
- - **No import step**: Existing markdown reports remain unchanged and chat-capable. They are not imported into SQLite.
441
- - **New reviews persist state**: After upgrading, each `diffowl review` writes both SQLite state and a markdown snapshot.
442
- - **Backlog semantics change**: Use `diffowl findings` for the unresolved backlog. Markdown `### Status` is `Open` (error/warning findings), `Advisory` (info-only), or `Resolved` (none); it reflects the review snapshot only.
443
- - **Resolution workflow**: Prefer `diffowl findings fix|dismiss|defer` over editing report checklists when durable findings exist. Never mark fixed without recorded verification (`--verified-by`).
444
- - **Not in 0.3**: Semantic deduplication beyond fingerprint matching, automatic resolution when findings disappear, legacy report migration, retention cleanup, and SARIF export.
223
+ | Command | Purpose |
224
+ | -------------------- | ------------------------------------------- |
225
+ | `diffowl init` | Configure DiffOwl in the current repository |
226
+ | `diffowl review` | Run a review |
227
+ | `diffowl model` | View or change the selected model |
228
+ | `diffowl findings` | Inspect and update durable findings |
229
+ | `diffowl chat` | Reopen an OpenCode review session |
230
+ | `diffowl hook` | Manage the post-commit hook |
231
+ | `diffowl agent-hook` | Manage supported agent client hooks |
232
+ | `diffowl server` | Manage the local OpenCode server |
445
233
 
446
- ---
234
+ Run `diffowl <command> --help` for every option.
447
235
 
448
- ## Developing
236
+ ## Troubleshooting
449
237
 
450
- Clone the repository and link the CLI globally:
238
+ - No models found: run `opencode`, connect or re-authenticate a provider, then rerun `diffowl init`.
239
+ - Review timed out: retry with `diffowl review --depth shallow`.
240
+ - Hook review failed: run the retry command shown by the next foreground DiffOwl command, or inspect `.diffowl/hook.log`.
241
+ - Agent did not load `diffowl-resolve`: verify it with `npx skills list`, then restart or reload the agent.
242
+
243
+ ## Develop locally
451
244
 
452
245
  ```bash
453
246
  git clone https://github.com/gutierrezje/diffowl.git
@@ -457,23 +250,14 @@ pnpm run build
457
250
  pnpm link --global
458
251
  ```
459
252
 
460
- When making edits to `src/**`, rebuild to update the linked CLI and git hooks:
253
+ Run the checks:
461
254
 
462
255
  ```bash
463
- pnpm run build
464
- git add -p
465
- diffowl review --staged
466
- ```
467
-
468
- To verify model discovery against an authenticated OpenCode server already running on port 4096:
469
-
470
- ```bash
471
- DIFFOWL_INTEGRATION=1 pnpm exec vitest run src/opencode/models.integration.test.ts
256
+ pnpm run lint
257
+ pnpm run test
472
258
  ```
473
259
 
474
- Set `DIFFOWL_OPENCODE_PORT` when the server uses a different port. This live test is skipped during the normal test suite.
475
-
476
- ---
260
+ After changing `src/**`, rebuild before testing the globally linked `diffowl` command.
477
261
 
478
262
  ## License
479
263