{"id":32814238,"url":"https://github.com/remorses/critique","last_synced_at":"2026-04-02T19:04:33.219Z","repository":{"id":321956738,"uuid":"1072338307","full_name":"remorses/critique","owner":"remorses","description":"TUI for reviewing git changes","archived":false,"fork":false,"pushed_at":"2026-03-07T14:54:38.000Z","size":4380,"stargazers_count":1074,"open_issues_count":5,"forks_count":29,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-03-07T20:58:42.587Z","etag":null,"topics":["diff","opentui","tui"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/remorses.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-10-08T15:25:46.000Z","updated_at":"2026-03-07T14:54:42.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/remorses/critique","commit_stats":null,"previous_names":["remorses/critique"],"tags_count":39,"template":false,"template_full_name":null,"purl":"pkg:github/remorses/critique","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remorses%2Fcritique","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remorses%2Fcritique/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remorses%2Fcritique/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remorses%2Fcritique/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/remorses","download_url":"https://codeload.github.com/remorses/critique/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remorses%2Fcritique/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30278153,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T20:45:49.896Z","status":"ssl_error","status_checked_at":"2026-03-08T20:45:49.525Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["diff","opentui","tui"],"created_at":"2025-11-07T03:03:44.978Z","updated_at":"2026-04-02T19:04:33.207Z","avatar_url":"https://github.com/remorses.png","language":"TypeScript","funding_links":[],"categories":["Developer Tools"],"sub_categories":[],"readme":"# critique\n\nA beautiful terminal UI for reviewing git diffs with syntax highlighting, split view, and word-level diff.\n\n![Diff Viewer Demo](screenshot.png)\n\n## Installation\n\n\u003e **Note:** critique requires [Bun](https://bun.sh) - it does not work with Node.js.\n\n```bash\n# Run directly with bunx (no install needed)\nbunx critique\n\n# Or install globally\nbun install -g critique\n```\n\n## Usage\n\n### View Git Diff\n\n```bash\n# View unstaged changes (includes untracked files)\ncritique\n\n# View staged changes\ncritique --staged\n\n# View changes since a ref (like git diff)\ncritique HEAD~1         # shows last 1 commit (changes since HEAD~1)\ncritique HEAD~3         # shows last 3 commits\ncritique main           # shows changes since main (your branch's additions)\n\n# View a specific commit only (what that commit introduced)\ncritique --commit HEAD~1\ncritique --commit abc1234\n\n# Compare two refs (PR-style, shows what head added since diverging from base)\ncritique HEAD~3 HEAD    # shows all changes from 3 commits ago to now\n\n# Compare two branches (PR-style, shows what head added since diverging from base)\ncritique main feature-branch    # what feature-branch added vs main\ncritique main HEAD              # what current branch added vs main\n\n# Watch mode - auto-refresh on file changes\ncritique --watch\n\n# Filter files by glob pattern (can be used multiple times)\ncritique --filter \"src/**/*.ts\"\ncritique --filter \"src/**/*.ts\" --filter \"lib/**/*.js\"\n```\n\n### Navigation\n\n| Key | Action |\n|-----|--------|\n| `←` / `→` | Navigate between files |\n| `↑` / `↓` | Scroll up/down |\n| `Ctrl+P` | Open file selector dropdown |\n| `Option` (hold) | Fast scroll (10x) |\n| `Esc` | Close dropdown |\n\n### Git Difftool Integration\n\nConfigure critique as your git difftool:\n\n```bash\ngit config --global diff.tool critique\ngit config --global difftool.critique.cmd 'critique difftool \"$LOCAL\" \"$REMOTE\"'\n```\n\nThen use:\n\n```bash\ngit difftool HEAD~1\n```\n\n### Lazygit Integration\n\nUse critique as a custom pager in [lazygit](https://github.com/jesseduffield/lazygit):\n\n```yaml\n# ~/.config/lazygit/config.yml\ngit:\n  pagers:\n    - pager: critique --stdin\n```\n\nFor more details, see [lazygit's Custom Pagers documentation](https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md).\n\n### AI-Powered Diff Explanation\n\nGenerate AI-powered explanations of code changes using [OpenCode](https://opencode.ai) or [Claude Code](https://www.anthropic.com/claude-code) as the backend agent.\n\n**What it does:**\n- Orders hunks in logical reading order (types before implementation, etc.)\n- Splits large hunks into digestible chunks with focused explanations\n- Explains each change with diagrams, tables, and markdown\n- Groups related changes across files\n\n**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.\n\n```bash\n# Review unstaged changes (uses OpenCode by default)\ncritique review\n\n# Use Claude Code instead\ncritique review --agent claude\n\n# Review staged changes\ncritique review --staged\n\n# Review changes since a ref (like git diff)\ncritique review HEAD~1         # review last 1 commit\ncritique review main           # review changes since main\n\n# Review a specific commit only (what that commit introduced)\ncritique review --commit HEAD~1\ncritique review --commit abc1234\n\n# Review commit range (like a PR): critique review \u003cbase\u003e \u003chead\u003e\n# Shows what \u003chead\u003e added since diverging from \u003cbase\u003e\ncritique review main HEAD          # what current branch added vs main\ncritique review main feature-branch\n\n# Include session context (from opencode or claude sessions)\ncritique review --agent opencode --session \u003csession-id\u003e\ncritique review --agent claude --session \u003csession-id\u003e\n\n# Generate web preview instead of TUI\ncritique review --web\ncritique review --web --open\n```\n\n**Options:**\n\n| Flag | Description |\n|------|-------------|\n| `--agent \u003cname\u003e` | AI agent to use: `opencode` (default) or `claude` |\n| `--staged` | Review staged changes |\n| `--commit \u003cref\u003e` | Review changes from a specific commit |\n| `--session \u003cid\u003e` | Include session(s) as context (can be repeated) |\n| `--web` | Generate web preview instead of TUI |\n| `--pdf [filename]` | Generate PDF instead of TUI. Great for reading on e-ink devices — see [e-reader guide](docs/e-reader-guide.md) |\n| `--open` | Open in browser/viewer (with --web/--pdf) |\n| `--filter \u003cpattern\u003e` | Filter files by glob pattern |\n\n### Pick Files from Another Branch\n\nSelectively apply changes from another branch to your current HEAD:\n\n```bash\ncritique pick feature-branch\n```\n\nUse the interactive UI to select files. Selected files are immediately applied as patches, deselected files are restored.\n\n### Selective Hunk Staging\n\nNon-interactive hunk staging for scripts and AI agents. Similar to `git add -p` but scriptable.\n\n```bash\n# List all unstaged hunks with stable IDs\ncritique hunks list\n\n# List staged hunks\ncritique hunks list --staged\n\n# Filter by file pattern\ncritique hunks list --filter \"src/**/*.ts\"\n\n# Stage specific hunks by ID\ncritique hunks add 'src/main.ts:@-10,6+10,7'\n\n# Stage multiple hunks\ncritique hunks add 'src/main.ts:@-10,6+10,7' 'src/utils.ts:@-5,3+5,4'\n```\n\n**Hunk ID format:** `file:@-oldStart,oldLines+newStart,newLines`\n\nThe ID is derived from the `@@` header in unified diff format, making it stable across runs (unlike incremental IDs).\n\n**Example workflow:**\n\n```bash\n# 1. List available hunks\n$ critique hunks list\nsrc/main.ts:@-10,6+10,7\n@@ -10,6 +10,7 @@\n+import { newFeature } from './feature'\n---\nsrc/main.ts:@-50,3+51,5\n@@ -50,3 +51,5 @@\n+  newFeature()\n+  return result\n---\n\n# 2. Stage just the import hunk\n$ critique hunks add 'src/main.ts:@-10,6+10,7'\nStaged: src/main.ts:@-10,6+10,7\n\n# 3. Commit it separately\n$ git commit -m \"Add newFeature import\"\n\n# 4. Stage and commit the usage\n$ critique hunks add 'src/main.ts:@-50,3+51,5'\n$ git commit -m \"Use newFeature in main\"\n```\n\n### Web Preview\n\nGenerate a shareable web preview of your diff that you can send to anyone - no installation required.\n\n**Example:** [critique.work/v/b8faf4362c247bfc46f5098a028e00f0](https://critique.work/v/b8faf4362c247bfc46f5098a028e00f0)\n\nGreat for background agents that can't render terminal UIs, like [kimaki.xyz](https://kimaki.xyz) which runs OpenCode in Discord.\n\n![Web Preview](screenshot-web.png)\n\n```bash\n# Upload to critique.work and get a shareable URL\ncritique web\n\n# View staged changes\ncritique web --staged\n\n# View changes since a ref (like git diff)\ncritique web HEAD~1         # last 1 commit\ncritique web main           # changes since main\n\n# View a specific commit only (what that commit introduced)\ncritique web --commit HEAD~1\n\n# Compare branches (PR-style diff)\ncritique web main feature-branch\n\n# Filter specific files\ncritique web -- src/api.ts src/utils.ts\n\n# Custom title for the HTML page\ncritique web --title \"Fix authentication bug\"\n```\n\n**Features:**\n\n- **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.\n- **Dark/Light mode** - Automatically adapts to your system's color scheme preference using CSS `prefers-color-scheme`.\n- **Syntax highlighting** - Full syntax highlighting for 20+ languages, same as the terminal UI.\n- **Split view** - Side-by-side diff on desktop, unified view on mobile.\n- **Fast loading** - HTML is streamed for quick initial render, cached for 24 hours.\n\n**Options:**\n\n| Flag | Description | Default |\n|------|-------------|---------|\n| `--staged` | Show staged changes | - |\n| `--commit \u003cref\u003e` | Show changes from a specific commit | - |\n| `--cols \u003cn\u003e` | Terminal width for rendering | `240` |\n| `--mobile-cols \u003cn\u003e` | Terminal width for mobile version | `100` |\n| `--filter \u003cpattern\u003e` | Filter files by glob (can be used multiple times) | - |\n| `--title \u003ctext\u003e` | Custom HTML document title | `Critique Diff` |\n| `--theme \u003cname\u003e` | Theme for rendering (disables auto dark/light mode) | - |\n\n**How it works:**\n\n1. Renders the diff using opentui's test renderer to capture structured frame data\n2. Converts the captured spans to styled HTML with syntax highlighting\n3. Generates both desktop (240 cols, split view) and mobile (100 cols, unified view) versions\n4. Uploads to [critique.work](https://critique.work) (Cloudflare Worker + KV storage)\n5. Returns a shareable URL that expires after 7 days\n\n**Raw Patch Access:**\n\nEvery uploaded diff is also available as a raw unified diff (patch) by appending `.patch` to the URL:\n\n```bash\n# View the patch in your terminal\ncurl https://critique.work/v/b8faf4362c247bfc46f5098a028e00f0.patch\n\n# Apply the patch directly to your repo\ncurl -s https://critique.work/v/b8faf4362c247bfc46f5098a028e00f0.patch | git apply\n\n# Reverse the patch (undo the changes)\ncurl -s https://critique.work/v/b8faf4362c247bfc46f5098a028e00f0.patch | git apply --reverse\n```\n\nThis makes critique URLs useful for programmatic tools — share the HTML link for humans, use the `.patch` URL for machines.\n\n**Tips:**\n\n- The URL is based on a SHA-256 hash of the content, so identical diffs produce the same URL (deduplication)\n- Use `?v=desktop` or `?v=mobile` query params to force a specific version\n- If upload fails, critique automatically saves the HTML locally as a fallback\n\n## E-Ink Reading\n\nGenerate PDFs from diffs and AI reviews to read on Kindle or Boox e-readers. Useful when you have background agents writing code — tools like [kimaki](https://kimaki.xyz) (runs coding agents from Discord) or [clawdbot](https://clawd.bot) (self-hosted AI assistant connected to Discord/Slack/Telegram) — and you want to review their changes away from your desk on an e-ink device.\n\n```bash\ncritique --pdf                    # diff as PDF\ncritique review --pdf             # AI review as PDF\ncritique review main --pdf --open # review branch changes, open in viewer\n```\n\nThe PDF preserves syntax highlighting and diff formatting. Email it to your Kindle, drop it in BooxDrop, or save to a synced Google Drive folder. See [docs/e-reader-guide.md](docs/e-reader-guide.md) for detailed setup for each device.\n\n## Features\n\n- **Syntax Highlighting** - Powered by [Tree-sitter](https://tree-sitter.github.io/) via [opentui](https://github.com/sst/opentui) with support for 20+ languages\n- **Split View** - Side-by-side comparison for wide terminals (auto-switches to unified view on narrow terminals)\n- **Word-Level Diff** - Highlights specific word changes within modified lines\n- **File Navigation** - Quick file switcher with fuzzy search\n- **Click to Open** - Click line numbers to open in your editor (set `REACT_EDITOR` env var)\n- **Watch Mode** - Live updates as you edit files\n- **Web Preview** - Generate shareable HTML previews hosted on [critique.work](https://critique.work)\n- **Cherry Pick** - Interactive file picker to apply changes from other branches\n\n## Supported Languages\n\nTypeScript, JavaScript, TSX, JSX, JSON, Markdown, HTML, CSS, Python, Rust, Go, Java, C, C++, C#, Ruby, PHP, Scala, Haskell, Julia, OCaml, Clojure, Swift, Nix, YAML, Bash\n\n## Configuration\n\n| Environment Variable | Description | Default |\n|---------------------|-------------|---------|\n| `REACT_EDITOR` | Editor command for click-to-open | `zed` |\n| `CRITIQUE_WORKER_URL` | Custom worker URL for web preview | `https://critique.work` |\n\n## Ignored Files\n\nLock files are automatically hidden from diffs:\n- `pnpm-lock.yaml`\n- `package-lock.json`\n- `yarn.lock`\n- `bun.lockb`\n- `Cargo.lock`\n- `poetry.lock`\n- `Gemfile.lock`\n- `composer.lock`\n\nFiles with more than 6000 lines of diff are also hidden for performance.\n\n## Built With\n\n- [opentui](https://github.com/sst/opentui) - React-based terminal UI framework\n- [Tree-sitter](https://tree-sitter.github.io/) - Syntax highlighting\n- [diff](https://github.com/kpdecker/jsdiff) - Diff algorithm\n- [Hono](https://hono.dev/) - Web framework for the preview worker\n\n## Sponsors\n\n\u003ca href=\"https://coderabbit.link/remorses\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\n  \u003cimg src=\"https://github.com/coderabbitai.png\" alt=\"CodeRabbit\" height=\"24\" /\u003e\n\u003c/a\u003e\n\nSponsored by [CodeRabbit](https://coderabbit.link/remorses).\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fremorses%2Fcritique","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fremorses%2Fcritique","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fremorses%2Fcritique/lists"}