issuesort
Triage GitHub issues with AI — find duplicates and suggest labels. Zero dependencies.
When a new issue lands, issuesort compares it against the open issues by
meaning (embedding similarity) to surface likely duplicates, and asks a model
to pick fitting labels from your repository's own label set. It posts the result
as a comment, and can apply the labels for you.
Run it as a GitHub Action on every new issue, or invoke the CLI by hand. It uses any OpenAI-compatible API — including a local server — and nothing but the Python standard library.
Example comment
## issuesort triage
**Possible duplicates:**
- #128 App crashes when saving an empty file _(similarity 0.91)_
- #97 Save dialog throws on empty path _(similarity 0.86)_
**Suggested labels:** `bug`, `needs-repro`
Install
pip install issuesort
Requires Python 3.8+.
CLI usage
export OPENAI_API_KEY=sk-...
export GITHUB_TOKEN=ghp_...
# Print a triage for issue #42
issuesort --repo octocat/hello-world --issue 42
# Post it as a comment and apply the suggested labels
issuesort --repo octocat/hello-world --issue 42 --post --apply-labels
Options
| Flag | Description |
|---|---|
--repo OWNER/NAME |
Repository (required). |
--issue N |
Issue number (required). |
--threshold X |
Duplicate similarity cutoff, 0-1 (default 0.83). |
--top N |
Max duplicates to report (default 5). |
--no-labels |
Skip LLM label suggestion (duplicates only). |
--post |
Post the triage as an issue comment. |
--apply-labels |
Apply the suggested labels. |
--model / --embed-model |
Chat and embedding models. |
--base-url / --api-key |
Provider configuration. |
GitHub Action
Triage every newly opened issue. Store your provider key as a secret:
name: issuesort
on:
issues:
types: [opened]
permissions:
contents: read
issues: write
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: Sev7nOfNine/issuesort@v0.1.0
with:
api-key: ${{ secrets.OPENAI_API_KEY }}
apply-labels: "false"
How duplicate detection works
The issue's title and body are embedded and compared against every open issue by
cosine similarity. Anything at or above --threshold is reported, best match
first. Tune the threshold to taste: higher is stricter.
Privacy note
Issue text is sent to whichever provider you configure. Prefer a self-hosted
model via --base-url for private repositories.
Development
pip install -e ".[test]"
python -m pytest
Tests run offline; the network layers accept injectable fakes.
License
MIT — see LICENSE.
Metadata
Release files for issuesort 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| issuesort-0.1.0.tar.gz | 10.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| issuesort-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 22.1 kB
Release files / issuesort-0.1.0.tar.gz
| Download URL | issuesort-0.1.0.tar.gz |
|---|---|
| Size | 10.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fa07f0d9e4b6ff3e8f7d4a5606e17839b8e7ea98b8c4218d0825e349997929ff
|
|
BLAKE2b-256 checksum How to use checksums |
28469535b794ebca915e2803591a30fe71551f369fd887cf320e0c9bba2f6294
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.0
|
Release files / issuesort-0.1.0-py3-none-any.whl
| Download URL | issuesort-0.1.0-py3-none-any.whl |
|---|---|
| Size | 11.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3919d07d1e95e06303099a7476088eea0f2bc82869ba2d1ae5e4451bafcbe00f
|
|
BLAKE2b-256 checksum How to use checksums |
c3ed574a8a5c54a9ba9bb03b66a0bbc65b912d345300bfe39f6b023f916c976e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.0
|