{"id":50434035,"url":"https://github.com/thorrester/wyrd-diff","last_synced_at":"2026-05-31T16:01:44.566Z","repository":{"id":359591389,"uuid":"1245992629","full_name":"thorrester/wyrd-diff","owner":"thorrester","description":"in-session diff reviews for agents","archived":false,"fork":false,"pushed_at":"2026-05-22T17:46:01.000Z","size":1851,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-22T19:44:42.821Z","etag":null,"topics":["agentic-workflows","agents","ai","harness-engineering","productivity","review-tools","session-management"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thorrester.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2026-05-21T19:08:02.000Z","updated_at":"2026-05-22T17:45:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/thorrester/wyrd-diff","commit_stats":null,"previous_names":["thorrester/wyrd-diff"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/thorrester/wyrd-diff","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thorrester%2Fwyrd-diff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thorrester%2Fwyrd-diff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thorrester%2Fwyrd-diff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thorrester%2Fwyrd-diff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thorrester","download_url":"https://codeload.github.com/thorrester/wyrd-diff/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thorrester%2Fwyrd-diff/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33737692,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["agentic-workflows","agents","ai","harness-engineering","productivity","review-tools","session-management"],"created_at":"2026-05-31T16:01:43.950Z","updated_at":"2026-05-31T16:01:44.558Z","avatar_url":"https://github.com/thorrester.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# wyrd-diff\n\nKeep diffs wyrd\n\nA local diff review tool that pipes your review back to the coding agent while it's still working. Comment on the diff, dispatch the batch, the agent picks it up on its next turn through MCP and applies fixes. No PR round-trip. No copy-paste into chat.\n\n## The problem\n\nYou're running an agent on a branch. It produces 12 file changes. You want to actually review the diff before merging, not just skim what the agent claims it did.\n\nToday, the loop sucks. You either:\n\n- Paste diffs into chat one at a time and steer in prose (\"no, change line 47 to...\").\n- Wait for a PR, leave GitHub comments, then ask the agent to read them back.\n- Give up on review and trust the agent.\n\nAll three break the in-session feedback loop. The agent is right there with full context loaded. By the time you've copy-pasted line numbers into a chat box, that context is gone.\n\nwyrd-diff fixes that. You review the diff in a dense, fast desktop UI. You leave line-level comments. You hit \"Dispatch batch\". On the agent's next turn, it queries the MCP server, sees your queued feedback, and applies it. No context loss. No PR yet. The branch stays local until you're ready.\n\nIt also keeps the byproducts. Notes, decisions, and accepted fix trajectory get persisted locally so you can export trajectory as JSONL when you want it, and ignore it when you don't.\n\n## What you get\n\n- A desktop review surface (Tauri + SvelteKit) for line-level comments on a diff between two refs in a local repo.\n- A local Axum bridge on `127.0.0.1:8765` (falls back to 8766..8774 if taken).\n- An MCP server over HTTP at `/mcp`. Wire it into Claude Code, Codex, OpenCode, Gemini, or a custom harness you define.\n- Pull-based feedback delivery. The agent calls `wyrd_diff.pending_feedback`, gets queued threads with per-thread watermarks, and only sees deltas. No duplicate fixes.\n- A Stop-hook recorder that links each agent commit back to the review that triggered it.\n- JSONL export of accepted trajectory.\n\nTarget repo stays clean. No `.wyrd/` directory. No commits to scrub before pushing.\n\n## Screenshots\n\n\u003cp\u003e\n  \u003cimg\n    src=\"fixtures/homepage.png\"\n    alt=\"Wyrd Diff home view with the review-session composer open\"\n    style=\"border: 1px solid #2f3f46; border-radius: 6px;\"\n    width=\"49%\"\n  /\u003e\n  \u003cimg\n    src=\"fixtures/diff.png\"\n    alt=\"Wyrd Diff review view with a selected diff range and add-thread composer\"\n    style=\"border: 1px solid #2f3f46; border-radius: 6px;\"\n    width=\"49%\"\n  /\u003e\n\u003c/p\u003e\n\nThe home view tracks active reviews across repositories and branches. The review\nview keeps the file tree, highlighted diff, line selection, and thread composer\nin one workspace.\n\n## Install\n\nDownload the latest release from [GitHub Releases](https://github.com/thorrester/wyrd-diff/releases).\n\n### macOS\n\nTwo builds are available: `aarch64` (Apple Silicon) and `x86_64` (Intel). Download the `.dmg` for your architecture, open it, and drag `Wyrd Diff.app` to Applications.\n\n**Gatekeeper will refuse to open it** because the app is unsigned. Run this once after dragging:\n\n```bash\nxattr -dr com.apple.quarantine /Applications/Wyrd\\ Diff.app\n```\n\nThen open normally from Applications. This is a one-time step. Once open, it works like any other app.\n\n### Linux\n\n`.AppImage` works on most distributions without installation:\n\n```bash\nchmod +x wyrd-diff_*.AppImage\n./wyrd-diff_*.AppImage\n```\n\n`.deb` is also available for apt-based systems:\n\n```bash\nsudo dpkg -i wyrd-diff_*.deb\nwyrd-diff\n```\n\n### What runs when you open it\n\nThe app spawns a local Axum bridge on `127.0.0.1:8765` (falls back to 8766..8774 if taken) and an MCP server at `http://127.0.0.1:8765/mcp`. SQLite state lives at `~/.config/wyrd-diff/wyrd-diff.db`. That directory is created on first launch.\n\nFrom there, the status pill in the bottom-right corner shows bridge health and detected agent harnesses. Click \"Wire\" to write the MCP config for Claude, Codex, OpenCode, or Gemini and restart the agent client.\n\n## Build from source\n\nRequires Rust 1.91+, Node 24, pnpm 10. `mise` installs the toolchain.\n\n```bash\nmise install\nmise run db:migrate\nmise run dev\n```\n\n`mise run dev` launches the Tauri desktop app. The app spawns the bridge itself, so no separate API process is needed.\n\nAgent wiring works the same way as with the installed app. See [Agent wiring](#agent-wiring) below.\n\n## The loop\n\n1. Register a local repo.\n2. Start a review session against a base ref and head ref.\n3. Comment on exact diff lines. Each line discussion is a thread. Threads can have follow-up replies.\n4. When you have a coherent set of comments, hit \"Dispatch batch\". The threads are queued for delivery.\n5. The agent, on its next turn, calls `wyrd_diff.pending_feedback`. It receives the queued threads as a single markdown payload with per-thread sections.\n6. The agent applies fixes and commits.\n7. The Stop hook records the commit and links it to the review session.\n8. Mark fixes accepted or rejected. The session keeps going until the diff is what you want.\n\nDelivery is pull, not push. Dispatching a batch makes feedback available; it does not interrupt the agent. The agent fetches on its next turn. That matters because it works the same whether the agent is local, remote, headless, or interactive.\n\nPer-thread watermarks mean the agent never sees the same comment twice. Add a reply to a thread after the agent's first fix attempt and only the new message gets delivered next time.\n\n## Architecture\n\n```\n┌─────────────────────┐\n│  Tauri Desktop App  │  review UI, decisions, exports\n│  (SvelteKit)        │\n└─────────┬───────────┘\n          │ spawns\n          ▼\n┌─────────────────────┐         ┌──────────────────┐\n│  Local Axum Bridge  │ ◄─MCP── │  Agent Harness   │\n│  127.0.0.1:8765     │  HTTP   │  (Claude/Codex/  │\n│                     │         │   OpenCode/...)  │\n└─────────┬───────────┘         └──────────────────┘\n          │\n          ▼\n┌─────────────────────┐\n│  SQLite                       │  reviews, threads, notes,\n│  ~/.config/wyrd-diff/         │  decisions, fix trajectory\n│  wyrd-diff.db                 │\n└─────────────────────┘\n```\n\nCrates:\n\n- `wyrd-diff-core`: domain models, SQLite persistence, git/diff logic, export.\n- `wyrd-diff-api`: Axum routes for the desktop UI and MCP HTTP transport.\n- `wyrd-diff-cli`: CLI for hooks, migrations, agent wiring, standalone server.\n- `wyrd-diff-mcp`: agent-facing MCP tools.\n- `app/src-tauri`: Tauri shell, spawns the bridge on launch.\n- `app/src`: SvelteKit UI.\n\nEverything durable lives in `wyrd-diff-core`. The CLI, MCP, Axum, and Tauri layers are thin adapters. Swap the desktop shell for a web UI or replace MCP with another transport and the persistence layer does not move.\n\n## Agent wiring\n\nThree ways to wire an agent.\n\n### From the app\n\nThe status pill detects installed harnesses and shows a \"Wire\" button per harness. Click it. Config gets written, sibling entries left alone.\n\n### From the CLI\n\n```bash\nmise run configure:agents\n```\n\n### User config (`wyrd-diff.toml`)\n\nThe app reads `~/.config/wyrd-diff/wyrd-diff.toml` (honors `$XDG_CONFIG_HOME`). One file covers the repo home directory and any custom harnesses:\n\n```toml\nhome_dir = \"~/Documents/GitHub\"\n\n[[harness]]\nid = \"my-harness\"\ndisplay = \"My Harness\"\nbinary = \"my-harness\"\npath = \"~/.my-harness/mcp.json\"\nformat = \"claude-json\"\n```\n\n`home_dir` is where the composer scans for repos and is also writable from the app's home bar (it auto-detects `Documents/GitHub`, `github`, `code`, `src`, etc. on first launch). Legacy `harnesses.toml` in the same directory is still read when `wyrd-diff.toml` is absent.\n\nSupported harness formats: `claude-json`, `codex-toml`, `opencode-json`, `gemini-json`. User entries override built-ins on id collision. Path expansion handles `~/`, `~`, `$HOME/`, and absolute paths.\n\nIf config writing fails (permissions, unfamiliar schema), the app falls back to a copy-pasteable snippet for the harness format.\n\n## Session + trajectory hooks (optional but recommended)\n\nWyrd diff supports multiple repos, branches, and live agent sessions in parallel. To link a coding agent to the right review automatically, wire two hooks: `SessionStart` registers the agent against its `(repo, branch)`, and `Stop` records the resulting commit + response as a trajectory point. Both hooks are inert when no active review exists for the branch, so leaving them on is safe.\n\nPass two env vars when the hook fires:\n\n| Var | Value |\n| --- | --- |\n| `WYRD_DIFF_AGENT` | `claude`, `codex`, `opencode`, `gemini`, or your own name |\n| `WYRD_DIFF_AGENT_SESSION_ID` | The harness session id (`$CLAUDE_SESSION_ID`, `$CODEX_SESSION_ID`, etc.) |\n\nThe CLI infers `repo_path` from `git rev-parse --show-toplevel` and `branch` from `git rev-parse --abbrev-ref HEAD`. Override either with `WYRD_DIFF_REPO_PATH` / `WYRD_DIFF_BRANCH` if your harness runs outside the repo root.\n\nHook commands:\n\n```bash\n# SessionStart\ncargo run --manifest-path /path/to/wyrd-diff/Cargo.toml --locked -p wyrd-diff-cli -- hook agent-start\n\n# Stop\ncargo run --manifest-path /path/to/wyrd-diff/Cargo.toml --locked -p wyrd-diff-cli -- hook agent-stop\n```\n\nExample configs:\n\n- `examples/claude-settings.local.json`\n- `examples/codex-hooks.json`\n\nFor Claude Code, put the hook in `.claude/settings.local.json`. For Codex, `.codex/hooks.json`. Both go in the target repo. Do not commit them — they contain machine-specific paths.\n\nOnce registered, agents can call `wyrd_diff.pending_feedback` with `{ agent_session_id, agent_name }` and the MCP server resolves the linked review automatically. No more hand-pasting session ids.\n\n## Development\n\n```bash\nmise install\nmise run db:migrate\nmise run dev          # Tauri desktop + bridge\nmise run dev:ui       # SvelteKit only\nmise run dev:api      # Axum bridge only\nmise run dev:mcp      # MCP over stdio (for debugging)\nmise run check        # fmt + lint + typecheck + tests\n```\n\nTargeted Rust tests:\n\n```bash\ncargo test --locked -p wyrd-diff-core\n```\n\nReset local DB if a migration goes sideways:\n\n```bash\nmise run db:reset\n```\n\nSee `AGENTS.md` for ownership boundaries and contributor conventions.\n\n## Status\n\nPre-1.0. APIs and schema can change. Migrations are forward-only with no automatic rollback. If you depend on the JSONL export shape, pin a commit.\n\n## License\n\nMIT.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthorrester%2Fwyrd-diff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthorrester%2Fwyrd-diff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthorrester%2Fwyrd-diff/lists"}