critique 0.1.12 → 0.1.28

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 (39) hide show
  1. package/AGENTS.md +33 -0
  2. package/CHANGELOG.md +182 -0
  3. package/README.md +102 -15
  4. package/bun.lock +112 -220
  5. package/package.json +14 -10
  6. package/screenshot-web.png +0 -0
  7. package/scripts/capture-acp-events.ts +106 -0
  8. package/scripts/preview-review.tsx +307 -0
  9. package/src/ansi-html.test.ts +7 -3
  10. package/src/ansi-html.ts +9 -10
  11. package/src/cli.tsx +939 -625
  12. package/src/components/diff-view.tsx +57 -0
  13. package/src/components/index.ts +2 -0
  14. package/src/diff-utils.ts +188 -0
  15. package/src/dropdown.tsx +25 -8
  16. package/src/logger.ts +83 -0
  17. package/src/review/acp-client.ts +624 -0
  18. package/src/review/acp-stream-display.test.ts +240 -0
  19. package/src/review/acp-stream-display.ts +213 -0
  20. package/src/review/fixtures/simple-response.json +98 -0
  21. package/src/review/fixtures/tool-call-response.json +307 -0
  22. package/src/review/hunk-parser.test.ts +1084 -0
  23. package/src/review/hunk-parser.ts +545 -0
  24. package/src/review/index.ts +35 -0
  25. package/src/review/review-app.test.tsx +1191 -0
  26. package/src/review/review-app.tsx +565 -0
  27. package/src/review/session-context.test.ts +166 -0
  28. package/src/review/session-context.ts +158 -0
  29. package/src/review/stream-display.test.tsx +223 -0
  30. package/src/review/stream-display.tsx +176 -0
  31. package/src/review/types.ts +107 -0
  32. package/src/review/yaml-watcher.ts +228 -0
  33. package/src/store.ts +56 -0
  34. package/src/themes/github.json +8 -8
  35. package/src/themes.ts +87 -22
  36. package/src/web-utils.ts +190 -0
  37. package/src/worker.ts +13 -7
  38. package/tsconfig.json +1 -0
  39. package/src/highlight.tsx +0 -143
package/AGENTS.md CHANGED
@@ -79,3 +79,36 @@ NEVER update existing changelog bullet points for previous version unless you ad
79
79
  - minimize number of props. do not use props if you can use zustand state instead. the app has global zustand state that lets you get a piece of state down from the component tree by using something like `useStore(x => x.something)` or `useLoaderData<typeof loader>()` or even useRouteLoaderData if you are deep in the react component tree
80
80
 
81
81
  - do not consider local state truthful when interacting with server. when interacting with the server with rpc or api calls never use state from the render function as input for the api call. this state can easily become stale or not get updated in the closure context. instead prefer using zustand `useStore.getState().stateValue`. notice that useLoaderData or useParams should be fine in this case.
82
+
83
+ ## cli
84
+
85
+ the main cli functionality is in src/cli.tsx
86
+
87
+ the main command shows the git diff in a tui. the web command uploads the terminal output to html to domain critique.work
88
+
89
+ the command review helps the user review agents diffs, reordering and splitting diff hunks to create a progressive disclosure document with explanations and diagrams. it also supports using --web to upload the result to critique.work
90
+
91
+ this command takes a long time to run, because it uses ACP to generate the result using an LLM. so to test styles changes we will usually modify scripts/preview-review.tsx instead, which let you preview how the cli looks like. and passing --web to that script to also preview how the website looks like
92
+
93
+ <!-- opensrc:start -->
94
+
95
+ ## Source Code Reference
96
+
97
+ Source code for dependencies is available in `opensrc/` for deeper understanding of implementation details.
98
+
99
+ See `opensrc/sources.json` for the list of available packages and their versions.
100
+
101
+ Use this source code when you need to understand how a package works internally, not just its types/interface.
102
+
103
+ ### Fetching Additional Source Code
104
+
105
+ To fetch source code for a package or repository you need to understand, run:
106
+
107
+ ```bash
108
+ npx opensrc <package> # npm package (e.g., npx opensrc zod)
109
+ npx opensrc pypi:<package> # Python package (e.g., npx opensrc pypi:requests)
110
+ npx opensrc crates:<package> # Rust crate (e.g., npx opensrc crates:serde)
111
+ npx opensrc <owner>/<repo> # GitHub repo (e.g., npx opensrc vercel/ai)
112
+ ```
113
+
114
+ <!-- opensrc:end -->
package/CHANGELOG.md CHANGED
@@ -1,3 +1,185 @@
1
+ # 0.1.28
2
+
3
+ - Default command:
4
+ - Add `--stdin` option to read diff from stdin (for lazygit pager integration)
5
+ - Faster scroll acceleration (`A: 1.5`, `maxMultiplier: 10`)
6
+ - `review` command:
7
+ - Remove hunk ID prefix (`#1`, `#2`) from hunk headers
8
+ - Faster scroll acceleration (`A: 1.5`, `maxMultiplier: 10`)
9
+ - Code blocks now use `wrapMode: "none"` to prevent word-wrapping (content truncates at viewport edge instead)
10
+ - Prose max width now respects terminal width: `Math.min(80, width)`
11
+ - Code blocks use full terminal width minus padding
12
+ - Tests:
13
+ - Added test for code block wrapMode behavior with renderer
14
+
15
+ # 0.1.27
16
+
17
+ - GitHub theme:
18
+ - Reduce intensity of diff added/removed background colors for softer appearance
19
+
20
+ # 0.1.26
21
+
22
+ - `review` command:
23
+ - Make filename bold in hunk header
24
+ - Add gap of 1 between filename header and diff
25
+
26
+ # 0.1.25
27
+
28
+ - Default command:
29
+ - Change file picker shortcut from `ctrl p` to plain `p`
30
+ - Make `--web` bold in footer for better visibility
31
+ - `review` command:
32
+ - Make `--web` bold in footer for better visibility
33
+
34
+ # 0.1.24
35
+
36
+ - Default command:
37
+ - Add `--web [title]` flag to generate web preview instead of TUI
38
+ - Add `--open` flag to open in browser (with `--web`)
39
+ - Add `--theme <name>` flag to set theme (works for both TUI and web)
40
+ - Add `--cols` and `--mobile-cols` flags for web render dimensions
41
+ - Show all files in scrollable view instead of one-at-a-time pagination
42
+ - `ctrl p` dropdown now scrolls to selected file
43
+ - Add "--web to share & collaborate" tip to footer
44
+ - `review` command:
45
+ - Add "--web to share & collaborate" tip to footer
46
+ - Deprecate `web` command (use `--web` flag instead)
47
+
48
+ # 0.1.23
49
+
50
+ - `review` command:
51
+ - Add `gap` prop to `ReviewAppView` to control spacing between markdown descriptions and hunks (default: 2)
52
+
53
+ # 0.1.22
54
+
55
+ - Use `<markdown>` component instead of `<code filetype="markdown">` for rendering markdown content:
56
+ - `review` command: MarkdownBlock component
57
+ - `stream-display`: Message blocks
58
+ - Update opentui to PR #433 with MarkdownRenderable support
59
+ - Variable-width markdown rendering in `review` command:
60
+ - Prose (headings, paragraphs, lists) constrained to 80 chars, centered
61
+ - Code blocks and tables expand to full available width, centered
62
+ - Uses `renderNode` callback to customize block rendering
63
+ - Added test for wide code blocks and tables
64
+ - Add example diagrams and tables to `scripts/preview-review.tsx`
65
+
66
+ # 0.1.21
67
+
68
+ - `review` command:
69
+ - Add clack spinners for analysis start and tool call activity
70
+ - Show file names for read/write/edit tool logs
71
+ - Show animated "generating..." indicator in the TUI footer
72
+ - Add spinner while loading session context
73
+ - Upgrade `@clack/prompts` for taskLog support
74
+
75
+ # 0.1.20
76
+
77
+ - Add theme picker to `review` command:
78
+ - Press `t` to open theme picker with live preview
79
+ - Theme selection persisted and shared with main diff view
80
+ - Extract zustand store to `src/store.ts`:
81
+ - Shared state between main diff view and review view
82
+ - Theme changes auto-persist to `~/.critique/state.json`
83
+ - Fix diff background colors:
84
+ - Wrap diff component in box with theme background color
85
+ - Ensures no black/transparent gaps in diff view
86
+ - Fix theme reactivity in DiffView:
87
+ - Memoize resolved theme and syntax style properly
88
+ - Fix Dropdown component:
89
+ - Add `focused` prop for proper focus management
90
+ - Fix stale closure issue in move/onFocus callbacks
91
+ - Separate useEffect for selection changes to fix theme preview reactivity
92
+ - Fix hardcoded colors in review UI:
93
+ - Scrollbar, footer, and hunk headers now use theme colors
94
+ - Add `scripts/preview-review.tsx` for standalone review component testing
95
+ - Simplify generating indicator (show only animated dots)
96
+
97
+ # 0.1.19
98
+
99
+ - `review` command:
100
+ - Pass `_meta: { critique: true }` when creating review sessions for future filtering support
101
+ - Filter out critique-generated sessions from context selection (by `_meta` or title pattern)
102
+
103
+ # 0.1.18
104
+
105
+ - Replace `@xmorse/bun-pty` with `bun-pty` (official package)
106
+ - Remove unused dependencies: `react-error-boundary`, `node-pty`, `shiki`, `@shikijs/langs`, `@shikijs/themes`
107
+ - Remove unused `highlight.tsx` example file
108
+
109
+ # 0.1.17
110
+
111
+ - Rename `explain` command to `review`
112
+ - Add Claude Code support:
113
+ - `critique review --agent claude` to use Claude Code instead of OpenCode
114
+ - Session listing works for both agents
115
+ - `web` command:
116
+ - Use Fira Code font from Google Fonts for better box drawing character rendering
117
+ - Update `ghostty-opentui` to v1.3.12
118
+
119
+ # 0.1.16
120
+
121
+ - `explain` command:
122
+ - Add explicit instruction that diagrams must be wrapped in code blocks
123
+
124
+ # 0.1.15
125
+
126
+ - `explain` command:
127
+ - Add `--web` flag to generate web preview instead of TUI
128
+ - Add `--open` flag to open web preview in browser
129
+ - Web mode waits for full AI generation before rendering
130
+ - Hide keyboard shortcuts footer in web mode
131
+ - New `src/web-utils.ts` module:
132
+ - Shared utilities for web preview generation
133
+ - `captureToHtml` - PTY capture and ANSI to HTML conversion
134
+ - `captureResponsiveHtml` - Generate desktop and mobile versions
135
+ - `uploadHtml` - Upload to critique.work worker
136
+ - `openInBrowser` - Platform-specific browser opening
137
+ - `writeTempFile` / `cleanupTempFile` - Temp file helpers
138
+ - Refactored `web` command to use shared utilities
139
+ - Fix markdown syntax highlighting in review mode:
140
+ - Add markdown colors to theme resolution
141
+ - Add Tree-sitter markdown scopes (markup.heading, markup.bold, etc.)
142
+ - Fix empty space in web preview rendering:
143
+ - Add `minHeight: 0` to scrollbox contentOptions
144
+ - Replace `height: 100%` with `flexGrow: 1` for flexible layout
145
+ - Add `showFooter` prop to ReviewAppView for web mode
146
+
147
+ # 0.1.14
148
+
149
+ - New `explain` command:
150
+ - AI-powered diff explanation and review using ACP (Agent Client Protocol)
151
+ - Usage: `critique explain [base] [head]`
152
+ - Options:
153
+ - `--agent <name>` - AI agent to use (default: opencode)
154
+ - `--staged` - Explain staged changes
155
+ - `--commit <ref>` - Explain changes from a specific commit
156
+ - `--filter <pattern>` - Filter files by glob pattern
157
+ - Features:
158
+ - Parses git diff into indexed hunks with unique IDs
159
+ - Connects to opencode via ACP to analyze changes
160
+ - AI groups related hunks and generates markdown descriptions
161
+ - Streams results as YAML file is updated
162
+ - Renders scrollable TUI with prose descriptions above each hunk group
163
+ - Supports keyboard navigation (j/k or arrows) between groups
164
+ - Uses split view for hunks with both additions and deletions
165
+ - Centers prose descriptions with max-width 80
166
+ - New dependencies: `js-yaml`, `@agentclientprotocol/sdk`
167
+ - New `src/review/` module:
168
+ - `acp-client.ts` - ACP client for opencode communication
169
+ - `hunk-parser.ts` - Parse diffs into indexed hunks with `buildPatch`/`createHunk` helpers
170
+ - `session-context.ts` - Compress sessions for AI context
171
+ - `yaml-watcher.ts` - Watch and parse streaming YAML output
172
+ - `review-app.tsx` - TUI component for review mode
173
+ - `review-app.test.tsx` - Inline snapshot tests using opentui test renderer
174
+ - New `src/components/` module:
175
+ - `diff-view.tsx` - Shared DiffView component extracted from cli.tsx
176
+
177
+ # 0.1.13
178
+
179
+ - Docs:
180
+ - Enhance web preview section in README
181
+ - Add `/v/` short URL alias documentation
182
+
1
183
  # 0.1.12
2
184
 
3
185
  - Web preview:
package/README.md CHANGED
@@ -74,6 +74,74 @@ Then use:
74
74
  git difftool HEAD~1
75
75
  ```
76
76
 
77
+ ### Lazygit Integration
78
+
79
+ Use critique as a custom pager in [lazygit](https://github.com/jesseduffield/lazygit):
80
+
81
+ ```yaml
82
+ # ~/.config/lazygit/config.yml
83
+ git:
84
+ paging:
85
+ pager: critique --stdin
86
+ ```
87
+
88
+ For more details, see [lazygit's Custom Pagers documentation](https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md).
89
+
90
+ ### AI-Powered Diff Explanation
91
+
92
+ Generate AI-powered explanations of code changes using [OpenCode](https://opencode.ai) or [Claude Code](https://www.anthropic.com/claude-code) as the backend agent.
93
+
94
+ **What it does:**
95
+ - Orders hunks in logical reading order (types before implementation, etc.)
96
+ - Splits large hunks into digestible chunks with focused explanations
97
+ - Explains each change with diagrams, tables, and markdown
98
+ - Groups related changes across files
99
+
100
+ **Best for reviewing AI-generated changes:** Pass `--session` to include the coding session context, so the AI understands *why* changes were made and can explain them better.
101
+
102
+ ```bash
103
+ # Review unstaged changes (uses OpenCode by default)
104
+ critique review
105
+
106
+ # Use Claude Code instead
107
+ critique review --agent claude
108
+
109
+ # Review staged changes
110
+ critique review --staged
111
+
112
+ # Review the last commit
113
+ critique review HEAD
114
+
115
+ # Review a specific commit
116
+ critique review --commit HEAD~1
117
+ critique review --commit abc1234
118
+
119
+ # Review commit range (like a PR): critique review <base> <head>
120
+ # Shows what <head> added since diverging from <base>
121
+ critique review main HEAD # what current branch added vs main
122
+ critique review main feature-branch
123
+
124
+ # Include session context (from opencode or claude sessions)
125
+ critique review --agent opencode --session <session-id>
126
+ critique review --agent claude --session <session-id>
127
+
128
+ # Generate web preview instead of TUI
129
+ critique review --web
130
+ critique review --web --open
131
+ ```
132
+
133
+ **Options:**
134
+
135
+ | Flag | Description |
136
+ |------|-------------|
137
+ | `--agent <name>` | AI agent to use: `opencode` (default) or `claude` |
138
+ | `--staged` | Review staged changes |
139
+ | `--commit <ref>` | Review changes from a specific commit |
140
+ | `--session <id>` | Include session(s) as context (can be repeated) |
141
+ | `--web` | Generate web preview instead of TUI |
142
+ | `--open` | Open web preview in browser (with --web) |
143
+ | `--filter <pattern>` | Filter files by glob pattern |
144
+
77
145
  ### Pick Files from Another Branch
78
146
 
79
147
  Selectively apply changes from another branch to your current HEAD:
@@ -86,7 +154,13 @@ Use the interactive UI to select files. Selected files are immediately applied a
86
154
 
87
155
  ### Web Preview
88
156
 
89
- Generate a shareable web preview of your diff that you can send to anyone - no installation required:
157
+ Generate a shareable web preview of your diff that you can send to anyone - no installation required.
158
+
159
+ **Example:** [critique.work/v/b8faf4362c247bfc46f5098a028e00f0](https://critique.work/v/b8faf4362c247bfc46f5098a028e00f0)
160
+
161
+ Great for background agents that can't render terminal UIs, like [kimaki.xyz](https://kimaki.xyz) which runs OpenCode in Discord.
162
+
163
+ ![Web Preview](screenshot-web.png)
90
164
 
91
165
  ```bash
92
166
  # Upload to critique.work and get a shareable URL
@@ -95,29 +169,32 @@ critique web
95
169
  # View staged changes
96
170
  critique web --staged
97
171
 
98
- # View the last commit (works whether pushed or unpushed)
172
+ # View the last commit
99
173
  critique web HEAD
100
174
 
101
175
  # View a specific commit
102
176
  critique web --commit HEAD~1
103
177
 
104
- # View combined changes from last N commits
105
- critique web HEAD~3 HEAD
178
+ # Compare branches (PR-style diff)
179
+ critique web main feature-branch
180
+
181
+ # Filter specific files
182
+ critique web -- src/api.ts src/utils.ts
183
+
184
+ # Custom title for the HTML page
185
+ critique web --title "Fix authentication bug"
106
186
 
107
187
  # Generate local HTML file instead of uploading
108
188
  critique web --local
109
-
110
- # Adjust rendering size (use ~100 cols for mobile-friendly output)
111
- critique web --cols 100 --rows 2000
112
189
  ```
113
190
 
114
- **How it works:**
191
+ **Features:**
115
192
 
116
- 1. Captures the terminal UI output using a PTY (pseudo-terminal)
117
- 2. Converts ANSI escape codes to styled HTML with syntax highlighting
118
- 3. Uploads the HTML to [critique.work](https://critique.work) (Cloudflare Worker + KV storage)
119
- 4. Returns a shareable URL that expires after 7 days
120
- 5. Automatically opens the preview in your browser
193
+ - **Mobile optimized** - Automatically detects mobile devices and serves a unified diff view optimized for smaller screens. Add `?v=mobile` to any URL to force mobile view.
194
+ - **Dark/Light mode** - Automatically adapts to your system's color scheme preference using CSS `prefers-color-scheme`.
195
+ - **Syntax highlighting** - Full syntax highlighting for 18+ languages, same as the terminal UI.
196
+ - **Split view** - Side-by-side diff on desktop, unified view on mobile.
197
+ - **Fast loading** - HTML is streamed for quick initial render, cached for 24 hours.
121
198
 
122
199
  **Options:**
123
200
 
@@ -126,14 +203,24 @@ critique web --cols 100 --rows 2000
126
203
  | `--staged` | Show staged changes | - |
127
204
  | `--commit <ref>` | Show changes from a specific commit | - |
128
205
  | `--cols <n>` | Terminal width for rendering | `240` |
129
- | `--rows <n>` | Terminal height for rendering | `2000` |
206
+ | `--mobile-cols <n>` | Terminal width for mobile version | `100` |
130
207
  | `--local` | Save HTML locally instead of uploading | - |
131
208
  | `--filter <pattern>` | Filter files by glob (can be used multiple times) | - |
209
+ | `--title <text>` | Custom HTML document title | `Critique Diff` |
210
+ | `--theme <name>` | Theme for rendering (disables auto dark/light mode) | - |
211
+
212
+ **How it works:**
213
+
214
+ 1. Captures the terminal UI output using a PTY (pseudo-terminal)
215
+ 2. Converts ANSI escape codes to styled HTML with syntax highlighting
216
+ 3. Generates both desktop (240 cols, split view) and mobile (100 cols, unified view) versions
217
+ 4. Uploads to [critique.work](https://critique.work) (Cloudflare Worker + KV storage)
218
+ 5. Returns a shareable URL that expires after 7 days
132
219
 
133
220
  **Tips:**
134
221
 
135
- - Use `--cols 100` for mobile-friendly output (switches to unified diff view instead of split view)
136
222
  - The URL is based on a SHA-256 hash of the content, so identical diffs produce the same URL (deduplication)
223
+ - Use `?v=desktop` or `?v=mobile` query params to force a specific version
137
224
  - If upload fails, critique automatically saves the HTML locally as a fallback
138
225
 
139
226
  ## Features