From c914094e5f02ffa4aa32a6eb23d6f492231350ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20HOUZ=C3=89?= Date: Mon, 2 Mar 2026 01:35:14 +0100 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20docs=20=E2=80=94=20prerequisites/in?= =?UTF-8?q?stallation/quickstart=20pages,=20home=20redesign,=20remove=20gu?= =?UTF-8?q?ide=20(#10)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/.vitepress/config.mts | 12 +- docs/.vitepress/theme/custom.css | 264 +++++++++++++++++++++++++++ docs/getting-started/index.md | 98 +++------- docs/getting-started/installation.md | 91 +++++++++ docs/getting-started/quickstart.md | 70 +++++++ docs/guide/getting-started.md | 55 ------ docs/guide/how-it-works.md | 78 -------- docs/index.md | 94 ++++++++-- 8 files changed, 529 insertions(+), 233 deletions(-) create mode 100644 docs/getting-started/installation.md create mode 100644 docs/getting-started/quickstart.md delete mode 100644 docs/guide/getting-started.md delete mode 100644 docs/guide/how-it-works.md diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 969919a..4fa30e9 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -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..e049dd8 100644 --- a/docs/.vitepress/theme/custom.css +++ b/docs/.vitepress/theme/custom.css @@ -198,6 +198,270 @@ 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 { + font-size: 24px; + line-height: 1; + flex-shrink: 0; + margin-top: 2px; +} + +.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; + font-size: 1.25rem; + line-height: 1; + padding-top: 2px; +} + +.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..f33e0fc 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 refreshissue dispatch

+
+
+
+
📋
+
+ Compliance enforcement +

Search for missing licence headers → issue create → track progress via EPIC checklist

+
+
+
+
🔀
+
+ Framework migration +

Search for legacy import patterns → issue createissue 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). + +
From edf12074eee862d9d58e4899c1dde5a9d37d7b79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20HOUZ=C3=89?= Date: Mon, 2 Mar 2026 01:39:17 +0100 Subject: [PATCH 2/3] feat: replace home page emojis with inline SVG icons --- docs/.vitepress/theme/custom.css | 23 ++++++++++++++++++++--- docs/index.md | 16 ++++++++-------- docs/public/icons/clipboard-check.svg | 5 +++++ docs/public/icons/eye.svg | 4 ++++ docs/public/icons/grid.svg | 6 ++++++ docs/public/icons/rotate.svg | 4 ++++ docs/public/icons/shield.svg | 4 ++++ docs/public/icons/shuffle.svg | 6 ++++++ docs/public/icons/wrench.svg | 3 +++ 9 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 docs/public/icons/clipboard-check.svg create mode 100644 docs/public/icons/eye.svg create mode 100644 docs/public/icons/grid.svg create mode 100644 docs/public/icons/rotate.svg create mode 100644 docs/public/icons/shield.svg create mode 100644 docs/public/icons/shuffle.svg create mode 100644 docs/public/icons/wrench.svg diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css index e049dd8..afc84f1 100644 --- a/docs/.vitepress/theme/custom.css +++ b/docs/.vitepress/theme/custom.css @@ -260,10 +260,19 @@ body::before { } .uc-icon { - font-size: 24px; 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 { @@ -402,11 +411,19 @@ body::before { .pillar-icon { grid-area: icon; - font-size: 1.25rem; - line-height: 1; + 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; diff --git a/docs/index.md b/docs/index.md index f33e0fc..7a4ffc4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -40,28 +40,28 @@ features:
-
🔍
+
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 refreshissue dispatch

-
📋
+
Compliance enforcement

Search for missing licence headers → issue create → track progress via EPIC checklist

-
🔀
+
Framework migration

Search for legacy import patterns → issue createissue dispatch per team

@@ -89,22 +89,22 @@ Traditional issue triage doesn't scale: an agent can introduce
- + 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.
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 @@ + + + From 808a77463956dfd16c1605cf52c62ecdc5cb729a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20HOUZ=C3=89?= Date: Mon, 2 Mar 2026 01:58:23 +0100 Subject: [PATCH 3/3] feat: add terminal-style logo, favicon and apple-touch-icon --- README.md | 10 +++--- docs/.vitepress/config.mts | 6 ++-- docs/public/apple-touch-icon.png | Bin 0 -> 12826 bytes docs/public/favicon-72.png | Bin 0 -> 4503 bytes docs/public/favicon.svg | 36 ++++++++++++++++++++++ docs/public/logo.svg | 51 +++++++++++++++++++++++++++++++ 6 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 docs/public/apple-touch-icon.png create mode 100644 docs/public/favicon-72.png create mode 100644 docs/public/favicon.svg create mode 100644 docs/public/logo.svg 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 +github-issue-ops logo + +[![Docs](https://img.shields.io/badge/docs-fulll.github.io%2Fgithub--issue--ops-blue)](https://fulll.github.io/github-issue-ops/) +[![Latest release](https://img.shields.io/github/v/release/fulll/github-issue-ops)](https://github.com/fulll/github-issue-ops/releases/latest) [![CI](https://github.com/fulll/github-issue-ops/actions/workflows/ci.yaml/badge.svg)](https://github.com/fulll/github-issue-ops/actions/workflows/ci.yaml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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 4fa30e9..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: { diff --git a/docs/public/apple-touch-icon.png b/docs/public/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fc07165266de4666e09b904ad3ce51e51f02c7bf GIT binary patch literal 12826 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 be8PwXy2pL_JOf32?182vr!HF|Z5H%@p=W|j literal 0 HcmV?d00001 diff --git a/docs/public/favicon-72.png b/docs/public/favicon-72.png new file mode 100644 index 0000000000000000000000000000000000000000..a68991329e193503d5dad90f865bab4795ce38cb GIT binary patch literal 4503 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 literal 0 HcmV?d00001 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/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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + gio_ + + + + + + + + + + + + + + +