Paperclip plugin that imports GitHub issues into Paperclip tasks.
Each binding ties one GitHub repo to one Paperclip project inside a specific company. Configure as many bindings as you need across as many companies as you need — the plugin polls every binding on a 10-minute cron and creates / updates the corresponding Paperclip tasks.
- Multi-binding: N × (Paperclip company → GitHub repo) per plugin install.
- Idempotent import:
(bindingId, ghIssueNumber)mapping prevents duplicates. - Incremental polling using GitHub's
sincefilter. - Status mirroring: GitHub
closed→ Paperclipdone; reopened → configured default. Manual edits in Paperclip survive intermediate syncs. - In-page secret picker — operators never type secret UUIDs.
- Activity log entries per sync run.
paperclipai plugin install @wil0x91/paperclip-plugin-github-issuesThe plugin shows up under Settings → Plugins → GitHub Issues Sync.
- Settings → Plugins → GitHub Issues Sync.
- Pick a company from the dropdown at the top.
- Click + Add binding.
- Pick (or create inline) a Paperclip secret holding a GitHub PAT
(scope
repofor private,public_repofor public-only). - Type GitHub
ownerandrepo. - Pick the target Paperclip project.
- Choose default status / label prefix.
- Save binding. Allow ~30s for secret authorization to refresh, then click Sync on the new row.
You can repeat for multiple repos in the same company, or switch companies in the dropdown and add bindings there too.
The plugin stores all bindings inside its configJson:
{
"defaultPriority": "medium",
"bindings": [
{
"id": "<companyId>:<owner>/<repo>",
"companyId": "<uuid>",
"projectId": "<uuid>",
"owner": "acme",
"repo": "widgets",
"tokenRef": "<secret-uuid>",
"defaultStatus": "todo",
"labelPrefix": "github:",
"createdAt": "2026-04-26T19:00:00Z"
}
]
}Operators normally never edit this directly — the plugin's settings page does
it through POST /api/plugins/:id/config and the GitHub PAT is stored as a
Paperclip secret (referenced by UUID, never inlined).
issues.read,issues.create,issues.updateplugin.state.read,plugin.state.writejobs.schedulehttp.outboundsecrets.read-refactivity.log.writecompanies.readprojects.readinstance.settings.register
The plugin only reads / writes issues in companies and projects you bind explicitly. The GitHub PAT never leaves the Paperclip secret store except in process memory during the sync call.
- Cron:
*/10 * * * *(every 10 minutes), with a manual Sync now action per binding or for all bindings. - Issues are matched on
(bindingId, gh.number)and persisted in plugin state so re-runs are no-ops. - New issues are imported with the configured
defaultStatus. Closed GitHub issues flip the Paperclip task todoneonce. Reopened GitHub issues flip it back todefaultStatusonce. In between, Paperclip status edits made by humans / agents are preserved. - Imported description includes a link to the source GitHub issue, the author, the GitHub state, and a list of GitHub labels with a configurable prefix.
- One-way sync (GitHub → Paperclip). Paperclip status changes do not echo back to GitHub.
- No webhook support yet — relies on the 10-minute cron.
- No comment sync.
- No assignee mapping.
npm install
npm run typecheck
npm run test
npm run build
paperclipai plugin install --local "$(pwd)"When bumping the version, run npm version <patch|minor|major> — the
included version script keeps the manifest bundle filename in sync with the
package version (Paperclip's host caches plugin manifests by absolute import
path; a fresh filename per release avoids stale loads).
MIT — see LICENSE.