macOS shell scripts that format GitHub CLI (gh) output (PRs, issues, etc.) into rich text and copy it to the clipboard for pasting into Slack with clickable links and custom emoji.
gh-clippy— formats GitHub PRs/issues (andgh stackstacks) as rich text for Slackgh-syms— creates branch-named symlinks for git repo directories
brew install jsheffie/tap/gh-to-slack-
Create
~/binif it doesn't exist:mkdir -p ~/bin -
Download the scripts and make executable:
curl -fsSL https://raw.githubusercontent.com/jsheffie/gh-to-slack/v1.0.7/scripts/gh-clippy.sh \ -o ~/bin/gh-clippy && chmod +x ~/bin/gh-clippy curl -fsSL https://raw.githubusercontent.com/jsheffie/gh-to-slack/v1.0.7/scripts/gh-syms.sh \ -o ~/bin/gh-syms && chmod +x ~/bin/gh-syms
-
Add
~/binto your PATH (if not already there):zsh (
~/.zshrc):echo 'export PATH="$HOME/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc
bash (
~/.bashrc):echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc
- macOS (uses
NSPasteboardvia Swift for clipboard access) —gh-clippyonly ghCLI (authenticated) —gh-clippyonlyjq—gh-clippyonlygh-stackextension —gh-clippy stackonly- Swift runtime (ships with Xcode / Command Line Tools) —
gh-clippyonly git—gh-symsonly
List your recent PRs or issues formatted for Slack. Copies rich text to clipboard — Cmd+V into Slack gives clickable links.
Individual Developer Focused:
Defaults to @me for status reporting.
gh-clippy pr # Open, ready-for-review PRs
gh-clippy pr --all # All PRs
gh-clippy pr 12595 12593 # Specific PRs
gh-clippy pr --limit 20 # Up to 20 PRs
gh-clippy issue # Open issues assigned to me
gh-clippy issue --all # All issues
gh-clippy issue 42 57 # Specific issues
gh-clippy issue --limit 5 # Show 5 issues
gh-clippy pr django:pr:100 # PR 100 in ~/workspace/django
gh-clippy pr django:pr:100 api:issue:99 # Mixed repos and types, listed orderItems can be named as <repodir>:<pr|issue>:<number> to pull from another
repository. The repo directory resolves under ~/workspace — set
GH_CLIPPY_WORKSPACE to use a different root. Explicitly named items print in
the order given and ignore --limit, and PRs and issues can be mixed in one
list. These fully-qualified specs work from any directory, even one that
isn't a git repo at all; bare numbers and list mode still require the
current directory to be a GitHub repo.
Output is no longer re-sorted: pr and issue list in the order the GitHub CLI
returns, and named items list in the order you passed them. (activity still
sorts newest-first.)
Stacked PRs:
Formats a gh stack stack, one line per PR,
in stack order (bottom of the chain first).
gh stack view --json | gh-clippy stack # pipe the stack JSON in
gh-clippy stack # or let gh-clippy fetch it
gh stack view --json | gh-clippy stack --teams # MS Teams tablegh-clippy stack reads gh stack view --json from stdin when it is piped one,
and otherwise runs gh stack view --json itself in the current repo. Because the
piped JSON names its own repository, the piped form works from any directory.
stack is the only subcommand that reads stdin. Piping into any other one is an
error rather than a silent no-op — gh stack view --json | gh-clippy pr would
otherwise discard the JSON and print your open PRs, which overlap a stack enough
to look correct while answering a different question.
A stack prints in full: --limit, --all, --user, and item numbers are
rejected, since truncating or filtering a stack would misrepresent the chain.
Draft PRs are always shown — a draft in a stack is still part of it. Branches
added locally but not yet submitted have no PR to link, so they are skipped with
a note on stderr (the clipboard payload stays clean).
Requires the gh-stack extension:
gh extension install github/gh-stack.
Team/Management Focused:
gh-clippy activity # Recent issues & PRs (defaults to 10 each)
gh-clippy activity --user-display # With linked usernames
gh-clippy activity --limit 5 # 5 items per section
gh-clippy pr --user octocat # Open PRs by octocat
gh-clippy issue --user bob --user ben # Issues for multiple users
gh-clippy users # List collaborators with linksCreate branch-named symlinks for git directories in the current working directory. Running without a subcommand removes stale symlinks, creates fresh ones, then lists the result.
By default only directories named exactly <prefix> or <prefix><N> (e.g. django, django2, django3) are processed — not django-old or django_bak.
gh-syms django # Remove stale, create fresh, list
gh-syms django --verbose # Same, with removal/creation details
gh-syms django list # List existing symlinks only
gh-syms django clean # Remove all symlinks for django* dirs
gh-syms django --no-strict-nums-only # Also process django-old, django_bak, etc.Terminal output uses ANSI-colored status icons for quick visual scanning. The #number for each PR or issue is a clickable hyperlink in supported terminals (iTerm2, Terminal.app, Warp, etc.).
Each line is formatted as: emoji title #number. PRs use these status emoji:
| Emoji | State |
|---|---|
:git--merged: |
Merged |
:git--closed: |
Closed |
:git--draft: |
Draft |
:git--approved: |
Approved |
:git--changes-required: |
Changes requested |
:git--ready-for-review: |
Ready for review |
Issues use these status emoji:
| Emoji | State |
|---|---|
:git--issue: |
Open |
:git--closed: |
Closed |
- Fetches PR/issue data as JSON via
gh - Transforms it with
jqinto HTML (with<a>links) and plain text - Copies both formats to the macOS clipboard using an inline Swift snippet — Slack preserves hyperlinks from the HTML pasteboard type
MIT