{"id":"github-board","repo":"gpambrozio/paseo-plugins","url":"https://github.com/gpambrozio/paseo-plugins/tree/main/github-board","package":"@gpambrozio/paseo-github-board","npm":{"package":"@gpambrozio/paseo-github-board","version":"0.10.2","integrity":"sha512-B0zuK7CqyBaxmZcGsODkX1g676E3x8TPuSjfSfXhfBeJCE4HooadaK8a9sSFx1faANCaHgi1XocDHx6eG2F+LQ==","publishedAt":"2026-10-07T18:49:53.657Z","downloadsLast30Days":2485},"name":"github-board","description":"Paseo plugin: a GitHub sidebar board of your issues, draft and open pull requests, and discussions","categories":["github","productivity","monitoring"],"platforms":[],"caveats":["Requires gh installed and authenticated on the daemon machine, not the device running the app","Editing labels needs a gh login with write access to the repository"],"images":["https://raw.githubusercontent.com/gpambrozio/paseo-plugins/09509ce55ab06758623262e6aa71522ade6fda0c/github-board/docs/screenshot.png","https://raw.githubusercontent.com/gpambrozio/paseo-plugins/09509ce55ab06758623262e6aa71522ade6fda0c/github-board/docs/detail-panel.png"],"themes":[],"health":{"manifestValid":true,"hasReadme":true,"hasLicense":true,"hasTests":true,"hasTypecheckScript":true,"updatedRecently":true},"scannedAt":"2026-10-15T12:29:57.724Z","addedAt":"2026-09-09T16:19:20+03:00","npmSecurity":{"status":"passed","blockingFindings":0,"advisoryFindings":0,"scannedAt":"2026-10-15T12:14:24.405Z","version":"0.10.2","integrity":"sha512-B0zuK7CqyBaxmZcGsODkX1g676E3x8TPuSjfSfXhfBeJCE4HooadaK8a9sSFx1faANCaHgi1XocDHx6eG2F+LQ=="},"path":"github-board","version":"0.10.2","security":{"status":"passed","blockingFindings":0,"advisoryFindings":0,"scannedAt":"2026-10-15T12:14:24.405Z","commit":"09509ce55ab06758623262e6aa71522ade6fda0c"},"license":"MIT","paseoVersionRequirement":">=0.11.0","descriptionNodes":[{"type":"text","text":"Paseo plugin: a GitHub sidebar board of your issues, draft and open pull requests, and discussions"}],"caveatNodes":[[{"type":"text","text":"Requires gh installed and authenticated on the daemon machine, not the device running the app"}],[{"type":"text","text":"Editing labels needs a gh login with write access to the repository"}]],"manifest":{"id":"github-board","description":"Your GitHub issues, pull requests and discussions on one sidebar board","requirements":{"paseo":">=0.11.0"}},"repoMeta":{"stars":14,"defaultBranch":"main","pushedAt":"2026-10-09T21:12:13Z"},"owner":{"login":"gpambrozio","avatarUrl":"https://avatars.githubusercontent.com/u/672135?v=4"},"installNotesHtml":"<pre><code class=\"language-bash\">paseo plugin install npm:@gpambrozio/paseo-github-board\n</code></pre>\n<p>That is the shortest route on <strong>Paseo 0.11 or newer</strong>, which installs plugins straight from npm; add\n<code>@&#x3C;version></code> to pin one. On Paseo 0.9 or 0.10, install the last release that supports them:\n<code>paseo plugin install npm:@gpambrozio/paseo-github-board@0.9.3</code>. On 0.8, install the last release that supported it from this repository instead:</p>\n<pre><code class=\"language-bash\">paseo plugin add gpambrozio/paseo-plugins --path github-board\n</code></pre>\n<p>This repository holds five plugins, hence <code>--path</code>. The daemon clones it under <code>$PASEO_HOME/plugins</code>\nand runs no package manager — the plugin is source only, and everything it imports at runtime the\nhost provides. Pin a release with <code>--ref &#x3C;tag></code>; later, <code>paseo plugin status</code> and\n<code>paseo plugin update github-board</code> follow the branch.</p>\n<p>To hack on it instead, install from a clone of your own:</p>\n<pre><code class=\"language-bash\">git clone https://github.com/gpambrozio/paseo-plugins.git\ncd paseo-plugins/github-board\nnpm install\nnpm run typecheck\npaseo plugin install \"$PWD\"\n</code></pre>\n<p><code>install</code> records the directory, so keep that clone where it is — the daemon loads the plugin from\nthat path every time it starts. <code>npm install</code> is for the typecheck; installing needs none of it.</p>\n<p>The daemon needs <code>\"pluginsEnabled\": true</code> in its <code>config.json</code>. Run <code>paseo reload</code> after changing\nit. Plugin code is trusted and unsandboxed: the server half shells out to <code>gh</code> on the daemon\nmachine and the client half runs inside the Paseo app.</p>","readmeText":"# paseo-github-board\n\nA Paseo plugin that adds a **GitHub** sidebar screen showing your work — and the\nwork waiting on you — in four columns:\n\n| Column | Source |\n| --- | --- |\n| Issues | `gh api graphql`, `search(type: ISSUE)` for `is:issue state:open` |\n| Draft PRs | `gh api graphql`, `search(type: ISSUE)` for `is:pr state:open`, filtered to `isDraft` |\n| Open PRs | the same search, filtered to non-draft |\n| Discussions | `gh api graphql`, `search(type: DISCUSSION)` |\n\nEvery column runs its search **more than once** and unions the results: once for\n`author:<login>`, once for `user:<login>` — everything in the repositories that\nlogin owns, whoever opened it — and, for issues and pull requests, once for\n`assignee:<login>`. Those last two are why work somebody else opened shows up\nhere: an issue filed on your own repository, or one handed to you anywhere on\nGitHub. The card names its author when it is not you. Discussions get the first\ntwo only, since a discussion has no assignee. GitHub search ANDs its qualifiers,\nso they cannot be folded into one query; they are aliased searches sharing one\n`gh api graphql` request instead.\n\nBoth pull request columns come from one search, so the four columns cost three\n`gh` calls per refresh, not four or six — plus one more for the check runs on\nthe open pull requests, and one for how far each pull request's branch is\nbehind, when there are any. Everything goes through GraphQL\nrather than `gh search`, because only GraphQL exposes `closingIssuesReferences`\nand `statusCheckRollup` — see below.\n\n![The GitHub board: Issues, Draft PRs and Open PRs columns of cards, with the repository\nfilter, the settings gear and the refresh button in the header.](docs/screenshot.png)\n\n## Issues folded into their pull requests\n\nAn issue that already has an open pull request against it is the same piece of\nwork as that pull request, so it gets one card, not two: the issue drops out of\nthe **Issues** column and shows up as an accent-coloured `Issue #123` pill on\nthe pull request card. Drafts count — the work exists either way — so a draft\npull request claims its issue too.\n\nThe link is GitHub's own `closingIssuesReferences`, which sees both closing\nkeywords in the pull request body (`Closes #123`) and issues attached by hand\nfrom the Development panel. A pill reads `Issue owner/name#123` when the issue\nlives in another repository.\n\nThe fold happens after the repository filter, so hiding a pull request's\nrepository puts its issue back on the board rather than taking both cards away.\n\n## Empty columns come off the board\n\nA column with nothing in it is left out: the remaining columns share the full\nwidth, and on a phone the tab bar lists only the tabs that lead somewhere. It is\ncounted after the repository filter and the issue fold, so filtering a repository\ndown to nothing, or a pull request claiming the last issue, takes that column\nwith it.\n\nA column that **failed** to load stays, error and all — it is empty because the\nquery broke, not because there is no work. And when every column is empty the\nwhole board comes back, four \"Nothing here.\" columns saying it loaded and found\nnothing.\n\n## Checks on open pull requests\n\nAn open pull request card leads its footer with the state of CI on the head\ncommit, the same three counts Paseo's own sidebar shows on a workspace:\n\n| Pill | Means |\n| --- | --- |\n| `✓ 12` | checks that passed |\n| `✕ 1` | checks that failed, timed out, or need action — in the theme's danger colour |\n| `● 3` | checks still queued or running, in the accent colour |\n\nAn outcome nobody has is left out, so a green pull request shows one pill rather\nthan two zeroes, and a pull request whose head commit nothing reported on shows\nnone at all. Skipped and cancelled checks are counted nowhere: they are neither\na result nor something to wait for. Where a check has been re-run, only the\nlatest attempt counts.\n\n**Draft pull requests show no checks.** A draft says the work is not finished,\nso its CI is not yet anyone's business — and asking for fewer pull requests\nkeeps the extra request small.\n\nThe checks are a **separate `gh` call** from the search on purpose. A token\nwithout permission to read checks — a fine-grained PAT, usually — makes GitHub\nfail the whole GraphQL request, and folding the rollup into the search would\nturn that into two blank pull request columns. On its own, it costs only the\npills, and the reason lands in `paseo plugin logs github-board`.\n\nChecks are cached with the rest of the board for five minutes; **Refresh** is\nwhat re-reads a run that has finished since.\n\n## Out-of-date pull requests\n\nA draft or open pull request whose base branch has moved on since the branch was\nlast updated shows an **Out of date** pill, in the theme's warning colour, next\nto its checks — or **Conflicts**, in the danger colour, when the branch and its\nbase change the same lines and someone has to resolve them by hand. The base is\nwhatever the pull request targets — `main` for most, another branch for a\nstacked one. The detail panel shows the same pill and says how far behind on the\nbranch line: `feature → main · 12 commits behind`.\n\nWhere GitHub would let you bring it up to date, the card and the panel also\noffer **Update branch** — on a card it appears on hover beside **Send to chat**,\nand on a phone it sits in the card's button row. In a tablet's browser, where\nnothing hovers, open the card and use the button in the panel. It does what\nGitHub's own button does, merging the base branch into the pull request's branch\non GitHub; it never rebases, so a checkout of the branch elsewhere still pulls\ncleanly. The pill goes away once GitHub accepts the update.\n\nA pull request with conflicts never offers the button, since an automatic update\ncannot succeed there. GitHub only works out whether a branch has conflicts once\nsomebody asks, so the first time the board loads a pull request it may not know\nyet; pressing **Update branch** checks again first, and if it finds conflicts it\nmerges nothing, switches the pill to **Conflicts** and says so.\n\nOther out-of-date pull requests can show the pill and no button too. That is\nGitHub's answer, not the plugin's: it offers no update when your login cannot\npush to the branch, or when the repository has **Always suggest updating pull\nrequest branches** turned off — which is the default for a new repository — and\nbranch protection does not require an up-to-date branch. Turn that setting on\nunder the repository's **Settings → General → Pull Requests** to get the button\nthere.\n\nThis works for pull requests from forks too. How far behind a branch is comes\nfrom its own `gh` call, so if that fails the pills and buttons are left off and\nthe reason lands in `paseo plugin logs github-board`; the pull requests\nthemselves still load. Like checks, it is cached with the board for five\nminutes, and **Refresh** reads it again.\n\n## Configuring the prompts\n\nThe **gear button** in the header opens the settings view. It holds the GitHub\nlogin the board queries for, and the first message each kind of card is sent\nwith:\n\n| Column | Default prompt |\n| --- | --- |\n| Issues | `Read issue {url}, investigate and give me ways to address it.` |\n| Draft PRs | `Read draft pull request {url} and help me finish it.` |\n| Open PRs | `Review pull request {url} and tell me what needs attention.` |\n| Discussions | `Read discussion {url} and summarise what is being decided.` |\n\nTemplates can use `{url}`, `{title}`, `{number}` and `{repository}`. Anything\nelse in braces is passed through untouched. A template is only the starting\npoint — the launch dialog lets you rewrite the message before it is sent.\n\nPick a Paseo project from the row of chips to override those four prompts for\nthat project alone; a dot on a chip means it has overrides. Cards are matched to\na project by the repository's git remote, the same way sending one is — so a\nfork and the repository it was forked from share one set of prompts, and a\nrepository with no project needs none, since it cannot be sent anywhere either.\n\n**Clearing a field is how you reset it** — a blank project prompt falls back to\nthe one for all projects, and a blank prompt for all projects falls back to the\nbuilt-in default above. Nothing is saved until you press **Save prompts**.\n\n## Filtering by repository\n\nThe header dropdown next to **Set** lists every repository with a card anywhere\non the board and filters all four columns at once. Everything starts selected;\n**All** and **None** set the whole list.\n\nThe selection is saved by Paseo, per daemon, because the surface unmounts on\nevery workspace switch and component state would not survive it. Changing it on\none device shows up on the others without a reload. It is stored as the\n*hidden* repositories rather than the visible\nones, so a repository the filter has never seen — a new one, or one whose first\ncard only appears on a later refresh — arrives selected rather than silently\nfiltered out.\n\n## Reading a card\n\n**Click a card** and it opens in a panel beside the board — the right half of the screen, or the\nwhole of it on a phone. A link to the board that names a card opens it in the panel. The panel\nshows the title, who opened it, the comment count, the labels, a pull request's branches, and the\ndescription rendered the way GitHub renders it — including the HTML a bot like Dependabot writes,\nwhose release notes show as collapsible sections — followed by the assignees. A pill in the panel's header says whether the item is still open, or has been closed or\nmerged since the board was fetched.\n\n**Open on GitHub** is in the panel, next to **Send to chat**, so nothing the card used to do is\ngone — it is one press further away. **Refresh** reloads the description if it was edited on\nGitHub in the meantime; otherwise the panel remembers what it fetched for five minutes.\n\nA **Load comments** button at the foot of the panel fetches the conversation — the comments on an\nissue or pull request, or a discussion's comments with their replies indented under them. It shows\nthe first 50 and says so if there are more; pull request review comments on the diff are not\nincluded. Refresh reloads the comments too once they have been loaded.\n\nScreenshots pasted into the description or a comment are shown in the panel, including\nattachments on private repositories, which the plugin fetches through `gh` on the daemon. Press\none to open the original.\n\nOn a desktop the panel's left edge can be dragged to make it wider or narrower. The width is saved\nas a share of the board, so it comes back the same after a restart and scales with the window.\n\nWhile the panel is open the board behind it is blurred, and clicking it closes the panel. The open\ncard is outlined so you can see which one you are reading.\n\n![A pull request open in the detail panel: repository and state at the top, the title, who opened\nit and when, its branches, Send to chat and Open on GitHub buttons, and the description below,\nwith the board blurred behind it.](docs/detail-panel.png)\n\n## Labels\n\n**Right-click** an issue or pull request card — **long-press** on a phone or tablet — and its\nrepository's labels open where you clicked. Press a label to add it, press it again to remove it.\nEach press is applied to GitHub straight away and the card's pills update with whatever GitHub\nreports back, so a label a teammate added in the meantime shows up rather than being wiped by your\nedit.\n\nDiscussions have no label menu. Cards show three labels and then a `+2`, so an edit past the third\nis still visible as a change.\n\nEditing labels needs a `gh` login with write access to the repository; without it the menu says so\nand leaves the label alone. The menu lists the repository's first 100 labels by name, with a filter\nbox once there are more than eight.\n\n## Send to chat\n\nHover a card and a **Send to chat** button appears in its bottom-right corner.\nIt opens a **New workspace** dialog, the same choices Paseo asks for when you\nstart a chat yourself:\n\n- **Which computer** it runs on, when the app is connected to more than one — the\n  board's own, or any other that is online. Only shown when there is a choice.\n- **Local** or **New worktree** — a worktree is offered only for git projects.\n- The **agent**, picked the way Paseo picks one: a menu of providers with their\n  model counts, then that provider's models behind a back arrow, with a search\n  box that ranks across every provider.\n- **Thinking**, for models that have levels, and the **permission mode**, for\n  providers that have modes. Both follow the model you pick.\n- The **first message**, pre-filled from that column's prompt template and\n  yours to rewrite.\n\nPress **Send** and the plugin creates the workspace on the project checked out\nfrom that card's repository, titled after the issue, pull request or discussion,\nstarts the agent you chose in it, sends your message, and opens the new\nworkspace in the app.\n\nThe conversation opens with the card itself — repository and number, title,\nauthor and labels — as the first thing under your message. Click it to open the\noriginal on GitHub. It is saved with the conversation, so it is still there\nafter a restart and on your other devices, and it does not depend on your\nprompt template having mentioned the issue.\n\nYour choices are remembered, so the next card opens on the same agent. A model\nor provider that has since disappeared quietly falls back to what the host\nactually offers.\n\nIf no project has a git remote pointing at the repository, the dialog says so\nand creates nothing.\n\n### Sending to another computer\n\nThe board always comes from the computer it is installed on — that is where `gh`\nruns — but the agent does not have to. Pick another computer in the dialog and\nthe workspace, the agent and its models are that computer's; the plugin does not\nneed to be installed there. Two things work differently:\n\n- **The repository has to be the project's own there.** On the board's computer a\n  card also finds a fork that keeps the repository as a second remote; on\n  another one it only finds a project whose main remote is the card's\n  repository.\n- **The conversation does not open with the card.** Paseo only lets the plugin\n  add it on the board's own computer, so on another one the issue is only as\n  present as your message makes it — the default prompts include its link.\n\nOn phones and tablets there is no hover, so the button is always visible.\n\n## Caching\n\nRevisiting the board does not re-run `gh`. Two caches sit in front of it, both\nin memory and both five minutes:\n\n- The surface keeps the last board at module scope, so a workspace switch —\n  which unmounts it — repaints instantly. Past the window the stale board stays\n  on screen while a refresh runs underneath it.\n- The handler keeps the last board per login, so even a cold mount usually skips\n  the `gh` calls. A board with a failed column is not cached, so the retry\n  is not held off for five minutes.\n\n**Refresh** bypasses both. The repository filter is not part of the cached board\nat all — Paseo keeps it separately — so changing it cannot be undone by a cache\nhit.\n\n## Requirements\n\n- **Paseo 0.11.0 or newer**, for the daemon *and* the app that shows the board.\n  Both check the version themselves, so an older one reports the plugin as\n  incompatible rather than loading part of it.\n- `gh` installed and authenticated **on the daemon machine**, not the device\n  running the app. Handlers run in a subprocess next to the daemon.\n\n## Install\n\n```bash\npaseo plugin install npm:@gpambrozio/paseo-github-board\n```\n\nThat is the shortest route on **Paseo 0.11 or newer**, which installs plugins straight from npm; add\n`@<version>` to pin one. On Paseo 0.9 or 0.10, install the last release that supports them:\n`paseo plugin install npm:@gpambrozio/paseo-github-board@0.9.3`. On 0.8, install the last release that supported it from this repository instead:\n\n```bash\npaseo plugin add gpambrozio/paseo-plugins --path github-board\n```\n\nThis repository holds five plugi"}