Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

173 lines · 8.4 KBRaw History
1# Diffinery plugins for Claude Code and Codex
2
3A plugin marketplace, kept in the Diffinery repository itself, that makes Claude Code and
4OpenAI's Codex CLI work smoothly with repositories hosted on [Diffinery](https://diffinery.com),
5the git forge built for AI agents.
6It has two plugins: `diffinery` (Claude Code and Codex) and `diffinery-ci` (Claude Code),
7described below.
8
9The plugin adds:
10
11| Piece | Claude Code | Codex |
12| --- | --- | --- |
13| `diffinery` MCP server (`https://diffinery.com/mcp`, OAuth sign-in) | yes | yes |
14| `diffinery` skill: the CLI, git auth, the branch → PR → CI → merge loop, Diffinery's agent rules | yes | yes |
15| `pr-status`: this branch's PR, its checks, and the log tail of failing jobs | `/diffinery:pr-status` command | `pr-status` skill |
16| SessionStart hook: in a Diffinery clone, tells the agent the repo is on Diffinery and whether the `diffinery` CLI is installed and signed in | yes | yes, once you trust it (`/hooks`) |
17
18`diffinery-ci` is a Claude Code [mod](https://code.claude.com/docs/en/plugins/mods/overview)
19that shows the branch's pull request and its CI checks live, and tells Claude when CI settles:
20
21| Piece | Where it works |
22| --- | --- |
23| Band above the prompt: PR number, title, checks (`✗ 1 failed · ● 3 running · ✓ 6`), review and merge state | Terminal, desktop app (Code tab), VS Code |
24| `/diffinery-ci`: a pane with every check, its time and a link to its log, plus **Fix CI** and **Refresh**; `/diffinery-ci on` / `off` | Pane where Claude Code draws; a text answer everywhere else |
25| Status line entry (`PR #7 ✓ 10/10`) and a toast when CI passes or fails | Where Claude Code draws |
26| After the session pushes a branch or opens its PR, a note to Claude once that commit's checks settle (failures where the band shows the rest, passes too where nothing draws, so a cloud thread hears either way; `/diffinery-ci notes auto|failures|all|off` changes it, nothing to set up) | Everywhere hooks run, cloud sessions and project threads included |
27
28It reads Diffinery's GraphQL API with the token from `DIFFINERY_TOKEN`, `diffinery login`,
29or gh signed in to the host (`diffinery auth setup-gh`), and sends it nowhere else. It needs
30Claude Code 2.1.287 or later (the desktop app: 2.1.286). Cloud sessions run its hooks but
31draw no mod interface, so there it's the note to Claude and the `/diffinery-ci` text.
32
33Nothing here is needed just to use git: clone, fetch and push work with any git client
34(`diffinery auth setup-git` or a token as the HTTPS password). The plugin is for pull
35requests, CI and issues.
36
37## Install
38
39codician/diffinery is public, so adding the marketplace needs no sign-in. The plugin works through
40the `diffinery` CLI, so install it and sign in once per machine:
41
42```sh
43curl -fsSL https://diffinery.com/install | bash # Windows: irm https://diffinery.com/install.ps1 | iex
44diffinery login
45diffinery auth setup-git
46```
47
48### Claude Code
49
50```sh
51claude plugin marketplace add https://diffinery.com/codician/diffinery.git
52claude plugin install diffinery@diffinery
53```
54
55Or inside a session: `/plugin marketplace add https://diffinery.com/codician/diffinery.git`,
56then `/plugin install diffinery@diffinery`, then `/reload-plugins` (or restart).
57
58Add `claude plugin install diffinery-ci@diffinery` for the live CI band.
59
60### claude.ai, cloud sessions and projects
61
62claude.ai can't read this repository, so upload the plugins as files: download
63https://diffinery.com/-/claude/diffinery.zip and https://diffinery.com/-/claude/diffinery-ci.zip,
64then in claude.ai open **Customize → Plugins → Add → Upload plugin** for each. They reach your
65cloud sessions at their next start. For a project's threads, also add them under
66**Project settings → Plugins**. Build the same zips from a checkout with
67`python3 scripts/pack-plugins.py` at the repository root (they land in `dist/`).
68
69### Codex
70
71```sh
72codex plugin marketplace add https://diffinery.com/codician/diffinery.git
73codex plugin add diffinery@diffinery
74```
75
76Check with `codex plugin list` and `codex mcp list`. Codex runs plugin hooks only after
77you review and trust them: open `/hooks` in the Codex TUI and trust the `diffinery`
78SessionStart hook (optional; the skill works without it).
79
80## Sign in
81
82The MCP server signs you in with OAuth in the browser:
83
84- Claude Code: run `/mcp`, pick `plugin:diffinery:diffinery`, choose Authenticate.
85- Codex: `codex mcp login diffinery`.
86
87The skill also uses the `diffinery` CLI, which has its own sign-in:
88
89```sh
90curl -fsSL https://diffinery.com/install | bash # Windows: irm https://diffinery.com/install.ps1 | iex
91diffinery login # or: diffinery login --device
92diffinery auth setup-git # optional: git credential helper
93```
94
95## Headless use (CI, cloud sessions): `DIFFINERY_TOKEN`
96
97The `diffinery` CLI and `diffinery auth setup-git` pick up `DIFFINERY_TOKEN` on their own.
98
99The plugin's MCP server uses OAuth only. Neither client can take a token from the
100environment when it is set and fall back to OAuth when it is not, from one config:
101
102- Claude Code turns OAuth off as soon as the server config has an `Authorization`
103 header, even an empty one, and plugin header helpers do not see variables like
104 `DIFFINERY_TOKEN`.
105- Codex's `bearer_token_env_var` makes the server fail to start when the variable is unset.
106
107So on headless machines, add a token-based server of your own. It takes precedence over
108the plugin's:
109
110```sh
111# Claude Code: same URL, so the plugin's OAuth entry is hidden while this one exists
112claude mcp add --scope user --transport http diffinery https://diffinery.com/mcp \
113 --header 'Authorization: Bearer ${DIFFINERY_TOKEN}'
114
115# Codex: same name, so it replaces the plugin's server
116codex mcp add diffinery --url https://diffinery.com/mcp --bearer-token-env-var DIFFINERY_TOKEN
117# ...or just for one run, without touching config.toml:
118codex -c 'mcp_servers.diffinery.url="https://diffinery.com/mcp"' \
119 -c 'mcp_servers.diffinery.bearer_token_env_var="DIFFINERY_TOKEN"' exec "..."
120```
121
122Keep the single quotes in the Claude Code command: Claude Code expands
123`${DIFFINERY_TOKEN}` when it connects, so the token is never written to its config.
124
125## claude.ai and the Claude apps
126
127Settings → Connectors → Add custom connector, with the URL `https://diffinery.com/mcp`.
128You sign in with your Diffinery account when you connect it.
129
130## gh
131
132Prefer the `diffinery` CLI: it knows Diffinery's extras (`--intent`, auto-merge,
133`run logs`). `gh` works too once you run `diffinery auth setup-gh`, which signs gh in to
134diffinery.com as a GitHub Enterprise host. That is also what lets Claude Code show the
135branch's pull request with its CI status. See https://diffinery.com/docs/agents/github-cli.
136
137## Layout
138
139Paths from the repository root:
140
141```
142.claude-plugin/marketplace.json Claude Code marketplace
143.agents/plugins/marketplace.json Codex marketplace
144plugins/diffinery/
145 .claude-plugin/plugin.json Claude Code manifest
146 .codex-plugin/plugin.json Codex manifest
147 .mcp.json the diffinery MCP server (both clients)
148 skills/diffinery/SKILL.md the skill (both clients)
149 commands/pr-status.md /pr-status (Claude Code)
150 codex-skills/pr-status/SKILL.md pr-status skill (Codex has no plugin commands)
151 hooks/hooks.json SessionStart hook (both clients)
152 hooks/session-start.sh the hook: POSIX sh, no network, silent outside Diffinery repos
153plugins/diffinery-ci/ Claude Code only (a mod)
154 .claude-plugin/plugin.json manifest
155 hooks/hooks.json names the hooks module
156 hooks/register.tsx the mod: band, pane, status line, CI watch
157 hooks/lib.ts parsing and wording, no engine calls
158 types/index.d.ts the mod's state contract
159 tests/ci.test.tsx `claude plugin test plugins/diffinery-ci`
160scripts/pack-plugins.py builds dist/<plugin>-<version>.zip for upload
161apps/diffinery/claude-plugins/ the packed zips diffinery.com serves (see its README)
162```
163
164Check changes with `claude plugin validate .` and `claude plugin validate plugins/diffinery`
165from the repository root, and for the mod `claude plugin validate plugins/diffinery-ci` and
166`claude plugin test plugins/diffinery-ci`. Bump `version` in both plugin manifests and both marketplace entries
167together.
168
169More: https://diffinery.com/docs/connect
170
171## License
172
173Apache-2.0, like the rest of the repository. See [LICENSE](../LICENSE).