# CLI reference

> Every command and option of the diffinery command-line client, generated from its source.

Source: https://diffinery.com/docs/reference/cli

This page lists every command of the `diffinery` command-line client (version 0.1.0) with all of its options. It is generated from the CLI's own command definitions, so it always matches `diffinery <command> --help`.

## Install

```sh
curl -fsSL https://diffinery.com/install | bash      # Linux and macOS
diffinery setup                                     # sign in through your browser, set up git and gh
```

On Windows, in PowerShell: `powershell -c "irm https://diffinery.com/install.ps1 | iex"`. The CLI runs on Node.js 22 or later; the script installs one for it when yours is older or missing. `diffinery upgrade` updates it. See [Install and sign in to the CLI](https://diffinery.com/docs/accounts/cli-sign-in).

## Configuration

| Setting | Where | Notes |
| --- | --- | --- |
| Server URL | `DIFFINERY_URL`, else `url` in the config file, else `https://diffinery.com` | Set this for your own Diffinery instance. |
| Token | `DIFFINERY_TOKEN`, else `token` in the config file | `diffinery login` signs in through the browser and stores the CLI's token in the config file. |
| Config file | `~/.config/diffinery/config.json` (`$XDG_CONFIG_HOME/diffinery/config.json` when set) | Written by `diffinery login`. |

Commands that work on a repository take `-R OWNER/NAME`. Without it, the CLI uses the `origin` remote of the git repository you are in, when that remote points at the configured server.

Most read commands take `--json` to print the raw API response, for scripts and agents.

## Exit codes

| Code | Meaning |
| --- | --- |
| `0` | Success. |
| `1` | The command failed (an API error, a failed check, a failed run when waiting). |
| `2` | Usage error: unknown command, bad option or missing argument. Help is printed to stderr. |

## Commands

| Command | Summary |
| --- | --- |
| [`agent`](#diffinery-agent) | Manage agent accounts |
| [`api`](#diffinery-api) | Make an authenticated API request and print the response |
| [`auth`](#diffinery-auth) | Git and GitHub CLI integration |
| [`invite`](#diffinery-invite) | Invite someone by email (to an organization, or to the site as an admin) |
| [`issue`](#diffinery-issue) | Work with issues |
| [`login`](#diffinery-login) | Sign in through your browser (or with a token) |
| [`logout`](#diffinery-logout) | Sign out: forget the saved token, and revoke it if a browser sign-in created it |
| [`mcp-config`](#diffinery-mcp-config) | Print an MCP server config snippet for Claude Code and other MCP clients |
| [`migrate`](#diffinery-migrate) | Import repositories from other forges |
| [`pr`](#diffinery-pr) | Work with pull requests |
| [`repo`](#diffinery-repo) | Create, list, view and clone repositories |
| [`run`](#diffinery-run) | Inspect and control workflow runs |
| [`runner`](#diffinery-runner) | Run self-hosted workflow jobs on this machine |
| [`secret`](#diffinery-secret) | Manage Actions secrets |
| [`setup`](#diffinery-setup) | Set up this computer in one go: sign in, then git and gh |
| [`token`](#diffinery-token) | Manage personal access tokens |
| [`upgrade`](#diffinery-upgrade) | Update the CLI to the server's latest build |
| [`variable`](#diffinery-variable) | Manage Actions variables |
| [`whoami`](#diffinery-whoami) | Show the account the current token acts as |
| [`workflow`](#diffinery-workflow) | Run and validate workflows |

### diffinery agent

Manage agent accounts.

#### diffinery agent create

Create an agent account and print its token once.

```text
diffinery agent create <login> [options]
```

Creating an agent mints its first token, which tokens can't do: on diffinery.com create agents in the web UI (Settings → Agents); the command works against a local development server.

| Option | Description |
| --- | --- |
| `-o, --org ORG` | Owned by this organization instead of you |
| `-n, --name NAME` | Display name |
| `-s, --scope SCOPE` | Token scope: read, write (default) or admin Repeatable. |
| `-e, --expires-days DAYS` | Token lifetime in days (default 90) |
| `--json` | Print raw JSON |

#### diffinery agent disable

Disable an agent (its tokens stop working).

```text
diffinery agent disable <login>
```

#### diffinery agent list

List agents you or your organizations own.

```text
diffinery agent list [options]
```

| Option | Description |
| --- | --- |
| `--json` | Print raw JSON |

### diffinery auth

Git and GitHub CLI integration.

#### diffinery auth git-credential

Git credential helper (used by 'auth setup-git').

```text
diffinery auth git-credential <get|store|erase>
```

#### diffinery auth setup-gh

Sign the GitHub CLI (gh) in to Diffinery with your token.

```text
diffinery auth setup-gh
```

Runs: gh auth login --hostname <host> --with-token --git-protocol https, with the token
from the config file or DIFFINERY_TOKEN on its standard input. gh then treats the Diffinery host
like GitHub Enterprise Server: gh pr create, view, checks, status, merge and the rest work in
clones of Diffinery repositories, and so does the pull request badge of Claude Code, which
asks gh for its token.

#### diffinery auth setup-git

Make git use your Diffinery token for HTTPS remotes.

```text
diffinery auth setup-git
```

Runs: git config --global credential.<url>.helper "!diffinery auth git-credential"
(after resetting other helpers for that URL), so clone/fetch/push to the Diffinery host
authenticate with the token from the config file or DIFFINERY_TOKEN.

### diffinery issue

Work with issues.

#### diffinery issue close

Close an issue.

```text
diffinery issue close <number> [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-r, --reason REASON` | completed (default) or not_planned |
| `-c, --comment TEXT` | Leave a comment too |
| `--json` | Print raw JSON |

#### diffinery issue comment

Comment on an issue.

```text
diffinery issue comment <number> [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-b, --body TEXT` | Body text (Markdown) |
| `--body-file FILE` | Read the body from a file ('-' for stdin) |
| `--json` | Print raw JSON |

#### diffinery issue create

Open an issue.

```text
diffinery issue create [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-t, --title TEXT` | Title (required) |
| `-b, --body TEXT` | Body text (Markdown) |
| `--body-file FILE` | Read the body from a file ('-' for stdin) |
| `-l, --label NAME` | Add a label Repeatable. |
| `-a, --assignee LOGIN` | Assign a login Repeatable. |
| `--json` | Print raw JSON |

#### diffinery issue list

List issues.

```text
diffinery issue list [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-s, --state STATE` | open, closed or all (default: open) |
| `-l, --label NAME` | Only issues with this label |
| `-A, --author LOGIN` | Only issues opened by this login |
| `-S, --search QUERY` | Search text |
| `-L, --limit N` | Maximum number to show (default 30) |
| `--json` | Print raw JSON |

#### diffinery issue reopen

Reopen an issue.

```text
diffinery issue reopen <number> [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-c, --comment TEXT` | Leave a comment too |
| `--json` | Print raw JSON |

#### diffinery issue view

Show an issue and its comments.

```text
diffinery issue view <number> [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `--json` | Print raw JSON |

### diffinery migrate

Import repositories from other forges.

#### diffinery migrate github

Import a GitHub repository (git data, issues, pull requests, releases and more).

```text
diffinery migrate github <GH-OWNER/GH-REPO> [options]
```

Runs a full server-side import: git data (keeping issue and pull-request numbers), labels,
milestones, issues and pull requests with comments and reviews, branch protection, Actions
variables, release assets and deployment environments. The command follows progress until the
import finishes. Secret values are never read from GitHub; their names are listed to set by hand.

With --local, runs the old client-side import instead (mirror push plus a best-effort recreation
of issues and open pull requests); --issues then also copies labels, issues and comments.

GitHub access uses GH_TOKEN or GITHUB_TOKEN (needed for private repositories; GITHUB_API_URL
selects a GitHub Enterprise API).

| Option | Description |
| --- | --- |
| `-t, --to OWNER/NAME` | Diffinery repository to create (default: <you>/<gh-repo>) |
| `-p, --private` | Create the repository as private regardless of GitHub's visibility |
| `-l, --local` | Use the old client-side import (no server importer) |
| `-i, --issues` | With --local: also import labels, issues, comments and open pull requests |
| `--json` | Print raw JSON |

#### diffinery migrate github-org

Import many repositories from a GitHub organization or user.

```text
diffinery migrate github-org <GH-ORG-OR-USER> [options]
```

Starts a server-side bulk import of every repository in a GitHub organization or user account
(or just the ones named with --repos), into a Diffinery organization or user. Each repository is
imported in full, the same as "migrate github". The command follows progress until every
repository has finished.

GitHub access uses GH_TOKEN or GITHUB_TOKEN; GITHUB_API_URL selects a GitHub Enterprise API.

| Option | Description |
| --- | --- |
| `-t, --to OWNER` | Diffinery owner to import into (default: you) |
| `--repos A,B,C` | Comma-separated repository names to import (default: all) |
| `-p, --private` | Create every repository as private |
| `--exclude-forks` | Skip forks |
| `--exclude-archived` | Skip archived repositories |
| `-c, --concurrency N` | Repositories to import at once, 1–8 (default 3) |
| `--json` | Print raw JSON |

### diffinery pr

Work with pull requests.

#### diffinery pr checks

Show check status for a pull request.

```text
diffinery pr checks [<number>] [options]
```

Without a number, shows the open pull request for the current branch. With --watch, polls until no check is pending (waiting up to 2 minutes for the first check to appear, as right after a push), printing the checks whenever they change (on a terminal; otherwise once at the end).

Exit status: 0 when all checks passed, 1 when any failed, 8 when some are still pending (never with --watch).

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `--watch` | Wait until no check is pending |
| `-i, --interval SECONDS` | Seconds between polls with --watch (default 10) |
| `--json` | Print raw JSON |

#### diffinery pr comment

Comment on a pull request.

```text
diffinery pr comment [<number>] [options]
```

Without a number, comments on the open pull request for the current branch.

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-b, --body TEXT` | Body text (Markdown) |
| `--body-file FILE` | Read the body from a file ('-' for stdin) |
| `--json` | Print raw JSON |

#### diffinery pr create

Open a pull request.

```text
diffinery pr create [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-t, --title TEXT` | Title (required) |
| `-b, --body TEXT` | Body text (Markdown) |
| `--body-file FILE` | Read the body from a file ('-' for stdin) |
| `-H, --head BRANCH` | Branch with your changes (default: current branch) |
| `-B, --base BRANCH` | Branch to merge into (default: the repository's default branch) |
| `-d, --draft` | Open as a draft |
| `--intent TEXT` | What this change is for, for reviewers (agents should always set it) |
| `-r, --reviewer LOGIN` | Request a review from this login Repeatable. |
| `--auto` | Turn on auto-merge as it opens: it merges once the base branch's required checks pass and every rule is met |
| `--no-auto` | Keep auto-merge off, even if your setting turns it on for pull requests you open |
| `--json` | Print raw JSON |

#### diffinery pr diff

Show a pull request's changes as a unified diff.

```text
diffinery pr diff [<number>] [options]
```

Without a number, shows the open pull request for the current branch.

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `--name-only` | Only list changed file names |

#### diffinery pr list

List pull requests.

```text
diffinery pr list [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-s, --state STATE` | open, closed, merged or all (default: open) |
| `-L, --limit N` | Maximum number to show (default 30) |
| `-A, --author LOGIN` | Only pull requests opened by this login |
| `-H, --head BRANCH` | Only pull requests from this branch |
| `--json` | Print raw JSON |

#### diffinery pr merge

Merge a pull request.

```text
diffinery pr merge [<number>] [options]
```

Without a number, merges the open pull request for the current branch.

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-m, --merge` | Create a merge commit (default) |
| `-s, --squash` | Squash into one commit |
| `-r, --rebase` | Rebase the commits onto the base branch |
| `-d, --delete-branch` | Delete the head branch after merging |
| `-t, --subject TEXT` | Commit title |
| `-b, --body TEXT` | Body text (Markdown) |
| `--body-file FILE` | Read the body from a file ('-' for stdin) |
| `--match-head-commit SHA` | Only merge if the head is still at this SHA |
| `--admin` | Merge now, bypassing unmet branch rules and any merge queue (repository admins; audited) |
| `--auto` | Turn on auto-merge: merge (or join the merge queue) once every requirement is met |
| `--disable-auto` | Turn off auto-merge (and take the pull request out of the merge queue if it is in it) |
| `--json` | Print raw JSON |

#### diffinery pr ready

Mark a draft pull request ready for review.

```text
diffinery pr ready [<number>] [options]
```

Without a number, uses the open pull request for the current branch.

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `--undo` | Convert the pull request back to a draft |
| `--json` | Print raw JSON |

#### diffinery pr review

Approve, request changes or comment on a pull request.

```text
diffinery pr review [<number>] [options]
```

Without a number, reviews the open pull request for the current branch.

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-a, --approve` | Approve |
| `-r, --request-changes` | Request changes |
| `-c, --comment` | Comment without approving |
| `-b, --body TEXT` | Body text (Markdown) |
| `--body-file FILE` | Read the body from a file ('-' for stdin) |
| `--json` | Print raw JSON |

#### diffinery pr view

Show a pull request.

```text
diffinery pr view [<number>] [options]
```

Without a number, shows the open pull request for the current branch.

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-c, --comments` | Include the conversation |
| `--json` | Print raw JSON |

### diffinery repo

Create, list, view and clone repositories.

#### diffinery repo clone

Clone a repository.

```text
diffinery repo clone <OWNER/NAME> [directory]
```

The token is passed to this one git command as an HTTP header and is never written to .git/config.
Run 'diffinery auth setup-git' so later fetches and pushes authenticate too.

#### diffinery repo create

Create a repository.

```text
diffinery repo create <name> [options]
```

| Option | Description |
| --- | --- |
| `--org ORG` | Create it in this organization |
| `--private` | Only collaborators can see it (default) |
| `--public` | Anyone can see it |
| `-d, --description TEXT` | Description |
| `--default-branch BRANCH` | Default branch name |
| `--json` | Print raw JSON |

#### diffinery repo list

List repositories you can see.

```text
diffinery repo list [options]
```

| Option | Description |
| --- | --- |
| `--owner OWNER` | Only repositories owned by this user or organization |
| `--json` | Print raw JSON |

#### diffinery repo view

Show a repository.

```text
diffinery repo view [OWNER/NAME] [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `--json` | Print raw JSON |

### diffinery run

Inspect and control workflow runs.

#### diffinery run cancel

Cancel a queued or running run.

```text
diffinery run cancel <run-id> [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |

#### diffinery run list

List workflow runs.

```text
diffinery run list [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-b, --branch BRANCH` | Only runs for this branch |
| `-w, --workflow FILE` | Only runs of this workflow (file name or path) |
| `-s, --status STATUS` | Only runs with this status (queued, in_progress, completed, ...) |
| `-e, --event EVENT` | Only runs triggered by this event |
| `-c, --commit SHA` | Only runs for this commit SHA |
| `-L, --limit N` | Maximum number to show (default 20) |
| `--json` | Print raw JSON |

#### diffinery run logs

Print a job's log.

```text
diffinery run logs <job-id> [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `--json` | Print raw JSON |

#### diffinery run rerun

Re-run a workflow run.

```text
diffinery run rerun [run-id] [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `--failed` | Only re-run the failed jobs and the jobs that depend on them |
| `-j, --job JOB-ID` | Re-run this job and the jobs that depend on it (no run id needed) |
| `--json` | Print raw JSON |

#### diffinery run view

Show a run and its jobs.

```text
diffinery run view <run-id> [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `--json` | Print raw JSON |

#### diffinery run watch

Follow a run until it completes.

```text
diffinery run watch <run-id> [options]
```

Polls every 3 seconds and prints job status changes. Exits non-zero unless the run succeeds.

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-i, --interval SECONDS` | Seconds between polls (default 3) |

### diffinery secret

Manage Actions secrets.

#### diffinery secret delete

Delete an Actions secret.

```text
diffinery secret delete <NAME> [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-o, --org ORG` | Delete an organization secret instead |

#### diffinery secret list

List Actions secret names.

```text
diffinery secret list [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-o, --org ORG` | List organization secrets instead |
| `--json` | Print raw JSON |

#### diffinery secret set

Create or update an Actions secret.

```text
diffinery secret set <NAME> [options]
```

The value comes from --body, from stdin when piped, or a hidden prompt.
Repository level by default; --org sets an organization secret. An organization secret
reaches every repository unless --visibility (or --repos, which implies selected) says otherwise.

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-b, --body VALUE` | Secret value |
| `-o, --org ORG` | Set an organization secret instead |
| `--visibility all|private|selected` | Organization secrets: which repositories get it (all, private or selected) |
| `--repos a,b` | Organization secrets: the repositories that get it, comma separated |

### diffinery token

Manage personal access tokens.

#### diffinery token create

Create a personal access token (printed once).

```text
diffinery token create [options]
```

Tokens can't create tokens, so on diffinery.com this needs the web UI (Settings → Access tokens); the command works against a local development server.

| Option | Description |
| --- | --- |
| `-n, --name NAME` | Token name (required) |
| `-s, --scope SCOPE` | read, write (default) or admin Repeatable. |
| `-e, --expires-days DAYS` | Days until it expires (1-366, default 90) |
| `-R, --repo OWNER/NAME` | Restrict the token to this repository Repeatable. |
| `--json` | Print raw JSON |

#### diffinery token list

List your tokens.

```text
diffinery token list [options]
```

| Option | Description |
| --- | --- |
| `--json` | Print raw JSON |

#### diffinery token revoke

Revoke a token.

```text
diffinery token revoke <id>
```

### diffinery variable

Manage Actions variables.

#### diffinery variable list

List Actions variables.

```text
diffinery variable list [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `--json` | Print raw JSON |

#### diffinery variable set

Create or update an Actions variable.

```text
diffinery variable set <NAME> [options]
```

The value comes from --body, or from stdin when piped.

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-b, --body VALUE` | Variable value |

### diffinery workflow

Run and validate workflows.

#### diffinery workflow list

List the repository's workflows.

```text
diffinery workflow list [options]
```

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `--json` | Print raw JSON |

#### diffinery workflow run

Start a workflow_dispatch run.

```text
diffinery workflow run <workflow-file> [options]
```

The workflow is matched by path (.github/workflows/deploy.yml) or file name (deploy.yml).

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository (default: inferred from the git origin remote) |
| `-r, --ref REF` | Branch or tag to run on (default: the default branch) |
| `-f, --field KEY=VALUE` | Input value Repeatable. |
| `--json` | Print raw JSON |

#### diffinery workflow validate

Check workflow files for errors.

```text
diffinery workflow validate [files or directories...] [options]
```

Default: every .yml/.yaml file in .github/workflows and .diffinery/workflows of the
current repository. Uses the same parser as the server. Exits 1 when any file has errors.

| Option | Description |
| --- | --- |
| `--json` | Print raw JSON |

### diffinery api

Make an authenticated API request and print the response.

```text
diffinery api <METHOD> <PATH> [options]
```

PATH is relative to /api/v3 (e.g. /user, /repos/OWNER/NAME/pulls) unless it starts with /api/.
--input sends a JSON body from a file, or from stdin with '-'.

| Option | Description |
| --- | --- |
| `-i, --input FILE` | Request body file, or '-' for stdin |
| `-f, --field KEY=VALUE` | Add a string field to the JSON body (or query for GET) Repeatable. |

### diffinery invite

Invite someone by email (to an organization, or to the site as an admin).

```text
diffinery invite <email> [options]
```

| Option | Description |
| --- | --- |
| `-o, --org ORG` | Organization to join (omit for a site invite; site admins only) |
| `-r, --role ROLE` | member (default), admin or owner |
| `--json` | Print raw JSON |

### diffinery login

Sign in through your browser (or with a token).

```text
diffinery login [options]
```

Opens your browser on the server's authorize page; approve the sign-in there and the CLI
gets its own token, valid for 90 days and listed under Settings → Access tokens.

On a machine without a browser (over SSH, in a container), --device prints a short code to
enter at <server>/login/device from any browser; the CLI picks this by itself when it sees no
display. For scripts and CI, pass a token with --token, or pipe one in with --with-token
(piping into a plain `diffinery login` still works). The config file is written with mode 0600.

| Option | Description |
| --- | --- |
| `--url URL` | Server URL (default: DIFFINERY_URL, the saved URL, or https://diffinery.com) |
| `--scope SCOPE` | Access to ask for: read, write (default) or admin. You can change it on the authorize page |
| `--web` | Sign in through the browser on this computer (the default in a terminal) |
| `--device` | Sign in with a code you enter in a browser on any device |
| `--token TOKEN` | Use this token (dfy_...) instead of signing in through the browser |
| `--with-token` | Read a token from stdin |

### diffinery logout

Sign out: forget the saved token, and revoke it if a browser sign-in created it.

```text
diffinery logout
```

### diffinery mcp-config

Print an MCP server config snippet for Claude Code and other MCP clients.

```text
diffinery mcp-config [options]
```

By default the token is written as ${DIFFINERY_TOKEN} (expanded by clients such as
Claude Code from the environment). Pass --show-token to embed the saved token instead.

| Option | Description |
| --- | --- |
| `--show-token` | Embed the actual token in the snippet |

### diffinery runner

Run self-hosted workflow jobs on this machine.

```text
diffinery runner [options]
```

Polls the given repositories for jobs with 'runs-on: [self-hosted, ...]' whose labels this
runner offers, and runs each with the Diffinery runner agent. Jobs run directly on this machine
with your user's permissions.

The runner registers with each repository and claims jobs with its own token, which can't do
anything else. Register it with a registration token from a repository admin
(POST /repos/OWNER/NAME/actions/runners/registration-token, valid for an hour):

  diffinery runner -R OWNER/NAME --registration-token drg_... --labels linux

so the machine never holds a personal token, which the jobs it runs could read. The runner's
credentials are saved under ~/.config/diffinery/runners and used on the next start. Signed in
as a repository admin instead, the runner registers itself with your token.

--ephemeral registers a runner for one job: its token stops working once it takes the job, and
the runner exits when the job finishes.

The runner needs the Diffinery runner agent (a single Node.js file). Build it from the
Diffinery repository with:

  pnpm --filter @diffinery/runner build      # produces containers/runner/dist/agent.mjs

then pass --agent /path/to/agent.mjs or set DIFFINERY_RUNNER_AGENT.

| Option | Description |
| --- | --- |
| `-R, --repo OWNER/NAME` | Repository to take jobs from (default: the git origin) Repeatable. |
| `-l, --labels a,b` | Extra labels this runner offers, comma separated ('self-hosted' is implied) |
| `-n, --name NAME` | Runner name (default: host name) |
| `--once` | Run at most one job, then exit with its exit code |
| `-a, --agent PATH` | Path to the runner agent (agent.mjs); default DIFFINERY_RUNNER_AGENT |
| `-w, --work-dir DIR` | Working directory for jobs (default ~/.cache/diffinery/runner/<name>) |
| `--interval SECONDS` | Seconds between polls when idle (default 5) |
| `-q, --quiet` | Do not echo step output locally (logs still go to the server) |
| `--registration-token TOKEN` | Register this runner with a repository admin's registration token (one repository) |
| `--ephemeral` | Register for a single job, then exit when it finishes |

### diffinery setup

Set up this computer in one go: sign in, then git and gh.

```text
diffinery setup [options]
```

Signs in through your browser (or with a code, on a machine without one) unless the CLI is
signed in already, then runs `diffinery auth setup-git` so git clone, fetch and push use the
sign-in, and `diffinery auth setup-gh` when the GitHub CLI (gh) is installed. Where Claude Code is
installed, it also adds Claude Code's Diffinery plugins (diffinery and diffinery-ci): they're saved in
~/.claude/diffinery-plugins and named in ~/.claude/settings.json, so every new Claude Code session loads
them, with their Diffinery URL setting pointed at this server. Skip that with --no-claude-plugins (or
DIFFINERY_NO_CLAUDE_PLUGINS=1). For a server other than diffinery.com (--url, a self-hosted Diffinery), it
also points Codex's diffinery MCP server there when Codex is installed (codex mcp add; skip with
DIFFINERY_NO_CODEX=1). Last, on a terminal, it asks
whether to turn on auto-merge for the pull requests you open (--auto-merge says yes without asking,
--no-auto-merge skips the question). Safe to run again; it brings the plugins up to date.

With --repo OWNER/NAME it sets up an agent environment instead (a Claude Code cloud environment,
Codex, a CI runner), with no browser and no prompt: git and gh use the token in DIFFINERY_TOKEN
(and GH_ENTERPRISE_TOKEN with GH_HOST for gh) straight from the environment, so no token is written
to disk; the repository is cloned unless it's there already; then a self-test prints one line per
check, saying what to change when one fails, and reports the result to the repository's Agent setup
page. Exits 1 when a check fails. This is what <server>/OWNER/NAME/agent-setup.sh runs.

| Option | Description |
| --- | --- |
| `--url URL` | Server URL (default: DIFFINERY_URL, the saved URL, or https://diffinery.com) |
| `--scope SCOPE` | Access to ask for: read, write (default) or admin. You can change it on the authorize page |
| `--web` | Sign in through the browser on this computer (the default in a terminal) |
| `--device` | Sign in with a code you enter in a browser on any device |
| `--repo OWNER/NAME` | Set up an agent environment for this repository instead, with the token in DIFFINERY_TOKEN (what <server>/OWNER/NAME/agent-setup.sh runs) |
| `--no-clone` | With --repo: don't clone the repository (also DIFFINERY_NO_CLONE=1) |
| `--clone-dir DIR` | With --repo: where the clone goes (default: DIFFINERY_CLONE_DIR, /home/user in a Claude Code cloud environment, else the current directory) |
| `--no-report` | With --repo: don't report the result to the repository's Agent setup page |
| `--no-claude-plugins` | Don't add Claude Code's Diffinery plugins (also DIFFINERY_NO_CLAUDE_PLUGINS=1) |
| `--auto-merge` | Turn on auto-merge for pull requests you open, without asking (it still waits for each branch's required checks and approvals) |
| `--no-auto-merge` | Don't ask about auto-merge |

### diffinery upgrade

Update the CLI to the server's latest build.

```text
diffinery upgrade
```

Downloads <server>/-/cli/diffinery.mjs and replaces the file this CLI runs from, when it changed.
The install script (curl -fsSL https://diffinery.com/install | bash) does the same and sets up PATH.

### diffinery whoami

Show the account the current token acts as.

```text
diffinery whoami [options]
```

| Option | Description |
| --- | --- |
| `--json` | Print raw JSON |
