agentsclimarketplace

Gh

Skill andresd/jot-skills/gh

GitHub-only and Linear-only Claude Code skills that port the jot CLI loop — capture brain-dumps into well-formed tracker issues, decide what to work on next, and keep the backlog tidy. Each skill is a single SKILL.md invoked from inside Claude Code.

Install
npx -y skills add andresd/jot-skills --skill gh

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Capture, triage, and plan work on GitHub issues from natural language, across one or many repos. Auto-triggers on phrases like "capture this:", "what should I work on next", "what's on my plate today", "tidy the backlog", "find duplicate issues", "all <X> bugs to @<user>", and explicit `/jot-gh <cmd>`, `jot:`, or `jot-gh:` prefixes. Use when the user wants to turn brain-dump text into a well-formed GitHub issue, decide what to work on next, run dedup/stale passes, or bulk-edit issues by natural-language intent. Requires the `gh` CLI authenticated via `gh auth login`.

SKILL.md

15.8 KB, as published. Nobody here has run it

jot-gh

A GitHub-only port of the jot CLI loop: capture brain-dumps into well-formed issues, decide what to work on next, and keep the backlog tidy — all through gh calls. No tracker abstraction (GitHub only), no licensing, no persistent SQLite. Auth is whatever gh auth status already provides.

When to invoke

Explicit (always invoke):

  • /jot-gh <command> — slash form
  • jot: <command> or jot-gh: <command> — prefix form

Auto-invoke (use judgment, prefer explicit when unsure):

  • "capture this: ..." / "capture: ..." / "log this: ..."
  • "what should I work on (next)?" / "what's next?"
  • "what's on my plate today?" / "what am I doing today?"
  • "tidy the backlog" / "find duplicate issues" / "find stale issues"
  • "(re)assign all <X> bugs to @<user>"
  • "make all <X> issues P0/P1/P2/P3"
  • "what does the backlog say about <topic>?"

Do NOT invoke for:

  • General GitHub questions unrelated to issue triage ("what's the API for X?", "how do I fork?")
  • Pull request review or code review (that belongs to other skills)
  • Anything that does not touch the issue lifecycle (issues, labels, assignees, comments)

Prerequisites

Before any command, verify gh is authed:

gh auth status

If the exit code is non-zero, stop and tell the user:

Run gh auth login first. jot-gh uses your gh credentials directly and does not store its own auth.

Also ensure jq is available for parsing gh --json output (command -v jq — error clearly if missing).

Repo resolution

Most commands operate on one repo at a time. To pick:

  1. If the user passed --repo OWNER/REPO, use that.
  2. Otherwise, run gh repo view --json nameWithOwner -q .nameWithOwner from the current directory — if it returns a repo, use it.
  3. Otherwise, ask the user which repo via AskUserQuestion. Offer the 3 most-recent repos from gh repo list --json nameWithOwner --limit 10 -q '.[].nameWithOwner' as options.

Multi-repo flows (next by default, ask if no repo context): use gh search issues with --owner @me or assignee filters. Each issue carries its repo in the result; treat writes per-repo. Do not run tidy, assign, or reprioritize cross-repo — those are single-repo only.

Memory file: .github/jot.md

If .github/jot.md exists in the target repo, load it before any LLM-y step (extraction, ranking, dedup decision). It holds repo-specific rules: glossary, priority defaults, label conventions, "all bugs filed by @alice are P1", "anything tagged regression is P0", etc.

Read it via:

gh api "repos/OWNER/REPO/contents/.github/jot.md" --jq .content 2>/dev/null | base64 -d

Cap at ~4KB. If larger, take the first 4KB and tell the user the file was truncated.

Apply memory rules when:

  • Extracting structured fields in capture (priority, labels)
  • Ranking issues in next
  • Deciding dedup similarity in capture and tidy

If memory rules conflict with the user's explicit request in this turn, the user wins.

Cache: ~/.cache/jot-gh/

Cache recent issue digests at ~/.cache/jot-gh/<owner>__<repo>.json so next/tidy don't re-fetch 500 issues per invocation.

  • TTL: 10 minutes. Compare file mtime to now; if older, refetch.
  • Bypass: any command with --no-cache.
  • Miss path: gh issue list --repo OWNER/REPO --state open --limit 200 --json number,title,labels,assignees,updatedAt,body,url → write to cache file.
  • Cache is not load-bearing. Safe to delete at any time. Never treat a cached value as authoritative for writes — re-fetch before gh issue edit.

Action log: ~/.cache/jot-gh/actions.jsonl

Every successful write appends one JSON line:

{"ts":"2026-05-20T10:00:00Z","cmd":"capture","repo":"andresd/jot","action":"created","number":42,"url":"https://github.com/andresd/jot/issues/42","inverse":{"op":"close","number":42}}
  • Keep only the last 100 lines (trim head on each append).
  • Used exclusively by undo.
  • Skip the log for previews, dry-runs, and read-only commands.

Commands

capture <text>

Natural-language brain-dump → well-formed issue, with dedup check first.

Flow:

  1. Resolve repo. Load .github/jot.md if present.
  2. Pull existing labels once: gh label list --repo OWNER/REPO --json name --limit 100.
  3. Extract 3–5 keywords from <text> (noun phrases, key verbs).
  4. Dedup search:
    gh search issues --repo OWNER/REPO --state open --json number,title,body,url --limit 10 -- "<keywords joined with OR>"
    
  5. Score top 5 candidates for semantic similarity vs. <text>. If best score reads as "likely duplicate" (same bug/feature, not just same topic), surface that.
  6. Extract structured fields, constrained by the existing-labels list and memory rules:
    • title: concise, imperative for actions ("Fix login redirect loop"), declarative for observations ("Search returns 500 on empty query").
    • body: original text, then a blank line, then _Captured via jot-gh on YYYY-MM-DD._
    • labels: pick zero-or-more from the existing labels. Always include exactly one of P0|P1|P2|P3 (default P2 unless memory rules say otherwise). Include exactly one of bug|feature|chore|docs if clear from text.
    • assignee: only if <text> explicitly names a person via @handle.
  7. Preview via AskUserQuestion:
    • Create issue (default)
    • Comment on dup #N (only if a dup was found)
    • Edit fields first
    • Cancel
  8. On Create issue:
    gh issue create --repo OWNER/REPO --title "..." --body "..." --label "P2,bug" --assignee @me
    
    Append to action log with inverse: {op: "close", number: <new_number>}.
  9. On Comment on dup #N:
    gh issue comment <N> --repo OWNER/REPO --body "<captured text>\n\n_Linked via jot-gh dedup._"
    
    Log with inverse: {op: "delete_comment", number: <N>, comment_id: <id>}.
  10. On Edit fields first: ask which field (title/body/labels/assignee), update, re-prompt.

Do not invent labels that don't already exist on the repo. If the repo is missing P0..P3, tell the user and offer to create them (one-shot: gh label create P0 --color B60205 etc.).

next [--for @user] [--scope <filter>] [-n N] [--commit] [--repo OWNER/REPO]

Top-N ranked open issues with a one-line rationale per item. Defaults: --for @me, n=5, multi-repo.

Flow:

  1. List candidates:
    # multi-repo (default)
    gh search issues --assignee @me --state open --json repository,number,title,labels,updatedAt,body,url --limit 100
    # single-repo when --repo passed
    gh issue list --repo OWNER/REPO --assignee @me --state open --limit 100 --json number,title,labels,updatedAt,body,url
    
  2. For each distinct repo in the results, load .github/jot.md (cache the load per turn).
  3. Rank by, in order:
    • Priority label: P0 > P1 > P2 > P3 > (none)
    • jot-today label present (boost)
    • Age (newer wins for P0/P1, older wins for P2/P3)
    • Memory-rule hints
  4. Output a numbered list. Each line: [OWNER/REPO#N] prefix, title, priority badge, one-sentence rationale, then URL on the next line.
  5. If --commit: confirm via a single AskUserQuestion (Commit these N to today / Cancel), then for each chosen item:
    gh issue edit <N> --repo OWNER/REPO --add-label jot-today
    
    Log each. inverse: {op: "remove_label", label: "jot-today", number: <N>}.

tidy [--repo OWNER/REPO]

Interactive backlog hygiene. Single-repo only (multi-repo tidy is too noisy).

Flow:

  1. Resolve repo.
  2. Fetch all open issues: gh issue list --repo OWNER/REPO --state open --limit 500 --json number,title,labels,assignees,updatedAt,body,url.
  3. Run four passes:
    • dup — cluster by title+body similarity. Report any cluster of 2+, recommending the oldest as canonical and the rest to close-with-link.
    • staleupdatedAt > 30 days ago and not in an open milestone. Recommend close with comment, or label stale.
    • stale-assignment — has assignee, no comment or edit in last 14 days. Recommend unassign and ping.
    • missing-priority — no P0|P1|P2|P3 label. Recommend P2 as default (or memory-rule default).
  4. Output a single numbered list (text mode — not AskUserQuestion; tidy routinely produces 20+ findings):
    1. [dup]      #42 looks like dup of #38 — close #42 with link?
    2. [stale]    #15 — no activity since 2026-04-12 (38d). Close with comment?
    3. [stale-asn] #71 — @bob assigned 22d ago, no movement. Unassign?
    4. [priority] #88 — missing P-label. Add P2?
    ...
    
  5. Prompt the user in plain text:

    Apply which? Reply with numbers (e.g. 1,3,5), all, or cancel.

  6. Apply each accepted finding via the appropriate gh issue edit / gh issue close / gh issue comment. Log every write.

ask <question> [--repo OWNER/REPO]

NL Q&A over the backlog with #N citations. Read-only.

Flow:

  1. Resolve repo (or stay multi-repo if none given).
  2. Search both open and closed:
    gh search issues --repo OWNER/REPO --state all --json number,title,body,state,labels,closedAt,url --limit 30 -- "<keywords>"
    
  3. Answer in 2–4 sentences. Cite each referenced issue as [#42](URL) (markdown link).
  4. No writes. No action log.

assign <NL intent> [--repo OWNER/REPO]

Bulk reassignment by natural language. Single-repo only.

Example intents:

  • "all open auth bugs to @alice"
  • "@bob's open issues to @carol"
  • "everything labeled regression to @me"

Flow:

  1. Parse the intent into { label?, assignee_old?, assignee_new, state? }. If parsing is uncertain, ask via AskUserQuestion with the best-guess filter.
  2. List candidates:
    gh issue list --repo OWNER/REPO --state open --label "<label>" --assignee "<old_or_*>" --limit 200 --json number,title,assignees,url
    
  3. Show the numbered candidate list (text mode).
  4. Prompt:

    Reassign these to @<new>? Reply with numbers, all, or cancel. Numbers SKIPPED will keep their current assignee.

  5. For each chosen item, use TOCTOU best-effort:
    • Re-read the issue (fresh, no cache).
    • If <new> is already assigned, skip with a note.
    • Else: gh issue edit <N> --repo OWNER/REPO --add-assignee <new> (and --remove-assignee <old> if specified).
    • On HTTP 422/409 (concurrent edit), warn and continue.
  6. Log each. inverse: {op: "set_assignees", number: <N>, assignees: [<prev list>]}.

reprioritize <NL intent> [--repo OWNER/REPO]

Bulk priority change by natural language. Single-repo only.

Example intents:

  • "all launch-blocker label → P0"
  • "all P3 bugs older than 90 days → close as stale" (this overlaps with tidy; route to tidy if the intent is hygiene, not promotion)
  • "@alice's open issues to P1"

Same flow as assign, but operating on P0|P1|P2|P3 labels:

  • For each accepted item: gh issue edit <N> --repo OWNER/REPO --remove-label "<old P>" --add-label "<new P>".
  • Log with inverse: {op: "swap_label", number: <N>, from: <new>, to: <old>}.

status [--team] [--repo OWNER/REPO]

Default (no --team): list issues with jot-today label assigned to @me, across repos. Show priority and repo.

gh search issues --assignee @me --label jot-today --state open --json repository,number,title,labels,url

--team: list jot-today issues in the target repo across all assignees, grouped by assignee.

gh issue list --repo OWNER/REPO --label jot-today --state open --limit 100 --json number,title,assignees,labels,url

No writes.

clear-plan [--repo OWNER/REPO]

Remove jot-today from all issues currently labeled with it for @me.

Flow:

  1. List:
    gh search issues --assignee @me --label jot-today --state open --json repository,number,url
    
  2. Show count and titles. Confirm via AskUserQuestion: Clear N items / Cancel.
  3. For each: gh issue edit <N> --repo OWNER/REPO --remove-label jot-today. Log.

undo

Reverse the most recent action within 24 hours.

Flow:

  1. Read ~/.cache/jot-gh/actions.jsonl (tail).
  2. Find the most recent entry where ts > now - 24h. If none, tell the user no recent action is reversible.
  3. Show the action and its planned inverse via AskUserQuestion: Undo / Cancel.
  4. Re-read the affected issue's current state (no cache). If state has changed in a way that makes the inverse meaningless (e.g. issue already closed, label already gone), abort with a clear explanation rather than forcing it.
  5. Apply the inverse:
    • created #Ngh issue close <N> --comment "Reverted by jot-gh undo"
    • closed #Ngh issue reopen <N>
    • add_label X #Ngh issue edit <N> --remove-label X
    • remove_label X #Ngh issue edit <N> --add-label X
    • swap_label from=A to=B #Ngh issue edit <N> --add-label A --remove-label B
    • add_assignee U #Ngh issue edit <N> --remove-assignee U
    • set_assignees [list] #Ngh issue edit <N> --add-assignee <list...> after clearing current
    • commented #N (cmt_id)gh api -X DELETE "repos/OWNER/REPO/issues/comments/<id>"
  6. On success, remove the entry from the log. Do not chain undos — one undo reverses one action.

help

Print one line per command above. No gh calls. No log.


Output conventions

  • Cross-repo listings: always prefix items with [OWNER/REPO#N]. Single-repo listings: prefix with #N.
  • Every write reports the resulting URL on the next line (fetch via gh issue view <n> --repo OWNER/REPO --json url -q .url if not already known).
  • No emoji in skill output unless the user uses emoji first.
  • gh errors surface verbatim — do not swallow them. If gh exits non-zero on a write, stop the batch and report which item failed.

Confirmation patterns

  • Single write (capture create, single-item assign, undo, --commit): AskUserQuestion with Confirm / Edit / Cancel.
  • Multi-write (tidy, bulk assign, bulk reprioritize, clear-plan): numbered text list, free-text reply (1,3,5 / all / cancel). AskUserQuestion only fits 4 options, so it does not scale here.
  • Read-only (status, ask, next without --commit): no confirmation.

Rate limits

gh handles auth and rate-limit retry on its own. Avoid hand-built pagination loops — use --limit and let gh paginate internally. If a write batch encounters a rate-limit error, stop, report progress so far, and tell the user to retry after the reset window shown in the error.

Anti-patterns

  • Don't call the REST API via curl / gh api unless gh issue / gh search / gh label / gh repo cannot express the operation. gh handles auth, retries, and pagination.
  • Don't batch writes without showing a preview first, even when the user said "go ahead" earlier in the turn — previews are cheap insurance against an LLM misparse.
  • Don't invent labels that aren't already on the repo. If a needed label is missing, ask before creating it.
  • Don't write to closed issues unless the user explicitly named the issue.
  • Don't store any auth, tokens, or secrets. gh is the source of truth.
  • Don't treat the cache as authoritative for writes — always re-fetch the issue before gh issue edit.
  • Don't run tidy, assign, or reprioritize cross-repo. They are single-repo by design.
  • Don't chain undos. One undo reverses one action; if the user wants more, they invoke undo again.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.