diff --git a/README.md b/README.md
index 149c732..415547d 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,16 @@
# github-issue-ops
+
+
+[](https://fulll.github.io/github-issue-ops/)
+[](https://github.com/fulll/github-issue-ops/releases/latest)
[](https://github.com/fulll/github-issue-ops/actions/workflows/ci.yaml)
[](LICENSE.md)
CLI to industrialize GitHub issue campaigns (tech debt, security, migration, compliance) from code search results — create EPICs, refresh checklists, dispatch sub-issues per repo.
+→ **Full documentation: https://fulll.github.io/github-issue-ops/**
+
## What it does
`github-issue-ops` takes the output of [`github-code-search`](https://github.com/fulll/github-code-search) (or any markdown/JSON input) and turns it into a structured GitHub issue campaign:
@@ -44,10 +50,6 @@ github-issue-ops issue dispatch --epic myorg/tech-debt#42 --mode apply
github-issue-ops upgrade
```
-## Documentation
-
-Full documentation:
-
## License
[MIT](LICENSE.md) — Copyright (c) 2026 Fulll
diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts
index 969919a..8c9a737 100644
--- a/docs/.vitepress/config.mts
+++ b/docs/.vitepress/config.mts
@@ -18,10 +18,10 @@ export default defineConfig({
],
[
"link",
- { rel: "apple-touch-icon", sizes: "114x114", href: "/github-issue-ops/apple-touch-icon.png" },
+ { rel: "apple-touch-icon", sizes: "180x180", href: "/github-issue-ops/apple-touch-icon.png" },
],
- // fulll dark blue as browser theme colour
- ["meta", { name: "theme-color", content: "#0000CC" }],
+ // brand blue as browser theme colour
+ ["meta", { name: "theme-color", content: "#0033DD" }],
],
themeConfig: {
@@ -29,7 +29,6 @@ export default defineConfig({
nav: [
{ text: "Getting Started", link: "/getting-started/", activeMatch: "^/getting-started/" },
- { text: "Guide", link: "/guide/how-it-works", activeMatch: "^/guide/" },
{ text: "Reference", link: "/reference/create", activeMatch: "^/reference/" },
{ text: "Architecture", link: "/architecture/overview", activeMatch: "^/architecture/" },
{ text: "What's New", link: "/whats-new/", activeMatch: "^/whats-new/" },
@@ -40,17 +39,12 @@ export default defineConfig({
{
text: "Getting Started",
items: [
- { text: "Installation", link: "/getting-started/#installation" },
- { text: "Quickstart", link: "/getting-started/#quickstart" },
+ { text: "Prerequisites", link: "/getting-started/" },
+ { text: "Installation", link: "/getting-started/installation" },
+ { text: "Quickstart", link: "/getting-started/quickstart" },
],
},
],
- "/guide/": [
- {
- text: "Guide",
- items: [{ text: "How it works", link: "/guide/how-it-works" }],
- },
- ],
"/reference/": [
{
text: "CLI Reference",
diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css
index 067ddc5..afc84f1 100644
--- a/docs/.vitepress/theme/custom.css
+++ b/docs/.vitepress/theme/custom.css
@@ -198,6 +198,287 @@ body::before {
);
}
+/* ── Home page sections (after the fold) ────────────────────────────────── */
+
+/* Shared section wrapper */
+.VPHome .home-section {
+ max-width: 1152px;
+ margin: 0 auto;
+ padding: 56px 24px;
+}
+
+.VPHome .home-section h2 {
+ font-size: 1.75rem;
+ font-weight: 700;
+ letter-spacing: -0.02em;
+ margin-bottom: 2rem;
+ color: var(--vp-c-text-1);
+ border-top: none;
+ padding-top: 0;
+}
+
+/* ── Use Cases section ───────────────────────────────────────────────────── */
+.use-cases-section {
+ border-top: 1px solid var(--vp-c-divider);
+}
+
+.use-cases-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
+ gap: 16px;
+ margin-bottom: 1.5rem;
+}
+
+.use-case-card {
+ display: flex;
+ gap: 16px;
+ align-items: flex-start;
+ padding: 20px;
+ border-radius: 12px;
+ border: 1px solid rgba(0, 0, 204, 0.12);
+ background: linear-gradient(145deg, var(--vp-c-bg-soft), rgba(0, 0, 204, 0.03));
+ transition:
+ border-color 0.2s,
+ box-shadow 0.2s,
+ transform 0.2s;
+}
+
+.use-case-card:hover {
+ border-color: rgba(0, 0, 204, 0.3);
+ box-shadow: 0 4px 20px rgba(0, 0, 204, 0.08);
+ transform: translateY(-2px);
+}
+
+.dark .use-case-card {
+ border-color: rgba(102, 153, 255, 0.1);
+ background: linear-gradient(145deg, var(--vp-c-bg-soft), rgba(0, 0, 204, 0.06));
+}
+
+.dark .use-case-card:hover {
+ border-color: rgba(102, 153, 255, 0.28);
+ box-shadow: 0 4px 24px rgba(102, 153, 255, 0.12);
+}
+
+.uc-icon {
+ line-height: 1;
+ flex-shrink: 0;
+ margin-top: 2px;
+ display: flex;
+ align-items: flex-start;
+}
+
+.uc-icon svg {
+ width: 24px;
+ height: 24px;
+ color: var(--vp-c-brand-1);
+ stroke: currentColor;
+ flex-shrink: 0;
+}
+
+.uc-body strong {
+ display: block;
+ font-size: 0.95rem;
+ font-weight: 600;
+ color: var(--vp-c-text-1);
+ margin-bottom: 4px;
+}
+
+.uc-body p {
+ margin: 0;
+ font-size: 0.875rem;
+ line-height: 1.6;
+ color: var(--vp-c-text-2);
+}
+
+/* ── Agentic AI section ──────────────────────────────────────────────────── */
+@keyframes shimmer-bg {
+ 0% {
+ background-position: 0% 50%;
+ }
+ 50% {
+ background-position: 100% 50%;
+ }
+ 100% {
+ background-position: 0% 50%;
+ }
+}
+
+.agentic-section {
+ position: relative;
+ border-radius: 20px;
+ padding: 56px 48px !important;
+ margin: 0 24px 48px !important;
+ overflow: hidden;
+ background: linear-gradient(
+ 135deg,
+ rgba(0, 0, 204, 0.06) 0%,
+ rgba(68, 136, 255, 0.08) 40%,
+ rgba(102, 204, 255, 0.06) 70%,
+ rgba(255, 204, 51, 0.05) 100%
+ );
+ border: 1px solid rgba(0, 0, 204, 0.14);
+}
+
+.dark .agentic-section {
+ background: linear-gradient(
+ 135deg,
+ rgba(0, 0, 204, 0.12) 0%,
+ rgba(68, 136, 255, 0.14) 40%,
+ rgba(102, 204, 255, 0.1) 70%,
+ rgba(255, 204, 51, 0.07) 100%
+ );
+ border-color: rgba(102, 153, 255, 0.18);
+}
+
+/* Animated glow blob behind the section */
+.agentic-section::before {
+ content: "";
+ position: absolute;
+ inset: -40%;
+ background: radial-gradient(
+ ellipse 60% 60% at 50% 50%,
+ rgba(0, 0, 204, 0.07) 0%,
+ transparent 70%
+ );
+ background-size: 200% 200%;
+ animation: shimmer-bg 8s ease infinite;
+ pointer-events: none;
+ z-index: 0;
+}
+
+.agentic-section > * {
+ position: relative;
+ z-index: 1;
+}
+
+.agentic-lead {
+ font-size: 1.125rem;
+ line-height: 1.75;
+ color: var(--vp-c-text-1);
+ margin-bottom: 1rem;
+}
+
+.agentic-problem {
+ display: inline-block;
+ font-size: 1rem;
+ color: var(--vp-c-text-1);
+ background: rgba(0, 0, 204, 0.07);
+ border-left: 3px solid var(--vp-c-brand-1);
+ border-radius: 0 8px 8px 0;
+ padding: 10px 16px;
+ margin-bottom: 1.25rem;
+}
+
+.dark .agentic-problem {
+ background: rgba(102, 153, 255, 0.1);
+}
+
+.agentic-pillars {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
+ gap: 12px;
+ margin: 1.5rem 0;
+}
+
+.pillar {
+ display: grid;
+ grid-template-areas:
+ "icon label"
+ "icon desc";
+ grid-template-columns: 2rem 1fr;
+ column-gap: 10px;
+ row-gap: 2px;
+ align-items: start;
+ padding: 14px 16px;
+ border-radius: 10px;
+ background: rgba(255, 255, 255, 0.5);
+ border: 1px solid rgba(0, 0, 204, 0.1);
+ backdrop-filter: blur(4px);
+ transition:
+ transform 0.2s,
+ box-shadow 0.2s;
+}
+
+.pillar:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 16px rgba(0, 0, 204, 0.1);
+}
+
+.dark .pillar {
+ background: rgba(0, 0, 0, 0.25);
+ border-color: rgba(102, 153, 255, 0.12);
+}
+
+.pillar-icon {
+ grid-area: icon;
+ display: flex;
+ align-items: flex-start;
+ padding-top: 2px;
+}
+
+.pillar-icon svg {
+ width: 20px;
+ height: 20px;
+ color: var(--vp-c-brand-1);
+ stroke: currentColor;
+ flex-shrink: 0;
+}
+
+.pillar-label {
+ grid-area: label;
+ font-size: 0.875rem;
+ color: var(--vp-c-text-1);
+}
+
+.pillar-desc {
+ grid-area: desc;
+ font-size: 0.8rem;
+ color: var(--vp-c-text-2);
+ line-height: 1.5;
+}
+
+.agentic-quote {
+ margin-top: 1.75rem;
+ padding: 20px 24px;
+ border-radius: 12px;
+ background: linear-gradient(135deg, rgba(0, 0, 204, 0.08), rgba(68, 136, 255, 0.06));
+ border: 1px solid rgba(0, 0, 204, 0.16);
+ font-size: 1rem;
+ line-height: 1.7;
+ color: var(--vp-c-text-1);
+ text-align: center;
+ font-style: italic;
+}
+
+.dark .agentic-quote {
+ background: linear-gradient(135deg, rgba(0, 0, 204, 0.15), rgba(68, 136, 255, 0.1));
+ border-color: rgba(102, 153, 255, 0.2);
+}
+
+/* ── Used in production section ─────────────────────────────────────────── */
+.production-section {
+ border-top: 1px solid var(--vp-c-divider);
+ text-align: center;
+ padding-bottom: 72px !important;
+}
+
+.production-section h2 {
+ margin-bottom: 1rem !important;
+}
+
+/* Mobile adjustments */
+@media (max-width: 768px) {
+ .agentic-section {
+ padding: 36px 24px !important;
+ margin: 0 12px 36px !important;
+ border-radius: 14px;
+ }
+
+ .use-cases-grid {
+ grid-template-columns: 1fr;
+ }
+}
+
/* ── Footer (black — fulll.fr style) ─────────────────────────────────────── */
.VPFooter {
border-top: none !important;
diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md
index a7d6c0a..60c55e5 100644
--- a/docs/getting-started/index.md
+++ b/docs/getting-started/index.md
@@ -1,90 +1,38 @@
-# Getting started
+# Prerequisites
-## Prerequisites
+The only runtime prerequisite is a GitHub personal access token. The pre-compiled binary is self-contained — you do not need Bun to run it.
-- **Bun** or a POSIX shell to run the installer (Bun is only required if you build from source).
-- A GitHub personal access token with `repo` and `read:org` scopes:
+::: tip Building from source?
+If you want to build `github-issue-ops` from source, you will additionally need [Bun](https://bun.sh/) ≥ 1.0. See the [Installation guide](/getting-started/installation#from-source).
+:::
-```bash
-export GITHUB_TOKEN=ghp_...
-```
+## GitHub token
-## Installation
+A GitHub personal access token (PAT) is required to call the GitHub API.
-```bash
-curl -fsSL https://raw.githubusercontent.com/fulll/github-issue-ops/main/install.sh | bash
-```
+### Required scopes
-Or download the pre-built binary for your platform from [GitHub Releases](https://github.com/fulll/github-issue-ops/releases), then make it executable:
+| Scope | Purpose |
+| ---------- | --------------------------------------------------- |
+| `repo` | Creating and reading issues in private repositories |
+| `read:org` | Resolving team ownership (`--team-prefix`) |
-```bash
-chmod +x github-issue-ops
-mv github-issue-ops /usr/local/bin/
-```
+::: details Classic vs fine-grained tokens
+Both token types work. Classic tokens are simpler to configure for org-wide operations. Fine-grained tokens require explicit repository access per repo, which is impractical for org-wide campaigns.
+:::
-Verify the installation:
+### Set the token
```bash
-github-issue-ops --version
+export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
```
-## Quickstart
-
-The typical workflow is three commands: **create**, **refresh**, **dispatch**.
-
-### 1. Create an EPIC issue
-
-Pipe [github-code-search](https://fulll.github.io/github-code-search/) output into `issue create`:
-
-```bash
-github-code-search "TODO" --org acme --format markdown \
- | github-issue-ops issue create \
- --repo acme/platform \
- --title "Q1 2025: Address all TODOs" \
- --label epic \
- --label tech-debt
-```
-
-This creates a single EPIC issue in `acme/platform` with:
-
-- a Markdown checklist, one entry per matched repository,
-- a summary table,
-- embedded metadata so `refresh` and `dispatch` can replay the campaign.
-
-### 2. Refresh the checklist
+Add this to your shell profile (`~/.zshrc`, `~/.bashrc`, `~/.config/fish/config.fish`, …) to make it permanent.
-Re-run the search and let `issue refresh` reconcile the diff:
+::: warning Token security
+Never commit your token to version control. Use environment variables or a secrets manager.
+:::
-```bash
-github-code-search "TODO" --org acme --format markdown \
- | github-issue-ops issue refresh \
- --issue acme/platform#42
-```
-
-New repositories are appended; repositories that no longer appear are checked off automatically.
-
-### 3. Dispatch sub-issues
-
-Preview first, then execute:
-
-```bash
-# Preview
-github-issue-ops issue dispatch \
- --epic acme/platform#42 \
- --mode plan
-
-# Execute
-github-issue-ops issue dispatch \
- --epic acme/platform#42 \
- --mode apply
-```
-
-One sub-issue is created per repository in the checklist. Assignees are resolved in order: GitHub Teams → CODEOWNERS → JSON mapping → fallback.
-
-## Keep it up to date
-
-```bash
-github-issue-ops upgrade
-```
+## Next step
-See [What's New](/whats-new/) for the full changelog.
+→ [Install github-issue-ops](/getting-started/installation)
diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md
new file mode 100644
index 0000000..621d070
--- /dev/null
+++ b/docs/getting-started/installation.md
@@ -0,0 +1,91 @@
+# Installation
+
+## Via `curl` (recommended)
+
+The install script auto-detects your OS (Linux, macOS, Windows via MINGW/MSYS/Cygwin) and architecture (x64, arm64) and downloads the right pre-compiled binary from the [latest release](https://github.com/fulll/github-issue-ops/releases/latest) to `/usr/local/bin`.
+
+::: warning Windows
+On Windows, the script requires a bash-compatible shell (Git Bash, MSYS2, or Cygwin). Native PowerShell is not supported — download the binary directly from the [releases page](https://github.com/fulll/github-issue-ops/releases/latest) instead.
+:::
+
+```bash
+curl -fsSL https://raw.githubusercontent.com/fulll/github-issue-ops/main/install.sh | bash
+```
+
+### Custom install directory or version
+
+```bash
+INSTALL_DIR=~/.local/bin VERSION=vX.Y.Z \
+ curl -fsSL https://raw.githubusercontent.com/fulll/github-issue-ops/main/install.sh | bash
+```
+
+| Variable | Default | Description |
+| ------------- | ---------------- | ----------------------------------------------- |
+| `INSTALL_DIR` | `/usr/local/bin` | Directory where the binary is installed |
+| `VERSION` | latest release | Specific version tag to install (e.g. `v1.0.0`) |
+
+## Verify the installation
+
+```bash
+github-issue-ops --version
+# → 1.0.0 (abc1234)
+```
+
+The version string includes the commit SHA — useful for bug reports.
+
+## Upgrade
+
+Once installed, you can upgrade to the latest release with a single command:
+
+```bash
+github-issue-ops upgrade
+```
+
+## macOS Gatekeeper
+
+If you download the binary directly from the releases page in a browser (Chrome, Safari…), macOS marks it with a quarantine flag and Gatekeeper will block it on first launch.
+
+Remove the quarantine attribute once after downloading:
+
+```bash
+xattr -d com.apple.quarantine ./github-issue-ops-macos-arm64
+```
+
+::: tip
+This is unnecessary when installing via the `curl` script above, or when using the `upgrade` subcommand — both handle it automatically.
+:::
+
+## From source
+
+Requires [Bun](https://bun.sh/) ≥ 1.0.
+
+```bash
+git clone https://github.com/fulll/github-issue-ops
+cd github-issue-ops
+bun install
+bun run build.ts
+# → produces dist/github-issue-ops
+```
+
+Copy the binary wherever you like:
+
+```bash
+cp dist/github-issue-ops ~/.local/bin/
+```
+
+### Cross-compilation
+
+The build script accepts any Bun executable target via `--target`:
+
+```bash
+bun run build.ts --target=bun-linux-x64
+bun run build.ts --target=bun-linux-x64-baseline
+bun run build.ts --target=bun-linux-arm64
+bun run build.ts --target=bun-darwin-x64
+bun run build.ts --target=bun-darwin-arm64
+bun run build.ts --target=bun-windows-x64
+```
+
+## Next step
+
+→ [Run your first campaign](/getting-started/quickstart)
diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md
new file mode 100644
index 0000000..d413bd9
--- /dev/null
+++ b/docs/getting-started/quickstart.md
@@ -0,0 +1,70 @@
+# Quickstart
+
+The typical workflow is three commands: **create**, **refresh**, **dispatch**.
+
+## 1. Create an EPIC issue
+
+Pipe [github-code-search](https://fulll.github.io/github-code-search/) output into `issue create`:
+
+```bash
+github-code-search "TODO" --org acme --format markdown \
+ | github-issue-ops issue create \
+ --repo acme/platform \
+ --title "Q1 2025: Address all TODOs" \
+ --label epic \
+ --label tech-debt
+```
+
+This creates a single EPIC issue in `acme/platform` with:
+
+- a **Markdown checklist** — one entry per matched repository,
+- a **summary block** with progress stats,
+- an embedded **metadata comment** so `refresh` and `dispatch` can replay the campaign automatically.
+
+## 2. Refresh the checklist
+
+Re-run the search and let `issue refresh` reconcile the diff:
+
+```bash
+github-code-search "TODO" --org acme --format markdown \
+ | github-issue-ops issue refresh \
+ --issue acme/platform#42
+```
+
+New repositories are **appended** as unchecked items. Repositories that no longer appear are **checked off** automatically.
+
+## 3. Dispatch sub-issues
+
+Preview first, then execute:
+
+```bash
+# Preview what would happen
+github-issue-ops issue dispatch \
+ --epic acme/platform#42 \
+ --mode plan
+
+# Create the sub-issues
+github-issue-ops issue dispatch \
+ --epic acme/platform#42 \
+ --mode apply
+```
+
+One sub-issue is created per repository in the checklist. Assignees are resolved in order:
+
+1. GitHub Teams (`--team-prefix`)
+2. CODEOWNERS file in the repository
+3. JSON mapping in a central repo (`--central-repo`)
+4. Unassigned fallback
+
+## Keep it up to date
+
+```bash
+github-issue-ops upgrade
+```
+
+See [What's New](/whats-new/) for the full changelog.
+
+## Next steps
+
+- [CLI Reference](/reference/create) — all options for each subcommand
+- [Architecture](/architecture/overview) — how it works under the hood
diff --git a/docs/guide/getting-started.md b/docs/guide/getting-started.md
deleted file mode 100644
index f1fa5c8..0000000
--- a/docs/guide/getting-started.md
+++ /dev/null
@@ -1,55 +0,0 @@
-# Getting started
-
-## Installation
-
-```bash
-curl -fsSL https://raw.githubusercontent.com/fulll/github-issue-ops/main/install.sh | bash
-```
-
-Or download the latest binary from [GitHub Releases](https://github.com/fulll/github-issue-ops/releases).
-
-## Prerequisites
-
-- A GitHub personal access token with `repo` and `read:org` scopes.
-- Export it as `GITHUB_TOKEN` (or `GH_TOKEN`):
-
-```bash
-export GITHUB_TOKEN=ghp_...
-```
-
-## Quickstart
-
-### Create an EPIC issue
-
-Pipe [github-code-search](https://github.com/fulll/github-code-search) output into `issue create`:
-
-```bash
-github-code-search "TODO" --org acme --format markdown \
- | github-issue-ops issue create \
- --repo acme/platform \
- --title "Q1 2025: Address all TODOs" \
- --label epic \
- --label tech-debt
-```
-
-### Refresh the EPIC after new results
-
-```bash
-github-code-search "TODO" --org acme --format markdown \
- | github-issue-ops issue refresh \
- --issue acme/platform#42
-```
-
-### Dispatch sub-issues per repository
-
-```bash
-# Preview what would happen
-github-issue-ops issue dispatch \
- --epic acme/platform#42 \
- --mode plan
-
-# Create the issues
-github-issue-ops issue dispatch \
- --epic acme/platform#42 \
- --mode apply
-```
diff --git a/docs/guide/how-it-works.md b/docs/guide/how-it-works.md
deleted file mode 100644
index 7799b0c..0000000
--- a/docs/guide/how-it-works.md
+++ /dev/null
@@ -1,78 +0,0 @@
-# How it works
-
-`github-issue-ops` follows a three-step workflow:
-
-## 1. Create an EPIC
-
-```
-stdin (github-code-search output or JSON)
- │
- ▼
- parseResults() ← src/input/stdin.ts
- │
- ▼
- buildEpicBody() ← src/output/format.ts
- embedMetadata() ← src/core/metadata.ts
- │
- ▼
- createIssue() ← src/api/github-api.ts
- │
- ▼
- GitHub Issue (EPIC)
-```
-
-The EPIC issue body contains:
-
-- A **checklist** of all matched files — `- [ ] \`repo\` — \`path:line\` — text`
-- A **summary block** with progress stats
-- A hidden **metadata block** (HTML comment) storing config for future `refresh` / `dispatch` calls
-
-## 2. Refresh
-
-When you re-run the search with updated code:
-
-```
-stdin (updated results)
- │
- ▼
- diffChecklist() ← src/core/checklist.ts
- ┌──────────────────┐
- │ added items │ → appended unchecked
- │ removed items │ → checked-off
- │ unchanged items │ → preserved as-is
- └──────────────────┘
- │
- ▼
- updateIssue() ← src/api/github-api.ts
-```
-
-## 3. Dispatch
-
-```
-EPIC issue body
- │
- ▼
- parseChecklist() ← src/core/checklist.ts
- groupByRepo() ← src/commands/dispatch.ts
- │
- ├─ for each repo
- │ resolveOwners() ← src/core/ownership.ts
- │ findExistingIssue() ← src/core/dedup.ts
- │ createIssue() ← src/api/github-api.ts
- │ createSubIssueLink()
- │
- ▼
- One sub-issue per repo
-```
-
-## Metadata
-
-All state needed for `refresh` and `dispatch` is embedded in the EPIC body as an invisible HTML comment:
-
-```html
-
-```
-
-This makes EPICs fully self-contained — no external database or config file needed.
diff --git a/docs/index.md b/docs/index.md
index 3c85f55..7a4ffc4 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -16,50 +16,112 @@ hero:
features:
- title: Issue create
icon:
- src: /github-issue-ops/icons/epic.svg
+ src: /icons/epic.svg
details: Pipe github-code-search output to create a fully structured EPIC issue with a checklist, summary and embedded metadata.
link: /reference/create
linkText: Reference
- title: Issue refresh
icon:
- src: /github-issue-ops/icons/sync.svg
+ src: /icons/sync.svg
details: Re-run the search and refresh the checklist automatically — new repos added, removed repos checked off.
link: /reference/refresh
linkText: Reference
- title: Issue dispatch
icon:
- src: /github-issue-ops/icons/dispatch.svg
+ src: /icons/dispatch.svg
details: Split an EPIC into one sub-issue per repository with automatic assignee resolution via teams, CODEOWNERS or a JSON mapping.
link: /reference/dispatch
linkText: Reference
---
+
+
## Use cases
-| Scenario | Workflow |
-| -------------------------- | ----------------------------------------------------------------------------------------------------------------- |
-| **Tech-debt campaign** | Search for deprecated API usages → `issue create` → assign to teams → `issue dispatch` |
-| **Security patch rollout** | Search for vulnerable dependency → `issue create` → update results weekly with `issue refresh` → `issue dispatch` |
-| **Compliance enforcement** | Search for missing licence headers → `issue create` → track progress via EPIC checklist |
-| **Framework migration** | Search for legacy import patterns → `issue create` → `issue dispatch` per team |
+
+
+
+
+ Tech-debt campaign
+
Search for deprecated API usages → issue create → assign to teams → issue dispatch
+
+
+
+
+
+ Security patch rollout
+
Search for vulnerable dependency → issue create → update weekly with issue refresh → issue dispatch
+
+
+
+
+
+ Compliance enforcement
+
Search for missing licence headers → issue create → track progress via EPIC checklist
+
+
+
+
+
+ Framework migration
+
Search for legacy import patterns → issue create → issue dispatch per team
+
+
+
+
+Works with any tool that produces Markdown or JSON: [github-code-search](https://fulll.github.io/github-code-search/), custom scripts, or AI-generated reports.
-Works with any search tool that produces Markdown or JSON: [github-code-search](https://fulll.github.io/github-code-search/), custom scripts, or AI-generated reports.
+
+
+
## Why github-issue-ops in the agentic AI age?
+
AI coding agents generate code at unprecedented speed — and with it, new technical debt, security gaps, and compliance issues land across dozens of repositories simultaneously.
+
-Traditional issue triage doesn't scale: an agent can introduce a problem in 50 repos in the time it takes a human to open a single ticket.
+
+Traditional issue triage doesn't scale: an agent can introduce a problem in 50 repos in the time it takes a human to open a single ticket.
+
`github-issue-ops` closes this loop. It turns a structured search result — produced by a human, a CI check, or an AI agent itself — into a traceable GitHub issue campaign:
-- **Systematic**: every affected repository gets its own sub-issue, no repo is missed.
-- **Idempotent**: run the same command twice, the campaign is not duplicated.
-- **Refreshable**: as the agent fixes repos, `issue refresh` updates the EPIC in real time.
-- **Auditable**: metadata is embedded in the issue body; the full replay command is always one click away.
+
+
+
+ Systematic
+ Every affected repository gets its own sub-issue — no repo is missed.
+
+
+
+ Idempotent
+ Run the same command twice — the campaign is not duplicated.
+
+
+
+ Refreshable
+ As the agent fixes repos, issue refresh updates the EPIC in real time.
+
+
+
+ Auditable
+ Metadata is embedded in the issue body; the full replay command is always one click away.
+
+
+
+
+In an agentic world, github-issue-ops is the missing link between "AI found a problem at scale" and "every team knows about it, owns it, and can close it".
+
-In an agentic world, `github-issue-ops` is the missing link between "AI found a problem at scale" and "every team knows about it, owns it, and can close it".
+
+
+
## Used in production?
`github-issue-ops` is developed and used internally at [fulll](https://github.com/fulll) to drive organisation-wide refactoring and compliance campaigns across hundreds of repositories.
+
+Using it at your organisation? Share your experience in [GitHub Discussions](https://github.com/fulll/github-issue-ops/discussions).
+
+
diff --git a/docs/public/apple-touch-icon.png b/docs/public/apple-touch-icon.png
new file mode 100644
index 0000000..fc07165
Binary files /dev/null and b/docs/public/apple-touch-icon.png differ
diff --git a/docs/public/favicon-72.png b/docs/public/favicon-72.png
new file mode 100644
index 0000000..a689913
Binary files /dev/null and b/docs/public/favicon-72.png differ
diff --git a/docs/public/favicon.svg b/docs/public/favicon.svg
new file mode 100644
index 0000000..9acccfd
--- /dev/null
+++ b/docs/public/favicon.svg
@@ -0,0 +1,36 @@
+
diff --git a/docs/public/icons/clipboard-check.svg b/docs/public/icons/clipboard-check.svg
new file mode 100644
index 0000000..0a3a733
--- /dev/null
+++ b/docs/public/icons/clipboard-check.svg
@@ -0,0 +1,5 @@
+
diff --git a/docs/public/icons/eye.svg b/docs/public/icons/eye.svg
new file mode 100644
index 0000000..f579630
--- /dev/null
+++ b/docs/public/icons/eye.svg
@@ -0,0 +1,4 @@
+
diff --git a/docs/public/icons/grid.svg b/docs/public/icons/grid.svg
new file mode 100644
index 0000000..bd89dce
--- /dev/null
+++ b/docs/public/icons/grid.svg
@@ -0,0 +1,6 @@
+
diff --git a/docs/public/icons/rotate.svg b/docs/public/icons/rotate.svg
new file mode 100644
index 0000000..68c9d9b
--- /dev/null
+++ b/docs/public/icons/rotate.svg
@@ -0,0 +1,4 @@
+
diff --git a/docs/public/icons/shield.svg b/docs/public/icons/shield.svg
new file mode 100644
index 0000000..9fa708c
--- /dev/null
+++ b/docs/public/icons/shield.svg
@@ -0,0 +1,4 @@
+
diff --git a/docs/public/icons/shuffle.svg b/docs/public/icons/shuffle.svg
new file mode 100644
index 0000000..66285fc
--- /dev/null
+++ b/docs/public/icons/shuffle.svg
@@ -0,0 +1,6 @@
+
diff --git a/docs/public/icons/wrench.svg b/docs/public/icons/wrench.svg
new file mode 100644
index 0000000..be2a1be
--- /dev/null
+++ b/docs/public/icons/wrench.svg
@@ -0,0 +1,3 @@
+
diff --git a/docs/public/logo.svg b/docs/public/logo.svg
new file mode 100644
index 0000000..3b86bd1
--- /dev/null
+++ b/docs/public/logo.svg
@@ -0,0 +1,51 @@
+